GIT acfc79838298e6604461aba3e50289af20182d54 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-klibc.git commit acfc79838298e6604461aba3e50289af20182d54 Author: H. Peter Anvin Date: Tue Jun 27 19:58:40 2006 -0700 [klibc] Remove obsolete usr/Makefile usr/Makefile has been superceded by usr/Kbuild Signed-off-by: H. Peter Anvin commit dd2d7331073ef06bad1bf020784ddc495d7faed1 Author: H. Peter Anvin Date: Tue Jun 27 09:58:24 2006 -0700 [klibc] Document klibc configuration options, KLIBC_ERRLIST is EMBEDDED Add documentation for the klibc configuration options. In addition, allow EMBEDDED users to select whether or not to include the klibc error list. Signed-off-by: H. Peter Anvin commit 1a7fc20f96824bdf6c67cf544878175060134e7d Author: H. Peter Anvin Date: Tue Jun 27 08:33:57 2006 -0700 [klibc] Clean up merge conflict A merge conflict was inadvertently committed; clean it up. Signed-off-by: H. Peter Anvin commit 6fef631f332c1e66f24c8d9676b8b15082fe2f02 Author: NeilBrown Date: Tue Jun 27 17:06:05 2006 +1000 md: Fix "Will Configure" message when interpreting md= kernel parameter. If a partitionable array is used, we should say e.g. Will configure md_d0 (super-block) from .... rather than Will configure md0 (super-block) from .... which implies non-partitionable. Signed-off-by: Neil Brown ### Diffstat output ./usr/kinit/do_mounts_md.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff .prev/usr/kinit/do_mounts_md.c ./usr/kinit/do_mounts_md.c commit 17561350fb0a32fde4073170c650a4f3349a66ff Author: H. Peter Anvin Date: Mon Jun 26 22:19:25 2006 -0700 [klibc] errno.h: add multiple inclusion guards Although it's unlikely to be a problem if is included more than once, add inclusion guards for good measure. Signed-off-by: H. Peter Anvin commit 37138db5d96d89662f9c164bf674587ae5f6e1a4 Author: H. Peter Anvin Date: Mon Jun 26 22:15:29 2006 -0700 [klibc] Remove except for ia64 no longer have any general users; the only thing that still needs it is ia64, so leave it as an ia64-specific file. Signed-off-by: H. Peter Anvin commit 753d5cbe3621bcfb6814e2f99d9efde089dcfc08 Author: H. Peter Anvin Date: Mon Jun 26 19:59:31 2006 +0000 [klibc] 1.4.7 released, next version is 1.4.8 commit 6fbd8fafdcc793135988733996d72b0298afe934 Author: H. Peter Anvin Date: Mon Jun 26 12:57:05 2006 -0700 [klibc] Remove __clzdi2; it is unused and causes problems. clzdi2 doesn't have any consumers in klibc as it currently sits (clzsi2 does, however); furthermore, "bootstrapping" from __builtin_clz doesn't work on older gcc. Signed-off-by: H. Peter Anvin commit 0e5b4a43fa43578cc5268a5bb09ef0e5285871a2 Author: H. Peter Anvin Date: Sun Jun 25 22:26:28 2006 +0000 [klibc] 1.4.6 released, next version is 1.4.7 commit fdd5576a86522e66464a909b175f86f96595307d Author: H. Peter Anvin Date: Sun Jun 25 15:26:10 2006 -0700 [klibc] i386: use the standard calling convention for socketcalls Instead of relying on all users to have a separate calling convention for socketcalls, use the same calling convention for everything. This means doing a minor amount of parameter marshalling, but no big deal. Signed-off-by: H. Peter Anvin commit a83efd0838c3bb2a6f5c3b095a01b45014b8414e Author: H. Peter Anvin Date: Sun Jun 25 22:04:06 2006 +0000 [klibc] 1.4.5 released, next version is 1.4.6 commit 0ba34a10b095d25601dacd540420a97b71278a28 Author: H. Peter Anvin Date: Sun Jun 25 15:03:28 2006 -0700 [klibc] __assert_fail() is a __noreturn function __assert_fail() never returns, and telling that to the compiler can sometimes generate better code. Signed-off-by: H. Peter Anvin commit f9c47f51adf5a998180ee75344155c6086ea1bd1 Author: maximilian attems Date: Thu Jun 22 08:44:34 2006 +0200 [klibc] add reboot/poweroff install targets pick up the new puppys Signed-off-by: maximilian attems commit 36641427b2b7b3bce385ec44305f31dc174f57ad Author: H. Peter Anvin Date: Fri Jun 23 14:20:35 2006 -0700 [klibc] Add support for sendfile() Add the sendfile() system call and a header file for it. Signed-off-by: H. Peter Anvin commit 89d8664b9069c4b00268bd4b780c1cd9fc669dd1 Author: H. Peter Anvin Date: Fri Jun 23 14:20:02 2006 -0700 [klibc] i386: 4095 is the maximum errno Be consistent and use 4095 as the maximum errno value. Signed-off-by: H. Peter Anvin commit 19f303ea389f0f8a58cc866fe594f0a550b09b8c Author: H. Peter Anvin Date: Fri Jun 23 18:06:40 2006 +0000 [klibc] 1.4.4 released, next version is 1.4.5 commit f41b3ae4c4e37faa1f1eecf9599f8842813d0297 Author: Heiko Carstens Date: Fri Jun 23 15:30:05 2006 +0200 s390: fix klibc build Fix s390 31 bit klibc build. Cc: Martin Schwidefsky Cc: H. Peter Anvin Signed-off-by: Heiko Carstens commit 04b16a7e3f8ce7787d5ef2c69fd7cdefa7f62170 Author: H. Peter Anvin Date: Thu Jun 22 17:53:39 2006 +0000 [klibc] 1.4.3 released, next version is 1.4.4 commit bc02ec1dee2fa2f86815abbd0601ef0d4371ac0d Author: H. Peter Anvin Date: Thu Jun 22 10:52:20 2006 -0700 [klibc] Support Perl 5.6; add test for type signedness There seems to be a consensus that Perl 5.6 should be supported, which means we can't use the actually sane 3-operand form of open(). Furthermore, unpack("Z*") appears to be broken in Perl 5.6.1 -- at least in the version I built -- so open-code the decoding of the typesize file. Finally, while we're changing this code around, add a test for the signedness of types. This may end up being very useful for cases where registers need to be sign- or zero-extended, as appropriate. Signed-off-by: H. Peter Anvin commit 9986d2e5e4c8ee20a9ccc2ec3df6805df4897ebb Author: H. Peter Anvin Date: Wed Jun 21 14:33:30 2006 -0700 [klibc] -falign..=0 means "default", =1 mean "minimum" For the -falign options, 0 means default (same as no option given). 1 means byte alignment, which is translated into the smallest possible alignment, which appears to be 4 bytes (imposed by linker?) Signed-off-by: H. Peter Anvin commit b4d6e8d1046b2358110e8598f17ba59c3d029f95 Author: H. Peter Anvin Date: Wed Jun 21 14:04:25 2006 -0700 [klibc] Stealth whitespace cleanup Remove stealth whitespace. Signed-off-by: H. Peter Anvin commit f84032228845096d32d75ac6f9137965347f1011 Author: maximilian attems Date: Wed Jun 21 22:18:03 2006 +0200 add mknod to klibc utils add a simple mknod, allowing to create required devices before udev start or for static dev without udev. Signed-off-by: maximilian attems commit 1a5cf99bae9993a9241d4c143ee1b20e8e3225d4 Author: H. Peter Anvin Date: Wed Jun 21 18:40:08 2006 +0000 [klibc] 1.4.2 released, next version is 1.4.3 commit 540f76e3b9d0272b50e2cc9be086b1f77606cc58 Author: H. Peter Anvin Date: Wed Jun 21 11:36:58 2006 -0700 [klibc] Fix incorrect dependency Remove a bogus dependency which would cause circular rebuilds at high -j levels. Signed-off-by: H. Peter Anvin commit 52a83f25c64f52abb81c6e93977cf00247176e1b Author: H. Peter Anvin Date: Wed Jun 21 11:36:03 2006 -0700 [klibc] dash: generated header files live in $(obj), not $(src) Fix the generated header file dependencies to refer to $(obj), not $(src). Signed-off-by: H. Peter Anvin commit 46bf0e4bdecb36d6a5b0e6b1fe617fbc4ec87d9e Author: H. Peter Anvin Date: Wed Jun 21 16:52:08 2006 +0000 [klibc] 1.4.1 released, next version is 1.4.2 commit 4e51186fb663b57ac7c53517947510d2e1e9de01 Author: H. Peter Anvin Date: Wed Jun 21 09:49:35 2006 -0700 [klibc] Need EXTRA_KLIBCCFLAGS for O= to work correctly. For the syscalls build, need EXTRA_KLIBCCFLAGS in order for the build not to break with O=. Signed-off-by: H. Peter Anvin commit 79317ba49e3f83d40f37b59fcdd5bd7c7635ee32 Author: H. Peter Anvin Date: Wed Jun 21 09:48:53 2006 -0700 [klibc] Clean up the halt program somewhat; add symlinks Minor source cleanup in the halt program; add symlinks to "reboot" and "poweroff". Signed-off-by: H. Peter Anvin commit 4942c6734827b57155376c337366c557a9692337 Author: Joshua Hudson Date: Tue Jun 20 21:38:35 2006 -0700 klibc: add halt/reboot/poweroff utility Makes the halt, reboot, and poweroff utilities available in klibc in primitive form. Modified slightly by hpa. Signed-off-by: Joshua Hudson Signed-off-by: H. Peter Anvin commit bdb03f6d934e33a5075377bdeb17506626225a0c Author: H. Peter Anvin Date: Tue Jun 20 15:05:37 2006 -0700 [klibc] Warn the user if the "linux" symlink is missing. Very basic check for the existence of the "linux" symlink. This applies to the standalone build only, of course. Signed-off-by: H. Peter Anvin commit 18997de56426b2d0f1a9a7b92cb708fcb3741d92 Author: H. Peter Anvin Date: Tue Jun 20 12:49:38 2006 -0700 [klibc] Unify ARM and Thumb setjmp. Unify ARM and Thumb setjmp. The Makefile changes for this were mistakenly in a previous checkin (bd56c54ae409a2c36d23e61d4075e2d1ffcd1a23). Signed-off-by: H. Peter Anvin commit bd56c54ae409a2c36d23e61d4075e2d1ffcd1a23 Author: H. Peter Anvin Date: Tue Jun 20 12:44:02 2006 -0700 [klibc] ARM: More EABI and Thumb fixes. Make the syscall stubs smaller. More work on getting EABI and Thumb to reliably build. It should all be good now. When building for EABI or Thumb, make the syscall stubs extra small by using "bl" followed by an immediate; since we have already saved lr the additional clobber of lr is not a problem. Signed-off-by: H. Peter Anvin commit 34f10dcd6b9da8e5eaf25ed441ccfbd062b171ad Author: H. Peter Anvin Date: Tue May 9 11:12:49 2006 -0700 [klibc] Turn on extra debugging output At Andrew Morton's request, enable extra debugging output by default. Signed-off-by: H. Peter Anvin commit 378abd8f4d39024ea6c87eb5b54155238f647f0d Author: Heiko Carstens Date: Sun May 28 11:41:42 2006 +0200 klibc (inkernel): merge s390/s390x #4 Changes needed for the inkernel klibc merge of s390/s390x. Signed-off-by: Heiko Carstens commit b6842f656092e8c8b9563cb68d53f9e1dcc40796 Author: H. Peter Anvin Date: Sun Jun 18 18:59:24 2006 -0700 [klibc] Remove files that do not belong in the kernel tree Remove files which are used in the standalone klibc repository, but do not belong in the kernel tree. Signed-off-by: H. Peter Anvin commit fc8c0c09f9dd5139dd8d797eaf9fe33962b6cd2c Author: H. Peter Anvin Date: Thu May 25 22:34:47 2006 -0700 [klibc] sparc32: transfer arch-specific options to /arch.cmd Boot options which have been obtained in an architecture-specific fashion have to be copied to /arch.cmd in the rootfs. This implements that functionality for sparc32; the code is identical to sparc64 minus the openprom support for obtaining nfsroot options. Signed-off-by: H. Peter Anvin commit c6e5c5a77681f5bf6f9fea55d031115e9f58ada6 Author: H. Peter Anvin Date: Wed May 24 22:44:55 2006 -0700 [klibc] sparc64: transmit arch-specific options to kinit via /arch.cmd Sparc64 has support for a bunch of architecture-specific options taken from the PROM. Convert them to kernel command line form and write the file /arch.cmd in the rootfs, which can be recovered by kinit and processed. The kinit support has already been committed. Signed-off-by: H. Peter Anvin commit 060ee84166196f97abcb34bd6af7df1cfc677578 Author: H. Peter Anvin Date: Mon May 22 14:39:39 2006 -0700 [klibc] Default KLIBCARCH ?= $(ARCH) Special cases, like powerpc, can be handled in arch/*/Makefile. Signed-off-by: H. Peter Anvin commit 161e1dc16ec1129b30b634a2a8dcbbd1937800c5 Author: H. Peter Anvin Date: Sat May 20 16:24:05 2006 -0700 [klibc] Remove in-kernel nfsroot code The in-kernel nfsroot code is obsoleted by kinit. Remove it; it causes conflicts. Signed-off-by: H. Peter Anvin commit 018604e070e143657abcf0cb256a1e2dda205d97 Author: H. Peter Anvin Date: Mon May 15 21:25:33 2006 -0700 [klibc] UML: the klibc architecture is the underlying architecture On UML: the klibc architecture is the underlying architecture, so set KLIBCARCH to SUBARCH. Signed-off-by: H. Peter Anvin commit baacd5d81ff7151e8df3893850ec363441886a1e Author: H. Peter Anvin Date: Mon May 1 02:51:52 2006 -0700 [klibc] Enable CONFIG_KLIBC_ZLIB (now required to build kinit) After removing the private copy of zlib in kinit, we need CONFIG_KLIBC_ZLIB in order to build klibc. zlib is required in order to decompress classical ramdisks. In the future this should maybe be made conditional on CONFIG_BLK_DEV_RAM. Signed-off-by: H. Peter Anvin commit d669be433cc9bc413d958e140f8ec47211498a2a Author: H. Peter Anvin Date: Tue Feb 7 09:21:40 2006 -0800 Enable KLIBC_ERRLIST Signed-off-by: H. Peter Anvin commit 869206cac1cb04d54582dc4383248ee9721073e8 Author: H. Peter Anvin Date: Thu Mar 30 12:03:47 2006 -0800 [klibc] Remove prototype for name_to_dev_t() Signed-off-by: H. Peter Anvin (cherry picked from adcfc2bd22397db1dda1bd2b8a7bcb0f0b7300e7 commit) commit a36102c485caf951294301425ee8e87aa6ab4d92 Author: Sam Ravnborg Date: Mon Apr 17 13:54:47 2006 -0700 kbuild: support single targets for klibc and klibc programs With the following patch kbuild now supports: make usr/dash/arith_yylex.i make usr/klibc/umount.o make usr/klibc/umount.s Patch does also fix indention of CPP command Signed-off-by: Sam Ravnborg Signed-off-by: H. Peter Anvin commit 15ad2d153c3c214522eef889a14f3cd97f40864a Author: Sam Ravnborg Date: Mon May 1 02:28:18 2006 -0700 klibc: default initramfs content stored in usr/initramfs.default Harcoding default content of initramfs in the gen_initramfs_list.sh script seems ackward. Move it to a file named: usr/initramfs.default This also fixes a small bug when no arguments was passed to CONFIG_INITRAMFS_SOURCE (-d was passed twice to the script) Idea and bug report from: "H. Peter Anvin" Signed-off-by: Sam Ravnborg Signed-off-by: H. Peter Anvin commit 7c753dbe7467f0d5ff6904f1bf5840350527e3c4 Author: H. Peter Anvin Date: Thu Apr 6 14:15:53 2006 -0700 [klibc] Eliminate unnecessary whitespace delta vs. Linus' tree Linus' tree has a space-tab sequence for a few lines in these files, causing an unnecessary delta. Signed-off-by: H. Peter Anvin commit 0f5a324d655ad582246b6830843114d09835f593 Author: H. Peter Anvin Date: Thu Apr 6 14:07:43 2006 -0700 [klibc] Re-create ROOT_DEV, too many architectures need it. ROOT_DEV carries a root device number communicated in an architecture- specific way. We now pass it to kinit via the real-root-dev sysctl call. Signed-off-by: H. Peter Anvin commit f3e41698e540a7d39658d6590fde1379c0f5bab0 Author: H. Peter Anvin Date: Thu Apr 6 11:33:35 2006 -0700 [klibc] Need to export RANLIB from the top Makefile klibc needs RANLIB, and since KLIBCRANLIB is now generated from RANLIB, we need to actually define RANLIB. Signed-off-by: H. Peter Anvin commit 5ad9bee01be52a0593fedcf905ae26ef4fd65007 Author: H. Peter Anvin Date: Thu Apr 6 11:21:10 2006 -0700 [klibc] Support KLIBCARCH being different from the main ARCH This is particularly significant for powerpc, since in the main kernel tree the ppc and ppc64 architectures have been fully unified. Signed-off-by: H. Peter Anvin commit 79d8875c392c6eaf4b9537625c57690a02eab411 Author: H. Peter Anvin Date: Thu Mar 30 11:35:15 2006 -0800 [klibc] Remove parts moved to kinit Signed-off-by: H. Peter Anvin commit a2faf9b56a04fc16ef2a8a8e42e91601cae1dc75 Author: H. Peter Anvin Date: Sun Feb 12 20:44:56 2006 -0800 Remove root-mounting code from the kernel. Signed-off-by: H. Peter Anvin commit 646e16312efb438f6e1ea58bdb1d9afad9477933 Author: H. Peter Anvin Date: Sat Mar 25 16:36:59 2006 -0800 [klibc] Add klibc/kinit to MAINTAINERS file Signed-off-by: H. Peter Anvin commit 0e909e6d36929cf7e56930a6c347db109788d750 Author: H. Peter Anvin Date: Mon Jun 19 01:17:18 2006 +0000 [klibc] 1.4 released, next version is 1.4.1 commit affbcd24af30515f135c443956ad877b1b2887f6 Author: H. Peter Anvin Date: Sun Jun 18 18:16:19 2006 -0700 [klibc] Release as klibc-1.4 This version is slated for integration with the mainstream kernel. Tag it as version 1.4. Signed-off-by: H. Peter Anvin commit 6f251237158ed6e776d445415c0f0734a2cd3f7b Author: H. Peter Anvin Date: Thu Jun 15 23:15:08 2006 +0000 [klibc] 1.3.40 released, next version is 1.3.41 commit 5353ead27e66f65b1be151d1089d21dfcd1fecb1 Author: H. Peter Anvin Date: Thu Jun 15 16:13:54 2006 -0700 [klibc] Stealth whitespace cleanup Remove stealth whitespace which has snuck in. Signed-off-by: H. Peter Anvin commit 51808a7e0f72ba03ed3f41febe8aa6b2d56e1bf2 Author: H. Peter Anvin Date: Thu Jun 15 16:06:55 2006 -0700 [klibc] More sophisticate type size detection; handle (void) syntax The type size detection system was at least in theory vulnerable to issues if "make" doesn't detect a file change. Although I think this is strictly a theoretical issue, make it more foolproof by including the type names into the generated array and detecting missing types. Additionally, handle "int foo(void);" in SYSCALLS.def correctly. Signed-off-by: H. Peter Anvin commit 167d4e6fcef4dcf6c764ce5b17c3b59df042f303 Author: H. Peter Anvin Date: Thu Jun 15 16:03:51 2006 -0700 [klibc] When one of the Perl scripts fail, make sure make notices When syscalls.pl or socketcalls.pl fail, we execute "|| rm -f $@"; unfortunately that means make doesn't know the command didn't complete, since the rm -f returns a good status. Force it to return a bad status in that case. Signed-off-by: H. Peter Anvin commit 15f87e0ca250d79517df1b42e5098235e29102b9 Author: H. Peter Anvin Date: Thu Jun 15 15:59:50 2006 -0700 [klibc] For consistency, use () for all zero-argument system calls We have used () for zero-argument system calls in the past; continue that practice consistently. Signed-off-by: H. Peter Anvin commit 828666f0bda4c0049724604d03866b0a7ed773df Author: H. Peter Anvin Date: Wed Jun 14 14:41:44 2006 -0700 [klibc] ARM: Thumb fixes Thumb needs __muldi3 (and apparently lacks a working libgcc, still); additionally deprecate the old THUMB Makefile variable and pass options more appropriate to Thumb when CONFIG_KLIBC_THUMB is enabled. Signed-off-by: H. Peter Anvin commit 934591cd8a5f31e60a5ff4844b1588ab05dc183f Author: H. Peter Anvin Date: Wed Jun 14 18:06:36 2006 +0000 [klibc] 1.3.39 released, next version is 1.3.40 commit ce8a41d7f5883f4589b742bf279cc3ab22c60c7b Author: H. Peter Anvin Date: Tue Jun 13 13:41:19 2006 -0700 [klibc] ARM: fix EABI and Thumb versions of vfork() For EABI and Thumb, the system call number is in r7, which is a saved register; we need to save r7 into a clobbered register (using r3) around the system call. Signed-off-by: H. Peter Anvin commit f63975c195cfcac1c360a0db44abaf6902fc63e9 Author: H. Peter Anvin Date: Tue Jun 13 04:49:20 2006 +0000 [klibc] 1.3.38 released, next version is 1.3.39 commit 2eb80b6f2700a0c72ba24623e281607a10dd6e3c Author: H. Peter Anvin Date: Mon Jun 12 21:46:04 2006 -0700 [klibc] No need to exclude libgcc on sparc32 anymore With proper use of the grouping options, sparc32 doesn't need to exclude libgcc anymore. However, we still want to use our own functions, because they're significantly smaller than the libgcc functions, which appear to be heavily unrolled. Signed-off-by: H. Peter Anvin commit 8134f4ca29d410e791342bbffa2e4fd7a3837e1b Author: H. Peter Anvin Date: Mon Jun 12 21:30:26 2006 -0700 [klibc] Finalize ARM EABI support This checkin should complete EABI support for ARM. Signed-off-by: H. Peter Anvin commit 25c5e9a6bfb1f3aa8c08cefe14ba4c13babc0ab7 Author: H. Peter Anvin Date: Mon Jun 12 21:29:36 2006 -0700 [klibc] Group libc and libgcc On some architectures, libgcc has dependencies on libc. This requires use of the --start-group and --end-group options in the linker. Signed-off-by: H. Peter Anvin commit ed431984c2a0023b63ec9925547ef9b5a2a60214 Author: H. Peter Anvin Date: Mon Jun 12 17:28:49 2006 -0700 [klibc] Fix the typesize dependency chain The typesize generation should use "call if_changed" and be listed in the targets, otherwise it will be rebuilt every time. Signed-off-by: H. Peter Anvin commit abd606f99a08eed9e1770524fe63aa59ede91e7b Author: H. Peter Anvin Date: Mon Jun 12 12:11:41 2006 -0700 [klibc] libgcc functions: shift counts are type "int" Per the gcc internals manual, shift counts arguments are "int" (unclear if it is actually "int" or if it's "SImode" a.k.a. int32_t. However, it doesn't matter for Linux-compatible architectures.) Signed-off-by: H. Peter Anvin commit 56c104f03a081a7c2012c4ad8de797921ba435b4 Author: H. Peter Anvin Date: Sat Jun 10 18:17:45 2006 +0000 [klibc] 1.3.37 released, next version is 1.3.38 commit 8aa014779aae6e437ed1da99c29fcf1949b33cd7 Author: H. Peter Anvin Date: Sat Jun 10 11:16:10 2006 -0700 [klibc] Remove debugging code Remove some code which was used during development, and shouldn't matter anymore. Signed-off-by: H. Peter Anvin commit de6f630e6be90d6d32d8bf2fed3f856b0c32f7ba Author: H. Peter Anvin Date: Sat Jun 10 11:15:19 2006 -0700 [klibc] Detect the sizes of various types, and make available to sysstub.ph. This additional code effectively queries the C compiler for the sizes of various types, and makes an associative array %typesize available to sysstub.ph. This is currently not used, but it's expected that some architectures, e.g. s390, will need this to determine which registers go where, and how many registers are needed. Signed-off-by: H. Peter Anvin commit 034c1a00496805534c988398b7bf55e6aa68e2f6 Author: H. Peter Anvin Date: Sat Jun 10 11:13:16 2006 -0700 [klibc] The type is uid_t, not uid. Fix typo in type name. This will start to matter very, very soon. Signed-off-by: H. Peter Anvin commit d5571a3fd480e74ae072017e541c74c73d49a789 Author: H. Peter Anvin Date: Sat Jun 10 11:12:07 2006 -0700 [klibc] Fix for preprocessed SOCKETCALLS.def: correctly ignore #-lines Typo in regular expressions kept #-lines from being ignored, resulting in errors. Signed-off-by: H. Peter Anvin commit de6e9d28d4a7fad3648a93f0aa1546e4e685e64d Author: H. Peter Anvin Date: Sat Jun 10 17:12:11 2006 +0000 [klibc] 1.3.36 released, next version is 1.3.37 commit cef6e3a88e49b4d7a7891cf686b4f736d7583492 Author: H. Peter Anvin Date: Sat Jun 10 10:10:44 2006 -0700 [klibc] Use traditional C-style comments; it's the only safe option Use traditional C-style comments in the *.def files; it's the only thing we can guarantee is supported. That means having to preprocess SOCKETCALLS.def as well as SYSCALLS.def. Signed-off-by: H. Peter Anvin commit 123f39c5a5d811fdff028c0cc3c8ab3aa0908c79 Author: H. Peter Anvin Date: Fri Jun 9 13:11:34 2006 -0700 [klibc] ARM: use .balign instead of .align It seems the ARM toolchain is inconsistent as to the meaning of .align, resulting in massive bloat with some version of the toolchain. Fix that by explicitly using .balign to note that we mean aligning to 2- or 4- byte boundaries, not 8- and 16-byte. Signed-off-by: H. Peter Anvin commit 730bb3df2294e6a877777bb52e83b7cc6fb37a38 Author: H. Peter Anvin Date: Thu Jun 8 15:47:19 2006 +0000 [klibc] 1.3.35 released, next version is 1.3.36 commit 10e3a9305014b51cd3ad6d6ab4292c6487ab712b Author: H. Peter Anvin Date: Thu Jun 8 08:46:39 2006 -0700 [klibc] -x c++ breaks non-c++-capable versions of gcc. Use -x c instead. -x c++ was a safety for very old versions of gcc, but I had assumed it would always be available since we're just running the preprocessor. That apparently isn't the case, so undo that change and just treat it like C code. If someone has a really old gcc, it *should* still work since syscalls.pl will recognize the comments, but presence of quotes may make it unpredictable. In other words, no worse off than we previously were. Signed-off-by: H. Peter Anvin commit ce07e7bffadf8e89638c5f369892ae5a945ca8e0 Author: H. Peter Anvin Date: Wed Jun 7 23:43:53 2006 +0000 [klibc] 1.3.34 released, next version is 1.3.35 commit 517d9c2765ebae85dff81ad0b985b5df5386b0d1 Author: H. Peter Anvin Date: Wed Jun 7 16:43:40 2006 -0700 [klibc] Change the syntax of the *.def file to be more C-like. We have already had one build breakage due to quotes in comments confusing cpp on *some*, but not *all*, platforms, due to the use of -x assembler-with-cpp. Go to using C++-style comments, and use -x c++ (-x c should work too on gcc 3 and above; if this becomes an issue we can change it.) While we're add it, add back the final semicolon, to make the declarations look more like C prototypes. Signed-off-by: H. Peter Anvin commit 813826873509e67d94a4a3166d049e76df74356c Author: H. Peter Anvin Date: Wed Jun 7 21:22:00 2006 +0000 [klibc] 1.3.33 released, next version is 1.3.34 commit e56595fff1ba45f2538984f36ab3977d5e490457 Author: Heiko Carstens Date: Wed Jun 7 13:23:19 2006 +0200 s390: vfork support vfork support for s390/s390x. Signed-off-by: Heiko Carstens commit 6365e6120aef2bf15e1c9892913fba5c2cad6478 Author: Heiko Carstens Date: Wed Jun 7 13:22:37 2006 +0200 s390: fix mmap complilation Fix mmap compilation (missing errno.h include) and use correct minimum error number for compare. Signed-off-by: Heiko Carstens commit 8994667256a380dc9513a771a59f79c255947a5e Author: akpm@osdl.org Date: Wed Jun 7 09:20:09 2006 -0700 + klibc-ia64-fix.patch added to -mm tree The patch titled klibc-ia64-fix has been added to the -mm tree. Its filename is klibc-ia64-fix.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this commit 0033c77c17a781726b3cf252b6a0863245660917 Author: H. Peter Anvin Date: Wed Jun 7 04:24:11 2006 +0000 [klibc] 1.3.32 released, next version is 1.3.33 commit f07cd18e74777605b1d5cebafd7088be6c8b5bf0 Author: Bjorn Helgaas Date: Tue Jun 6 22:17:05 2006 -0600 kinit: convert '/' in block device names to '!', not '.' register_disk() converts the first slash in a disk name to "!", so a block device like /dev/cciss/c0d0 shows up in /sys as /sys/block/cciss!c0d0. kinit must use the same conversion in order for "root=/dev/cciss/c0d0p1" to find the device. Signed-off-by: Bjorn Helgaas commit 1ee2175426700988f540d2ed7064afc16bab67cb Author: H. Peter Anvin Date: Tue Jun 6 16:41:59 2006 -0700 [klibc] kinit: before exiting, tcdrain() any output If kinit returns, the kernel will usually panic. Often the serial port driver will not flush data out the port before it does so. Do tcdrain() on file descriptors 2 and 1 before exiting, so the user has a better chance of seeing the error. After a bug report from Bjorn Helgaas . Signed-off-by: H. Peter Anvin commit eda4d0f33a2f9f827e897553a0ba2f6e36454c32 Author: H. Peter Anvin Date: Tue Jun 6 16:35:12 2006 -0700 [klibc] Add tcdrain() function Under Linux, passing a nonzero argument to TCSBRK is defined as a drain. Signed-off-by: H. Peter Anvin commit c75f92bf8cf3a5242fee690c17973437546fe8e8 Author: H. Peter Anvin Date: Tue Jun 6 23:14:56 2006 +0000 [klibc] 1.3.31 released, next version is 1.3.32 commit 84970485bca6842ed0ff41dabb4f74ee86def163 Author: H. Peter Anvin Date: Tue Jun 6 16:14:32 2006 -0700 [klibc] dash: script to generate auto-generated file dependencies Quick script to generate dependencies on auto-generated header files. This needs to be properly integrated into the Kbuild framework; for now, it's just a maintainer tool. Signed-off-by: H. Peter Anvin commit cdbe83fa03bb5c2995de0aca75be42a457fe6ad4 Author: H. Peter Anvin Date: Tue Jun 6 16:13:13 2006 -0700 [klibc] dash: dependencies on generated header files Dependencies on generated header files. This really should be automatically generated, but that needs additional work. Signed-off-by: H. Peter Anvin commit 48861d2f07f98616302ca25f478f9055f8dad6b8 Author: H. Peter Anvin Date: Tue Jun 6 16:11:38 2006 -0700 [klibc] dash: remove unused file (we no longer use lex) dash no longer uses lex to tokenize expressions. Signed-off-by: H. Peter Anvin commit 8dfd69f5284496492fefb4fc611b17b9a1ce0df3 Author: H. Peter Anvin Date: Tue Jun 6 21:30:05 2006 +0000 [klibc] 1.3.30 released, next version is 1.3.31 commit 07e65cb1d12c1491a91b76e8a25d6a0aab135e69 Author: H. Peter Anvin Date: Tue Jun 6 21:27:45 2006 +0000 [klibc] 1.3.29 released, next version is 1.3.30 commit 44ae64c1599705929af23db553b48043bc2a2237 Author: H. Peter Anvin Date: Tue Jun 6 14:22:35 2006 -0700 [klibc] ppc32: address space fixes - klibc.so should be linked at 0x0f800000, so there is actually some "reach" in the +/- 16 MB calls. - On some distributions, the PowerPC linker defaults to the elf32ppc emulation rather than elf32ppclinux. This affects the start address, among other things. Thus, specify the emulation explicitly. - Add -m32 if gcc supports it, just in case someone ever makes a distro which defaults to ppc64. Signed-off-by: H. Peter Anvin commit cd0f24180910be745b5aa0b926f26421c0e8a0e0 Author: H. Peter Anvin Date: Tue Jun 6 14:53:17 2006 +0000 [klibc] 1.3.28 released, next version is 1.3.29 commit c7d1f0de0ebfcbc8174e79586d3ab131b2fabae2 Author: H. Peter Anvin Date: Tue Jun 6 07:49:37 2006 -0700 [klibc] i386: errno cutoff is 4095, not 4096 Apparently the "official word" is that maximum errno is 4095, not 4096. Signed-off-by: H. Peter Anvin commit 1556333845d90bb22ecf9609989a726d7f53020e Author: H. Peter Anvin Date: Tue Jun 6 07:46:31 2006 -0700 [klibc] i386: Non-CONFIG_REGPARM fix i386: When we are not compiling for CONFIG_REGPARM, __syscall_common and __syscall_varadic are the same function. The alias has to be defined in syscall.S, not varsyscall.S. Signed-off-by: H. Peter Anvin commit c2a362d0389e70b6c40b5bffe78e1e5d3340b737 Author: H. Peter Anvin Date: Mon Jun 5 21:00:55 2006 +0000 [klibc] 1.3.27 released, next version is 1.3.28 commit af228dc4be432a0686784d3411fd255e6578191d Author: H. Peter Anvin Date: Mon Jun 5 14:00:43 2006 -0700 [klibc] When using initrd in permanent mode, it still needs to be mounted... When initrd is used in permanent mode (don't run /linuxrc, proceed directly to /sbin/init) it still needs to be mounted at some point. The code incorrectly bypassed both places that can happen... Signed-off-by: H. Peter Anvin commit cbd8a4b88273983a8f27abc81d03461714ab0735 Author: H. Peter Anvin Date: Mon Jun 5 10:47:03 2006 -0700 [klibc] Additional header file needed for ARM File missing from previous checkin. Signed-off-by: H. Peter Anvin commit 75bc14622ec6671e9b5f3b1432c5ac4b9d05a905 Author: H. Peter Anvin Date: Sun Jun 4 18:30:42 2006 -0700 [klibc] ARM: add EABI support, fix Thumb problems This change should add EABI support to the system call, but probably there are still issues to be resolved dealing with EABI help functions. Additionally, this fixes a fair number of Thumb problems; Thumb should at the very least compile now. Signed-off-by: H. Peter Anvin commit e1b23bbeea7d04ff0ddd968e4aab5c5f376054c0 Author: H. Peter Anvin Date: Sun Jun 4 11:11:28 2006 -0700 [klibc] For the i386 MCONFIG, use Kbuild facilities Kbuild has standard facilities for testing availability of gcc options. Use them. Additionally, key REGPARM off CONFIG_REGPARM, for compatibility with Kconfig. Although the standalone build doesn't yet use Kconfig proper, it still has a configuration file, and that's where this sort of stuff belongs. Signed-off-by: H. Peter Anvin commit 189c403002bee3e6dd194bcd8a3ff9f553b0f061 Author: H. Peter Anvin Date: Sun Jun 4 11:04:40 2006 -0700 [klibc] sparc: define __sparc32__ and __sparc64__ SPARC doesn't have a standard define for 32- or 64-bit mode, requiring awkward testing of multiple defines. Make our own. Signed-off-by: H. Peter Anvin commit c74eb3d095fcca08a1adbbb13b8ca8e1f336211e Author: H. Peter Anvin Date: Sun Jun 4 11:03:33 2006 -0700 [klibc] Die if defconfig changes without .config changing We don't want to wipe the users .config without intervention, but the user might not even know it's there. Signed-off-by: H. Peter Anvin commit 19be72ebb02161ae086eb63268adda7f51819f85 Author: H. Peter Anvin Date: Sat Jun 3 15:58:30 2006 -0700 [klibc] Make struct statfs a per-architecture configurable There are basically two formats used for struct statfs(64); one which is used by all 32-bit architectures plus alpha and s390x, and one which is used by all other 64-bit architectures. Make it a per-architecture configuration variable, going with the concept of centralizing architectural dependencies. Signed-off-by: H. Peter Anvin commit e95929f39bcae7c9c5741898c7907f950c2f1310 Author: H. Peter Anvin Date: Fri Jun 2 21:53:20 2006 -0700 [klibc] Recognize /dev/ram as an alias for /dev/ram0 Very early on we only supported one ramdisk, called /dev/ram. Unfortunately /dev/ram seems to have lived on in boot instructions for no good reason, so we need to recognize it. "Putting the backwards into backwards compatibility." Signed-off-by: H. Peter Anvin commit d80ef5ab99c0c9758352c707008f09d2d699a79b Author: H. Peter Anvin Date: Thu Jun 1 16:38:42 2006 -0700 [klibc] arm: vfork.S needs vfork.S needs for __NR_vfork Signed-off-by: H. Peter Anvin commit fe113fdbd8582b06a8f1288617fcb594bf47f96a Author: H. Peter Anvin Date: Wed May 31 09:15:09 2006 -0700 [klibc] arm/vfork.S: name the function correctly Some remains of __syscall_common still remained... Signed-off-by: H. Peter Anvin commit 58cf033cdecb61c8f7e4cef666dae1b7dbc95ef4 Author: H. Peter Anvin Date: Tue May 30 22:51:32 2006 -0700 [klibc] vfork test: check the exit code We want to check the exit code from the vforked process. Signed-off-by: H. Peter Anvin commit 5fee7cea632c49a993498c3553a3ebba34719c0d Author: H. Peter Anvin Date: Tue May 30 22:47:11 2006 -0700 [klibc] Add vfork assembly stubs to a number of architectures. vfork() needs to have zero stack footprint. This means the standard system call stubs can't be used on most architectures. Signed-off-by: H. Peter Anvin commit 6ccbb12599a43f33589eeb12d4baa91bd68300b4 Author: H. Peter Anvin Date: Mon May 29 21:56:13 2006 +0000 [klibc] 1.3.26 released, next version is 1.3.27 commit 444ebf4700685a69edaa30016851566b815a5014 Author: H. Peter Anvin Date: Mon May 29 14:56:07 2006 -0700 [klibc] nfsmount: better debugging info and error messages In particular, the error message we get when the kernel doesn't have the appropriate NFS support was very confusing. Signed-off-by: H. Peter Anvin commit a8faea73a2bfe9661080ddec9169e2102f3861b4 Author: H. Peter Anvin Date: Mon May 29 14:54:48 2006 -0700 [klibc] getopt(): additional heuristics; style changes Add additional heuristics for when to reset the getopt() state; group private state into a structure. Signed-off-by: H. Peter Anvin commit 897aa86c9e0a7221e17b40b9acd46b44021ca65d Author: H. Peter Anvin Date: Mon May 29 14:50:15 2006 -0700 [klibc] Make it harder to confuse getopt() when used more than once getopt(), unfortunately, relies on global state. Apply some trivial heuristics as to when the state is no longer good. Signed-off-by: H. Peter Anvin commit 90fbc4df58d6a81ae492a58d40a00f8fc7d005ca Author: H. Peter Anvin Date: Mon May 29 18:53:15 2006 +0000 [klibc] 1.3.25 released, next version is 1.3.26 commit 29cfec508f796b3efc73311eb89fd60ca7002b4e Author: H. Peter Anvin Date: Mon May 29 11:52:49 2006 -0700 [klibc] nfsmount: cleanup; use types Using double-underscore types for pure userspace is silly, and encourages including which is unsafe. Signed-off-by: H. Peter Anvin commit 7301e503e0b771d08d8fe78e4c2a88d4e70d65ae Author: H. Peter Anvin Date: Fri May 26 22:26:45 2006 -0700 [klibc] ipconfig: don't include should never be included explicitly. Signed-off-by: H. Peter Anvin commit 170d962ae64c400f198276140298b568d3a0ce7e Author: H. Peter Anvin Date: Fri May 26 22:25:35 2006 -0700 [klibc] net/if.h: linux/if.h needs sys/types.h to not cause damage linux/if.h tries to include linux/types.h, which is dangerous unless sys/types.h has already been included. Signed-off-by: H. Peter Anvin commit 9f02c2c3a6dfd3d8ed0e1f95299d3a046adc83fe Author: H. Peter Anvin Date: Fri May 26 22:19:31 2006 -0700 [klibc] ipconfig: formatting cleanups, use types For userspace code, there is no reason to use the double-underscore types, which exist so the Linux kernel can export types without stepping on the C library's namespace. Signed-off-by: H. Peter Anvin commit 355a10e36a5ffd1bd76c70e15c9684d726721d77 Author: H. Peter Anvin Date: Fri May 26 22:10:47 2006 -0700 [klibc] A bit more robust bootp/dhcp option parsing Be a bit more strict about our BOOTP/DHCP option parsing. Also allow falling back to the server ID if the next server ID is zero. Signed-off-by: H. Peter Anvin commit 6435ed3d8b8f7441591387a389960f791c791977 Author: H. Peter Anvin Date: Sun May 28 22:55:52 2006 +0000 [klibc] 1.3.24 released, next version is 1.3.25 commit 6ac93831b2a5884a38f07c0d6118ad3d94b7385d Author: Heiko Carstens Date: Sun May 28 11:41:03 2006 +0200 klibc: merge s390/s390x #4 Merge s390/s390x in the standalone klibc tree. Signed-off-by: Heiko Carstens commit 603f94b07e59afc1c907af3768d0a37e9d715f41 Author: H. Peter Anvin Date: Fri May 26 11:56:56 2006 -0700 [klibc] Correctly handle "ro" and "rw" options overriding each other The kernel command line parsing rules are "last instance wins." This is very important, since different parts of the command line may come from different sources. In particular, some may come from /arch.cmd. This introduces a general framework for handling mutually overriding boolean options, and uses it for "ro" and "rw". Signed-off-by: H. Peter Anvin commit 4a0d114fe9089c92b3ddb13b92f72e8cb8da31cd Author: H. Peter Anvin Date: Wed May 24 22:05:07 2006 +0000 [klibc] 1.3.23 released, next version is 1.3.24 commit fe46f1eb45ac1ddc77c35824b13a1ed934aa2f0d Author: H. Peter Anvin Date: Wed May 24 15:01:29 2006 -0700 [klibc] sparc: deal with SA_RESTORER; sparc64 requires a restorer function Fake out SA_RESTORER on sparc; sparc64 requires a restorer function, so make sure one is provided. Signed-off-by: H. Peter Anvin commit 9b8b4bd30dc7e82caccdb175203a2ce1c40d2d98 Author: H. Peter Anvin Date: Tue May 23 23:39:43 2006 -0700 [klibc] Clean up fork and signal test Clean up the fork and signal test (tests/sigint.c) a bit. Signed-off-by: H. Peter Anvin commit 28b884992aa251ce54e4a098c4341c1c7098e7cb Author: H. Peter Anvin Date: Tue May 23 23:38:42 2006 -0700 [klibc] Fix forkish system calls on sparc64 sparc64 has sparc-style forkish system calls. Signed-off-by: H. Peter Anvin commit 63881ab2af51bdb8e884366f7cd5b1623943f13a Author: H. Peter Anvin Date: Tue May 23 20:29:57 2006 -0700 [klibc] kinit: NULL-terminate cmdv array The cmdv array should be NULL-terminated, just like argv. Signed-off-by: H. Peter Anvin commit a8d06ef2005224a75fcc80cfbf39d8a563999f11 Author: H. Peter Anvin Date: Tue May 23 16:08:51 2006 -0700 [klibc] dd: handle trunc/notrunc correctly; open output O_WRONLY Previous dd behaviour was equivalent to always using notrunc, plus we opened the output O_RDWR for no good reason. Bug report by Martin Michlmayr. Signed-off-by: H. Peter Anvin commit 96bbd05b6891d3a89467fd4d75ac741f88a58c40 Author: H. Peter Anvin Date: Tue May 23 14:00:22 2006 -0700 [klibc] kinit: clean up command line parsing, add /arch.cmd support Clean up the command line parsing, including enforcing the invariant that a later command line argument overrides an earlier one. This will use on-the-command-line arguments only after an -- argument. Signed-off-by: H. Peter Anvin commit bd4b7a7861a20d593309f5d96d9c396d928927b2 Author: H. Peter Anvin Date: Tue May 23 13:58:43 2006 -0700 [klibc] kinit/readfile.c: Formatting cleanup Clean up formatting after Lindent Signed-off-by: H. Peter Anvin commit 3b89c299b60a6d61cfbd6a6157d4f26a6cbdd1e8 Author: H. Peter Anvin Date: Tue May 23 11:10:14 2006 -0700 [klibc] kinit: use identify_fs() before trying all /proc/filesystems Use the identify_fs() library to identify the root filesystem type is available. This enforces any specific ordering between the filesystem types, and should be substantially faster. Signed-off-by: H. Peter Anvin commit ea12e127b4c1d8be84ae9faf4b997e660d9801e5 Author: H. Peter Anvin Date: Tue May 23 11:05:49 2006 -0700 [klibc] fstype: allow the bytes argument to identify_fs() to be NULL. It's standard to allow nonessential return pointers to be NULL. Signed-off-by: H. Peter Anvin commit f71f0418fa5d3e5eab06b2fff5ef26e262d8b721 Author: H. Peter Anvin Date: Tue May 23 10:54:40 2006 -0700 [klibc] We still want to actually run ipconfig when compiled with INI_DEBUG INI_DEBUG actually turned ipconfig off! This is a bad thing, especially since the in-kernel tree has INI_DEBUG turned on by default. Thanks to Aaron Griffin for spotting this. Signed-off-by: H. Peter Anvin commit 39078615636e6d92ab905ace09d546d0b3260337 Author: H. Peter Anvin Date: Tue May 23 10:28:55 2006 -0700 [klibc] Support root=major:minor syntax; separate name_to_dev for testing Allow root=major:minor decimal syntax; additionally, separate name_to_dev out into a separate file so that it can be compiled independently of kinit for testing. Signed-off-by: H. Peter Anvin commit 3af21d58c0965c060f9ae558f9bf277d62cf491d Author: H. Peter Anvin Date: Mon May 22 14:32:50 2006 -0700 [klibc] Fix generation of usr/include/asm symlink The generation of the usr/include/asm symlinks was broken in the kernel-integrated build when O= was specified, due to KLIBCKERNELSRC not being defined. Signed-off-by: H. Peter Anvin commit 4392e8662e1204f41cb2ae7f31d955c4077935f2 Author: H. Peter Anvin Date: Sun May 21 16:33:29 2006 -0700 [klibc] sparc64 fixes; at least attempt to get signals working from sparc64 With these changes it appears that the right thing is passed to the rt_sigaction system call, but yet something isn't quite working right... Signed-off-by: H. Peter Anvin commit f77af169d800f139459f995a3f9c17fec22558c7 Author: H. Peter Anvin Date: Sun May 21 16:28:43 2006 -0700 [klibc] sparc: sparc has a messed up rt_sigaction() system call SPARC has a nonstandard rt_sigaction() system call, and does appear to not even have the SA_RESTORER flag. Simply drop it for now. Signed-off-by: H. Peter Anvin commit 2b00e12f3757adb8a90021e39c62cafb206abaf7 Author: H. Peter Anvin Date: Sat May 20 19:48:12 2006 -0700 [klibc] m68k: need to adjust the stack pointer for the return address After longjmp, the stack pointer should match the stack pointer after return to setjmp. This means we either need to save the stack pointer adjusted, or adjust it upon longjmp. This patch does the former. Signed-off-by: H. Peter Anvin commit 696699ebb2417411180dca8fe251d55a40ffb7b2 Author: H. Peter Anvin Date: Sat May 20 16:21:21 2006 -0700 [klibc] sparc64: need special handling of pipe() Like many architectures, sparc64 special-cases pipe() as a dual register return syscall. Signed-off-by: H. Peter Anvin commit 266ed1f673793314e9afe0126bf7fddfd465c312 Author: H. Peter Anvin Date: Sat May 20 16:15:49 2006 -0700 [klibc] sparc32: sparc also handles pipe() with dual register return Like many other architectures, sparc32 special-cases pipe() as a dual-register return. Signed-off-by: H. Peter Anvin commit effa4c090752a63529e9ab8d5cb7cf8e284fe0b1 Author: H. Peter Anvin Date: Sat May 20 15:45:18 2006 -0700 [klibc] sparc architecture fixes It seems that the sparc32 port has bitrotted significantly. This brings it up to date. Signed-off-by: H. Peter Anvin commit b561521050670e43e302ea6c95ef2230762b7004 Author: H. Peter Anvin Date: Sat May 20 11:52:36 2006 -0700 [klibc] memmove: adjust asm() formatting Adjust asm() formatting for readability. Signed-off-by: H. Peter Anvin commit a2097c4b7f48b8e725ac65c8f0eac6417ff6c0d8 Author: H. Peter Anvin Date: Mon May 15 22:35:35 2006 -0700 [klibc] Handle architectures which need total ARCH/KLIBCARCH separation Some architectures, like UML, have no relationship whatsoever between $(ARCH) and $(KLIBCARCH); in particular, they need completely different include/asm-* directories. This change enables that for the in-kernel build; no effect on the standalone build. Signed-off-by: H. Peter Anvin commit 7e7c943b9bba6683b94908b30fc829c34d43161e Author: H. Peter Anvin Date: Mon May 15 22:08:43 2006 +0000 1.3.22 released, next version is 1.3.23 commit 3e1ec9b847907b16146954b8bef38f36556408b6 Author: H. Peter Anvin Date: Mon May 15 15:08:10 2006 -0700 [klibc] alpha: fix pipe() system call Fix setting the return value for the pipe() system call. I managed to forget that Alpha syntax is backwards compared to MIPS. Signed-off-by: H. Peter Anvin commit 3e223c1cd6a767ba9a149cbc3842b128cb6fbfac Author: H. Peter Anvin Date: Mon May 15 15:06:50 2006 -0700 [klibc] Add test for the "pipe" system call; it's special on many arches The "pipe" system call has a special calling convention on way too many architectures. Create a simple test for it. Signed-off-by: H. Peter Anvin commit 850981e61cd258354be73d64a5e0e6c92851088d Author: H. Peter Anvin Date: Mon May 15 07:39:03 2006 +0000 1.3.21 released, next version is 1.3.22 commit 49e48b9e925b3f15c7e24c150f7be4d65e9d9fe7 Author: H. Peter Anvin Date: Mon May 15 00:36:56 2006 -0700 [klibc] alpha: write pipe() system call in assembly pipe() was written in C, but the implementation used macros from the kernel which are no longer good. Just write the danged thing all in assembly. Signed-off-by: H. Peter Anvin commit 86e028bac1b6ee221b52c63694fd4674bf732c99 Author: H. Peter Anvin Date: Mon May 15 00:25:22 2006 -0700 [klibc] Remove #ident tags Some files in the tree had #ident tags back from the CVS era. Remove them. Signed-off-by: H. Peter Anvin commit e338ad42f1e8fbc797e4015eb46b1abde3aafea0 Author: H. Peter Anvin Date: Mon May 15 00:23:14 2006 -0700 [klibc] Reformat to better match the kernel CodingStyle Run Lindent on the whole source tree, and then clean up the resulting damage. Signed-off-by: H. Peter Anvin commit eb7e954facc8f5294cc7de532f2d950048086217 Author: H. Peter Anvin Date: Tue May 9 12:08:38 2006 -0700 [klibc] Need to move zconf.h to match zlib.h zconf.h is included from zlib.h, so it needs to be moved with it. Signed-off-by: H. Peter Anvin commit dc8b31229bb795ecf6b5c4518c12801b8b5a28f4 Author: H. Peter Anvin Date: Tue May 9 11:25:40 2006 -0700 [klibc] Move zlib.h to the include directory We need to move zlib.h to the include directory so it gets picked up properly by applications. This seems to not bite in the standalone tree for unknown reasons, but it definitely bites in the kernel one. Signed-off-by: H. Peter Anvin commit 30522aa69a7fba2dde7bb3cea84142fb4ca8d260 Author: H. Peter Anvin Date: Mon May 8 12:33:35 2006 -0700 [klibc] setjmptest: be more explicit what actually goes on The output from setjmptest was misleading at best. Fix that. Signed-off-by: H. Peter Anvin commit d553f61af3eacaff0ca1c97267d9592c304077f6 Author: H. Peter Anvin Date: Mon May 8 11:15:20 2006 -0700 [klibc] cg-rm-for-kernel.sh: Also delete the root README file The root README file is not for kernel consumption. Signed-off-by: H. Peter Anvin commit e9604ebeba73f4979d8dea989e0436d6904fa6c3 Author: H. Peter Anvin Date: Mon May 8 11:13:56 2006 -0700 [klibc] cg-rm-for-kernel.sh: use "sort -r" not "rev" "rev" reverses characters in a line, not lines in a file. Use "sort -r" instead. Signed-off-by: H. Peter Anvin commit 4bf32b17990118dc47b0f363d88f94aa49d6a375 Author: H. Peter Anvin Date: Mon May 8 11:12:36 2006 -0700 [klibc] cg-rm-for-kernel.sh: use cg-rm -rf for directories; chmod a+x Use cg-rm -rf so it doesn't complain about directories (still not sure if this is really needed to get rid of stub directories.) Make the script mode a+x. Signed-off-by: H. Peter Anvin commit f92b3412d30962aa3607ef64061b2160dc5e59a0 Author: H. Peter Anvin Date: Mon May 8 11:09:05 2006 -0700 [klibc] cg-rm-for-kernel.sh: need "cg-rm -f" We need "cg-rm -f" so we can see what actually happened... Signed-off-by: H. Peter Anvin commit 664eb8e962104fdac639690b4fec31ba31f14be8 Author: H. Peter Anvin Date: Mon May 8 11:07:34 2006 -0700 [klibc] Add a script to prune the klibc repository for kernel merge This script removes entries we do not want to carry over into the kernel tree. Signed-off-by: H. Peter Anvin commit 73df92ae5e9cda3e92cc25ef31b09df316525863 Author: H. Peter Anvin Date: Mon May 8 17:59:43 2006 +0000 1.3.20 released, next version is 1.3.21 commit 1dd509d4d754749fb07dcd9f41776c6d7f349956 Author: maximilian attems Date: Mon May 8 11:29:27 2006 +0200 s390 syscall.c declare err commit 54599b2bfd5e0c66d74c721f0a96acb4822a64d7 removed err declaration usr/klibc/arch/s390/syscall.c: In function '__syscall_common': usr/klibc/arch/s390/syscall.c:10: error: parameter name omitted usr/klibc/arch/s390/syscall.c:12: error: 'err' undeclared (first use in this function) Signed-off-by: maximilian attems commit 5a135393453c4ccb9c4e0f64204f76f5eaac60df Author: H. Peter Anvin Date: Sun May 7 19:53:46 2006 +0000 1.3.19 released, next version is 1.3.20 commit d503aef4bde443b48e022f75157fac80396ea5ed Author: maximilian attems Date: Fri May 5 22:55:36 2006 +0200 m68k archstat typo found by Christian T. Steigies usr/include/arch/m68k/klibc/archstat.h:12: error: syntax error before '__dev64' better use __stdev64 defined in klibc/stathelp.h Signed-off-by: maximilian attems commit 3d3328733842512cc710583daab1876ddebe0ed1 Author: H. Peter Anvin Date: Sat May 6 22:23:36 2006 +0000 1.3.18 released, next version is 1.3.19 commit 54599b2bfd5e0c66d74c721f0a96acb4822a64d7 Author: H. Peter Anvin Date: Sat May 6 15:20:32 2006 -0700 [klibc] Hopefully correct the handing of error return for s390/s390x s390 was comparing against an outdated max errno value. s390x was additionally getting the sign wrong in errno. Signed-off-by: H. Peter Anvin commit 8068a70c17cec71888d5d5303500d69f49fed75a Author: Heiko Carstens Date: Wed May 3 11:26:45 2006 +0200 s390: fix stat struct definition Remove duplicate member st_dev from struct stat. Signed-off-by: Heiko Carstens commit ed6eebfa256a2cf355b60cdd9fb1f0de8cc566cd Author: H. Peter Anvin Date: Sat May 6 15:14:50 2006 -0700 [klibc] kinit: avoid using vfork() until we can guarantee vfork works ok After some careful consideration, I'm not convinced that the vfork implementation in klibc is correct. Worse, it has to be corrected on a per-architecture basis. Disable using vfork() for now. Signed-off-by: H. Peter Anvin commit ddbad6b01ef1bba4aed4495f6d955de512baf697 Author: H. Peter Anvin Date: Sat May 6 21:17:21 2006 +0000 1.3.17 released, next version is 1.3.18 commit 66cac3b8429067c3c4a00b44eb33199d8f1148f3 Author: H. Peter Anvin Date: Sat May 6 14:16:40 2006 -0700 [klibc] m68k fixes crt0.S: __libc_init, not ___libc_init sysstub.ph: use move.l not moveq Signed-off-by: H. Peter Anvin commit 40830f0b2b863f3830c7502a6a0a99419f88efe0 Author: H. Peter Anvin Date: Tue May 2 07:43:57 2006 -0700 [klibc] Remove cp-to-kernel.sh The script cp-to-kernel.sh was meant to help the transition from the standalone klibc tree to the kernel tree, but was never really used. Now files are all in the same location, and all we'd need is a "rm-for-kernel.sh" script which might be a good idea. Signed-off-by: H. Peter Anvin commit 61cdb0e3a000464ddfca8102cba960b0eea05cea Author: H. Peter Anvin Date: Mon May 1 16:47:31 2006 -0700 [klibc] dash: really kill the "times" command The "times" command is used mostly for interactive use, and doesn't work right under klibc. Kill it. Signed-off-by: H. Peter Anvin commit 29172f3d17f4a064048cba0e18e4d609c4a19216 Author: H. Peter Anvin Date: Mon May 1 16:13:11 2006 -0700 [klibc] dash: remove "times" command, and defang printf to avoid fp Floating-point isn't supported in klibc. Remove (largely unnecessary) floating-point support in dash. Signed-off-by: H. Peter Anvin commit ac0cab9860a9969863b2057b141aa80d9febedec Author: H. Peter Anvin Date: Mon May 1 15:50:49 2006 -0700 [klibc] clz builtins return number of leading 0's, i.e. 31-bitpos As written, these computed the position of the most significant 1 bit. Signed-off-by: H. Peter Anvin commit e03412ddb4d90b4a36decc4df2c7d6df5114af37 Author: H. Peter Anvin Date: Mon May 1 22:26:59 2006 +0000 1.3.16 released, next version is 1.3.17 commit 9760f9d7c43fb5de750c9a7b59ee4fee14b61dbd Author: H. Peter Anvin Date: Mon May 1 15:26:51 2006 -0700 [klibc] MIPS: add new libgcc functions MIPS can't use the standard libgcc from klibc functions, so we need to make sure we have a full compliment. This adds the find-zero functions and 64-bit shifts. Signed-off-by: H. Peter Anvin commit 05154faa0c9d64db8f4672a2ec816eede2acc5ac Author: H. Peter Anvin Date: Mon May 1 15:25:12 2006 -0700 [klibc] Add 64-bit shift functions (needed by e.g. MIPS32) Add libgcc functions for 64-bit shifts on 32-bit platforms that can't use standard libgcc, e.g. MIPS32. Signed-off-by: H. Peter Anvin commit f515d8ecda6494d811e2abdc1bbabaf5588c6365 Author: H. Peter Anvin Date: Mon May 1 15:12:25 2006 -0700 [klibc] Add libgcc functions for __clz*i2; fix __modsi3 Add libgcc functions for __clz[sd]i2; needed e.g. by MIPS. Also fix a warning in __modsi3. Signed-off-by: H. Peter Anvin commit 2976dbe3cf1b221bc8b3f2eb3e2eaa196f915bc7 Author: H. Peter Anvin Date: Mon May 1 14:28:41 2006 -0700 [klibc] Really, really work on architectures without ppoll... Got the test for ppoll existence backwards. Fix it. Signed-off-by: H. Peter Anvin commit 910a9e365ca9ee375303f186f008edbc522d2033 Author: H. Peter Anvin Date: Mon May 1 14:12:30 2006 -0700 [klibc] Fix location of test directory klibc/tests -> usr/klibc/tests Signed-off-by: H. Peter Anvin commit 4c5ec85ff9b85ca0c44ebf9fd5deea53956183d5 Author: H. Peter Anvin Date: Mon May 1 11:16:07 2006 -0700 [klibc] m68k: need to save/restore d2-d6 around system calls d2-d7 are saved registers; we use d0-d6, so we need to preserve d2-d6. Signed-off-by: H. Peter Anvin commit 6ba38fadb25e326e88706136c934ce57d20d6c4c Author: Sam Ravnborg Date: Mon May 1 09:54:28 2006 -0700 kbuild: support single targets for klibc and klibc programs [This is the klibc side of a patch which also includes changes to the kernel tree. -hpa] With the following patch kbuild now supports: make usr/dash/arith_yylex.i make usr/klibc/umount.o make usr/klibc/umount.s Patch does also fix indention of CPP command Signed-off-by: Sam Ravnborg Signed-off-by: H. Peter Anvin commit 73d45b73913cfbd49c42400e596f1b05e9f37f87 Author: H. Peter Anvin Date: Mon May 1 16:27:46 2006 +0000 1.3.15 released, next version is 1.3.16 commit 2ecbf8bf1eb729d70750c128916beef7504a84b7 Author: H. Peter Anvin Date: Mon May 1 09:26:29 2006 -0700 [klibc] m68k: add archsetjmp.h file The m68k port still missed archsetjmp.h. Signed-off-by: H. Peter Anvin commit 44f6a9e0932ca9158403ff642123e9a7ba994af0 Author: H. Peter Anvin Date: Mon May 1 01:21:05 2006 +0000 1.3.14 released, next version is 1.3.15 commit ad46cb7f8688b9cce1d3f5cc2ab1aa6b8bff516c Author: H. Peter Anvin Date: Sun Apr 30 18:11:06 2006 -0700 [klibc] Update locations of documentation files klibc -> usr/klibc Signed-off-by: H. Peter Anvin commit 161e8b3cbf9874923d52435be47e8b0c0c0f68e6 Author: H. Peter Anvin Date: Sun Apr 30 18:08:28 2006 -0700 [klibc] make install: update build location of include files include -> usr/include Signed-off-by: H. Peter Anvin commit 7a1fc94cc0c48d8831f1b0b0aebe945b283d535f Author: H. Peter Anvin Date: Sun Apr 30 18:07:55 2006 -0700 [klibc] maketar.sh: Correct location of version file version -> usr/klibc/version Signed-off-by: H. Peter Anvin commit c4f5665d83a7191eb6a4d0ba09803cd92fa7c641 Author: Jeff Bailey Date: Mon May 1 02:36:41 2006 +0200 ppoll really fix arch without it on commit dc7ec367a05141c1f76ddf82a5a63422c0fc3a72 this small bit of fixing non ppoll archs went missing Signed-off-by: Jeff Bailey Signed-off-by: maximilian attems commit 0017135e3da46dcd294767fd9bf19d48dffaa6f1 Author: H. Peter Anvin Date: Sun Apr 30 18:01:35 2006 -0700 [klibc] Need CONFIG_KLIBC_ZLIB since kinit depends on it After removing kinit's own copy of zlib, we need CONFIG_KLBIC_ZLIB. Signed-off-by: H. Peter Anvin commit 0a62504dde77aa7c50d584c7c89a7dd222f6c763 Author: H. Peter Anvin Date: Sun Apr 30 17:58:52 2006 -0700 [klibc] Correct location of version file for makerpm.sh version -> $(KLIBCSRC)/version Signed-off-by: H. Peter Anvin commit 5dea5e01daaaff0685016f23b5cb46240f28e792 Author: H. Peter Anvin Date: Sun Apr 30 17:56:02 2006 -0700 [klibc] Reorganize the standalone klibc tree to match the in-kernel tree Right now, it's harder than it should to apply and test patches using the standalone klibc tree. Reorganize the standalone tree to match the in-kernel tree. Signed-off-by: H. Peter Anvin commit 5c0a24afe48e1b135bc12a3d48f27f711ce5f586 Author: H. Peter Anvin Date: Sun Apr 30 23:32:18 2006 +0000 1.3.13 released, next version is 1.3.14 commit f4ccd53c539cdebcced16f3e9dcbc4d7c6463b63 Author: H. Peter Anvin Date: Sun Apr 30 23:27:02 2006 +0000 1.3.12 released, next version is 1.3.13 commit 40ff964360fb38e7caad37516592b103cd70f60e Author: H. Peter Anvin Date: Sun Apr 30 16:26:47 2006 -0700 [klibc] Officially give up and include zlib into klibc. Accordingly, get rid of the ad hoc copy of zlib used for kinit. Signed-off-by: H. Peter Anvin commit a2df1c9fcd06e5f93077a2d53955f873aebb2027 Author: H. Peter Anvin Date: Sat Apr 29 18:07:06 2006 +0000 1.3.11 released, next version is 1.3.12 commit 282f9091a0087dc5b0eae970c2692785c74067e3 Author: H. Peter Anvin Date: Sat Apr 29 11:06:48 2006 -0700 [klibc] Fix the ARM Makefile.inc to match the new variable naming standard Somehow, the ARM Makefile.inc escaped the jihad on ARCH* variables in favour of KLIBCARCH*. Fix this. Bug reported by Maximilian Attems, since I currently lack an ARM system :( Signed-off-by: H. Peter Anvin commit 8bc81542a17b2e30c97785e04fb5f729af74b24c Author: H. Peter Anvin Date: Thu Apr 27 22:11:58 2006 -0700 [klibc] Possibly enable shared library support on m68k... Provide enough that we might at least theoretically be able to do shared library support on m68k. Signed-off-by: H. Peter Anvin commit 82f9fe34ee880b98cf5eecd317251e81b5058c75 Author: H. Peter Anvin Date: Thu Apr 27 09:00:10 2006 -0700 [klibc] m68k *might* actually work now... m68k might theoretically work now. Add m68knommu to the list. Signed-off-by: H. Peter Anvin commit 32646a31d550761020623f1681ef6b8d4a5981b9 Author: H. Peter Anvin Date: Wed Apr 26 17:22:48 2006 -0700 [klibc] devname.c: since we define BUF_SIZE, use it consistently No point in defining symbolic constants if we don't use them... Signed-off-by: H. Peter Anvin commit e29477bc27cdcbbb2ac41b64492e70f4bc8ca449 Author: H. Peter Anvin Date: Wed Apr 26 17:21:30 2006 -0700 [klibc] : add DT_* constants We can't include the kernel version of this file because of namespace issues, so we need to also provide our own versions of the DT_* constants. Signed-off-by: H. Peter Anvin commit c3be942ab1fdbe1b1f7a84cbd42b23896bf1e21c Author: H. Peter Anvin Date: Wed Apr 26 17:17:33 2006 -0700 [klibc] Be extra paranoid about buffer overflows. They suck. Eliminate a highly theoretical buffer overflow. Signed-off-by: H. Peter Anvin commit 24eb09c4b8df5b2c634c8d5e01ed2e4c1045da0b Author: H. Peter Anvin Date: Wed Apr 26 17:11:53 2006 -0700 [klibc] Make bdevname() work for partitions, and add test functionality This patch corrects the behaviour of bdevname() for partitions, and it adds the ability to build devname.c standalone for testing. Signed-off-by: H. Peter Anvin commit 5f58e45e5cc34b0cae6d04655f913e1792e4d01f Author: H. Peter Anvin Date: Wed Apr 26 09:36:41 2006 -0700 [klibc] kinit: print human-friendly device names Get human-friendly device names from /sys/block. Yes, it's bloat, but it's constructive bloat... Signed-off-by: H. Peter Anvin commit bdaf4df8a19e3290fef430195f8ba882ed685ae7 Author: H. Peter Anvin Date: Wed Apr 26 08:56:31 2006 -0700 [klibc] Cleanup sweep of On several architectures, was no longer current. Additionally, the use of 64-bit dev_t fields conflict with using a 32-bit dev_t in . Fix this as cleanly as possible. Signed-off-by: H. Peter Anvin commit b4882c4f58d3caa517e6f949976f8cc6d9e19f37 Author: H. Peter Anvin Date: Wed Apr 26 08:55:00 2006 -0700 [klibc] Separate into a user-visible and an internal version Separare into with user-visible symbols, and which only uses double-underscore symbols. That lets us include from our own headers as needed. Signed-off-by: H. Peter Anvin commit d633d94c95e365aa75a9d1461d615a59a00daa96 Author: H. Peter Anvin Date: Wed Apr 26 08:53:32 2006 -0700 [klibc] Whitespace cleanup Remove stealth whitespace Signed-off-by: H. Peter Anvin commit fad1c01535ed722229f6e95472b0fcb0d95e19fc Author: H. Peter Anvin Date: Wed Apr 26 08:08:48 2006 -0700 [klibc] More work on the m68k port. Get the assembly syntax correct, at least... Signed-off-by: H. Peter Anvin commit 51c7d996919ec967ee433f19f875967901647a50 Author: H. Peter Anvin Date: Tue Apr 25 16:51:10 2006 -0700 [klibc] Beginnings of m68k support Initial coding of m68k support. Signed-off-by: H. Peter Anvin commit bc3f0bbdb4552f777d69ff9d60a4959e04858bda Author: H. Peter Anvin Date: Sun Apr 23 23:52:59 2006 +0000 1.3.10 released, next version is 1.3.11 commit 5ce45dfe27bec377c08fcc8aa83a8dfef18144ee Author: H. Peter Anvin Date: Sun Apr 23 16:52:37 2006 -0700 [klibc] ctype: provide prototypes even if we aren't inlining. Signed-off-by: H. Peter Anvin commit fff1116341c5b60a69c9488304b80fa097e08e3e Author: H. Peter Anvin Date: Sun Apr 23 16:47:07 2006 -0700 [klibc] Make dash use library-provided facilities Now we should have all the appropriate library-provided facilities; make dash actually use them. Signed-off-by: H. Peter Anvin commit 919138408e28bdb0727678a92dc57bd3934bb683 Author: H. Peter Anvin Date: Sun Apr 23 16:44:32 2006 -0700 [klibc] Provide out-of-line versions of the ctype functions Some programs need to be able to call the ctype functions indirectly. Accordingly, we need to make them available in the library. Signed-off-by: H. Peter Anvin commit fb723a539608632adc711d2ab7a29efd19fe19d9 Author: H. Peter Anvin Date: Sun Apr 23 16:43:13 2006 -0700 [klibc] Prototype for strsignal() strsignal() needs a prototype, too. Signed-off-by: H. Peter Anvin commit cfdbaad2180edde3f76d94267b513d55b2a37e4a Author: H. Peter Anvin Date: Sun Apr 23 16:19:21 2006 -0700 [klibc] Fix warnings in strsignal.c Missing cast and missing header file; fix. Signed-off-by: H. Peter Anvin commit 0f13b7478ef6b1a597a0e17c6fe708ce55e8dea0 Author: H. Peter Anvin Date: Sun Apr 23 16:17:54 2006 -0700 [klibc] Add strsignal() function The function strsignal() is generically useful; don't limit its implementation to dash. Signed-off-by: H. Peter Anvin commit 6865f7f14bc8cd784cc90df91d72279728f268c4 Author: H. Peter Anvin Date: Sun Apr 23 16:16:53 2006 -0700 [klibc] Actually build the bsearch() function Forgot to add this to the Kbuild file. Signed-off-by: H. Peter Anvin commit 13abb3365d904040352de270ad31eeb2d21aff95 Author: H. Peter Anvin Date: Sun Apr 23 16:15:14 2006 -0700 [klibc] Add the bsearch() function We had qsort() but not bsearch() already... makes no sense. Signed-off-by: H. Peter Anvin commit 34b54d1512f6273778958f9daf03b1cedc8a7c47 Author: H. Peter Anvin Date: Sun Apr 23 15:56:45 2006 -0700 [klibc] SIGRTMAX should be inclusive, not exclusive. POSIX states SIGRTMIN..SIGRTMAX is an inclusive range, not exclusive. Most kernel headers get this wrong, however, so adjust accordingly. Signed-off-by: H. Peter Anvin commit 38d56540befb3f46b984be2e632b2d915110cceb Author: H. Peter Anvin Date: Sun Apr 23 22:47:30 2006 +0000 1.3.9 released, next version is 1.3.10 commit 4109e7a9ce72e7dea60a76a541d136935b6c5c73 Author: H. Peter Anvin Date: Sun Apr 23 15:47:15 2006 -0700 [klibc] Use rt_sig*() system calls on i386 On i386, only part of the signal space is accessible through the legacy calls. In order to use the rt_sig*() calls, however, we have to implement our own signal header file instead of relying on . Signed-off-by: H. Peter Anvin commit 7af85cfe5c1644cf5d54c6d506a39018822e82d6 Author: H. Peter Anvin Date: Sun Apr 23 15:21:12 2006 -0700 [klibc] Move #include into Some platforms, notably i386, have which has old compatibility stuff in it (in the case of i386, it has the libc5 definitions.) Move the include of into so it can be removed if appropriate to a specific platform. Signed-off-by: H. Peter Anvin commit 874ad23095d6cd7c7489273f222827ce83fa4e63 Author: H. Peter Anvin Date: Sat Apr 22 18:19:58 2006 -0700 [klibc] Add remove() remove() is unlink() for a file or rmdir() for a directory. Signed-off-by: H. Peter Anvin commit b2cac50153502bb3b9159088327ad6a93a1f65a1 Author: H. Peter Anvin Date: Sat Apr 22 16:54:17 2006 +0000 1.3.8 released, next version is 1.3.9 commit dc7ec367a05141c1f76ddf82a5a63422c0fc3a72 Author: Jeff Bailey Date: Sat Apr 22 09:51:55 2006 -0700 [klibc] Deal with architectures which haven't implemented ppoll() yet We did this for pselect already, but missed out on it on ppoll. Signed-off-by: Jeff Bailey Signed-off-by: H. Peter Anvin commit 73f7139ba97199a3ff0fca2f16713aeaebd7612d Author: H. Peter Anvin Date: Sat Apr 22 09:50:06 2006 -0700 [klibc] IA64 doesn't have sys_fork, it uses sys_clone instead Signed-off-by: Jeff Bailey Signed-off-by: H. Peter Anvin commit 8dcb78b186a4e9c76e3f91e99cbc0a56cd9a950c Author: H. Peter Anvin Date: Thu Apr 20 04:38:22 2006 +0000 1.3.7 released, next version is 1.3.8 commit 206a62ce3b55f7b6953586761a14ce0bf6641977 Author: H. Peter Anvin Date: Wed Apr 19 21:31:09 2006 -0700 [klibc] Continue to build on kernels with no pselect system call We don't want to *require* pselect() just yet. Signed-off-by: H. Peter Anvin commit 817586792675f6a393b271f8c28a3bdf13fde86e Author: H. Peter Anvin Date: Wed Apr 19 21:29:50 2006 -0700 [klibc] Support for pselect, ppoll, sync_file_range, splice, tee New system call bonanza. Defined splice() and tee() in ; sync_file_range() in , pselect() in (per POSIX) and ppoll in . Make -> . Signed-off-by: H. Peter Anvin commit 0c6893a46531ddb3ca6639de0687aa9d2b019641 Author: Sam Ravnborg Date: Wed Apr 19 12:48:47 2006 +0200 klibc: fix sparc build Fix build of klibc on sparc. Following patch is only tested on a kernel build but should work on a native klibc build too. The patch fixes a bug in klibc/Kbuild so assignments to the variable targets in arch/$(KLIBCARCH)/Makefile.inc is not lost. Without this 'make clean' did not work as expected. Based on input from maximilian attems and Fabio Massimo Di Nitto . Signed-off-by: Sam Ravnborg commit 379d7ec46c5d97fa027e514a53fe6c89072d3f4e Author: maximilian attems Date: Tue Apr 18 22:34:22 2006 +0200 alpha build fix fix builderror introduced in 1.3.3 commit 67a8defdb192d3b7361f5d93099f1864c9626fc5: klibc/syscalls/SYSCALLS.i:187: Undefined system call: sigprocmask thanks to Falk Hueffner for checking belows fix see: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=361910 Signed-off-by: maximilian attems commit 3206767be926b272ce485491a73e5e4c4b01cf23 Author: H. Peter Anvin Date: Tue Apr 18 12:16:48 2006 -0700 [klibc] Need FORCE to use if_changed; add *.list to the targets The if_changed macros need FORCE; however, according to Sam things should work correctly once we have changes {sys,socket}calls.o -> .list in the targets. He seems to be right. Signed-off-by: H. Peter Anvin commit 3511cd76f0f8e22a2121d8b35e9d86a76f4e4985 Author: H. Peter Anvin Date: Tue Apr 18 12:13:25 2006 -0700 [klibc] Don't use the ar @ feature; it's too new (binutils 2.16.9x) Instead of using the @ feature of ar and ld, just expand the command line using `cat file`. The @ feature seems to have been introduced only in the 2.16.90 version of ar. Signed-off-by: H. Peter Anvin commit 3e05937993a3bef0123019e177b5332f11047185 Author: H. Peter Anvin Date: Tue Apr 18 10:42:06 2006 -0700 [klibc] Roll back incorrect SPARC fix This SPARC patch is broken. Roll it back until fixed. Signed-off-by: H. Peter Anvin commit a5503385bdb3503c3ef57776a22cf95a2876df03 Author: H. Peter Anvin Date: Tue Apr 18 10:41:00 2006 -0700 [klibc] No need to FORCE building the list files The list files should be regenerated based on ordinary dependencies; FORCEing them causes unnecessary rebuilds. Signed-off-by: H. Peter Anvin commit 9c77b69d82583c6a2d41ff6b5ece2eb17efa3be0 Author: H. Peter Anvin Date: Tue Apr 18 10:24:43 2006 -0700 [klibc] Stealth whitespace cleanup This whitespace cleanup brought to you by "cleanfile" Signed-off-by: H. Peter Anvin commit 8f7f89aa44fcb6332d642f57f5d531ed07281bbf Author: David Härdeman Date: Tue Apr 18 18:31:03 2006 +0200 fstype fix ext3 <-> lvm2 detection if a partition has been used as lvm2 and has not been cleared with pvremove, fstype would recognise the ext3 partition as lvm2. workaround that by detection lvm2 after ext3. Bonuspoint remove long fs list as this one just generates conflicts. Signed-off-by: David Härdeman Signed-off-by: maximilian attems commit 191f5ff42754a96b5a97625b93fdf210493ef992 Author: maximilian attems Date: Tue Apr 18 18:19:47 2006 +0200 sparc build fix add object rules so that the division, remainder and friends get really build on sparc, patch from Fabio M. Di Nitto . reworked to apply on latest git tree. Signed-off-by: maximilian attems commit 74a43ae1c3d8767f76fb77a4f3b0c14cef5e8030 Author: H. Peter Anvin Date: Mon Apr 17 16:13:09 2006 -0700 [klibc] Default to the "real root device" as last resort If there is no information communicated via the command line, use /proc/sys/kernel/real-root-dev as a carrier of architecture-specific root device information. Signed-off-by: H. Peter Anvin commit d4ec1a139cbfb60b5b1c0698bccd1dc5803ee258 Author: H. Peter Anvin Date: Mon Apr 17 16:04:05 2006 -0700 [klibc] Maintain each .o file's identity Combining .o files into larger .o files means that the whole compound can only be included or excluded from the final link. This is bad for statically linked binaries. Signed-off-by: H. Peter Anvin commit f686d15ef359ccc95fbaff3846b9307c8b205199 Author: H. Peter Anvin Date: Mon Apr 17 14:18:51 2006 -0700 [klibc] Use bdevname() even in debugging statements We want to use bdevname() consistently, even when debugging. Signed-off-by: H. Peter Anvin commit 2d016e1014c18206c59081a2e14b085caf2ac127 Author: H. Peter Anvin Date: Mon Apr 17 14:04:15 2006 -0700 kbuild: support single targets for klibc and klibc programs With the following patch kbuild now supports: make usr/dash/arith_yylex.i make usr/klibc/umount.o make usr/klibc/umount.s Patch does also fix indention of CPP command Signed-off-by: Sam Ravnborg Signed-off-by: H. Peter Anvin commit 386d7185fcda9bebc7affab6a7ef2781351cb395 Author: Sam Ravnborg Date: Mon Apr 17 13:38:43 2006 -0700 [PATCH] klibc: default initramfs content stored in usr/initramfs.default Harcoding default content of initramfs in the gen_initramfs_list.sh script seems ackward. Move it to a file named: usr/initramfs.default This also fixes a small bug when no arguments was passed to CONFIG_INITRAMFS_SOURCE (-d was passed twice to the script) Idea and bug report from: "H. Peter Anvin" Signed-off-by: Sam Ravnborg Signed-off-by: H. Peter Anvin commit d4fe4f42b4dc0bbb20e0186ac32159abe89f8b9e Author: Sam Ravnborg Date: Mon Apr 17 21:27:36 2006 +0200 klibc: generate havesyscall in $(objtree) with make O=.. Avoiding full path to KLIBCINC will result in havesyscall.h being generated in the $(objtree). We do not want generated files in the source tree with make O=.. -I parmeters to gcc now prefixed with $(srctree) allowing to pick up the generated .h file in $(objtree) Signed-off-by: Sam Ravnborg commit 30e5354ebbafd7b4713c950be1ebc3c6054a3f6d Author: Sam Ravnborg Date: Mon Apr 17 16:10:46 2006 +0200 klibc: rebuild cpio image when content changes Generate dependencies almost like done by fixdep in the kernel. This teaches make to rebuild cpio image when content has changed. Also restructured usr/Kbuild a little so we better utilise parallel makes (dash, gzip, utils and kinit are now build in parallel). Signed-off-by: Sam Ravnborg commit 1b57131f05f7ab85d4c5aadab69c0914ded9bcd6 Author: Sam Ravnborg Date: Mon Apr 17 16:01:30 2006 +0200 klibc/dash: list side effect explicitly List side effect in dash Kbuild file explicitly. Use a simple $(Q): command in both cases. The better fix would be to teach dash NOT to generate two output files with one command. Signed-off-by: Sam Ravnborg commit b9562ec57deb43b3584e5230f7bfb415460afb66 Author: Sam Ravnborg Date: Mon Apr 17 15:43:38 2006 +0200 klibc: remove debugging leftovers in Kbuild.klibc Signed-off-by: Sam Ravnborg commit cbe8e56eea2e98c1b88e87526fabcd3af09384e6 Author: H. Peter Anvin Date: Sun Apr 16 19:10:44 2006 -0700 [klibc] Update cross-compilation instructions. Signed-off-by: H. Peter Anvin commit f4d8f6e129d0343068bbb9e6ceada46f2b8cf9b3 Author: H. Peter Anvin Date: Mon Apr 17 02:01:43 2006 +0000 1.3.6 released, next version is 1.3.7 commit 96c10beee2df718e446ec1e972c81dc3f4957d8c Author: H. Peter Anvin Date: Sun Apr 16 19:01:22 2006 -0700 [klibc] Change KLIBCARCH -> ARCH for klcc, for backwards compatiblity klcc doesn't use the KLIBC- prefixes, as it is redundant in the context of klcc. Signed-off-by: H. Peter Anvin commit 8a9a4e4a115e2b325ee5e18a2e941e108347ca64 Author: Sam Ravnborg Date: Sat Apr 15 11:39:35 2006 -0700 [klibc] [PATCH] klibc: fix gen_initramfs_init.sh when using -d gen_initramfs_list.sh failed to generate a dependency list when it was supplied the -d option. Restructured gen_initramfs_list.sh to support dependency info with -d. This also fixes a bug where we did not properly process when more than one dir was specified. Finally update dependency info for the -d case (list_default_initramfs) In usr/Kbuild remove "" around CONFIG_RAMFS_SOURCE so the shell recognize two directories as two arguments. Signed-off-by: Sam Ravnborg commit af44e296b15fa5a5b58ce49ec7676f2141d4b4cc Author: H. Peter Anvin Date: Sat Apr 15 02:35:17 2006 -0700 [klibc] bdevname() interface to print a dev_t instead of %x Add a bdevname() function to print a dev_t (for block devices); for now print (%u,%u) but we can add sysfs search later. Signed-off-by: H. Peter Anvin commit 229f0f10341bcfdf4c9ba57a9615e19cfda7acb2 Author: Sam Ravnborg Date: Sat Apr 15 11:06:53 2006 +0200 klibc: sync initramfs build with vanilla kernel Adapt initramfs build to recent changes in vanilla kernel. With these fixes we now properly rebuild initramfs if: 1) content changes 2) gen_initcpio changes 3) arguments (root uid/group uid) changes Signed-off-by: Sam Ravnborg commit 035175b242577d2d6dc69cb4885f4f69edb4bd23 Author: Sam Ravnborg Date: Tue Apr 11 22:21:12 2006 +0200 klibc: relink klibc programs when klibc library is changed Add klibc libraries as prerequisites so we relink klibc programs when klibc changes. We need to avoid rebuilding the libraries when we do not build klibc so added a special rule that are only active when we do not build klibc to avoid klibc libraries to be updated. Signed-off-by: Sam Ravnborg commit a4c731619fbac2b2ac7428f27ff9592ae849c8df Author: Sam Ravnborg Date: Tue Apr 11 22:17:55 2006 +0200 klibc: avoid using check helper in dash/Kbuild The check target seems to be introduced only to create the bltin/ directory needed by mkbuiltins. Do it explicit and drop the check target. Signed-off-by: Sam Ravnborg commit f9e3a23ec8a481a8449d6890ce4dd5a27a283039 Author: Sam Ravnborg Date: Tue Apr 11 22:16:39 2006 +0200 klibc: fix build breakage with make O=.. The *.c files in socketcalls/ are generated. For klibc kbuild does on purpose not add this include automagically so do it explicit here. This allows klibc to be build using make O=.. in the kernel. Signed-off-by: Sam Ravnborg commit b9c7a6afb0e1166d7544498a23482bb4b0a4d310 Author: Sam Ravnborg Date: Tue Apr 11 22:15:27 2006 +0200 klibc: delete havesyscall.h during make clean In the kernel KLIBCINC expands to a full path, whereas in klibc it expands to a relative path. So specify havesyscalls.h twice to cover both situations. Note: kbuild will prefix relative paths with $(obj) when deleting. Later we may use same type of definition for KLIBCINC but until then we keep this workaround. Signed-off-by: Sam Ravnborg commit 6c8cc0219a667678646158cb4f7cfc115ba62cb5 Author: H. Peter Anvin Date: Sat Apr 15 00:34:13 2006 -0700 [klibc] Revert usr/Kbuild change to use usr/gen_initramfs.sh This change was part of a changeset which turned out to be bogus. Signed-off-by: H. Peter Anvin commit 191b2ba43437ff4e08c7da7cb57ba4187a087e69 Author: H. Peter Anvin Date: Thu Apr 13 09:13:59 2006 -0700 [klibc] Stealth whitespace cleanup Remove stealth whitespace which had crept in. Signed-off-by: H. Peter Anvin commit a9809e39f61045839385975c3d0b35216e975015 Author: H. Peter Anvin Date: Thu Apr 13 09:11:46 2006 -0700 [klibc] nfsmount: portmap spoofer cleanups Clean up the code surrounding the portmap spoofer, and disable the portmap spoofer on uClinux (no fork). Signed-off-by: H. Peter Anvin commit 8d5a7e281eccb04dd7f3563fc86ba73be75c18f6 Author: H. Peter Anvin Date: Wed Apr 12 22:35:57 2006 -0700 [klibc] kinit: use vfork() rather than fork(), for the benefit of uClinux uClinux doesn't have fork(). Replace fork() with vfork() where it is legal to do so. Signed-off-by: H. Peter Anvin commit 4d1fbed64bb5436ca8c18df8d5582dd361e0e63d Author: H. Peter Anvin Date: Wed Apr 12 22:33:49 2006 -0700 [klibc] Correct support for uClinux uClinux DOES have mmap et al; uClinux DOES NOT have fork and brk. Also update porting guide. Signed-off-by: H. Peter Anvin commit 873d3ee2f9f056c033b80f62907412a25c7d5a57 Author: Herbert Xu Date: Sun Apr 9 15:21:30 2006 -0700 [klibc] dash: force signedness where needed to make cross-compile-safe dash used to rely on mksyntax being run on the same architecture as the final binary in order to determine signedness of "char". This doesn't work for cross-compiling. Hi Peter: Here is the patch. I chose signed char instead of unsigned char as the canonical form as that generates better/smaller code on x86. I've verified that the assembly output is identical on x86 except for a real bug fix in expand.c. Signed-off-by: Herbert Xu Signed-off-by: H. Peter Anvin commit ae2e31a69bb4ff2ff0a700fb0a5536227f484f12 Author: Sam Ravnborg Date: Sun Apr 9 23:06:30 2006 +0200 kbuild: fix usr/Kbuild to use new usr/gen_initramfs.sh Fix usr/Kbuild so it utilise the new gen_initramfs.sh script which will rebuild initramfs when the content has changed. Signed-off-by: Sam Ravnborg commit b5018b63b2021bbe0b58c1b4f10dbacb3ba2a90d Author: H. Peter Anvin Date: Sun Apr 9 02:47:00 2006 +0000 1.3.5 released, next version is 1.3.6 commit 38ae493c625a978c415acc1a955db7fb2e1422c7 Author: H. Peter Anvin Date: Sat Apr 8 19:45:58 2006 -0700 [klibc] Add missing #includes needs since many of the defaults are keyed on the existence of specific system calls. malloc.c needs in case _KLIBC_NO_MMU is defined. Signed-off-by: H. Peter Anvin commit d13edce6198ea1ef393d53cb771b7f66580f4fd2 Author: H. Peter Anvin Date: Sat Apr 8 19:36:00 2006 -0700 [klibc] dash: More Kbuild rule cleanup Use "&&" after cd instead of ";"; invoke mksyntax by name. Signed-off-by: H. Peter Anvin commit 1897d16ee37a2ff391c3c1365c536f322505bb85 Author: H. Peter Anvin Date: Sat Apr 8 19:33:19 2006 -0700 [klibc] dash: clean up mksyntax rules; remove mksignames mksyntax was run twice for no good reason (and possible to the detriment of parallel execution); use a dummy rule like for mknodes. mksignames isn't used (and it was never cross-compile correct.) Remove it. Signed-off-by: H. Peter Anvin commit f9b06b7c6ffac6cc6ffd24d9e43e8bce6d3bce6f Author: H. Peter Anvin Date: Sat Apr 8 19:28:01 2006 -0700 [klibc] More portable use of mktemp Just plain "mktemp" apparently doesn't work on all platforms. Also honour $TMPDIR if it's set. Based on a patch from Andrew Morton , with corrections from Bodo Eggert <7eggert@gmx.de>. Signed-off-by: H. Peter Anvin commit 6bdcf0ef757752b7d2bee17444c185c922bc26ac Author: Andrew Morton Date: Sat Apr 8 19:24:31 2006 -0700 [klibc] Prevent multiple inclusion of header files From: Andrew Morton In file included from usr/dash/arith_yylex.c:37: usr/dash/expand.h: At top level: usr/dash/expand.h:37: error: redefinition of `struct strlist' usr/dash/expand.h:43: error: redefinition of `struct arglist' In file included from usr/dash/arith_yylex.c:38: usr/dash/error.h:59: error: redefinition of `struct jmploc' Signed-off-by: Andrew Morton Modified-by: H. Peter Anvin Signed-off-by: H. Peter Anvin commit 585abf0d3d8c9c7bb775a03c535450ae52167d10 Author: H. Peter Anvin Date: Sat Apr 8 19:20:45 2006 -0700 [klibc] Handle dependencies on bison output correctly Bison produces both arith.c and arith.h from arith.y. make doesn't handle this properly for an explicit rule, running the program twice in parallel, causing havoc. Instead of the hack used previously to make this running in parallel safe, use a pattern rule which makes make behave correctly. Also, kbuild-ize the bison rule. Based on a bug report and patch by Andrew Morton . Signed-off-by: H. Peter Anvin commit c1b9302d276ee12e055c54b405ed9867e9241ce4 Author: H. Peter Anvin Date: Thu Apr 6 16:35:02 2006 -0700 [klibc] kinit support for mounting MTDs as root Signed-off-by: H. Peter Anvin commit 39bca1add0c2c534fa82c5148a4bee8a3fe28631 Author: H. Peter Anvin Date: Thu Apr 6 21:52:47 2006 +0000 1.3.4 released, next version is 1.3.5 commit 326e55533be812d204707084110cd19666fa4ef0 Author: H. Peter Anvin Date: Thu Apr 6 14:51:35 2006 -0700 [klibc] Fix comment: __getpageshift not __getpagesize Fix a mistaken reference to __getpagesize() in a comment (there is no such function.) It is supposed to be __getpageshift(). Signed-off-by: H. Peter Anvin commit be962ad974eb6cbd4557a8902cbc31f5c20bf42b Author: H. Peter Anvin Date: Thu Apr 6 14:50:19 2006 -0700 [klibc] Smart default for _KLIBC_NO_MMU Assume we have an MMU if either sys_mmap or sys_mmap2 exist; otherwise not. This can of course be overridden by still. Signed-off-by: H. Peter Anvin commit 984d40b0fc4ca56e0e021b19ce10382659ce7398 Author: Sam Ravnborg Date: Thu Apr 6 11:19:01 2006 -0700 [klibc] Make building dash O= friendly - dash was broken with make O=.. - fixet - fix bug in vanilla kbuild so arguments to hostprogs are properly passed also with make O=.. Signed-off-by: Sam Ravnborg Signed-off-by: H. Peter Anvin commit 85ea1cc7b3527b4536b8d378a6b9c2142029ee2a Author: Sam Ravnborg Date: Thu Apr 6 11:14:59 2006 -0700 [klibc] Make Kbuild.klibc aware of .config variables Fix by Sam Ravnborg Signed-off-by: H. Peter Anvin commit 1b6fafeaf9e411a2c96206c20fc05594935d3d37 Author: H. Peter Anvin Date: Thu Apr 6 11:10:11 2006 -0700 [klibc] Add KLIBCOBJCOPY and KLIBCOBJDUMP, should we ever need them Signed-off-by: H. Peter Anvin commit 87af3d8d1d7886d15d60109eed0c98e36d47382d Author: Sam Ravnborg Date: Thu Apr 6 11:07:58 2006 -0700 [klibc] kbuild: need klibc-objs as well as klibc-dirs We need to add $(klibc-objs) as well as $(klibc-dirs) to $(output-dirs), or the build breaks with O=. Fix from Sam Ravnborg . Signed-off-by: H. Peter Anvin commit 0d7e10ed729950ee590ea2e1cff45e74247c9aeb Author: H. Peter Anvin Date: Thu Apr 6 11:05:36 2006 -0700 [klibc] Move socketcommon.h to klibc/socketcalls There is a problem with building with O= due to us using a relative path to find socketcommon.h. Just move socketcommon.h into the socketcalls directory since kbuild automatically adds that as an include path. Signed-off-by: H. Peter Anvin commit 3caf14894fc3a4c6cf1109c94c5237bc8f6260cb Author: H. Peter Anvin Date: Thu Apr 6 10:18:10 2006 -0700 [klibc] Pick up standard tools defines unless overridden With this patch, klibc will pick up the standard tools defines like $(CC) unless explicitly overridden as $(KLIBCCC). Overriding $(KLIBCROSS) is provided in the standalone build for backwards compatibility, but will no longer be supported in the in-kernel build. After a patch by Sam Ravnborg . Signed-off-by: H. Peter Anvin commit 201d159a5d4ceb8a8447bc5a194f3bd49bede6b3 Author: H. Peter Anvin Date: Wed Apr 5 23:45:55 2006 -0700 [klibc] Fix a couple of cases of double KLIBC prefixes Signed-off-by: H. Peter Anvin commit df206631d399c0644d8760cbeabf34a6dd22df32 Author: H. Peter Anvin Date: Wed Apr 5 22:54:39 2006 -0700 [klibc] Change ARCH to KLIBCARCH Change ARCH to KLIBCARCH, in preparation for architectures which need separate architecture support for the kernel and userspace. Signed-off-by: H. Peter Anvin commit 0a491e7f7247b2c09889400db627a1d059df2357 Author: H. Peter Anvin Date: Thu Apr 6 05:30:53 2006 +0000 1.3.3 released, next version is 1.3.4 commit ccf5d04af219e88c25afaae5271ee2b87fa11d8b Author: H. Peter Anvin Date: Wed Apr 5 22:27:04 2006 -0700 [klibc] x86: the memory version of bit scan is weird, don't use it. Signed-off-by: H. Peter Anvin commit 64b2391e174bb029322d6e9c88cc52003dd62839 Author: H. Peter Anvin Date: Wed Apr 5 22:21:38 2006 -0700 [klibc] If we have gcc4, use __builtin_clz() to do a binary logarithm If we have gcc4, we can use __builtin_clz() to do the binary logarithm necessary to compute __page_shift. Do foo^31 instead of 32-foo since that seems to be how gcc is implemented; this means gcc can figure out how to properly optimize the result afterwards. Signed-off-by: H. Peter Anvin commit 1cc44330a42c56e40f893f576b8090be598f29e3 Author: H. Peter Anvin Date: Wed Apr 5 22:09:46 2006 -0700 [klibc] Add missing #include mmap.c needs Signed-off-by: H. Peter Anvin commit 5ff2da25555b5a52d1fb70aa3833faa18ede0fe0 Author: H. Peter Anvin Date: Wed Apr 5 22:07:15 2006 -0700 [klibc] Fix incorrect cast Quiet a warning caused by wrong signedness in a cast Signed-off-by: H. Peter Anvin commit e21615b26b4fdfa2f2641735a5d8447198951435 Author: H. Peter Anvin Date: Wed Apr 5 22:04:50 2006 -0700 [klibc] Use to deal with mmap vs mmap2 weirdness Most 32-bit architectures use sys_mmap2 for mmap(). Unfortunately, sys_mmap2 is not always consistently defined, due to some confusion about how it was to be defined. Use the mechanism to isolate this dependency. Signed-off-by: H. Peter Anvin commit 67a8defdb192d3b7361f5d93099f1864c9626fc5 Author: H. Peter Anvin Date: Wed Apr 5 20:36:52 2006 -0700 [klibc] A much more general structure for arch-specific configuration. The fewer places we have architecture-specific information, the better. Centralize a bunch of stuff to , and provide a generic header, , which can provide defaults for most things. Signed-off-by: H. Peter Anvin commit fef14987e77d17c67a86deefc76bf30af20a6538 Author: H. Peter Anvin Date: Wed Apr 5 06:05:25 2006 +0000 1.3.2 released, next version is 1.3.3 commit 88a187ef7a997cc5d28c4c1a78ea7f93f4453122 Author: maximilian attems Date: Tue Apr 4 22:40:23 2006 +0200 statfs64 sparc_v9 fix It seems that klibc uses __sparc64__ to determine if it's compiled in 64 bit mode on sparc, gcc doesn't define __sparc64__ use __sparc_v9__ instead as proposed by Kyle McMartin , based on a patch by Sjoerd Simons Signed-off-by: maximilian attems commit fc6fb9853581476bc47f886885b3b587a1a59cd4 Author: Bastian Blank Date: Tue Apr 4 22:38:11 2006 +0200 s390 errno values are negative Fix syscall.c to return positive errno values. Signed-off-by: maximilian attems -- resend commit 63852759defbcb671ba0fa608f8de58aa87b1cdf Author: H. Peter Anvin Date: Tue Apr 4 13:24:10 2006 -0700 [klibc] Parentesize macro arguments properly Signed-off-by: H. Peter Anvin commit 7f499c9d2d57efbc9164d0a6fc85520dfb876f7c Author: H. Peter Anvin Date: Tue Apr 4 13:17:19 2006 -0700 [klibc] Remove stealth whitespace Signed-off-by: H. Peter Anvin commit e18ee6d973b5c019718ac9db516bf624d1584656 Author: H. Peter Anvin Date: Tue Apr 4 13:16:28 2006 -0700 [klibc] Add double-underscore version of dev macros which are expressions Inline functions can't be used as case statements, for example... Signed-off-by: H. Peter Anvin commit 0346b40986548a41da52025d45bee79d2c8f8861 Author: H. Peter Anvin Date: Tue Apr 4 11:25:06 2006 -0700 [klibc] Remove backwards-compatibility Makefile cruft Signed-off-by: H. Peter Anvin commit 4b6f960b67e5c6f80f2f9204ad2fe24209f5c46a Author: H. Peter Anvin Date: Tue Apr 4 10:44:33 2006 -0700 [klibc] nfsmount: restructure code slightly to avoid longjmp warning Signed-off-by: H. Peter Anvin commit 7200a2b45806db6a1ab142ddd0c6a31b09fc2aef Author: H. Peter Anvin Date: Tue Apr 4 10:40:48 2006 -0700 [klibc] dash: avoid uninitialized variable warning Signed-off-by: H. Peter Anvin commit dedced15ecf639f5f7530074d751fe7dda49f168 Author: Sam Ravnborg Date: Mon Apr 3 23:45:16 2006 +0200 klibc: support for make dir/file.i, make dir/file.s Implement support for: make dir/file.i => Generate preprocessed source code make dir/file.s => Generate assembler code It has a few drawbacks: - Works only for .c files - Requires a Kbuild file in the same dir as the .c file Signed-off-by: Sam Ravnborg commit b90c7f6c76532597117dd25050cfbbb04deb7c92 Author: Sam Ravnborg Date: Mon Apr 3 23:05:35 2006 +0200 klibc: support building individual files Enable the syntax: make dir/file.o It has a few drawbacks: - Works only for .c files - Requires a Kbuild file in the same dir as the .c file Signed-off-by: Sam Ravnborg commit 38297b60db76ba563b21977728c14511d022ca00 Author: H. Peter Anvin Date: Mon Apr 3 09:33:15 2006 -0700 [klibc] kinit: remove unused die() function Signed-off-by: H. Peter Anvin commit 0511c62a1b513c5253c8eef355157bb9c72ced2f Author: H. Peter Anvin Date: Mon Apr 3 09:28:35 2006 -0700 [klibc] run_init() now returns an error message instead of calling die() Calling a global function which can't return is pretty antisocial for a librarized function. It's possible to pass in a suitable die function as an argument, which could contain either exit or longjmp depending on the needs of the caller. However, this is overkill for run_init(), which really only just needs to return the error message, if applicable. Signed-off-by: H. Peter Anvin commit ee148f539e3f9d2824e6d252268ca9ff62b037e2 Author: H. Peter Anvin Date: Sat Apr 1 22:12:37 2006 +0000 1.3.1 released, next version is 1.3.2 commit 2f7cdff4361e65c6405a0a0e17363e9684567fa0 Author: H. Peter Anvin Date: Sat Apr 1 14:11:11 2006 -0800 [klibc] Test for ext3/ext2 before testing minix Based on a patch by Jeff Bailey Signed-off-by: Jeff Bailey Signed-off-by: H. Peter Anvin commit 3def9e8b76f265ce6e5556f1a14d5772bc407ad7 Author: H. Peter Anvin Date: Sat Apr 1 14:07:50 2006 -0800 [klibc] Fix bogus check that failed for ro-mounted filesystems Based on a patch by Aaron Griffin . Signed-off-by: H. Peter Anvin commit 1640a26093439b3c7ac94d9e62c7cc96f4cc4739 Author: H. Peter Anvin Date: Sat Apr 1 14:06:47 2006 -0800 [klibc] Fix error message Based on a patch by Aaron Griffin > Signed-off-by: H. Peter Anvin commit c3394343067326edc4b5c4c9040b85e313050aba Author: H. Peter Anvin Date: Thu Mar 30 11:54:29 2006 -0800 [klibc] Compile even if CONFIG_PM_STD_PARTITION isn't defined Signed-off-by: H. Peter Anvin commit fa7396dd6f9037737de71ae051f277ef13505282 Author: H. Peter Anvin Date: Thu Mar 30 11:22:21 2006 -0800 [klibc] Support for swsusp Signed-off-by: H. Peter Anvin commit 39fc52776c1a30905e09fb1f4f30f81c620f4ec5 Author: H. Peter Anvin Date: Wed Mar 29 02:30:34 2006 +0000 1.3 released, next version is 1.3.1 commit 6e7ef867e5f00ca8f2d58f4efe1041c5fcde2478 Author: H. Peter Anvin Date: Tue Mar 28 18:30:09 2006 -0800 [klibc] It's time for a stable release, make the next release 1.3 Signed-off-by: H. Peter Anvin commit 16a7b938ba25830c4966c88a41210e3ad7832d86 Author: H. Peter Anvin Date: Tue Mar 28 18:29:34 2006 -0800 [klibc] Upgrade zlib to zlib 1.2.3 Signed-off-by: H. Peter Anvin commit a2320807acd000c6651a726409dd7c8015be0dc0 Author: H. Peter Anvin Date: Wed Mar 29 01:30:05 2006 +0000 1.2.8 released, next version is 1.2.9 commit a65e52d98700063ecf873cca14f6b5c15a97bddf Author: David Härdeman Date: Thu Mar 23 00:56:37 2006 +0100 Add LVM2 detection to fstype The attached patch adds the ability to fstype to detect lvm2 physical volumes (PV's). Signed-off-by: David Härdeman commit 8759e0e03cd7464438fd1a015b5197ebb21f54a4 Author: H. Peter Anvin Date: Wed Mar 29 01:23:42 2006 +0000 1.2.7 released, next version is 1.2.8 commit afc73dde7e87ffc8ed8957a0e21c41b872d4da12 Author: Herbert Xu Date: Tue Mar 28 17:22:43 2006 -0800 [klibc dash] Use alloca() instead of longjmp() Patch by Herbert Xu Signed-off-by: H. Peter Anvin commit 941020cfddbee2efbabe7af6f3d11ecd2b2cd630 Author: H. Peter Anvin Date: Tue Mar 28 17:21:22 2006 -0800 [klibc] Fix type warning Signed-off-by: H. Peter Anvin commit a3c5932d144dd257d09f1d85153300807926cf5d Author: H. Peter Anvin Date: Tue Mar 28 17:00:46 2006 -0800 [klibc] Fix ramdisk loading and late command-line parsing - kinit can now correctly load a compressed or uncompressed ramdisk - Unlike the stock kernel, allows the user to specify the ramdisk source - Fix the handling of "rw" and "init=" Signed-off-by: H. Peter Anvin commit 48af981ad1699329e69fb0f1ad1e6cc0ee8d9e29 Author: H. Peter Anvin Date: Mon Mar 27 19:10:26 2006 -0800 [kinit] Return to a saner buffer size Signed-off-by: H. Peter Anvin commit 2adb2ee4b4e604d4ce69e5da5ae3bd4dd9350aa0 Author: H. Peter Anvin Date: Mon Mar 27 19:09:32 2006 -0800 [klibc] ipconfig, nfsmount: when used embedded in kinit, don't exit on error Signed-off-by: H. Peter Anvin commit e051c718d84924052fa3baf5d5ec6c0b1f9d0228 Author: H. Peter Anvin Date: Mon Mar 27 18:59:45 2006 -0800 [klibc] Additional cleanups from devfs removal Signed-off-by: H. Peter Anvin commit 8268a3bcd69824cd466bc484f24d9edb910cec69 Author: H. Peter Anvin Date: Mon Mar 27 18:51:24 2006 -0800 [klibc] More devfs removal Signed-off-by: H. Peter Anvin commit 79f32fa7ffac2ba8b7082def93fed7e66a558c6c Author: H. Peter Anvin Date: Mon Mar 27 18:37:33 2006 -0800 [klibc] Fix old-style initrd handling; remove devfs support Signed-off-by: H. Peter Anvin commit dcc3be4dd3fc0b18c0b6579bbfcedf31e605e3ff Author: H. Peter Anvin Date: Mon Mar 27 18:29:43 2006 -0800 [klibc] Add getchar() macro Signed-off-by: H. Peter Anvin commit cc384a4e32254aaad12dac0b4627b1c765a359d3 Author: H. Peter Anvin Date: Mon Mar 27 18:29:25 2006 -0800 [klibc] Clean up new mmap() test Signed-off-by: H. Peter Anvin commit aff07e2e669a4d27e132c9aee566353e69c5c113 Author: H. Peter Anvin Date: Fri Mar 24 15:43:25 2006 -0800 [kinit] Use looping versions of pread/pwrite for ramdisk copy commit b3e310bc3b434af23dfd746bb1668b02a706e1d3 Author: H. Peter Anvin Date: Fri Mar 24 14:29:41 2006 -0800 [klibc] dev_t is unsigned int on all Linux platforms Remove warning-killing cast in case dev_t changes Signed-off-by: H. Peter Anvin commit fe03ea3f6c2f87df31c8f0844891134f46411bf9 Author: H. Peter Anvin Date: Fri Mar 24 10:09:40 2006 -0800 [klibc] dash: clean up some uninitialized variable warnings Signed-off-by: H. Peter Anvin commit ebfd9912cecec74aa4c348dbba0c3273b80b5943 Author: H. Peter Anvin Date: Fri Mar 24 10:04:31 2006 -0800 [klibc] Correct the calculation of bytes to read from ramdisk Signed-off-by: H. Peter Anvin commit 3522bc5dd1048371c0571b95885bd6ecb3f75c5b Author: H. Peter Anvin Date: Fri Mar 24 09:55:45 2006 -0800 [klibc] nfs_port is an int Signed-off-by: H. Peter Anvin commit 85367a59157100a7b24023092c8ec0729042274f Author: H. Peter Anvin Date: Fri Mar 24 09:55:05 2006 -0800 [klibc] We pass &nfs_port as an int *, so nfs_port needs to be an int Signed-off-by: H. Peter Anvin commit d9adffcea322f9c442429c51df30f0fd9fb3f292 Author: H. Peter Anvin Date: Fri Mar 24 09:48:43 2006 -0800 [klibc] Remove broken hacked, and nowadays unused, gzio.c Signed-off-by: H. Peter Anvin commit 199c4bb5c7d8c198b9067b1d714546ef84607e7e Author: H. Peter Anvin Date: Fri Mar 24 09:46:40 2006 -0800 [klibc] Fix initializer so as to not cause warnings Signed-off-by: H. Peter Anvin commit 167e83f5b346f9de734c33c937dd1ce030e7f594 Author: H. Peter Anvin Date: Fri Mar 24 09:29:05 2006 -0800 End-of-file stealth whitespace cleanup Signed-off-by: H. Peter Anvin commit 50cc46fcd9b086f09fbe025655d8cc708c9d55fb Author: H. Peter Anvin Date: Fri Mar 24 09:22:40 2006 -0800 [klibc] Mass cleanup of end-of-file stealth whitespace Signed-off-by: H. Peter Anvin commit cd27c7b38596d7fc0b61086ad2a8d5e93ab90d0b Author: H. Peter Anvin Date: Fri Mar 24 09:06:05 2006 -0800 Mass extermination of stealth whitespace Signed-off-by: H. Peter Anvin commit dd45faf25737bede721de70bc9c9e400a8bb3b2f Author: H. Peter Anvin Date: Mon Mar 20 20:10:06 2006 +0000 1.2.6 released, next version is 1.2.7 commit 3f2659fb1a67141814021885facf0023732ce05e Author: H. Peter Anvin Date: Mon Mar 20 12:08:25 2006 -0800 Correctly parse the newer /sys/block/*/dev format Signed-off-by: H. Peter Anvin commit ee4309e5da8539cada5aa05d4c73f122b7cad476 Author: H. Peter Anvin Date: Mon Mar 20 12:06:35 2006 -0800 Better mmap() test Signed-off-by: H. Peter Anvin commit 872fbe1173f92effa8b988169799c194b2128852 Author: H. Peter Anvin Date: Sat Mar 18 16:35:28 2006 -0800 kinit: cleanup initializing one device in a multidevice system Signed-off-by: H. Peter Anvin commit e34df64d99a034db0515f1685a23d51a4294c0b4 Author: H. Peter Anvin Date: Mon Mar 13 07:14:13 2006 +0000 1.2.5 released, next version is 1.2.6 commit 19c3071fc36baa7903e567d2e8bb8ce5c8a206cb Author: H. Peter Anvin Date: Sun Mar 12 23:12:31 2006 -0800 Enforce 64-bit alignment on the data buffer (Reported by Fabio Di Nitto) commit 7a3728f1058a791118628ecc372fd3155ee3ec5e Author: H. Peter Anvin Date: Thu Mar 2 09:33:33 2006 -0800 Ralf (linux-mips maintainer) has confirmed intent for MIPS to be << 12 commit e23998816190bb25724e1be49a6f8b893907f880 Author: H. Peter Anvin Date: Thu Feb 23 03:49:35 2006 +0000 1.2.4 released, next version is 1.2.5 commit d19295c972e7064dbd3b146a7653c4622e19e61b Author: H. Peter Anvin Date: Wed Feb 22 19:49:12 2006 -0800 Update status Signed-off-by: H. Peter Anvin commit f286f25aa6291ec2d9c9eafb18d720efb0f52c04 Author: H. Peter Anvin Date: Wed Feb 22 19:47:08 2006 -0800 Remove trailing whitespace Signed-off-by: H. Peter Anvin commit 5d32c57e924737a9258eede97e517f357cbdcdf5 Author: H. Peter Anvin Date: Wed Feb 22 19:45:42 2006 -0800 More sys_mmap2 madness. Different architectures implement this differently. Not only is the shift count inconsistent, but some architectures test that the offset is valid, others don't, so do it ourselves. Signed-off-by: H. Peter Anvin commit dcda0e42ac005d0f087b375acf61d22bd17a724b Author: H. Peter Anvin Date: Wed Feb 22 16:03:45 2006 -0800 extern int -> extern unsigned int commit eb184c7f1c748219615958fecf90c8c895c55c0e Author: H. Peter Anvin Date: Wed Feb 22 15:57:53 2006 -0800 Apparently, most architectures really *do* use PAGE_SIZE for the mmap2 offset commit 37f3265266c01fcf304d9c7ac3b7247ecfe57372 Author: H. Peter Anvin Date: Tue Feb 21 14:24:52 2006 -0800 Don't build openat() if the kernel headers are too old commit c6983927de4b7d27c6094838b97bbc0f46511edb Author: H. Peter Anvin Date: Thu Feb 16 11:26:40 2006 -0800 Make sure "make clean" actually cleans up the test directory Signed-off-by: H. Peter Anvin commit 16d63d11a41fc6ed1287ccf6a0fd5decec03e3a2 Author: H. Peter Anvin Date: Thu Feb 16 11:25:49 2006 -0800 On some architectures, the libgcc path depends on the compiler flags Signed-off-by: H. Peter Anvin commit dd2f3d671a6d8b510ad62c49df99d6b0a67ab303 Author: H. Peter Anvin Date: Wed Feb 15 16:29:00 2006 +0000 1.2.3 released, next version is 1.2.4 commit 609aa9b0fc1dbaa21f2ab5d895fc6c30e26a4af5 Author: H. Peter Anvin Date: Wed Feb 15 08:28:30 2006 -0800 Deal with architectures which haven't implemented openat() yet Signed-off-by: H. Peter Anvin commit d4d4d1c4ed9ad6f3d3332e6108c9dab764398eef Author: H. Peter Anvin Date: Wed Feb 15 08:26:58 2006 -0800 MIPS: Store the result of pipe() to the right place. Signed-off-by: H. Peter Anvin Acked-by: Martin Michlmayr commit 55d16e268a5a769b147b0b908daf3bb22dde9129 Author: H. Peter Anvin Date: Tue Feb 14 08:07:02 2006 -0800 Remove another redundant instance of commit 6c4eeccf7e8f0e1d4da26c771e6d26f4fcba06e7 Author: H. Peter Anvin Date: Tue Feb 14 07:51:11 2006 -0800 Remove from ; userspace should use getpagesize() commit 9f7b9b5d241e13d7d8badae4c2761a44dd90bbdd Author: H. Peter Anvin Date: Mon Feb 13 17:58:52 2006 -0800 Make sure to decrement the bytes to read counter Signed-off-by: H. Peter Anvin commit 1475e2b7b8d5e9900578a645c293097b61e9aba1 Author: H. Peter Anvin Date: Mon Feb 13 17:56:13 2006 -0800 A cleaner way to do the decompression loop; formatting cleanups Signed-off-by: H. Peter Anvin commit 560c157036ba616a26217f81c812f2b267da50df Author: H. Peter Anvin Date: Mon Feb 13 09:37:53 2006 -0800 Clean up ramdisk loading; allow multiple media (untested) Signed-off-by: H. Peter Anvin commit 2bd4b81fc35107cedfac0969fcc2886f042aa4ec Author: H. Peter Anvin Date: Fri Feb 10 10:22:19 2006 -0800 Initial implementation of *at() system calls commit f75c3b21e9a1dfcded4ffc7614201c6b0ede23a3 Author: H. Peter Anvin Date: Tue Feb 7 17:08:08 2006 +0000 1.2.2 released, next version is 1.2.3 commit 37bde2e79b36940e46690ad5e934f67583895146 Author: H. Peter Anvin Date: Tue Feb 7 09:03:57 2006 -0800 Call md_run() not md_run_setup() Signed-off-by: H. Peter Anvin commit 18f67863cbe2fdd919fbd4dc3773daa9f0faf39c Author: H. Peter Anvin Date: Tue Feb 7 09:03:40 2006 -0800 Add get_option() so do_mounts_md.c compiles now... Signed-off-by: H. Peter Anvin commit 5ba00cd485a92a35f05259f58c633e40e2f9c659 Author: H. Peter Anvin Date: Tue Feb 7 08:51:45 2006 -0800 Accept actual device names without leading /dev/ Signed-off-by: H. Peter Anvin commit c4c5b912cd1dd90983c2150dde3a4dbd08aeea7c Author: H. Peter Anvin Date: Tue Feb 7 08:46:27 2006 -0800 Remove unused variables Signed-off-by: H. Peter Anvin commit c178303de822c8672c2be4474748bee766e12944 Author: H. Peter Anvin Date: Tue Feb 7 08:45:43 2006 -0800 Remove redundant code (our name_to_dev_t is smarter than the kernel one) Signed-off-by: H. Peter Anvin commit e9dcf1c6e65eae654b695ff63b69ddc5b9180748 Author: H. Peter Anvin Date: Tue Feb 7 08:41:47 2006 -0800 Remove redundant != 0 Signed-off-by: H. Peter Anvin commit e9d420f011e6d5cf5999f9579d3fb72e0d043bf7 Author: H. Peter Anvin Date: Tue Feb 7 08:38:17 2006 -0800 bstat() implementation for do_mounts_md.c Signed-off-by: H. Peter Anvin commit 1d03ace4fc83340268a698245ef0fbe23c48db65 Author: H. Peter Anvin Date: Tue Feb 7 08:34:32 2006 -0800 Get mdp major from /proc/devices. Dynamic majors, sigh... Signed-off-by: H. Peter Anvin commit 32fe7c87e274b7482f5035be23dc28fa7ac0cec2 Author: H. Peter Anvin Date: Tue Feb 7 08:20:34 2006 -0800 Export name_to_dev_t() for the benefit of do_mounts_md.c commit ee69350730fae17700c22b3662c11ed81cdb0c32 Author: H. Peter Anvin Date: Mon Feb 6 19:23:11 2006 -0800 Remove unused variable Signed-off-by: H. Peter Anvin commit 880c6f6f2c301b22fbee55f71b3705ca862766a5 Author: H. Peter Anvin Date: Mon Feb 6 19:22:06 2006 -0800 Remove dependency on PAGE_SIZE for swap; minor cleanups Signed-off-by: H. Peter Anvin commit 35edc342e617fa1eda2cc14149ba72ef62392711 Author: David Härdeman Date: Mon Feb 6 19:13:17 2006 -0800 This patch adds support for swap detection to fstype (to be applied on top of the previous luks patch). The patch is now against klibc's git tree instead of klibc-1.2. Signed-off-by: David Härdeman commit 4a5ef0ad97abef209806ac24c32c7f576cb406f7 Author: David Härdeman Date: Mon Feb 6 19:06:07 2006 -0800 The attached patch adds support for detecting LUKS partitions (Linux Unified Key Setup - http://luks.endorphin.org/) to fstype. This makes it easier to automatically detect and activate encrypted (root) partitions from an initramfs image. The patch is now against klibc's git tree instead of klibc-1.2. Signed-off-by: David Härdeman commit ea6af2b08cb18ba60e55c5e8f0f65ddac1672ca0 Author: H. Peter Anvin Date: Mon Jan 30 19:07:31 2006 -0800 Wrapper file for the various md includes commit 08a9494c819c7588d93b168676057e9069bc3965 Author: H. Peter Anvin Date: Mon Jan 30 19:06:58 2006 -0800 do_mounts_md: more userspace adaption commit 9245f25ab3514cb36f42413adabee1a6feec1f10 Author: H. Peter Anvin Date: Mon Jan 30 19:06:38 2006 -0800 Missing defines commit 13db8883743c8cf8243cb39117f79cddcadee0fa Author: H. Peter Anvin Date: Mon Jan 30 19:05:01 2006 -0800 Add ramdisk_load.o to the list of objects needed commit d8b04d01e66e7da5e81157e0ea389ca49aa34804 Author: H. Peter Anvin Date: Mon Jan 30 19:00:53 2006 -0800 Adapt for userspace, step 1 commit 4718c83cf1f3430bcbe4d5f8d161386a5e622468 Author: H. Peter Anvin Date: Mon Jan 30 18:59:56 2006 -0800 do_mounts_md.c from kernel commit e1ce4a5a30062e8f38529db86ad1e6baa7533408 Author: H. Peter Anvin Date: Mon Jan 30 16:11:40 2006 -0800 Break things into smaller files commit 617221f3534274f00fdb7bb8aa252ba4e5b8400a Author: H. Peter Anvin Date: Mon Jan 30 15:59:17 2006 -0800 Code to load ramdisk, and decompress it if necessary commit e625b99ff6069fb13f998a9b5bb326a9fb3eae30 Author: H. Peter Anvin Date: Mon Jan 30 15:56:41 2006 -0800 Don't build compress.o commit d2ff0df0373daa4de125122064585ba3bb520886 Author: H. Peter Anvin Date: Mon Jan 30 15:55:52 2006 -0800 Fix building only the inflate components commit 50ea10696aad28a408527b026303840c54d0bda2 Author: H. Peter Anvin Date: Mon Jan 30 15:43:38 2006 -0800 Add the option to have an offset commit 9ffc740c6358a900328acef67db40101ae3dace6 Author: H. Peter Anvin Date: Mon Jan 30 15:38:14 2006 -0800 Add copy of zlib for kinit commit 72acd3f29f29f5a4c1101df759466fc20e0bfc05 Author: H. Peter Anvin Date: Mon Jan 30 14:59:27 2006 -0800 Make sure DYNAMIC_CRC_TABLE is actually defined. commit ee6dbcf1abdcbd30075d2dccc31db4d636682ba7 Author: H. Peter Anvin Date: Mon Jan 30 14:51:43 2006 -0800 Properly remove fstype commit 5884b8d26dbc761976d0dea0c046feb8df711b57 Author: H. Peter Anvin Date: Mon Jan 30 14:46:37 2006 -0800 Clean up fstype and move into a kinit subdirectory commit a03bedd55b4b35a89d82551ef773103aa6e6d48c Author: H. Peter Anvin Date: Mon Jan 30 10:50:32 2006 -0800 Some initial work on loading ramdisk commit 38e0da49b09dd9fdc41c5ad676f8c667180f63e6 Author: H. Peter Anvin Date: Sun Jan 29 23:32:28 2006 -0800 Add run-init as a subdirectory commit 5f75ddd7a0f3f3068515935d7a1257351dd0ce90 Author: H. Peter Anvin Date: Sun Jan 29 23:14:55 2006 -0800 Proper path to tarball commit 30e95b12af46ad62e3e2c8cdee4d9644159bc811 Author: H. Peter Anvin Date: Sun Jan 29 23:13:07 2006 -0800 Move RPM generation to its own script, and make it actually work commit 6140a68ff88432b7353c06d922e972b0db88c1a3 Author: H. Peter Anvin Date: Sun Jan 29 23:09:15 2006 -0800 Move run-init to under usr/kinit commit 0a59875fa6833009a7b18019a6a4f66b6b4a9e68 Author: H. Peter Anvin Date: Sun Jan 29 21:12:28 2006 -0800 1.2.1 released, next version is 1.2.2 commit 64187a8b51fe5e9380e3528c6d08a7651fead139 Author: H. Peter Anvin Date: Sun Jan 29 21:10:12 2006 -0800 Call run-init from kinit commit 460f7bfcdf8810b75bdacb042fa5b4d1cc5ba3a7 Author: H. Peter Anvin Date: Sun Jan 29 21:09:38 2006 -0800 If we have nfsroot= or nfsaddrs=, default to root=nfs commit ac8f51553e49bef481120d929368940ed3ac719f Author: H. Peter Anvin Date: Sun Jan 29 21:09:06 2006 -0800 Fix typo commit 7e3d0d45593627513d87947566b6cae38aca1584 Author: H. Peter Anvin Date: Sun Jan 29 19:20:38 2006 -0800 Handle the errlist correctly by default. commit e163259b93c8c2dfd26af0ad69515acbf67f090e Author: H. Peter Anvin Date: Sun Jan 29 18:40:03 2006 -0800 Break run-init into a wrapper and a utility function Break run-init into a wrapper and a utility function, so we can use it from kinit. commit a449e051ac75f7bae815a660a8bd84a461d58f0b Author: H. Peter Anvin Date: Sun Jan 29 18:07:14 2006 -0800 Configure only one interface When passing "ip=dhcp" et al, or the -o option, stop after at least one interface has been configured. commit 3c769d8df16ddfd8932d942da31edcd950b7010c Author: H. Peter Anvin Date: Sun Jan 29 17:50:17 2006 -0800 Better error messages commit 631a8abc1fc812de5502ac2a6388df229064eb58 Author: H. Peter Anvin Date: Sun Jan 29 17:50:02 2006 -0800 Handle syntax like "ip=dhcp" commit 885aff619fdc226ebf74c09cffab60db79204afd Author: H. Peter Anvin Date: Fri Jan 27 10:03:55 2006 -0800 1.2 released, next version is 1.2.1 commit 2c65b95c87acdd9d07c500327e05c8345d2a65cc Author: H. Peter Anvin Date: Fri Jan 27 10:03:32 2006 -0800 It's time for a stable release. commit 0673d67bfe96b39e2f27c2ec81298a14fe3957bd Author: Martin Michlmayr Date: Tue Jan 17 01:07:32 2006 +0000 doesn't compile on little-endian Fix klibc compilation on little-endian mips > When I compile klibc on little-endian mips, I get: > KLIBCLD klibc/libc.so > ld: klibc/arch/mips/crt0.o: compiled for a little endian system and target is big endian > ld: klibc/arch/mips/crt0.o: endianness incompatible with that of the selected emulation > ld: failed to merge target specific data of file klibc/arch/mips/crt0.o Signed-off-by: Martin Michlmayr commit a9d5737df2ef030d2e55f6b6ed2f80a21ac03126 Author: maximilian attems Date: Mon Jan 9 23:42:19 2006 +0100 arch status On Sun, 08 Jan 2006, Sam Ravnborg wrote: > Not a big deal for a single patch, but with current patch flood for > klibc I bet it matters for hpa. > > Sam hehe see what a choice by jbailey for the Debian and Ubuntu initramfs generator pushes. ;) please update the arch status: alpha is working shared, parisc too i know that ia64 is only working static atm, but kyle is working on it so leave that.. Signed-off-by: maximilian attems commit 206a4cd64f35a8f93195920dc41416d12e4b93eb Author: H. Peter Anvin Date: Sun Jan 8 14:07:50 2006 -0800 Reminder to fix warning... commit 91821848ca544c7a5be46269e00eef4421983f28 Author: H. Peter Anvin Date: Sun Jan 8 12:16:23 2006 -0800 Kill a bunch of stealth whitespace commit c8683c946e1c6d38dc26922836e75cf1b5376693 Author: Martin Michlmayr Date: Sun Jan 8 19:50:33 2006 +0000 The path of the linker script on mips is not correct: tbm@raq2:~/tmp/src/klibc-1.1.14$ make KLIBCLD klibc/libc.so ld: cannot open linker script file arch/mips/klibc.ld: No such file or directory commit e9e9356b131c1049fcd039752cdf141dfcc338e1 Author: Martin Michlmayr Date: Sun Jan 8 18:59:12 2006 +0000 fix newline warning in setjmp.S When I compile klibc on mips, I get: KLIBCAS klibc/arch/mips/setjmp.o klibc/arch/mips/setjmp.S:82:2: warning: no newline at end of file commit d3d51e7f064eb406887711dabfb2e6342a5240e1 Author: Kyle McMartin Date: Sun Jan 8 11:29:26 2006 -0500 Set SHAREDFLAGS on parisc This seems like as good a place as any to put it. Tested and works fine for the test utils. Signed-off-by: Kyle McMartin commit fb1a6fbc4974c1018fe227bc88f622d75df37c8a Author: Kyle McMartin Date: Sun Jan 8 11:29:24 2006 -0500 Fix DT_FINI function pass-in to _start on parisc The PA-RISC ELF ABI puts the function pointer to be registered with atexit in %r23. Use this instead of passing in NULL. While it's unlikely to be used, doing the right thing is good. Signed-off-by: Kyle McMartin commit dc0f93a81e7a62e92bed90bc1ede95eb0416f116 Author: H. Peter Anvin Date: Thu Jan 5 22:11:44 2006 -0800 1.1.16 released, next version is 1.1.17 commit a1d1224379db621fd3d36b1a4c23fe06258e818a Author: Sam Ravnborg Date: Thu Jan 5 21:01:48 2006 +0100 Fix generation of Alpha divide stubs On Thu, Jan 05, 2006 at 10:17:05AM +0100, maximilian attems wrote: > > > > Some strange things are going on in alpha land. > > I need to try it out before attemting to fix it. > > the debian initramfs-tools rely on klibc hope you find a fix soon :) It was actually very simple. alpha plays some clever tricks to share divide.c for all __* routines. commit 5c8e790c8f4400c2c94a06846836bf3b29d00b71 Author: Kyle McMartin Date: Tue Jan 3 15:25:55 2006 -0500 fix build failure on 64-bit parisc On PA-RISC machines running in 64-bit mode, uname -m returns `parisc64' instead of `parisc.' Thus, we must sed this to match like a few other platforms. From: Kyle McMartin Signed-off-by: Kyle McMartin commit 0831b93d3571635b48f5ae648661fa7d806292ee Author: H. Peter Anvin Date: Tue Jan 3 12:22:20 2006 -0800 1.1.15 released, next version is 1.1.16 commit 040dac1752a5c3728fc4abbb2217ecd9c011aae3 Author: Jürg Billeter Date: Tue Jan 3 18:06:23 2006 +0100 Fix fstype crash fstype is currently broken in klibc (1.1.14 and git). It segfaults on startup when not invoked with an argument. Attached patch fixes that. PS: The previously reported problems with klibc 1.1.8 don't occur anymore, thanks. Regards, Jürg -- Jürg Billeter commit 49ab561194c19b980850c8f46973b317ea6e4857 Author: H. Peter Anvin Date: Sat Dec 31 16:56:18 2005 -0800 Handle src/obj directories cleaner, and add support for asm-powerpc commit dc6694ab699720c9e3519c5a98afd160f04a6fdc Author: H. Peter Anvin Date: Sat Dec 31 16:55:42 2005 -0800 Define BITS_PER_LONG (needed by on ppc) commit 94a4cce00ba7b91e0a58dec217ea04e185513b0e Author: H. Peter Anvin Date: Fri Dec 30 15:58:09 2005 -0800 Allow copying into an empty directory commit 36f97418048a4bdaa8053d07aa8e077b179e78ce Author: H. Peter Anvin Date: Wed Dec 28 22:30:37 2005 -0800 is a fairly dangerous header; include only what we need from it. commit 7ac5241a52dc06b48e305046141d58fea7291a5a Author: H. Peter Anvin Date: Wed Dec 28 22:08:54 2005 -0800 1.1.14 released, next version is 1.1.15 commit 59b8efc60fc1311140df7d1162a981900967119c Author: Jurij Smakov Date: Thu Dec 29 01:19:42 2005 +0100 sparc64 fix stat() I've investigated the sparc stat() klibc problem a bit and found that the definition of 'struct stat' in klibc's include/arch/sparc64/archstat.h is (most probably) incorrect. I've written a simple test case using stat() function and then looked at preprocessed source, which includes the 'struct stat' definition (from glibc headers) and copied that to include/arch/sparc64/archstat.h. That required changing the storage size for some fields, rearranging them, and adding some padding fields where neccessary. Attached patch implements these changes. With this change I was able to successfully boot my ultra5 box. Signed-off-by: maximilian attems commit 0dc802f4a2ea174a8f41081eaea698b23d87e8bc Author: H. Peter Anvin Date: Wed Dec 28 21:59:19 2005 -0800 Add commit ab3d3edf8069c437cd88eb29b7f16e31a4cf7a74 Author: H. Peter Anvin Date: Wed Dec 28 18:10:54 2005 -0800 1.1.13 released, next version is 1.1.14 commit 6580e8b5782cc300b1fea1dfcc25cd282da57bf0 Author: H. Peter Anvin Date: Wed Dec 28 18:10:26 2005 -0800 Make more robust; don't rely on qw() commit 66401f9a3e7b6b49008f50f0956aa82a5b491980 Author: H. Peter Anvin Date: Wed Dec 28 18:04:37 2005 -0800 Remove bogus paren commit 41064db33c18cc7a6ea6b061e140a540cc7817f5 Author: H. Peter Anvin Date: Wed Dec 28 17:38:17 2005 -0800 Remove stray ash files commit ed3a96791272e5b67ff2540b6178c57dd7249fab Author: Sam Ravnborg Date: Thu Dec 29 00:34:30 2005 +0100 kbuild: clean a bit better kbuild: better cleaning Let make clean delete generated dot-files and .o files. Introduce distclean/mrproper that deletes .config, linux symlink and all files left behind by editors and patch. Signed-off-by: Sam Ravnborg commit 15df289c162a94e0b5a19ca2e5d663ba3f03f1fb Author: H. Peter Anvin Date: Wed Dec 28 14:09:03 2005 -0800 1.1.12 released, next version is 1.1.13 commit a2311db0600ef451e4f8663e2a4912de79547e68 Author: H. Peter Anvin Date: Wed Dec 28 14:08:45 2005 -0800 Make sure klcc defines __KLIBC__ et al commit ab84a6656b3ec5f7a474f7d6cdc7d6d5dd0bac60 Author: H. Peter Anvin Date: Wed Dec 28 11:14:52 2005 -0800 Use %zu for size_t arguments commit 2ca15de080bb033a4cecc6fd39b207f734df493d Author: H. Peter Anvin Date: Wed Dec 28 11:12:54 2005 -0800 Kbuild changed the handling of ARCHREQFLAGS commit 00341c8cdb37e351ec91a2db49614bbbfab992bf Author: H. Peter Anvin Date: Wed Dec 28 11:12:28 2005 -0800 Remove old-style Makefile commit 8994a1d2c0d45e047327fad3886277c7692c49f5 Author: H. Peter Anvin Date: Wed Dec 28 10:53:51 2005 -0800 Proper type for "ep" commit fdaab771ad6108847ac1542b209f11f2cb1557c8 Author: H. Peter Anvin Date: Wed Dec 28 10:53:19 2005 -0800 Define "ep" where needed instead commit 94e7145a136811a6d755691f2cfff3aad8be41e7 Author: H. Peter Anvin Date: Wed Dec 28 09:09:13 2005 -0800 1.1.11 released, next version is 1.1.12 commit 942255f19a0ddedaa1c1cfb95b35d787ce6ad400 Author: maximilian attems Date: Wed Dec 28 09:08:38 2005 -0800 please revert commit aaa4e02c9baea24371ab021de4f00d69cb681095 that patch was a quick workaround for alpha, the issue beeing fixed by commit 1181b5904272b884afda429461765142e72e34fc commit 4f9923b5d416c4674f69e270d6269c554d4ccc72 Author: H. Peter Anvin Date: Wed Dec 28 09:02:51 2005 -0800 1.1.10 released, next version is 1.1.11 commit 69542d706961ab71cc0755b89673c1882c383df1 Author: H. Peter Anvin Date: Wed Dec 28 09:02:25 2005 -0800 Unused variable commit eeb628f0a1d040f36c78a4bc9fbbeb1de958bdd1 Author: H. Peter Anvin Date: Wed Dec 28 09:02:00 2005 -0800 Add commit c4a891a47edcfe5f9a45e4a264333772af199a11 Author: H. Peter Anvin Date: Wed Dec 28 09:01:25 2005 -0800 1.1.9 released, next version is 1.1.10 commit 73e2a8496a532dc6554a746c06f23d59a699cccb Author: H. Peter Anvin Date: Wed Dec 28 09:01:07 2005 -0800 Handle architectures without user-visible real-time signals. commit 5822262483ba2957baed20b4499649774c44494d Author: H. Peter Anvin Date: Mon Dec 19 15:18:35 2005 -0800 Off-by-one error in list value checking commit 831acebfc57b7149152ae0db36700768c126deba Author: H. Peter Anvin Date: Mon Dec 19 10:38:22 2005 -0800 1.1.8 released, next version is 1.1.9 commit 52ffc2eadc2ff4801e6b8fa140311db4ed21c69c Author: H. Peter Anvin Date: Mon Dec 19 10:33:32 2005 -0800 Signal numbers relative to SIGRTMIN commit 9c4ef9342be70a72118fec098b692b003fd5f351 Author: H. Peter Anvin Date: Mon Dec 19 10:33:10 2005 -0800 Add missing SIGTRAP and SIGCONT commit 67586db0bcd17ab216b26c32f878f274a42b26d7 Author: H. Peter Anvin Date: Mon Dec 19 10:30:07 2005 -0800 Use sys_sigabbrev[] and beef up the parsers a bit commit e993ccb2b2a7f6e83c0348e6b9a739e42d99ae92 Author: H. Peter Anvin Date: Mon Dec 19 10:14:47 2005 -0800 Add sys_sigabbrev[] commit 96dbaf294d9ff6c8b93da6cb5f4922598aa8f167 Author: H. Peter Anvin Date: Mon Dec 19 09:54:13 2005 -0800 1.1.7 released, next version is 1.1.8 commit 1181b5904272b884afda429461765142e72e34fc Author: maximilian attems Date: Mon Dec 19 10:34:53 2005 +0100 fix defintion of struct statfs64 On Sun, 18 Dec 2005, maximilian attems wrote: > Fix the definition of struct statfs64, > required for run-init to work on alpha. > > verified to have no regressions on amd64. while relooking at this patch i'm not shure why amd64 still worked. first i thought of just adding || defined(__alpha__) as least likely to break something that's already working. belows excludes those archs where the line is drawn. Signed-off-by: maximilian attems Signed-off-by: H. Peter Anvin commit 3811854a8b2cf0302672c6705f69776f565f69f1 Author: Steve Langasek Date: Sun Dec 18 01:45:33 2005 +0100 alpha grab errno from right register after syscall The next problem in line was that when trying to clear the initramfs to free memory before overmounting, run-init was getting EPERM instead of EISDIR when calling unlink() on directories. After stepping through both glibc and klibc linked binaries, I've concluded that the issue is simply that klibc is trying to read the errno from the wrong register. Initially, I was concerned this meant unlink was different from other syscalls on alpha, which didn't make sense; then I realized that none of the other syscalls I was looking at were *returning* a non-zero errno, just a return value. verified by indepent test boots that both patches fixes alpha klibc. Signed-off-by: maximilian attems Signed-off-by: H. Peter Anvin commit aaa4e02c9baea24371ab021de4f00d69cb681095 Author: Steve Langasek Date: Sun Dec 18 01:45:14 2005 +0100 fix defintion of struct statfs64 Fix the definition of struct statfs64, required for run-init to work on alpha. verified to have no regressions on amd64. Signed-off-by: maximilian attems Signed-off-by: Frederik Schüler Signed-off-by: H. Peter Anvin commit 1704b3472ea779027d9b97eec807b7d3ec15f611 Author: Herbert Xu Date: Mon Dec 19 23:18:40 2005 +1100 Parallel build of dash still fails On Sun, Dec 18, 2005 at 12:28:27PM -0800, H. Peter Anvin wrote: > > Could you generate it against either klibc-1.1.6 or the current HEAD, > which is 62507c399766ae423b08a5bf14ff62dd57f428ec? The patch doesn't > apply against the current HEAD, and branching and merging gives a conflict. Sure, here it is. -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt Signed-off-by: H. Peter Anvin commit 62507c399766ae423b08a5bf14ff62dd57f428ec Author: H. Peter Anvin Date: Tue Dec 13 17:12:28 2005 -0800 1.1.6 released, next version is 1.1.7 commit 33030d0321e3cb23aafb4c226047a36529e981e0 Author: Sam Ravnborg Date: Tue Dec 13 22:22:04 2005 +0100 Non-kbuild klibc obsoleted On Tue, Dec 13, 2005 at 09:48:44AM -0800, H. Peter Anvin wrote: > Hi there, > > Just found a problem... the old Makefile produced e.g. > utils/{static,shared,static.g,shared.g} with and without debugging > turned on. This is important, since with klibc sometimes these aren't > just the same thing as building with debugging and then stripping; that > doesn't work too well on e.g. x86-64. > > Any idea how to get this back? I took the simple approch and always do it when building the shared / static binaries. I assume this cover your need. Please note one major drawback. If you delete the *.g file kbuild will NOT notice and will not rebuild it. Sam kbuild: create stripped versions of programs When building utilities always create a file.g that is the non-stripped binary. Please note that the file.g file is created as a side effect, so kbuild does not know about it. In other words kbuild will not rebuild the .g file if you delete it. And it will overwrite it no matter the timestamp on the file Signed-off-by: Sam Ravnborg commit 3ac494926e4b96b7f6b3eb82697de7ab766e18ec Author: H. Peter Anvin Date: Tue Dec 13 09:55:19 2005 -0800 1.1.5 released, next version is 1.1.6 commit 4ba3cfc41ea951cfd6793b5c3c9908cf86527277 Author: H. Peter Anvin Date: Tue Dec 13 09:54:59 2005 -0800 Need -R before klibc.so commit b1753d641d0331cca6221ff6977ec09694995eb0 Author: H. Peter Anvin Date: Mon Dec 12 13:41:34 2005 -0800 1.1.4 released, next version is 1.1.5 commit c6b4d9e6249b884c52b1b851a1dbcd95735ccf1c Author: H. Peter Anvin Date: Mon Dec 12 13:41:17 2005 -0800 Ignore onexit pointer; causes more harm than good commit 82039b135d0bf58b850eef94cc2c0ab01d71d462 Author: H. Peter Anvin Date: Mon Dec 12 13:37:16 2005 -0800 ABI fixes: ppc/ppc64 don't pass a valid fini pointer commit 35bd0ac111a768e8b649053c3d196723191fe996 Author: H. Peter Anvin Date: Mon Dec 12 13:34:33 2005 -0800 Support fractional-second sleep commit 52732d887cb09bf6755cfda2efd4638b69877992 Author: Jeff Bailey Date: Mon Dec 12 13:32:16 2005 -0800 On parisc-linux, gcc defines size_t as unsigned int: # 1 "" #define __SIZE_TYPE__ unsigned int This mismatch causes dash to fail to build because of a malloc parameter mismatch. commit b976ad711c43ddc3225a2f3ba6eb14e238dd6819 Author: H. Peter Anvin Date: Wed Dec 7 22:02:18 2005 -0800 Remove file in the wrong place commit 950bf23f84d2b12d6404edd34e8d3206c83ed9c3 Author: H. Peter Anvin Date: Wed Dec 7 22:00:01 2005 -0800 1.1.4 released, next version is 1.1.5 commit c68bfe9157595217efc8a040ba9e7f3633acc43c Author: H. Peter Anvin Date: Wed Dec 7 21:59:35 2005 -0800 Support "fstype /dev/foo" instead of "fstype < /dev/foo" commit 0f1f3a79de11b65a76bd3d87da19edd62b1fec48 Author: H. Peter Anvin Date: Wed Dec 7 21:58:36 2005 -0800 Add missing file commit 19f9a6515e37462d5bd5e15cef1fb6a05183b1f3 Author: Jeff Bailey Date: Tue Sep 13 17:57:44 2005 -0400 [PATCH] Support JFS in fstype Here's a patch to support JFS in fstype. Given that this runs as root, would you consider a patch to take the device as an argument rather than stdin? I get really nervous that one of these days I'm going to > rather than <. But otherwise... =) Tested against 1.0.14, but there's nothing in there that should keep it from applying against current git that I can see. Tks, Jeff Bailey commit 7e98a3cc86c8ae6076253616f16be7e66f777b13 Author: H. Peter Anvin Date: Wed Dec 7 21:45:08 2005 -0800 Tabify source commit bb09cc1bf3caade163b3ae19e77c6d598bca92a1 Author: H. Peter Anvin Date: Wed Dec 7 21:44:57 2005 -0800 No atexit pointer for parisc commit 7cc5ec33cdf3f0cdc1696c902c00440b0bfc773c Author: Herbert Xu Date: Mon Dec 5 19:45:17 2005 +1100 [SHELL] Fixed dash kbuild support I've redone the kbuild support by starting with the dash Makefile and adding the necessary kbuild glue to it. I've also changed a few remaining occurences of ash to dash. Signed-off-by: Herbert Xu commit 7f35881ee18e1463a111c09ae0627339612e3dcf Author: H. Peter Anvin Date: Sun Dec 4 13:35:33 2005 -0800 Beginnings of a dash Kbuild file commit d85c5a9f533a3ba46d467af7a1eee6ae2e3f58e8 Author: H. Peter Anvin Date: Sun Dec 4 13:35:13 2005 -0800 Allow sending output to a different directory commit 2a8fc6bd5f164326bf8605ba0aa9ccbaabf71b81 Author: H. Peter Anvin Date: Sun Dec 4 13:34:37 2005 -0800 Build dash, not ash commit 51b45790e1047722735f2cb30fc05b643bdef17e Author: H. Peter Anvin Date: Sun Dec 4 13:34:25 2005 -0800 Remove merge junk commit f4958b589637e705679b3b6db088f1e3869264b8 Author: H. Peter Anvin Date: Sun Dec 4 11:55:11 2005 -0800 exit.o, not exitc.o (see 4c9547f930f405fd6d7c0d2b19df29e6b6a1bc86) commit f0932364c4ce626eaf2e03eb2aa746edcb9c4123 Author: H. Peter Anvin Date: Sat Dec 3 23:04:30 2005 -0800 1.1.3 released, next version is 1.1.4 commit 86569cd1cb7fb88dc7e10ace41b0bf079b82902a Author: H. Peter Anvin Date: Sat Dec 3 23:03:26 2005 -0800 Add clearenv(), and don't barf if the user does "environ = NULL;" commit 1893c45628afb5a8bcf5830aea9dffc95529f2af Author: H. Peter Anvin Date: Sat Dec 3 14:37:12 2005 -0800 1.1.2 released, next version is 1.1.3 commit cc3e317d54e335d571f3ef3fffda541080c8d650 Author: H. Peter Anvin Date: Sat Dec 3 13:58:06 2005 -0800 Remove printf (it's a builtin in dash) commit bf0c9ceceb85850bfcb58009163294e8f5217e30 Author: Kyle McMartin Date: Sat Dec 3 02:10:51 2005 -0500 [PATCH] Fix invalid operands compile error in parisc/crt0.S The iitlbp instruction needs the space register explicitly specified with newer toolchains. Specify sr0, but it doesn't really matter as the insn is just used to crash the program. Signed-off-by: Kyle McMartin commit 79670fd645df9a31e556e6433d2c426591fe4dd9 Author: Kyle McMartin Date: Fri Nov 25 14:44:54 2005 -0500 [PATCH] Fix syscalls with more than four arguments on parisc Reimplement __common_syscall in assembler. The 32-bit ABI says that the fifth and sixth arguments to the function are passed on the stack, but our syscall ABI says they are passed in %arg4 and %arg5 like the 64-bit ABI. Also, tried to optimize the code slightly by making use of the cmpb delay slot to load the errno return of -1. Signed-off-by: Kyle McMartin commit d4d7f2e5665c9db48cd0473d0a0c12fcab785890 Author: Herbert Xu Date: Fri Nov 4 22:42:49 2005 +1100 [SHELL] Replace ash with dash This change replaces ash with dash. The rationale for doing so are: 1) dash is significantly smaller than ash (about 19% on i386). 2) dash has had more testing compared to the current port of ash. 3) dash has built-ins such as printf which have also been optimised for size. dash can be downloaded from http://gondor.apana.org.au/~herbert/dash/dash.git/ This klibc change corresponds to the dash change 3c98399cdf8d376b2c1ebd9cd32ca5d8c84f3ac9 The only modifications made are the addition of a klibc config.h and a Makefile to build with klibc. Signed-off-by: Herbert Xu commit 4c9547f930f405fd6d7c0d2b19df29e6b6a1bc86 Author: Peter Anvin Date: Wed Oct 12 12:24:37 2005 -0700 Remove hook stuff for atexit, and just implement _exit() like any other system call. It's just easier that way. commit 605ec753b87fc93e167cd1429a5471e118de8993 Author: H. Peter Anvin Date: Tue Sep 6 18:15:14 2005 -0700 Correct path for kinit README commit 218ee03bb7434e2b11c72513e39b824bbed01fc0 Author: H. Peter Anvin Date: Tue Sep 6 18:14:18 2005 -0700 Correct path for ipconfig README commit bc56b1091bf246c396fd7cc25e7178b490912ffc Author: H. Peter Anvin Date: Tue Sep 6 18:11:00 2005 -0700 Quiet warning commit 135cec4fbbd550de234f7fb6f0aabde0e276d3af Author: H. Peter Anvin Date: Tue Sep 6 13:49:48 2005 -0700 1.1.1 released, next version is 1.1.2 commit 31b0a822aeff0f3b0f908268711e985568ebb221 Author: Peter Anvin Date: Tue Sep 6 13:42:29 2005 -0700 Add actual prototypes to commit c2b32f948195c3af6c0f7722a6e9551629901f56 Author: Peter Anvin Date: Fri Sep 2 16:50:38 2005 -0700 Clean up merge (git doesn't really handle moves too well, sigh) commit f5260f8737517f19a03ee906cd64dfc9930221cd Author: Peter Anvin Date: Fri Sep 2 16:38:05 2005 -0700 Warnings cleanup commit 3aa89352d3915b5dae0d98b37ff99cb01d2de5ea Author: H. Peter Anvin Date: Fri Sep 2 09:08:47 2005 -0700 Add , for applications that are just way behind the times commit 59709a172ee58c9d529a8c4b6f5cf53460629cb3 Author: H. Peter Anvin Date: Thu Sep 1 23:16:47 2005 -0700 Remove obsoleted files from merge commit f52be163e684fc3840e557ecf242270926136b67 Author: H. Peter Anvin Date: Thu Sep 1 22:56:49 2005 -0700 socketcalls aren't always *.S files; they can also be *.c commit 97e5354555be413f1814d3db8a38af70e078b3b0 Author: H. Peter Anvin Date: Thu Sep 1 22:56:29 2005 -0700 Fix signedness warnings commit 9d7bd02fe642816343f1f41d3b695dd4aaa1ea22 Author: H. Peter Anvin Date: Thu Sep 1 22:56:06 2005 -0700 Add explicit "int" declarations to external defines commit 5d1940d2ad03c92e99dfb16df250e7aeae7493d1 Author: H. Peter Anvin Date: Thu Sep 1 22:55:26 2005 -0700 Remove .o files which should never have been checked in commit 3a41b60f6730077db3f04cf2874c96a0e53da453 Author: H. Peter Anvin Date: Thu Sep 1 22:45:27 2005 -0700 1.1 released, next version is 1.1.1 commit 51b4fe0e33842fd5edec6b0f431e64adae6d6974 Author: H. Peter Anvin Date: Thu Sep 1 22:34:24 2005 -0700 Try avoid problems with cp copying links commit 65b61000d8025079654077891bb122a61503d4f3 Author: H. Peter Anvin Date: Thu Sep 1 22:29:34 2005 -0700 Add kernel-devel as a build dependency commit d1c30e2d45933e582dc037b655aa2b750aa6e5c8 Author: H. Peter Anvin Date: Thu Sep 1 22:19:30 2005 -0700 Support index() and rindex() as aliases for strchr() and strrchr(). commit 58269c85a073488ff7b580306ee6b4458b6806e6 Author: Jeff Bailey Date: Wed Jun 1 10:05:07 2005 -0400 Without this, comma separated options to the nfs server don't come through. commit 4a684a5322bebf2e7c23231f46659ef4ab788d81 Author: Erik van Konijnenburg Date: Sun Jun 5 14:09:00 2005 +0200 [PATCH] avoid spurious umount error message In nfsmount, the function mount_call() is used to invoke both the mount and umount PRC's. These take identical arguments, but umount returns void rather than a file handle, so result should not be checked. This avoids a spurious 'incomplete reply' message if mount(2) system call fails. Signed-off-by: Erik van Konijnenburg Signed-off-by: H. Peter Anvin commit 77e72ca8c62e16efaced8c35f7ac1216a8322f4c Author: Erik van Konijnenburg Date: Sun Jun 5 14:10:57 2005 +0200 [PATCH] avoid name clash on nfs_fh in nfsmount Avoid a name clash in nfsmount on Fedora glibc. The name nfs_fh is used in both kernel and in nfsmount application, but one uses it to mean the argument to mount(2), the other means the data as captured from the wire. The package glibc-kernelheaders in Fedora makes the kernel structure visible to user space, so conflict results in compilation errors. With klibc, the homonym is harmless because its hidden by ifdef __KERNEL__. Signed-off-by: Erik van Konijnenburg Signed-off-by: H. Peter Anvin commit bab38cd42f70ea32b84e1e11f2c52d829dc8b7dc Author: H. Peter Anvin Date: Thu Sep 1 22:05:54 2005 -0700 commit f659fab0c4b6bff3588de08882a5b02b8870f537 Author: Martin Schlemmer Date: Fri Aug 5 10:18:11 2005 +0200 klibc m4 script for autoconf use commit 08478726b7238d0f3dec7a8d329518afa677ffd0 Author: H. Peter Anvin Date: Thu Sep 1 21:53:54 2005 -0700 Next version 1.1 commit b059b6cc9f336abf40ec368467c0345904d9637a Author: H. Peter Anvin Date: Thu Sep 1 20:49:29 2005 -0700 Add commit 1d5c8e36a281d008630b09303e4bc76a4caf7814 Author: Kay Sievers Date: Tue Aug 9 04:06:51 2005 +0200 Support inotify system calls commit 11cda3ca8d507524b9ccc3f9e8e186d9dfbda0c7 Author: Martin Schlemmer Date: Thu Aug 25 11:23:26 2005 +0200 Pass -nostdlib to REQFLAGS to avoid confusing hardened gcc commit 1d774a8cbd8e8b90759491591987cb509122bd78 Author: H. Peter Anvin Date: Sun Aug 7 15:47:43 2005 -0700 Explain why execvpe/execlpe work the way they do. commit 5492ae07007399d8838dea5f44b3d9cf3603abc3 Author: Sam Ravnborg Date: Sun Aug 7 22:53:42 2005 +0200 kbuild: add klibc/tests to kbuild Add a kbuild file so we now can build the test programs. A new dedicated target is used: make test Signed-off-by: Sam Ravnborg commit 64dda666c087b6e537892ac9984aff57d2b32c47 Author: Sam Ravnborg Date: Sun Aug 7 11:08:02 2005 +0200 kbuild: tidy up printout during quiet build Less verbose and make sure text are properly aligned Signed-off-by: Sam Ravnborg commit 58879b7699c19fa532095342ca3142ae34783004 Author: Sam Ravnborg Date: Sun Aug 7 10:57:18 2005 +0200 kbuild: zlib needs -DDYNAMIC_CRC_TABLE Signed-off-by: Sam Ravnborg commit 757fb676ac86106577c1b6164e5f6398ab86a3e2 Author: Sam Ravnborg Date: Sun Aug 7 10:49:28 2005 +0200 delete unused files A number of files are no longer in use after we shifted over to use kbuild for klibc - delete them. Signed-off-by: Sam Ravnborg commit 423986135aac6073aff2e1b8efd01f3dadf3fe77 Author: Sam Ravnborg Date: Sun Aug 7 10:39:22 2005 +0200 kbuild: install of kinit, ipconfig and nfsmount When they moved we now have the possibility to install them, so do it. Signed-off-by: Sam Ravnborg commit 50b7344b545588cbc413081ed19c625ffaa6a5ef Author: Sam Ravnborg Date: Sun Aug 7 10:29:02 2005 +0200 kbuild: make clean Just copied over scripts/Makefile.clean and a few modifications later it worked. Signed-off-by: Sam Ravnborg commit 19e2ffa06ebdef2b16d3f69ca400fcfb93b32a61 Author: Sam Ravnborg Date: Sun Aug 7 10:06:14 2005 +0200 Move kinit, ipconfig and nfsmount kinit, ipconfig and nfsmount has moved: kinit -> usr/kinit ipconfig -> usr/kinit/ipconfig nfsmount -> usr/kinit/nfsmount ipconfig and nfsmount are subdirectories to kinit due to kinit being dependent on these two. The new location under usr/ reflect the desired location in the kernel, and act as a preparation for a future kernel merge. Signed-off-by: Sam Ravnborg commit f0b0bb120b3104e4b7493f533e096e33cc1737cf Author: Sam Ravnborg Date: Sun Aug 7 09:18:34 2005 +0200 kbuild: make install Added infrastructure for make install and start usign it. The file scripts/Kbuild.install contains both logic for descending subdirectories and the final install steps. For a normal binary just use: install-y := binary For special requirements use: install-rule: commands to execute Only user of install-rule for now is klibc/Kbuild To test the install do: make INSTALLROOT=~/tmp/test install To better support make install a new Kbuild file is created in top-level directory, and some functionality thus moved from ./Makefile to ./Kbuild Signed-off-by: Sam Ravnborg commit d621115d41d24f209588b9896fcc95729cd9008f Author: Sam Ravnborg Date: Sun Aug 7 08:50:37 2005 +0200 kbuild: fix so binaries is now working Passsing the wrong options when compiling .S files had the unfortunate sideeffect that the binaries did not work. This is presumeably due to -mregparm=3. Fix it so correct flags is passed. Also included a fix to obey ARCHREQFLAGS. Signed-off-by: Sam Ravnborg commit e6d3b4d5f0457708ba55e85e360c3ca3bfc5be7c Author: Sam Ravnborg Date: Fri Aug 5 00:21:53 2005 +0200 kbuild: kbuildtify klibc - add klibc, ash, gzip and utils This is second step in using kbuild to build klibc. This time a few files were added from the kernel to support building .c files. Also more kbuild compatibility were added to top-level Makefile. Outstanding issues: - ipconfig and nfsmount must be moved under kinit so satisfy kbuild - install target is broken - clean target is broken Signed-off-by: Sam Ravnborg commit f2a3b9614dd9d426b01d92e0b795739db852b7a1 Author: Sam Ravnborg Date: Thu Aug 4 23:05:33 2005 +0200 kbuild: move klcc to directory named klcc In a preparation to kbuildtify klibc move klcc down to a klcc subdirectory. kbuild is used to build klcc, so started to add some kbuild definitions to the top-level Makefile. In klinc.config the old names are kept on the left-hand side. This was chosen so we do not break compatibility with existing klcc users. Signed-off-by: Sam Ravnborg commit 3346986f08271f35630e5c5b4b3af47eb8b874ab Author: Sam Ravnborg Date: Thu Aug 4 22:30:19 2005 +0200 kbuild: fix make O= in kernel A few places needed to be fixed in order to support make O= Actually suprisingly few places needed to change, and we really want this feature to work before pushing to -mm Signed-off-by: Sam Ravnborg commit 19eaf1b12e932acfc29ae3747c4935bc0800f2aa Author: Sam Ravnborg Date: Thu Aug 4 21:42:25 2005 +0200 kbuild: s/USER/KLIBC/g In general replaced the term USER with the more specific term KLIBC. When included in the kernel the term USER is ambigious, especially if kbuild are expanded with specific UML support. So introduce the common prefix 'KLIBC' as replacement for USER. While in the process Kbuild.klibc is now more careful to pick up definitions from arch specific MCONFIG. This is made backward compatible since we share the arch specific MCONFIG files with the old klibc buildsystem for now. Also brought back EMAIN - we may need it soon for klcc. Signed-off-by: Sam Ravnborg commit 157d230bc48c273232b9fab4a51fee425f91dd9c Author: Sam Ravnborg Date: Tue Aug 2 23:18:50 2005 +0200 kbuild: add -Wno-sign-compare hpa wrote: Please add -Wno-sign-compare to the CFLAGS And so I did - wondering how -Wsign-compare slept in at all. Signed-off-by: Sam Ravnborg commit b4c1af03a5b0c908b32ab60473cdfaa20ecfe0f6 Author: Sam Ravnborg Date: Tue Aug 2 23:00:30 2005 +0200 kbuild: fix cleaning in kernel tree To support cleaning a bit of resturcturing was needed in usr/Kbuild. The current structure descend into klibc binary subdirectories only if CONFIG_KLIBC is selected. The is not yet support for adding the binaries to the initramfs image. That will wait until we find a nice way to do so. Also added a few statements to various Kbuild files to let 'make clean' pick up all output files. There is room for some generalization - but that will wait until klibc hit mainline. Signed-off-by: Sam Ravnborg commit 5069497d1331ed907edbc1a22155fa8778569f84 Author: Sam Ravnborg Date: Mon Aug 1 23:24:08 2005 +0200 kbuild: let static-y + shared-y depend on lib.a Introducing this dependency allows us to build a lib.a in a directory using: lib-y := file.o And then using EXTRA_USERLDFLAGS we can tell the linker to use this file. There is no users in klibc atm, but the possibility was so good that I decided to keep it (developed it for utils/ but decided for a better solution there). Signed-off-by: Sam Ravnborg commit e29ea2b12b68a3fb9b548ebdbb52e35c40c25889 Author: Sam Ravnborg Date: Mon Aug 1 23:21:46 2005 +0200 kbuild: add Kbuild for utils and ash Added a Kbuild file for utils/ and ash. For utils/ I had to tell kbuild for each single binary what .o file it used because the binary is placed in a subdirectory. For ash I had to teach some of the script files that the output files are stored in a directory != current directory. cp-to-kernel also copies utils and ash now. Signed-off-by: Sam Ravnborg commit 1b8f997e4838bb3f152d0f54067d64cc52dbb209 Author: Sam Ravnborg Date: Mon Aug 1 16:38:32 2005 +0200 kbuild: replace obj- with lib- When we changed from built-in.o to lib.a it makes less sense to use the obj- syntax. So switch it over to lib- Signed-off-by: Sam Ravnborg commit c8da2e7a7d748918be96965829fcf8249d87be04 Author: Sam Ravnborg Date: Mon Aug 1 00:43:51 2005 +0200 kbuild: Use archives rather than object files Executables that consist of objects from a subdirectory were previously linked to a built-in.o file. Convert this to use archives. Signed-off-by: Sam Ravnborg commit 6ec5f2d923dc945d942a36ed7875733678644712 Author: Sam Ravnborg Date: Mon Aug 1 00:01:34 2005 +0200 kbuild: Included kinit, nfsmount and ipconfig in kernel build The kinit (and the rest) are build both as static and shared linked executables. To support this in a clean way the support in Kbuild.klibc was reworked considerably. Now to tell when you want a static linked executables use: static-y := binary Likewise for shared executables use: shared-y := binary To test things out a Kbuild file was created for kinit, ipconfig and nfsmount. Things worked out pretty well and the syntax is kept nice and readable. Due to the fact that kinit uses ipconfig and nfsmount they were in the kernel placed as subdirectories for kinit. This is the only sane way to express the dependencies when doing recursive build like in the kernel. With the current scheme a .o file is created for ipconfig and nfsmount. If we are better served with a ar file then this is easy to fix. Signed-off-by: Sam Ravnborg commit e7daa9d72c3c7ea2cf23ff34bf601989ced7c6e1 Author: Sam Ravnborg Date: Sun Jul 31 13:51:43 2005 +0200 kbuild: build all targets in gzip The gzip program had a few aliases - using ln to reach them. Build these. Also introduce gzip.stripped since it was present in the original Makefile. To support this a few new rules was added to scripts/Kbuild.klibc Signed-off-by: Sam Ravnborg commit 6b1838e0265930a078ab79815dfa8fe86102a562 Author: Sam Ravnborg Date: Sat Jul 30 22:19:06 2005 +0200 kbuild: move kbuild files to reflects directory structure in the kernel To make it more obvious where the files are supposed to end up move files so they reflect the directory structure in the kernel. mkdir usr mv kernel/Kbuild usr mkdir scripts mv kernel/* scripts/ rmdir kernel Furthermore updated cp-to-kernel to refelct new directory layout And added '#' in front of comment in usr/Kbuild Signed-off-by: Sam Ravnborg commit 6327408a6bf07cf284adb344e982cb91b6eed4a7 Author: Sam Ravnborg Date: Sat Jul 30 22:07:11 2005 +0200 kbuild: use KLIBSRC + KLIBINC consistent in kbuild files Using KLIBSRC + KLIBINC all over the place allow os to centralize to a single place where we hardcode where in the kernel tree klibc is placed. While visiting the files alignment was fixed in a few spots. Signed-off-by: Sam Ravnborg commit 3d669f9229cb75affb2c13df3fff98f3c71dd94c Author: Sam Ravnborg Date: Sat Jul 30 21:54:33 2005 +0200 kbuild: Update to latest kbuild tree changes, fix make clean, add gzip to kernel This update requires the latest changes from the kbuild tree to be fully operational. The changes are planned to hit mainstream kernel when 2.6.14 opens up. This patch should work with older kernels too, except for the make clean functionality. Included in this patch: - Fixes so make clean is now working - Added gzip to kernel tree (in cp-to-kernel) including a small Kbuild file - Updated to latest Kbuild.include - Modified CFLAGS to match the klibc supplied values Signed-off-by: Sam Ravnborg commit 5691e96ebfccd21a1f75d3518dd55a96b311d1aa Author: H. Peter Anvin Date: Thu May 26 22:02:40 2005 -0700 1.0.14 released, next version is 1.0.15 commit fdb8a185ef261568f01140989745b8636212db71 Author: H. Peter Anvin Date: Thu May 26 22:01:44 2005 -0700 Add missing n--; (from Adrian Drzewiecki) commit 7550797141764aab6ae51571c8adc7fe8c39eacd Author: H. Peter Anvin Date: Thu May 26 21:51:32 2005 -0700 "make release" to turn a checkout into a tarball commit f46dfcff3df110272b7d89644742f88d8160b465 Author: H. Peter Anvin Date: Thu May 26 21:44:16 2005 -0700 Fix more pathname problems commit c7de805eb2cd834f024526e8a564ffe47281f1a1 Author: H. Peter Anvin Date: Thu May 26 21:30:23 2005 -0700 Support klcc on stdin, from Daniel Thaler (take 2) commit 0124ca9c6ebbc6ce2f6b96246a39dadc2e36a06a Author: H. Peter Anvin Date: Thu May 26 21:30:01 2005 -0700 Switch from CVS to git commit 7b116c9fff740640d8851e0b4fd79a65dc06f7f3 Author: H. Peter Anvin Date: Wed May 25 10:33:33 2005 -0700 1.0.13 released, next version is 1.0.14 commit e525df6a124a87e2dbff2dd2b915efbe7e43e811 Author: Peter Anvin Date: Wed May 25 10:31:32 2005 -0700 Back out stdin patch to klcc; it's broken. commit ea31a2eaf3d41ed7cc7816adda9d76e90796be7d Author: H. Peter Anvin Date: Wed May 25 09:21:38 2005 -0700 1.0.12 released, next version is 1.0.13 commit d9d829b93d359a98e27fd610da9a244c892e33a6 Author: H. Peter Anvin Date: Wed May 25 09:20:45 2005 -0700 SHLIBDIR should *NOT* have INSTALLDIR prepended. commit bfa2c0f2504021248854f71e114b9f5ebb0e2c03 Author: H. Peter Anvin Date: Tue May 24 23:18:38 2005 -0700 Let klcc pass input from STDIN to gcc Some packages want to pass input to gcc via STDIN (iptables for example) This patch lets klcc accept '-' as a valid input filename, prevents it from setting -x in that case and changes the invocation of gcc from system() to open3() so that gcc's STDIN can be connected to klcc's STDIN. Daniel Thaler commit 44acbaf1564f0202f8bc73a5f5f7e8b055feb238 Author: H. Peter Anvin Date: Tue May 24 23:17:04 2005 -0700 Respect INSTALLROOT when installing klibc-*.so commit ef8b2c8315bb060419afb0a6642a849bde2312c3 Author: H. Peter Anvin Date: Tue May 24 23:12:00 2005 -0700 Handle leading plus signs correctly commit 330d77fc70357bcf1a002081cb00d2164736cefa Author: H. Peter Anvin Date: Tue May 24 22:57:16 2005 -0700 1.0.11 released, next version is 1.0.12 commit c9ce000796afc734caecaade5a5ad974604036d2 Author: H. Peter Anvin Date: Tue May 24 22:46:56 2005 -0700 [patch 12/12] new include file net/route.h Provide . This is the same as , but under glibc it has the advantage that it does not suck in which conflicts with . Signed-off-by: Erik van Konijnenburg commit efc909ad68dea9e7606ed8ed4cbbc8aaef186a94 Author: H. Peter Anvin Date: Tue May 24 22:45:04 2005 -0700 [patch 10/12] make struct timeval visible Include for definition of struct timeval. Signed-off-by: Erik van Konijnenburg commit dd70885e437bc8f1ed57c5aaa78252f0ca3692f4 Author: H. Peter Anvin Date: Tue May 24 22:44:25 2005 -0700 [patch 09/12] avoid use of linux/if.h via linux/if_arp.h Use rather than , otherwise you suck in , which conflicts with in glibc. Signed-off-by: Erik van Konijnenburg commit 4ada9d085bb5fa08d9656f22e8f997db573fc5d9 Author: H. Peter Anvin Date: Tue May 24 22:43:37 2005 -0700 glibc uses and commit 8f75903eeb44b58c727b5e68b4f8805e7008b2b1 Author: H. Peter Anvin Date: Tue May 24 22:35:16 2005 -0700 [patch 07/12] make ioctl defines visible Defines such as SIOCGIFFLAGS are available via in glibc. Signed-off-by: Erik van Konijnenburg commit d373abc18c9b0ff32e5f335e142d9d7e8ce816cf Author: H. Peter Anvin Date: Tue May 24 22:34:19 2005 -0700 Add to handle __constant_hton*() on glibc commit 1e5c6224177c8e49b51b5460e1b611d0696cef5e Author: H. Peter Anvin Date: Tue May 24 22:33:04 2005 -0700 [patch 03/12] make getopt visible The getopt(3) function is declared in unistd.h. Signed-off-by: Erik van Konijnenburg commit e785d10ec4b64a3b972a85eadb75d0730a2c37c2 Author: H. Peter Anvin Date: Tue May 24 22:28:13 2005 -0700 [patch 02/12] make __u8 and friends visible The type __u8 and friends are not normally visible to userspace. Include (which *must* have included before) to make this available. A possible alternative is to replace __u8 with uint8_t everywhere and include . Perhaps cleaner, but more intrusive. Signed-off-by: Erik van Konijnenburg commit c6b9722562572c03832bba08a9bd859f37d07261 Author: H. Peter Anvin Date: Tue May 24 22:26:18 2005 -0700 We really need __constant_hton*() after all... commit ceca18a974eaa88851d7beb8960b52aef6396928 Author: H. Peter Anvin Date: Tue May 24 22:17:30 2005 -0700 [patch 01/12] avoid exit on valid usage in nfsmount Nfsmount_main may exit on usage errors, illegal arguments for example, but will return rather than exit on environment errors. This allows kinit to retry nfsmount with a different option if nfs over tcp happens to be unsupported. Signed-off-by: Erik van Konijnenburg commit 336be5cda5504bff69bb880132e5476ef6eb99f6 Author: H. Peter Anvin Date: Tue May 24 22:16:20 2005 -0700 Don't use __constant_hton*() explicitly commit 6ea2b1010a16bdbfd17fe5059b3d5e87f2cdf3a4 Author: H. Peter Anvin Date: Fri May 20 12:41:15 2005 -0700 1.0.10 released, next version is 1.0.11 commit de82c7b17af72c300eec0d17dd48e7cee6b896da Author: H. Peter Anvin Date: Fri May 20 12:25:03 2005 -0700 Be TOTALLY obnoxiously anal about wrapping sigaction... commit 1db8f1a3e7d4f4c2a4b3575471cb4df3318a3276 Author: H. Peter Anvin Date: Fri May 20 11:55:18 2005 -0700 Don't copy the sigaction structure if we don't need to... commit 5a95bffb87d23666976fe8cd5d29be34b3827ce6 Author: H. Peter Anvin Date: Thu May 19 23:37:53 2005 -0700 1.0.9 released, next version is 1.0.10 commit 8cf8cae74e3a8e531ded243d5a3e465be852906f Author: H. Peter Anvin Date: Thu May 19 23:34:19 2005 -0700 1.0.8 was released in April, next is 1.0.9 commit 17bf1f89c0b1620a0aab46e5a6a672d660079827 Author: Peter Anvin Date: Thu May 19 23:01:25 2005 -0700 Correct function name commit 876692c59bccce27b2e5ed069c00e216529b48db Author: H. Peter Anvin Date: Thu May 19 22:54:30 2005 -0700 Use sigreturn on i386 and x86-64, not on other architectures. commit 29af393bc341b235b0b88209b6c3cdaca1ced251 Author: Peter Anvin Date: Thu May 19 21:40:26 2005 -0700 Signal handling change: don't expose the rt_* system calls to userspace; always add a restorer function since the kernel can't be trusted to have a valid restorer available (e.g. x86-64, or Fedora/i386) commit c8227b841201571d760501b8b41ef3211e52bdac Author: Peter Anvin Date: Thu May 19 21:39:32 2005 -0700 Avoid usually-taken overbranches commit bddd5547edb5759a0f9aceacea38fb7a6d170f97 Author: Peter Anvin Date: Thu May 19 21:38:46 2005 -0700 Add support for building with debugging on x86-64 commit 7d090a0683801e63d2447e73959543777304e251 Author: H. Peter Anvin Date: Tue Apr 19 23:14:40 2005 +0000 Flesh out man page a little more; add license commit f2baaf24acdc57737d2ceb0acabfc0c48d6ed679 Author: H. Peter Anvin Date: Tue Apr 19 23:14:40 2005 +0000 Add missing kbuild files commit 019ce0eb5d517424a49337869398bb2db49ee78d Author: H. Peter Anvin Date: Mon Apr 11 15:39:32 2005 +0000 1.0.7 released, next version is 1.0.8 commit a617cc20accc4a3f6725b710ad95904d9d6843be Author: H. Peter Anvin Date: Sun Apr 10 00:54:12 2005 +0000 More changes for the benefit of kbuild. commit c5138ca59b8196cb57ed840a8d6ac72c4aa95c36 Author: H. Peter Anvin Date: Sun Apr 10 00:54:12 2005 +0000 1.0.6 released, next version is 1.0.7 commit 4419fcc42fd49fc8ea98af09aa188eddb8ed0219 Author: H. Peter Anvin Date: Sun Apr 10 00:33:46 2005 +0000 Perl changes to make kbuild integration easier. commit 910b6a39ddd063374eae1cccf5604466183550b4 Author: H. Peter Anvin Date: Sun Apr 10 00:33:46 2005 +0000 Do pathname canonicalization in Perl instead of relying on invoking bash. commit 0835dbbd1f56ff530cb23a411e413377a9009304 Author: H. Peter Anvin Date: Thu Mar 31 09:23:48 2005 +0000 One more step toward a full-featured kinit; do lots of cleanups commit 8bf9758178e6d8dd835baef54e4acea373da73fe Author: H. Peter Anvin Date: Mon Mar 28 16:56:53 2005 +0000 local-spotless should depend on local-clean commit 344efab29d0bbd64ca13ffc38adc6791f868f57a Author: H. Peter Anvin Date: Mon Mar 28 15:22:04 2005 +0000 1.0.5 released, next version is 1.0.6 commit 4644bd92e21c7fd9a48dd8dfd0c4f8ef772843f0 Author: H. Peter Anvin Date: Tue Mar 22 21:00:32 2005 +0000 strlcpy()/strlcat() fixes, mostly from Kay Sievers commit ccb24e02a3ffc6ef67a427aab2f0953bd40e1303 Author: H. Peter Anvin Date: Tue Mar 22 21:00:32 2005 +0000 1.0.4 released, next version is 1.0.5 commit 9991f3014e2cb90439682ac009e02d445f5f0e59 Author: H. Peter Anvin Date: Thu Mar 10 01:24:48 2005 +0000 Fix sig_atomic_t, add signal handler test commit 9e997973be0b22dcf5e8c28a02d7992c228c9c8d Author: H. Peter Anvin Date: Thu Mar 10 01:24:48 2005 +0000 1.0.3 released, next version is 1.0.4 commit 173dee11a099c9982095ed8dce91d306888e0a05 Author: H. Peter Anvin Date: Thu Mar 10 01:20:24 2005 +0000 Barf instead of trying to fix things if __KLIBC__ not defined. It's a serious error and needs to be caught. commit 5704d1429ada3f6fa247575629f5036b78a167f7 Author: H. Peter Anvin Date: Thu Mar 10 01:20:24 2005 +0000 1.0.2 released, next version is 1.0.3 commit b39c8c1c074fb0ec8fe999b426ff2fe87e4098e5 Author: H. Peter Anvin Date: Thu Mar 10 01:14:50 2005 +0000 Define __KLIBC__= and __KLIBC_MINOR__= commit 8f81955ba3952de4e57a4efa6f4b30895610d3f9 Author: H. Peter Anvin Date: Thu Mar 10 01:14:50 2005 +0000 1.0.1 released, next version is 1.0.2 commit fc87a07637ca70152ef638a86422f5c99d1dd5ed Author: H. Peter Anvin Date: Thu Mar 10 01:11:42 2005 +0000 qw ( ) to qw( ) commit ed2cef436451e5d8ed3826c4ac048118250c2ddc Author: H. Peter Anvin Date: Thu Mar 10 01:11:42 2005 +0000 Correct the case when variables are empty commit 3a21c6181f18c818c7c2028e26c5b4a6d74148ba Author: H. Peter Anvin Date: Tue Mar 8 19:00:40 2005 +0000 New 3-part version number commit 71333534fe585f00da5474a2007382fc6880253b Author: H. Peter Anvin Date: Tue Mar 8 18:50:56 2005 +0000 1.0 released, next version is 1.1 commit 303fc63afe9bda1e312f6dda2bb329e5ce6ee22a Author: H. Peter Anvin Date: Mon Mar 7 21:44:49 2005 +0000 Bump the version number to 1.0 commit 3ba8e6f25aa2d8d05572ac61c19a4c81bb1b839b Author: H. Peter Anvin Date: Mon Mar 7 21:44:49 2005 +0000 Clean up the handing of object files with -c commit 6fe789902ee805b9e43c4cc37a5f372404e75c1f Author: H. Peter Anvin Date: Mon Mar 7 20:04:21 2005 +0000 0.217 released, next version is 0.218 commit 0037d1bc0deaf7daec3778496656cb04b4e4b9d0 Author: H. Peter Anvin Date: Mon Mar 7 20:01:40 2005 +0000 Fix -print-klibc and --version commit fc6db92a17568b83c57eb191199eea50df394e28 Author: H. Peter Anvin Date: Mon Mar 7 20:01:40 2005 +0000 0.216 released, next version is 0.217 commit 1a955fa30b5ee0b8dcc47ed4741a04fafc147699 Author: H. Peter Anvin Date: Mon Mar 7 19:55:33 2005 +0000 Better handling of -M options, and handle -x option commit ed93e82c2c7a080e99c07487396f21fe3572c566 Author: H. Peter Anvin Date: Mon Mar 7 19:55:33 2005 +0000 More work on handling -M options commit 858e570353758969a04ed5b9e01871732a42e7dc Author: H. Peter Anvin Date: Mon Mar 7 18:18:57 2005 +0000 0.215 released, next version is 0.216 commit 359b03755262459481eb796502b8155ad24febfe Author: H. Peter Anvin Date: Sun Mar 6 19:38:38 2005 +0000 Support -l/-L, -M*, and -print-klibc-* options in klcc commit d79fa90921dca3428c89d28b18ea9a1019a69d6a Author: H. Peter Anvin Date: Sun Mar 6 19:38:38 2005 +0000 0.214 released, next version is 0.215 commit 96590039d93da05f05a56096713a8d2335d610e0 Author: H. Peter Anvin Date: Sun Mar 6 07:32:21 2005 +0000 Changes for SPARC; we genuinely need libgcc on some arches commit 2f239f2468a063026680630f99ec5d799df4da46 Author: H. Peter Anvin Date: Sun Mar 6 07:32:21 2005 +0000 Specify 32 bits, in case we're building with a 64-bit compiler commit cfbac593bdc06dba0260eb6d98f5c91b44520c1b Author: H. Peter Anvin Date: Sat Mar 5 20:34:54 2005 +0000 0.213 released, next version is 0.214 commit bc4948e34db88f0378a54064014cce80b746e882 Author: H. Peter Anvin Date: Sat Mar 5 20:03:31 2005 +0000 __GNUC_MAJOR__ -> __GNUC__ commit 61943f414571abad90f4cc2191bc15fd960644ed Author: H. Peter Anvin Date: Sat Mar 5 20:03:31 2005 +0000 0.212 released, next version is 0.213 commit b821e339f10c4048618779908bfa4b68fa7b97a1 Author: H. Peter Anvin Date: Fri Mar 4 19:35:24 2005 +0000 We need the scsi/ directory tree, too commit c41fd0ae6902df06ed3489c4ee96c8e373b348de Author: H. Peter Anvin Date: Fri Mar 4 19:35:24 2005 +0000 Disable the use of libgcc; klcc doesn't provide it, and some architectures can't use the standard libgcc for klibc-compiled code. It would be best if we didn't need it, but smoke out any problems. commit 248a6473cf1f361479524792419884ebe0b8f6a2 Author: Olaf Hering Date: Fri Mar 4 13:56:30 2005 +0000 include crt0i.S with relative path commit 841326b0c47cea3b5b5ae4e859a9066196dd60ee Author: H. Peter Anvin Date: Fri Mar 4 07:57:33 2005 +0000 0.211 released, next version is 0.212 commit f700cd60fccdc9f72fd1e57b342bea550bb0dc7f Author: H. Peter Anvin Date: Fri Mar 4 07:48:58 2005 +0000 We can't get rid of non-rt_sig*() just yet commit 98385131f1e546f2a5f1bf259481bed39891fe81 Author: H. Peter Anvin Date: Fri Mar 4 07:48:58 2005 +0000 REGPARM -> _REGPARM commit cb4301281b0156dc51a7120ec67574e072ccb9a1 Author: H. Peter Anvin Date: Fri Mar 4 07:42:31 2005 +0000 - Always use the rt_* versions of the signal system calls, just in case our sigset_t differs from the kernel; - Fix the handling of regparm on i386; enable -fomit-frame-pointer. commit 4044492c86f710033100bd31b562719830cfed57 Author: H. Peter Anvin Date: Fri Mar 4 07:26:12 2005 +0000 0.210 released, next version is 0.211 commit e246a8ac70c105abefcc9fba8ede418d99ec5c13 Author: H. Peter Anvin Date: Fri Mar 4 00:23:17 2005 +0000 Add some definitions that the stock kernel hides commit 7e891e477b1dc4f56b808fa43e301bb24a0b3442 Author: H. Peter Anvin Date: Fri Mar 4 00:23:17 2005 +0000 0.209 released, next version is 0.210 commit c26f54c9381964e6649c6770251fe329e7e2d870 Author: H. Peter Anvin Date: Thu Mar 3 23:32:23 2005 +0000 Use loops; be more tolerant of missing trees commit 12e51f884a755375f23faba5592bf1bd3719d27e Author: H. Peter Anvin Date: Thu Mar 3 23:32:23 2005 +0000 0.208 released, next version is 0.209 commit 927b8ed555602d2e5ae1faea2d463ac8ab569162 Author: H. Peter Anvin Date: Thu Mar 3 23:30:03 2005 +0000 Fix commit 5c54959c65a5a2e1b6fee650fd1565f3e3d44b64 Author: H. Peter Anvin Date: Thu Mar 3 23:30:03 2005 +0000 Fix open() on 32-bit architectures. commit 5651723e3af6d6b7d99e987e3dab8609789892db Author: H. Peter Anvin Date: Thu Mar 3 21:46:22 2005 +0000 Handle gcc 4 commit 4306c4ce7488a87d77e099247dfe6c1b1065ccb0 Author: H. Peter Anvin Date: Thu Mar 3 21:12:10 2005 +0000 0.207 released, next version is 0.208 commit 5786c425ab975c45d04ba36c5db3d30f67593c06 Author: H. Peter Anvin Date: Thu Mar 3 21:05:34 2005 +0000 For the time being, include libc.so and interp.o in the main package. commit 6191107655bdf46b83f72d6cb52ec2fa208c3248 Author: H. Peter Anvin Date: Thu Mar 3 21:05:34 2005 +0000 0.206 released, next version is 0.207 commit 32f3670c1655369d88bcbb723e54cdcc4b7c6732 Author: H. Peter Anvin Date: Thu Mar 3 20:40:39 2005 +0000 Split CROSS and KCROSS; x86-64 needs asm-i386 in addition to asm-x86_64; some architectures need to reference their own asm-$(ARCH) by name. commit 251cabd48c8188736f3a6f5346646c221163132f Author: H. Peter Anvin Date: Thu Mar 3 20:40:39 2005 +0000 Add missing %{buildroot} commit 0f4ae64b266ccd03bd73bd1256f13c131e33b33a Author: H. Peter Anvin Date: Thu Mar 3 20:33:04 2005 +0000 Fix paths. commit 1987cc32fca5d2bcbe753f59f1a1c61a2ef9c5ed Author: H. Peter Anvin Date: Thu Mar 3 20:25:03 2005 +0000 Split the runtime and devel out into separate rpms. commit 11690dd91a78ec653dfd8e5753e49587950715dc Author: H. Peter Anvin Date: Thu Mar 3 01:22:17 2005 +0000 0.205 released, next version is 0.206 commit 6bc1d57e8931c5f0013c6d7e330347bda9bd775f Author: H. Peter Anvin Date: Thu Mar 3 01:07:17 2005 +0000 The x86-64 headers define NSIG to be 32, but it's actually 64 commit 1fc01c98bf8b759b7185e9580ef6dc2215d0283a Author: H. Peter Anvin Date: Thu Mar 3 01:07:17 2005 +0000 Try again to handle SIGRTMIN, SIGRTMAX sanely commit 5449a015d2812d5c86221172420ede57a37bea22 Author: H. Peter Anvin Date: Thu Mar 3 01:03:35 2005 +0000 Hide real-time signals from userspace if they don't actually exist. commit 90db70e75ecdfed9d70c24097153f5d3c5589a99 Author: H. Peter Anvin Date: Thu Mar 3 01:01:56 2005 +0000 Try to keep NSIG and _NSIG consistent. commit 83764972b357f1772e45d6162028ff4840fb2893 Author: H. Peter Anvin Date: Thu Mar 3 00:55:38 2005 +0000 Portability fixes from Erik van Konijnenburg commit 474c2c8d38d42b6fd1f5d5a5ccd05daf05647a5e Author: H. Peter Anvin Date: Thu Mar 3 00:49:53 2005 +0000 Handle -include, don't lose object files. commit 8a17e68b385cc561d8d38e082ef8a2dcdcb17228 Author: H. Peter Anvin Date: Wed Mar 2 20:34:36 2005 +0000 0.204 released, next version is 0.205 commit 95c02e6cc18321be87ded7d0598582f77fb1a0d9 Author: H. Peter Anvin Date: Wed Mar 2 20:25:33 2005 +0000 Handle conjoined and disjoint versions of -D -U -I commit 83fdecab8b21e009b617eb349bfe85420316feff Author: H. Peter Anvin Date: Wed Mar 2 20:25:33 2005 +0000 0.203 released, next version is 0.204 commit b8ef48ca015704ecd95bcb5a8b491e76ef5723d5 Author: H. Peter Anvin Date: Wed Mar 2 02:36:30 2005 +0000 Handle -D -U and -I options (Erik van Konijnenburg) We use 'obj' for linker files, not 'none' Pass -c -S and -E options to gcc commit 8301e27da87ae0f877ea121b72abb58c41583eb0 Author: H. Peter Anvin Date: Wed Mar 2 02:36:30 2005 +0000 0.202 released, next version is 0.203 commit f06ad24dca2738a89f2ea71fbd5238d0ba8bd4ab Author: H. Peter Anvin Date: Wed Mar 2 02:26:12 2005 +0000 Actually compile using the correct language (-x option). commit 292f4232fd43e055644f21252a08b65d5f785ac8 Author: H. Peter Anvin Date: Wed Mar 2 02:26:12 2005 +0000 0.201 released, next version is 0.202 commit 34b124182097bf49a1edac54a31bf7ece7384555 Author: H. Peter Anvin Date: Wed Mar 2 02:21:59 2005 +0000 Use -s to strip. commit 6e454c398bdfde87f647a20eaf01301a89e82474 Author: H. Peter Anvin Date: Wed Mar 2 02:21:59 2005 +0000 Correction: SHAREDFLAGS is only used to build klibc.so itself! commit e94b6328791517b2ea67748c85da3ff751210123 Author: H. Peter Anvin Date: Wed Mar 2 02:13:06 2005 +0000 %{_libdir} is not necessarily /usr/lib on 64-bit platforms, for example; however, we have our own way of dealing with that. commit 25a973a8b397a5141b964a88bc294ce2cdc6bc7d Author: H. Peter Anvin Date: Wed Mar 2 02:05:25 2005 +0000 Pass LDFLAGS and SHAREDFLAGS to ld commit c05f7ec304696beedd76ae1256131de7e856b7e1 Author: H. Peter Anvin Date: Wed Mar 2 01:16:26 2005 +0000 0.200 released, next version is 0.201 commit 738312f472c52c49a1a5b1f590c690811fe9013b Author: H. Peter Anvin Date: Wed Mar 2 00:49:14 2005 +0000 Add the crosscompilation prefix to the install path commit 3c6dac73404e96ff96a9b5c7020b267e34819f38 Author: H. Peter Anvin Date: Wed Mar 2 00:49:14 2005 +0000 Install the correct header file directory...! commit 1f2db011c9475ace92df1cbe40b469caa458085c Author: H. Peter Anvin Date: Wed Mar 2 00:42:47 2005 +0000 WTF didn't the previous attempt work? Trying something different... commit 24d6c1a10226c40bdbb05c4275c71f4202a66a33 Author: H. Peter Anvin Date: Wed Mar 2 00:36:22 2005 +0000 Avoid confusion w.r.t. %docdir commit fcd2a4ce2eb269fbbeaabc1fba5245c365cef694 Author: H. Peter Anvin Date: Wed Mar 2 00:29:45 2005 +0000 Try again for correct handling of the docdirs commit a152e8a67ffb5c0087bd3742003b8afb3149c41c Author: H. Peter Anvin Date: Wed Mar 2 00:23:53 2005 +0000 More fixing of paths. commit 146eff7ba353b1b3f255cf5ae619d91ab8fd3cc8 Author: H. Peter Anvin Date: Wed Mar 2 00:04:50 2005 +0000 Add missing continuation slash commit 07147afd5462de3e6199383ebafcf46b82b4e9e1 Author: H. Peter Anvin Date: Wed Mar 2 00:04:16 2005 +0000 Change set -e to set -xe in loop commit 6733628d76351b7187e5bfb3867333b5ec192db2 Author: H. Peter Anvin Date: Tue Mar 1 23:58:06 2005 +0000 Fix handling of compressed man pages commit 3a8fb0976e5da5814619efab61e1d696740ad04b Author: H. Peter Anvin Date: Tue Mar 1 23:57:00 2005 +0000 Copy only specific include directories. commit 45b9e97a1d7c1f1acf9a916e718c3f0f238de9d6 Author: H. Peter Anvin Date: Tue Mar 1 23:45:55 2005 +0000 $ -> % in a few places commit 3970aa25ab589a8378869f0a8df8f21a51e32d7b Author: H. Peter Anvin Date: Tue Mar 1 23:37:31 2005 +0000 Add missing %{buildroot} macros commit d51e5447d412e0ee4c41bd5af7a3bf0439f6aeda Author: H. Peter Anvin Date: Tue Mar 1 23:29:57 2005 +0000 Try to get the docdir stuff right commit 5a019a7a1ba887051fa5654cc01d8ac263b96774 Author: H. Peter Anvin Date: Tue Mar 1 23:23:55 2005 +0000 Don't include the config/ directory; make sure we copy files and not just links. commit 94a9ca1599495697490af19b26834d8d48a9c49c Author: H. Peter Anvin Date: Tue Mar 1 23:16:39 2005 +0000 Require klibc = klibc-utils commit e2033d71455eec65c2ca2f55b76b7bb108f73b46 Author: H. Peter Anvin Date: Tue Mar 1 23:15:45 2005 +0000 klibc-utils require klibc commit a82484b0cd90b1f17b6cc2b608a6e6c71cbccb26 Author: H. Peter Anvin Date: Tue Mar 1 23:11:24 2005 +0000 Set INSTALLROOT commit d6676670735196c05036271deda562127ba1c9f6 Author: H. Peter Anvin Date: Tue Mar 1 23:07:10 2005 +0000 Shouldn't need to do make prepare... commit d874d1d93febb2d4f8763e7f1ec436c9c985e440 Author: H. Peter Anvin Date: Tue Mar 1 23:04:24 2005 +0000 cp -as -> cp -dRs commit ad7a556044feeda891639a85072b41c911ce6f16 Author: H. Peter Anvin Date: Tue Mar 1 23:01:53 2005 +0000 kernel-source package is obsolete commit 67a5ec24849f8933bbc3f005615675ea38e3ff21 Author: H. Peter Anvin Date: Tue Mar 1 22:56:58 2005 +0000 Man page for klcc commit 51a41c4ba553f5477e68d98029db5dd29116daca Author: H. Peter Anvin Date: Tue Mar 1 22:36:42 2005 +0000 Make "make install" do the same thing; try to change the spec file accordingly. commit f3d0a2e2b2bb04fefe53e96e9e6b2a000db8de60 Author: H. Peter Anvin Date: Tue Mar 1 22:10:22 2005 +0000 Better handling of strip in klcc commit 95abd4d1cc5a67505bc1f10e3ba7bb02c3f20a2a Author: H. Peter Anvin Date: Tue Mar 1 22:01:39 2005 +0000 makeklcc -> makeklcc.pl; export CROSS and use it commit ae7493a1882bc02f6100252942d9ec5d2531d925 Author: H. Peter Anvin Date: Tue Mar 1 21:53:06 2005 +0000 Beginnings of a proper "make install" commit 9d2b5041a997637184a81c31e75b33e4eb328de7 Author: H. Peter Anvin Date: Tue Mar 1 21:39:30 2005 +0000 Support --help commit 852369bf3ebbf3e1e603d1c4f24614ef2188c602 Author: H. Peter Anvin Date: Tue Mar 1 01:52:30 2005 +0000 Use the new handling of bitsize commit 26ddf61e979df6a3d3be69d0fd52e940a99cef14 Author: H. Peter Anvin Date: Mon Feb 28 23:29:49 2005 +0000 First cut at automatic generation of klcc commit 1b2ad46cb890741cf8bdb3ecf32651a38ac33767 Author: H. Peter Anvin Date: Mon Feb 28 23:28:15 2005 +0000 Remove -DBITSIZE define commit 8ea1828b0d40b18e27e588f02869057c7d56ce41 Author: H. Peter Anvin Date: Mon Feb 28 22:08:43 2005 +0000 Support compiling klibc for i386 on an x86-64 system without needing a bunch of extra futz commit c219f528550a4b8f0695f0138075e24e8224bf93 Author: H. Peter Anvin Date: Mon Feb 28 22:06:57 2005 +0000 Make us something that will compile properly commit 3e1ca0d88ca80a84b80cc9d8362d4c47c0b791a0 Author: H. Peter Anvin Date: Mon Feb 28 05:09:25 2005 +0000 More work... commit 59b40cf30fdeeca69a09d4c27657c1e11a24ef4d Author: H. Peter Anvin Date: Mon Feb 28 04:14:17 2005 +0000 Handle the optimization options. commit 12984597637e055379ba94164db26c8c0499857a Author: H. Peter Anvin Date: Sun Feb 27 23:30:06 2005 +0000 More work on klcc commit 2e8abf58f0317055be6a099543d9616dfa681670 Author: H. Peter Anvin Date: Sun Feb 27 23:15:36 2005 +0000 Make it possible to include zlib in klibc; however, this makes it a lot larger. commit 2d039b0a6ea8ccc9d0b08c797d39a0f219a1f397 Author: H. Peter Anvin Date: Sun Feb 27 23:10:00 2005 +0000 The beginnings of a klibc gcc wrapper commit 6baf848f1a91c9b7642f4bdfed6c026e26e26560 Author: H. Peter Anvin Date: Tue Feb 22 23:06:46 2005 +0000 0.199 released, next version is 0.200 commit a782bfd442113d46f17c56a5ad184f8f3da2d553 Author: Olaf Hering Date: Sun Feb 20 20:49:01 2005 +0000 A utils/cramfs_fs.h A utils/minix_fs.h A utils/romfs_fs.h remove the need for 3 linux headers commit fbcc90ec6d5e7a66164155218ca0a3decf3d9b45 Author: Olaf Hering Date: Sun Feb 20 20:49:01 2005 +0000 klibc/ is not in the include pathh anymore, so use a relative include to sparc/crt0i.S commit 35d01af8f90eac78a10a63e33bc102ed9ecf070c Author: Olaf Hering Date: Sun Feb 20 20:43:30 2005 +0000 add include/arch/parisc/klibc/archsetjmp.h fix klibc/arch/parisc/setjmp.S, store %r27 instead of %dp fix klibc/arch/parisc/sysstub.ph compilation, .type is not needed at least with ld version 2.15.94 20050220 and gcc-3_4-branch commit 750bdde660d9c3e6147e51d238122db7582d88e1 Author: Olaf Hering Date: Thu Feb 17 18:34:56 2005 +0000 memmem did not handle string size of 1 at all. Just check for 1 and use a different way of searching. also, run Lindent commit e1dbc85f8f56d741745bdb5d4f0d9029f1a6ef60 Author: Olaf Hering Date: Mon Feb 14 13:46:05 2005 +0000 On Mon, Feb 14, Jan Beulich wrote: >Is there a requirement for the .align keyword? vfork.S doesnt have one. Not a requirement, but it's desirable. The default (text) section alignment is 16, but it is generally recommended (for performance reasons) to align procedures of non-neglectable size to at least 32-byte boundaries. commit c9bb4d46eda681423348f8b2d1a18da74f2dc6bc Author: Olaf Hering Date: Mon Feb 14 13:08:52 2005 +0000 new ia64 assembler requires the .proc keyword, it was missing in setjmp.S vfork had the function name missing in .endp commit bb9c7e9714b4c81d36fd069f7d4e846b1a7dc1a1 Author: Olaf Hering Date: Sun Feb 13 16:13:22 2005 +0000 add ext2_fs.h for fstype and use it, instead of the kernel header commit 4a4f92ad15c03db15575a644218d1073183794ec Author: Olaf Hering Date: Sat Feb 12 21:03:28 2005 +0000 time_stamp is time_t commit afc172362c4e14f333bf04dfd0005082f8d67bd6 Author: Olaf Hering Date: Sat Feb 12 17:55:39 2005 +0000 add an option 'DEBUG=y' to make, to build instripped debug binaries commit 400058dd2205a91792b7d4b4558cdc90343a4f90 Author: Olaf Hering Date: Sat Feb 12 17:43:08 2005 +0000 improve dependencies in ash and utils Makefile to avoid spurious rebuilds From Harald Dunkel commit 80fe5d290304b0ba7ea3c2b93292d8461aea953a Author: Olaf Hering Date: Sat Feb 12 13:48:32 2005 +0000 remove unused variable nn commit 42bc171d481526314db51b1dbbdcfef6f4783980 Author: Olaf Hering Date: Fri Feb 11 10:05:46 2005 +0000 -fomit-frame-pointer is a no-op when CAN_DEBUG_WITHOUT_FP is defined in gcc. This is true for alpha, arm, ia64, m32r, mips, ppc, s390 and sparc commit 0494f1568ca61ec8646d64e0b66ba7c9b5f0fcc9 Author: H. Peter Anvin Date: Thu Jan 27 21:23:31 2005 +0000 0.198 released, next version is 0.199 commit efb8d967466928c6f2112d2c26fb036b5787f270 Author: Olaf Hering Date: Sat Jan 22 00:22:52 2005 +0000 Use perl instead of sed so we can use whitespace matching commit 08202d1509bb1086e7b1e10ff7920637b73c17fd Author: Olaf Hering Date: Sat Jan 22 00:22:52 2005 +0000 allow ash debug via trace file recognize enviroment variable KLIBC_ASH_DEBUGTRACE commit a98623ea573862d3e44538be06bc643ce37d92ca Author: Olaf Hering Date: Fri Jan 21 23:57:41 2005 +0000 va_args bug in exverror: a va_list can not be used twice commit 5456b586519962101434e83ddc684f0195f9a3c6 Author: H. Peter Anvin Date: Fri Jan 21 22:10:20 2005 +0000 0.197 released, next version is 0.198 commit 5c524dc5b640ee330df3ad1f1784e8e0adca01c1 Author: Olaf Hering Date: Fri Jan 21 19:51:36 2005 +0000 shared ipconfig and nfsmount depends on $(CRTSHARED) add interp.o to all target commit 039b0a7c37a0916adffbc1a5447dc6796b309cbf Author: Olaf Hering Date: Fri Jan 21 19:51:36 2005 +0000 The klibc strncat doesnt behave like described in the man page. It doesnt terminate the string if size < strlen(src). It doesnt make dst longer than size. #include #include int main(void) { unsigned char olh[42]; memset(olh, 'A', sizeof(olh)); sprintf(olh, "abc"); fprintf(stderr, "olh: '%s'\n", olh); bar(olh, "123456789", 7); fprintf(stderr, "olh: '%s'\n", olh); return 0; } olh: 'abc' olh: 'abc1234AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' commit 51d7fe38246ef1e99f0a8f847d6f3f33786bb580 Author: H. Peter Anvin Date: Thu Jan 20 23:01:03 2005 +0000 Undo bum checkin commit afb42d4b3cdad5b7ade07450dafc35c8f0f5eb8f Author: H. Peter Anvin Date: Thu Jan 20 22:58:41 2005 +0000 Make output match RFC3548 commit 28c4cc243d9828c194c32adb566f1b12f4a788d2 Author: H. Peter Anvin Date: Tue Jan 18 00:45:33 2005 +0000 Don't set errno on EINTR commit f01c683cc6bd5d8ca283e7eede894a10f9bb3fee Author: H. Peter Anvin Date: Sat Jan 8 03:17:19 2005 +0000 0.196 released, next version is 0.197 commit 2cba991ac1f593ebb68782045c0ddb546e1134c0 Author: H. Peter Anvin Date: Sat Jan 8 03:02:08 2005 +0000 Fix warnings commit a0293189cb80ab509937a7f07e3342535dea8076 Author: H. Peter Anvin Date: Sat Jan 8 03:02:08 2005 +0000 Thayne Harbaugh: - memchr() needs to increment pointer or it's just a busy loop (unless c matches the first character in s) - add memrchr.c hpa: Add memrchr() to commit 00cc52ccaae41d902c6f741bae0842b507066d75 Author: H. Peter Anvin Date: Sat Jan 8 02:58:05 2005 +0000 0.195 released, next version is 0.196 commit 530903748615256cd88613358064c536396010c4 Author: H. Peter Anvin Date: Sat Jan 8 02:55:15 2005 +0000 Thayne Harbaugh: >* The check_path() calls check for "/root" and "/old_root" - I believe >> that should be "/root" and "/root/old_root". >> >> * chdir("/") is recommended after pivot_root() >> >> * init_argv[0] isn't set properly to the basename pointed to by char *s >> - this fix also eliminates six lines of unecessary code and improves >> readability by using get_arg(). The get_arg() simplification causes "int i" to be unused. commit ba9ac5610d9427f382f1225df3e442927d5bb422 Author: H. Peter Anvin Date: Sat Jan 8 02:55:15 2005 +0000 Thayne Harbaugh: This is an updated patch that removes some of gratuitous debug statements I had in the last patch. This patch also fixes a bug where mount_nfs_root() stomps on the argv of init - it now creates a new "nfs_argv" to pass to nfsmount_main(). commit 8f38cd4ef0b21b00d2626236ae08f93ad6ae6260 Author: H. Peter Anvin Date: Sat Jan 8 02:51:14 2005 +0000 Thayne Harbaugh: kinit/nfsmount.c:mount_nfs_root() should use the bootpath specified by bootp/dhcp. If the "nfsroot" option is specified then it overrides the boot server bootpath and a message indicating the override is printed. commit 1091e2dcc0f61edb60eb688e9042b5b25712f390 Author: H. Peter Anvin Date: Sat Jan 8 02:48:37 2005 +0000 Thayne Harbaugh: kinit/do_mounts.c:name_to_dev_t() has an inverted logic problem and also doesn't return the correct value for "/dev/nfs". commit bb4340482438eda7c3abe719072bae018ae9697c Author: H. Peter Anvin Date: Sat Jan 8 02:44:30 2005 +0000 Thayne Harbaugh: There's an "if" statement in kinit.c:get_arg() that is too restrictive and prevents args from having arguments - which causes all get_arg() calls to fail. commit cbc31f9039e875c20b8086e40dfdcde92b0e27c3 Author: H. Peter Anvin Date: Sat Jan 8 02:41:06 2005 +0000 Make sure to advance optind (from Thayne Harbaugh) commit 9f40193bcea6656a0b73794f5f1eb28350f666e1 Author: H. Peter Anvin Date: Sat Jan 1 22:34:34 2005 +0000 Make it possible to compile on glibc by including constants missing from the glibc headers. commit 1ef5d3ff13c17547747448be5119b06299dba7ff Author: H. Peter Anvin Date: Tue Dec 14 01:39:52 2004 +0000 0.194 released, next version is 0.195 commit 7e54b08ee0b138130725d6411bb936ecd5a2ccb4 Author: H. Peter Anvin Date: Wed Dec 1 04:02:31 2004 +0000 Add \n "when required" commit 886767255d9df6b37669d61df42464d2fcf6291c Author: H. Peter Anvin Date: Wed Dec 1 04:02:31 2004 +0000 Add M32R commit b3f61f9a9f1b036bdc36b15d9fa3a7dc53b3faaf Author: H. Peter Anvin Date: Tue Nov 30 23:18:37 2004 +0000 0.193 released, next version is 0.194 commit 2fdb2f4f38c576ab2be9e9a4920271440048de8a Author: H. Peter Anvin Date: Tue Nov 30 23:11:02 2004 +0000 Remove CRIS-specific stuff from M32R code commit a359e1fc1c63abafcfc81f835d8ff36257359dc9 Author: H. Peter Anvin Date: Tue Nov 30 23:11:02 2004 +0000 Include files for m32r architecture commit 3b6eb54a1e31bf5b130890bec356822b4208a884 Author: H. Peter Anvin Date: Tue Nov 30 03:14:06 2004 +0000 First steps toward an M32R port. commit 889777ede80c25952aa862a2f4214cd48eafc8e6 Author: H. Peter Anvin Date: Mon Nov 1 20:43:50 2004 +0000 0.192 released, next version is 0.193 commit 648abf248cbaad9958b53dddcfd3f600d105a6a1 Author: H. Peter Anvin Date: Sun Oct 31 05:55:17 2004 +0000 Fix shared libraries on x86-64. commit e380cc91bc7178e4d85b85e56ad32927d2786cf8 Author: H. Peter Anvin Date: Sun Oct 31 05:55:17 2004 +0000 Break apart the various strspn functions commit 0d0c29027b0a55a1c3fc8bf6d71a73e1192dffbe Author: H. Peter Anvin Date: Sun Oct 31 05:44:07 2004 +0000 Use an array of char instead of a bitmask; the bitmask isn't worth the trouble. commit 3330552cd6a2c1e1aa5cd0be1ae55a15ee188a5d Author: H. Peter Anvin Date: Tue Oct 26 07:24:12 2004 +0000 More mount flags; a few more options for syslog; Lots of work on kinit but still very much a work in progress commit 7e8b9288b5a338ee2064b5c2e071b078c7f52e60 Author: H. Peter Anvin Date: Tue Oct 26 02:33:06 2004 +0000 0.191 released, next version is 0.192 commit b04218488913fba57fe4037ee73af5da016c4616 Author: Olaf Hering Date: Sun Oct 24 17:02:54 2004 +0000 Add uname(1), from Thayne Harbaugh commit 5e8a8260a903e83eeb3b4a8ba3329cae163b41cd Author: Olaf Hering Date: Sun Oct 24 17:02:54 2004 +0000 call makeerrlist.pl with -q option, prevents output of error strings. if the package build fails, the script that checks the log gets confused because it thinks the buildhost has a diskspace of nfs problem commit 5ffd28581ad18027b892e8830552893f3e1fc7d2 Author: Olaf Hering Date: Sat Oct 23 19:13:51 2004 +0000 fix gcc4 error: onexit.c:10: error: static declaration of '__atexit_list' follows non-static declaration atexit.h:16: error: previous declaration of '__atexit_list' was here commit 8d74077a5d1ae76494fe509dc90eb8b4c858f324 Author: Olaf Hering Date: Sat Oct 23 13:13:26 2004 +0000 use klibc asprintf commit 382490a78cbaa6df422932c17a19f584c84de4ae Author: Olaf Hering Date: Sat Oct 23 13:11:19 2004 +0000 comparsion between signed and unsigned in for() loop commit 861e6a5a8679273fbcdf85b0aea0366989feb686 Author: Olaf Hering Date: Sat Oct 23 13:10:35 2004 +0000 No newline at end of file commit 2303ff0416706151f6315309751b7cafcbe941ef Author: H. Peter Anvin Date: Fri Oct 22 22:33:47 2004 +0000 0.190 released, next version is 0.191 commit fef33f265ac6f9110ab9922c636624870a078481 Author: H. Peter Anvin Date: Thu Oct 21 23:02:35 2004 +0000 Fix off-by-one error in (v)asprintf() commit b4c9bd471a0c736e15bb576314808d7495000352 Author: H. Peter Anvin Date: Thu Oct 21 23:02:35 2004 +0000 Be extra picky with the casts. commit 640269d766c898e180c539bd5cb2d0abb1ba68c7 Author: H. Peter Anvin Date: Thu Oct 21 22:15:19 2004 +0000 0.189 released, next version is 0.190 commit 5c40e30299c197150e688a623573f2e0383022c9 Author: H. Peter Anvin Date: Thu Oct 21 22:12:25 2004 +0000 Add flags for glibc compatibility commit f7d1ff5c2b889b94c39f48f151069942c81514f1 Author: H. Peter Anvin Date: Thu Oct 21 22:12:25 2004 +0000 Prototype for system() commit 467478d00106467bca42cbc57449436a695b0f64 Author: H. Peter Anvin Date: Thu Oct 21 22:11:57 2004 +0000 Prototypes for [v]asprintf commit 4b632a20b72f6879392501d248027e1d93d78b24 Author: H. Peter Anvin Date: Thu Oct 21 06:48:16 2004 +0000 Remove old-style exclusion rule that can be handled by commit 7d2a5b20a28cbcc50868ce14c7ada79eaf7f71ef Author: H. Peter Anvin Date: Tue Oct 19 18:33:17 2004 +0000 0.188 released, next version is 0.189 commit 972fe3498e5605cc9304709106e6f7d97ad14bc6 Author: H. Peter Anvin Date: Tue Oct 19 18:26:40 2004 +0000 sparc64 almost certainly has been fixed, but it hasn't been tested. commit 2d6c7287e73216c1cc549862ee2ef0c07a0e7617 Author: H. Peter Anvin Date: Tue Oct 19 18:26:40 2004 +0000 Fixes for powerpc64 commit 2241444653999239541fe1b769488f43a3549e43 Author: H. Peter Anvin Date: Tue Oct 19 18:21:17 2004 +0000 Add insmod commit 937dfe1347d4e679baeadc79d822b9b2d41633fa Author: Olaf Hering Date: Tue Oct 19 18:16:48 2004 +0000 fwrite takes const void *ptr, not void *ptr commit 4c5aa7f3664cba3d80af9d4f75576f10c9f7fc6f Author: H. Peter Anvin Date: Tue Oct 19 06:02:51 2004 +0000 0.187 released, next version is 0.188 commit f488338a1f768867d2a4a5ba5616a80fa176173f Author: H. Peter Anvin Date: Mon Oct 18 19:12:46 2004 +0000 Add comment commit cfb20568aa92c2efd0ffd8c5fe189332ccc6cdc0 Author: H. Peter Anvin Date: Mon Oct 18 19:12:46 2004 +0000 Remove bogus __clone() definition commit b3b06b8f923ad6d4a02ecd867e0468509825b200 Author: H. Peter Anvin Date: Mon Oct 18 18:48:50 2004 +0000 Clean up __clone() emulation for ia64 commit cf2161e4899c9c0b4381a31c9ac104b47a7c7332 Author: H. Peter Anvin Date: Mon Oct 18 18:45:45 2004 +0000 Add where __clone() is defined commit bb41f7f6db350a7e95679e7d3256cc63ecca1504 Author: Olaf Hering Date: Mon Oct 18 18:39:57 2004 +0000 use sys/syscall.h instead of syscommon.h commit 41d51e1723f2b83714a27a7f553a796e51c36d3f Author: Olaf Hering Date: Mon Oct 18 17:42:03 2004 +0000 fix compile on i386, add __cdecl to onsig() declaration commit 7bcffac5ee5dea7e28fd9ad94b63a856fd8b7811 Author: H. Peter Anvin Date: Mon Oct 18 14:29:24 2004 +0000 Fix the return value from sbrk() commit eb52dbe51c05dddba16377dcde8796ed1af0d4da Author: H. Peter Anvin Date: Sun Oct 17 20:31:40 2004 +0000 0.186 released, next version is 0.187 commit e5509e2c8525f177f012b8be8f1262e73bc5981e Author: H. Peter Anvin Date: Sat Oct 16 23:24:41 2004 +0000 Fix handling of the real root commit cfe657d2e9ec2e718f0769265765495ddd76d0d1 Author: H. Peter Anvin Date: Sat Oct 16 23:24:41 2004 +0000 0.185 released, next version is 0.186 commit 2aea3652612b1d0b25d32f1b8697b85e29c562c2 Author: H. Peter Anvin Date: Thu Oct 14 04:33:12 2004 +0000 Fix total Makefile thinko. commit 5599e74d522cd95ed675d2125098687be7f94d07 Author: H. Peter Anvin Date: Thu Oct 14 04:33:12 2004 +0000 0.184 released, next version is 0.185 commit 0273771dbd5b35fc50d380b5bf96685032ba63d8 Author: H. Peter Anvin Date: Wed Oct 13 05:08:52 2004 +0000 Fix dependency generation for non-C files; support separate kernel source/obj directories commit fba2f3e52af6b7025a71312a5cfdca78550ee2af Author: H. Peter Anvin Date: Wed Oct 13 05:08:52 2004 +0000 0.183 released, next version is 0.184 commit 9b23403f6d6d01592a2a83a933e8524197e4d7e7 Author: H. Peter Anvin Date: Sun Oct 10 19:29:13 2004 +0000 Get rid of the last remaining use of the syscall macros (for _exit()); Optimize the ppc64 syscall stubs slightly commit 55d922ad05ada849d74b6fb01fd2edd5d756e8ee Author: H. Peter Anvin Date: Sun Oct 10 19:29:13 2004 +0000 0.182 released, next version is 0.183 commit a2fb0779412a620260cf36df58c8114ffdf740e1 Author: Olaf Hering Date: Sun Oct 10 17:17:46 2004 +0000 add "rw" and "ro" option to nfsmount commit 26b076f667bcb9803cd6ec3509ef6e0167009876 Author: Olaf Hering Date: Sun Oct 10 17:17:46 2004 +0000 add cat command to PROGS commit 7025a00f6f5f0ab7d9244a9218b951df663502b0 Author: Olaf Hering Date: Sun Oct 10 17:17:08 2004 +0000 add changes for klibc compilation commit 604444f8f1234bbb402c64b4569442abb8c42503 Author: Olaf Hering Date: Sun Oct 10 17:15:52 2004 +0000 add cat(1) command $NetBSD: cat.c,v 1.43 2004/01/04 03:31:28 jschauma Exp $ commit 793e1356489e7562b401ef91bf0e4de1ee9711d9 Author: H. Peter Anvin Date: Sat Oct 9 23:40:52 2004 +0000 Make ppc64 work commit cf75e651a07b25289f8e8aae343ed8168bec4345 Author: H. Peter Anvin Date: Fri Oct 1 06:05:58 2004 +0000 CRIS is working commit 1d44c0e37c8e83ae63f4ac26280b8ff7e7e06437 Author: H. Peter Anvin Date: Fri Oct 1 05:29:47 2004 +0000 0.181 released, next version is 0.182 commit 628ef1a5c7fb6ccd5cbcbd783ecc84a15241197a Author: H. Peter Anvin Date: Mon Sep 27 22:49:02 2004 +0000 Fix strncpy() and strncat(). commit 52ae5dfd4153deae98b3e96e59d8913567285593 Author: H. Peter Anvin Date: Mon Sep 27 22:49:02 2004 +0000 Reorganize slightly for improved scheduling (= smaller size) commit d38d9a8a017afafde1f72fcd89cd6db64797e76b Author: H. Peter Anvin Date: Mon Sep 27 22:44:10 2004 +0000 Minor cleanups commit 310037f1a7c717da1982b3c5fc9453f7f1148436 Author: H. Peter Anvin Date: Mon Sep 27 21:28:46 2004 +0000 0.180 released, next version is 0.181 commit 0ce23d93118f49d47452382dd674e00e82863d9b Author: H. Peter Anvin Date: Mon Sep 27 21:22:57 2004 +0000 Add declaration of fork() accidentally deleted commit f8d198c94c48a255fd59c13b97196de9ffc88fbb Author: H. Peter Anvin Date: Mon Sep 27 21:22:57 2004 +0000 Add prototypes for clone(2) commit 9ffb315ff9e86630af48de98a42c901e1b9bcbee Author: H. Peter Anvin Date: Mon Sep 27 21:22:43 2004 +0000 Add memchr() commit 33bc527fcbe9253e005992e1b63a6d01f74de634 Author: H. Peter Anvin Date: Mon Sep 27 21:22:16 2004 +0000 Add linux/include2 to the paths, if it exists commit a7c481fd8516ba8ec038e41e7b2ac6ec811aefed Author: H. Peter Anvin Date: Mon Sep 27 21:09:14 2004 +0000 CRIS fixes commit f4a6392e5f1dbaece2551d4e2027baec263c8cb8 Author: H. Peter Anvin Date: Mon Sep 20 14:59:52 2004 +0000 0.179 released, next version is 0.180 commit 6cd8df5ab7d1ac6401a25997e4f87854f35c433c Author: Olaf Hering Date: Sun Sep 19 16:45:51 2004 +0000 elf*.h need commit 3cc72ffc2ff82ecf2403bde1b518fd0ef1292aca Author: Olaf Hering Date: Sun Sep 19 16:45:51 2004 +0000 -I$(KLIBSRC) is gone from main MCONFIG, fix include of socketcommon.h commit 647946f20ceba8e6bf874712c57881e2bae3deac Author: Olaf Hering Date: Sun Sep 19 13:48:35 2004 +0000 include/arch/ppc64/klibc/archstat.h: struct stat: match reality commit 7c16b115a16c72d4b7d9721f76cd521d0561ab4b Author: Olaf Hering Date: Sun Sep 19 13:11:32 2004 +0000 add an extra dependency to mknodes.sh call, or 2 threads may call the script commit 0b5df65f5f898b1aa893956e98df944c2fb32b02 Author: H. Peter Anvin Date: Thu Sep 16 20:25:32 2004 +0000 0.178 released, next version is 0.179 commit 8162685853777248894ec5da167bc0fb2bf3e909 Author: H. Peter Anvin Date: Thu Sep 16 00:15:11 2004 +0000 The environment variable is called KBUILD_VERBOSE, not V. commit 3261c85afaa771d2ead6bf5fd421aa84cd8f9a76 Author: H. Peter Anvin Date: Thu Sep 16 00:15:11 2004 +0000 0.177 released, next version is 0.178 commit cdd01285c18e3bea6058910804c640541f70f176 Author: H. Peter Anvin Date: Wed Sep 15 22:36:16 2004 +0000 Adjust for new location of include files commit 07c85386dfc855d262f45d72372a540e50a89f29 Author: H. Peter Anvin Date: Wed Sep 15 22:36:16 2004 +0000 Allow for quiet building, either by adding a -q option to the various Perl scripts, or by having a V=0 option in the environment. commit 16ea71ece88a7037ba3620cb057c6631b33ffdb6 Author: H. Peter Anvin Date: Wed Sep 15 22:08:24 2004 +0000 Add -q (quiet) option, or look for a V option in the environment commit 04295a58f9e7ab57ca9b17de712bbc6a9302552e Author: H. Peter Anvin Date: Wed Sep 15 21:42:06 2004 +0000 0.176 released, next version is 0.177 commit 6797ec7ebec7267de0cdd3ea15ec4b80580f121b Author: H. Peter Anvin Date: Wed Sep 15 21:36:58 2004 +0000 Reinstate the __cdecl for now, and specify the first kernel version (2.6.9-rc2) for which it's not needed. commit a313e3e988b4a24753681f4faa181d020dedf6ce Author: H. Peter Anvin Date: Wed Sep 15 21:36:58 2004 +0000 Replace ash with ash from NetBSD commit 05d7077e1304079d993bb4ed10dae4ca5ac943fa Author: H. Peter Anvin Date: Wed Sep 15 03:38:37 2004 +0000 0.175 released, next version is 0.176 commit 2f0930f0c0a64ce31aeb11283fd62132e801a0ce Author: H. Peter Anvin Date: Wed Sep 15 02:51:16 2004 +0000 Really ugly hack to make ppc64 work. commit 04fcd4bf246753758da62871c584b20e010873ed Author: H. Peter Anvin Date: Wed Sep 15 02:51:16 2004 +0000 0.174 released, next version is 0.175 commit 4d02057566c00e14ad01f9dc9b9c419ea6dca2fb Author: Olaf Hering Date: Tue Sep 14 14:24:48 2004 +0000 Support __le* and __be* types used in the most recent kernels commit 4e4060000cf68960402e05bd85b82b58596c94c8 Author: Olaf Hering Date: Tue Sep 14 14:24:48 2004 +0000 fix setjmp on ppc64 lmw and stmw operate only on the low-order bits. From Alan Modra. commit 339ff4a013b0bdd841460641496ca9f215209c4a Author: H. Peter Anvin Date: Sat Sep 11 23:46:22 2004 +0000 0.173 released, next version is 0.174 commit b84fb2a3784674dd5b0f17ce1ec35f9380edeaf7 Author: H. Peter Anvin Date: Thu Sep 2 22:13:23 2004 +0000 Add fchdir(), dirfd() Original patch by olh, modified by me to make dirfd() inline commit 70338277ef1fc3e40e13e203911ccdc9084301b9 Author: H. Peter Anvin Date: Thu Sep 2 22:13:23 2004 +0000 0.172 released, next version is 0.173 commit 96da4f968194ec65e5a5682c18659cb7ef93aa4b Author: H. Peter Anvin Date: Thu Sep 2 22:10:57 2004 +0000 Don't modify the length of an option - parse failure results. Bug fix from Olaf Hering. commit 65eb86d049b93a6d35d935bf33436c569667756f Author: H. Peter Anvin Date: Thu Sep 2 22:10:57 2004 +0000 Work around RH bug by avoiding __kernel_timer_t commit c9d57398f85100ff7d145c2c9090134426d62f55 Author: H. Peter Anvin Date: Wed Sep 1 03:31:27 2004 +0000 0.171 released, next version is 0.172 commit 3b36c76ee9fd4c337f61be465ff812b2661429a6 Author: H. Peter Anvin Date: Thu Aug 26 06:03:42 2004 +0000 Fix logic for static IP configuration (patch from olh, massaged by me) commit 3508680d900252436356c074fb6cf7e3f5787751 Author: H. Peter Anvin Date: Thu Aug 26 06:03:42 2004 +0000 Fix strncpy(), strncat() so they work according to the (braindead) specs; add [v]asprintf(), strlcpy(), strlcat() since they're good for security commit 4e2d20f0421b10096b5b554d36922ab08eaafcb4 Author: H. Peter Anvin Date: Thu Aug 26 01:50:20 2004 +0000 0.170 released, next version is 0.171 commit 05ede8b8d99004dd7a064c7889e5ac1811a83641 Author: H. Peter Anvin Date: Thu Aug 26 01:43:11 2004 +0000 Special handling of fcntl64 for mips32 commit 4f0adf2e9ce55bde9c845915d699d0692302075b Author: H. Peter Anvin Date: Thu Aug 26 01:43:11 2004 +0000 Simple test for fcntl() commit 4149ad1475cc52b29fc5149c9a4c53b760975b94 Author: H. Peter Anvin Date: Wed Aug 25 21:58:58 2004 +0000 0.169 released, next version is 0.170 commit 7bc93c4d2238731ba78642e79bd3bd6e1bd7151b Author: H. Peter Anvin Date: Mon Aug 23 18:08:14 2004 +0000 Use fcntl64() where applicable. The handling of "struct flock" is now broken on MIPS, but it was previously broken on all 32-bit arches. commit 11f88810b1fc78693d7cce6b5c22e92b99db4d52 Author: H. Peter Anvin Date: Mon Aug 23 18:08:14 2004 +0000 Specify a base address for ppc shared commit 768769fe78240811ec87b8fb6878024ffedb9c65 Author: H. Peter Anvin Date: Mon Aug 23 14:45:46 2004 +0000 Make Alpha build again commit 9553e169a6207466a64790821bf25579c64bb4ca Author: H. Peter Anvin Date: Mon Aug 23 14:37:58 2004 +0000 0.168 released, next version is 0.169 commit b2cbff841b0038f29d94e3d44da2daf4f1c04272 Author: H. Peter Anvin Date: Mon Aug 23 02:58:14 2004 +0000 Fix ppc64 handling of syscall error commit f22381d738025d532777e09dc54b150944862389 Author: H. Peter Anvin Date: Mon Aug 23 02:58:14 2004 +0000 0.167 released, next version is 0.168 commit acaec35ec347d6fc3587490391d8d5297e3ce95b Author: H. Peter Anvin Date: Fri Aug 20 21:25:09 2004 +0000 Fix ppc64 build commit f44734f4fc305235d1ce922ffaab0cff838c058f Author: H. Peter Anvin Date: Fri Aug 20 21:25:09 2004 +0000 0.166 released, next version is 0.167 commit f0bbf428454cb5072720275f0f4cd3973a407456 Author: H. Peter Anvin Date: Thu Aug 19 17:37:58 2004 +0000 Set sizes to 0, i.e. server's choice commit 1dfb70c27493402b0101b220c50aac4400d24679 Author: H. Peter Anvin Date: Thu Aug 19 17:37:58 2004 +0000 0.165 released, next version is 0.166 commit bd040c99247215d57614b36e5a2d8ea6bf28da65 Author: H. Peter Anvin Date: Thu Aug 19 16:20:40 2004 +0000 Add missing stop bit. commit e9536db04d65c3e8b2f09b28e1f631a3e81dbbeb Author: H. Peter Anvin Date: Thu Aug 19 16:20:40 2004 +0000 0.164 released, next version is 0.165 commit 11b180ac3f104f22c9fc0d76efc7b4454efd1467 Author: H. Peter Anvin Date: Thu Aug 19 16:09:23 2004 +0000 Fix merge errors commit fa2a4ca07c34d16af04503eef4807cb0923591a6 Author: H. Peter Anvin Date: Thu Aug 19 16:09:23 2004 +0000 0.163 released, next version is 0.164 commit 0bf657dcca708c03e660bf392cd145c97f706abc Author: H. Peter Anvin Date: Thu Aug 19 16:03:00 2004 +0000 Fix broadcast address (Olaf Hering) commit 67cf656e4bfc6e9e996cfdd137dfbbb019135ace Author: H. Peter Anvin Date: Thu Aug 19 16:03:00 2004 +0000 0.162 released, next version is 0.163 commit b765d3f4397859fd648ae4a7ea0327dcfa8ed34f Author: H. Peter Anvin Date: Thu Aug 19 15:48:36 2004 +0000 *** empty log message *** commit b9c7cf837d60c8854973a0646f465abd7c4bc561 Author: H. Peter Anvin Date: Thu Aug 19 15:48:36 2004 +0000 Use reliable NFS options by default commit 3c9b149ea70c065135fc1ddd251e36d909851954 Author: H. Peter Anvin Date: Thu Aug 19 15:47:57 2004 +0000 Handle netmask properly; "both" means BOOTP+RARP, not DHCP. commit 97afac3cd76ece6b152b8ac7ce619921918e704a Author: H. Peter Anvin Date: Sun Aug 15 21:10:25 2004 +0000 0.161 released, next version is 0.162 commit 9919dee4d83f5773685eaafb9105ec40a3cf89f7 Author: H. Peter Anvin Date: Sun Aug 15 02:17:34 2004 +0000 Make the documentation match reality a bit better; add -g to the i386 CFLAGS (strip DTRT on i386.) commit 6170431424815b44550de0738d4c35768a1fc9df Author: H. Peter Anvin Date: Sun Aug 15 02:17:34 2004 +0000 Fix alignment (from Olaf Hering) commit cf70d564617138b12fc0e8a4a00dd966338cef3b Author: H. Peter Anvin Date: Fri Aug 13 22:25:58 2004 +0000 0.160 released, next version is 0.161 commit b0b32aea6e738add0ce5e9223863612f2689e901 Author: H. Peter Anvin Date: Fri Aug 13 22:24:20 2004 +0000 Fix make spotless; from Olaf Hering commit 1bbdd0fe77e79cdfcbfc59a5ce2982eb11a0c85d Author: H. Peter Anvin Date: Fri Aug 13 22:24:20 2004 +0000 printf(1) from netbsd; from Olaf Hering commit 25ccc6409aecdf41fc0013c7d37f8feb6c9b7513 Author: H. Peter Anvin Date: Thu Aug 12 04:55:12 2004 +0000 For the benefit of MMU-less architecture: make sbrk() align memory commit 5122964ed89f2b177aecad59f8dc9998712d9dc3 Author: H. Peter Anvin Date: Thu Aug 12 01:45:40 2004 +0000 Deal with more than one kernel source RPM installed commit 36f718e7d482f00414deda635058b18769546737 Author: H. Peter Anvin Date: Thu Aug 5 01:43:14 2004 +0000 Split up the various rand48 functions commit 950b429968ddfdc04c04fb5f5d1eae8354240331 Author: H. Peter Anvin Date: Thu Aug 5 01:31:51 2004 +0000 0.159 released, next version is 0.160 commit 704377c0342cecf8b1e0990fe870b1fa2ea202ea Author: H. Peter Anvin Date: Wed Aug 4 00:04:32 2004 +0000 Use for htonl commit c0df67a2123b39da1269e333d34f9a7aefb4e350 Author: H. Peter Anvin Date: Wed Aug 4 00:04:32 2004 +0000 0.158 released, next version is 0.159 commit d35214ea2b670fba0e17953cee5fc43a8c24da66 Author: H. Peter Anvin Date: Tue Aug 3 23:54:53 2004 +0000 Add test for strtotime*() commit f65724cb4a1709b0a78c8da4d3d09f1fc6e77412 Author: H. Peter Anvin Date: Tue Aug 3 23:54:53 2004 +0000 Actually correct implementation of strtotime*() commit 98af3d67b7f36e5beaf842eaa6f4d4e006ab4618 Author: H. Peter Anvin Date: Tue Aug 3 23:50:32 2004 +0000 Don't bother to pretend we're datatype ignorant commit e2880125cdeeddf81b869cb80779916ef4a5a49a Author: H. Peter Anvin Date: Tue Aug 3 23:49:25 2004 +0000 Even more efficient implementation to strtotime*() commit 7e7af701cff2b69e6556e78266681cfbea7ace43 Author: H. Peter Anvin Date: Tue Aug 3 23:41:00 2004 +0000 Avoid multiple tests for iscntrl() commit 8e225a68896e5fbc6ac1d504408cf164f40a5c8f Author: H. Peter Anvin Date: Tue Aug 3 23:34:23 2004 +0000 Unify strtotimespec with strtotimeval commit f1764ebc22e4de45d01c3c556a528fdf1a33dd88 Author: H. Peter Anvin Date: Tue Aug 3 23:29:51 2004 +0000 timeval has 6 decimal places, not 9 commit 1e45b406b2f7f52f304272ef91d84c464baca0d1 Author: H. Peter Anvin Date: Tue Aug 3 23:27:01 2004 +0000 More efficient implementation of strtotime*() commit 4cafd6ffa6d6078c12645399dc2d7cf89066ec7f Author: H. Peter Anvin Date: Tue Aug 3 21:23:33 2004 +0000 0.157 released, next version is 0.158 commit e208b38334c505cc0acdf13c8b83a1c620da2108 Author: H. Peter Anvin Date: Tue Aug 3 21:07:05 2004 +0000 Move strtotime*() prototypes to commit 383dd54236c490d510d511c12a835eb4581028fa Author: H. Peter Anvin Date: Tue Aug 3 21:07:05 2004 +0000 Add functions to convert to struct time{spec|val} w/o floating point commit 15ebaa845c79640f206ad50a4e9ff731703b00ac Author: H. Peter Anvin Date: Tue Aug 3 20:40:42 2004 +0000 Fix daemon(), sched_setscheduler() commit 03277820ca9d86547a6fe0f97bbb6b75cb800692 Author: H. Peter Anvin Date: Tue Aug 3 01:16:20 2004 +0000 0.156 released, next version is 0.157 commit c12cb7dff5b42d8ec489b28f73469cc7a5ba46e9 Author: H. Peter Anvin Date: Mon Aug 2 23:51:18 2004 +0000 Add m[un]lock[all] system calls commit eca1a5049c9eda7c1207068a65874d06652d5583 Author: H. Peter Anvin Date: Mon Aug 2 23:51:18 2004 +0000 Fix header commit 012ebc69e037bf4412d2d863e0408e421e84e22e Author: H. Peter Anvin Date: Mon Aug 2 23:49:49 2004 +0000 Change status for parisc commit b12dd525fd95d4775f79cebb857de4e197e18a86 Author: H. Peter Anvin Date: Mon Aug 2 22:57:36 2004 +0000 Build x86-64 binaries without .eh_frame commit 6f3c672119b8e39c1ce60ec24b2e9a5cd3c657e9 Author: H. Peter Anvin Date: Mon Aug 2 22:44:31 2004 +0000 Actually *build* umount.o commit 2d041776b0ec3bcc4ee57cf11f50b820639b4090 Author: H. Peter Anvin Date: Mon Aug 2 21:46:04 2004 +0000 Add htonq/ntohq commit f20ac07cf399b14bc26eff852b0e3dbe44a40a24 Author: H. Peter Anvin Date: Mon Aug 2 20:15:37 2004 +0000 0.155 released, next version is 0.156 commit 6f63aa3879e1a5af24465e073eb140d2d24c37ae Author: H. Peter Anvin Date: Mon Aug 2 15:04:10 2004 +0000 The value limit for ldo is 0x1fff, not 0x3ff, so don't worry about it. commit 488f04ea6922897d63af75de96b8053869351476 Author: H. Peter Anvin Date: Mon Aug 2 15:04:10 2004 +0000 Try to update the pa-risc code. Do the syscall stub in C with special compilation options; seems to work OK. commit 1784768fd4a4358567339ab358f9dcc7d2e2e7c5 Author: H. Peter Anvin Date: Fri Jul 30 19:30:19 2004 +0000 0.154 released, next version is 0.155 commit 96ec027e7954c8ce1d532648c1a6ba9cb79bf6f5 Author: H. Peter Anvin Date: Fri Jul 30 16:26:59 2004 +0000 Support XFS commit 2d6eb8725cac30b78c25b3669b30d0440cbe056e Author: H. Peter Anvin Date: Fri Jul 30 16:26:59 2004 +0000 One more change stat -> lstat commit ddbfe8446fc7d1aceddd1aa5d6b79fde944d6688 Author: H. Peter Anvin Date: Fri Jul 30 16:24:11 2004 +0000 run-init: call lstat() not stat() commit 70fb47a7b3f49ad200dca3d5ad95d89e7f2981e9 Author: H. Peter Anvin Date: Fri Jul 30 16:22:47 2004 +0000 Avoid fixed allocations; support building both shared and static commit 90eb899958a506c4a0980eaaee65be3548706710 Author: H. Peter Anvin Date: Wed Jul 28 21:09:59 2004 +0000 gcc needs putchar(). Sigh. commit 55e2afa7735723eced75e5281527b0f76f3bfeef Author: H. Peter Anvin Date: Tue Jul 27 20:01:47 2004 +0000 Better way of finding the gcc version commit 9acd95a49fefb8ad94faa87615024a4073f3f5c0 Author: H. Peter Anvin Date: Mon Jul 26 22:28:06 2004 +0000 0.153 released, next version is 0.154 commit 95fa1a130b6ebecf0bebe7c92dfa84047db3e4ba Author: H. Peter Anvin Date: Mon Jul 26 22:10:31 2004 +0000 Fix bogus casts commit d2eabc7c9852e600ba6b58c6f35468ec1ad1a90e Author: H. Peter Anvin Date: Mon Jul 26 22:10:31 2004 +0000 Fix warnings commit 2f2e5260c348fc648e634d0da49a0b45629e255c Author: H. Peter Anvin Date: Mon Jul 26 22:02:49 2004 +0000 Guard against mistakes: this file shouldn't be included directly commit 9f088613267e049fd954682fdd382812f2d00487 Author: H. Peter Anvin Date: Sat Jul 24 15:08:52 2004 +0000 Build static and shared, stripped and unstripped commit 5137670f6f1e0289688a57a0c8d1a618fea8937a Author: H. Peter Anvin Date: Sat Jul 24 15:03:42 2004 +0000 Build static and shared versions commit 00a14c283a3f240994d0e5f8a341c53be6d5c677 Author: H. Peter Anvin Date: Tue Jul 20 04:32:42 2004 +0000 0.152 released, next version is 0.153 commit 23c7c39252a4ca004f7826898d77dec98e705852 Author: H. Peter Anvin Date: Thu Jul 15 17:52:38 2004 +0000 Add daemon() helper function commit cf47fd9038ee73c81d243a5cf9d0501ab119e6ea Author: H. Peter Anvin Date: Thu Jul 15 17:52:38 2004 +0000 0.151 released, next version is 0.152 commit 5b2a230d00474fdbfbcccc8aff6df5690cb8b10f Author: H. Peter Anvin Date: Thu Jul 15 17:42:08 2004 +0000 Use the BSR instruction on i386 to get the page shift commit b2fe4a9a9e69ad91544c424c3bb4c64d82e96490 Author: H. Peter Anvin Date: Thu Jul 15 17:42:08 2004 +0000 Use AT_PAGESZ from the ELF header to obtain the page size. commit 85e2b5f2fc29c83872a7f8772a45e23de9470064 Author: H. Peter Anvin Date: Thu Jul 15 16:42:19 2004 +0000 Fix possible segfault in strnlen() commit c21ffe42c5f7bcb737dd2871469c2623cfca83fd Author: H. Peter Anvin Date: Thu Jul 15 16:38:49 2004 +0000 Add strnlen(), from Harald Hoyer modified by me commit 747019dc98abe97cc25bc85801933f82aec6686d Author: H. Peter Anvin Date: Thu Jul 15 16:34:56 2004 +0000 IA64 update from hare@suse.de and schwab@suse.de commit 6d6514b0437b2b3388323b53e4a04a1b07d5a3ca Author: H. Peter Anvin Date: Wed Jul 7 21:23:27 2004 +0000 0.150 released, next version is 0.151 commit 8e3478d721b067b07f86f06943407dc83c56f128 Author: H. Peter Anvin Date: Wed Jul 7 19:09:17 2004 +0000 Fix __negdi2 on cris commit 1d38b22c363a9454aef50d20ae9aece2370e9695 Author: H. Peter Anvin Date: Wed Jul 7 19:09:17 2004 +0000 Make negdi2 a cris-specific function commit 92c60c6accecc8368a4e2695c74405d9ca302c56 Author: H. Peter Anvin Date: Wed Jul 7 00:42:05 2004 +0000 0.149 released, next version is 0.150 commit 14b144118dc3bf01f4cd073af5002382d9b5db13 Author: H. Peter Anvin Date: Wed Jul 7 00:37:02 2004 +0000 Clean up unnecessary parens commit 903cbd5e4190a2306069b03e218e84073707f419 Author: H. Peter Anvin Date: Wed Jul 7 00:37:02 2004 +0000 x86-64 needs here to prevent inclusion commit 24fa8beb114ed63b4d4560f8049aa03445dda6c4 Author: H. Peter Anvin Date: Wed Jul 7 00:28:07 2004 +0000 Attempt #2 at cleaning up the RH braindamage commit 162a8e54614405f5be090fa125a933d25ff1fcec Author: H. Peter Anvin Date: Wed Jul 7 00:25:15 2004 +0000 RedHat's kernel-source RPM is broken commit cd0a8cbe7fafd3dc4b6362526619068a05c42f49 Author: H. Peter Anvin Date: Wed Jul 7 00:20:44 2004 +0000 Make even more conventional... commit ad1f90c45e07c432b96475bdbec5300745743ea2 Author: H. Peter Anvin Date: Wed Jul 7 00:18:01 2004 +0000 Add %setup -q commit c57960b33ba548f67b5660334b2a2b2f9a95ef85 Author: H. Peter Anvin Date: Wed Jul 7 00:17:31 2004 +0000 Add conventional setup commit 4d82bdf4dd2896185a03f7c198529b1f77533fd2 Author: H. Peter Anvin Date: Wed Jul 7 00:15:41 2004 +0000 We might have to clean an old Linux directory... commit d8b65d7c2e1a72f8a2fab5ecf4f4f57ee50624a0 Author: H. Peter Anvin Date: Wed Jul 7 00:14:42 2004 +0000 Correct source list commit 1b622a87d3fdc7216e2cefe55663dd1a4bfcc98c Author: H. Peter Anvin Date: Wed Jul 7 00:12:11 2004 +0000 2.6 kernel, please commit 0deef9cf0bd10ccb73de66750218a2273a67c26e Author: H. Peter Anvin Date: Wed Jul 7 00:11:45 2004 +0000 Use symbolic links commit 730c9fef903dd76a90b2f677c84b35d14c7ee2f5 Author: H. Peter Anvin Date: Wed Jul 7 00:10:43 2004 +0000 -d- not -c- in cut command line commit 31dc6e78a274d3af67626a901a9da46470bf0baf Author: H. Peter Anvin Date: Wed Jul 7 00:09:32 2004 +0000 Remove .tar* commit 6584e69392b19f98309af81d550226e9d01d3701 Author: H. Peter Anvin Date: Wed Jul 7 00:08:45 2004 +0000 Updates to make rpmbuild -ta work better commit 3b3f17d8ef6f7ac66fe934f602266972d80bd77f Author: H. Peter Anvin Date: Tue Jul 6 21:36:59 2004 +0000 New better malloc() test commit 20a43985752a22bdaa2d032e93256675baf6f907 Author: H. Peter Anvin Date: Fri Jul 2 14:20:21 2004 +0000 0.148 released, next version is 0.149 commit daf8a40620e072d727b782758ad73aa3054ab6bc Author: H. Peter Anvin Date: Fri Jul 2 14:15:46 2004 +0000 Put the proper version number in the spec file. commit fdc60178037344cbc2d8ed75c46d40fd81fa9342 Author: H. Peter Anvin Date: Fri Jul 2 14:15:46 2004 +0000 S390, shared library changes, mostly from Arnd. commit 670b26367eeffc1938740532f6ff88ce55cde5c3 Author: H. Peter Anvin Date: Fri Jul 2 00:02:29 2004 +0000 0.147 released, next version is 0.148 commit e4905f5a963c58444181d08f768db05b60c06cd7 Author: H. Peter Anvin Date: Thu Jul 1 23:39:19 2004 +0000 Remove unnecessary option commit 932c4810337cf5f536774a406285cd940d7c9b0b Author: H. Peter Anvin Date: Thu Jul 1 23:39:19 2004 +0000 Cris architecture fixes commit b3418324e337fb66ed5db090777d8c142782f993 Author: H. Peter Anvin Date: Thu Jul 1 23:22:38 2004 +0000 Updates for the cris architecture commit 1698736567971341d60814b90d23a64622dc1847 Author: H. Peter Anvin Date: Fri Jun 18 00:10:34 2004 +0000 0.146 released, next version is 0.147 commit 7c484677f4acdf4ac88c24cc7fbea833d5167aa6 Author: H. Peter Anvin Date: Fri Jun 18 00:08:03 2004 +0000 Default to giving real error messages. commit 91bc06ab4ecb55fcab13b65b3a53d2bde9494bbb Author: H. Peter Anvin Date: Fri Jun 18 00:08:03 2004 +0000 Add ; document need for loopback device commit 96b84c7b1a2738c1f2e420071c996fd57ad187c8 Author: H. Peter Anvin Date: Fri Jun 18 00:06:56 2004 +0000 Add support for bringing up the loopback device. commit c2daf48b0bc2d1edac4a86417e1ef0538e7a9848 Author: H. Peter Anvin Date: Thu Jun 17 16:16:38 2004 +0000 0.145 released, next version is 0.146 commit b9a218665802eeedb779c2a6adc5d51221577846 Author: H. Peter Anvin Date: Thu Jun 17 07:40:58 2004 +0000 Break up the portmap spoofer into a bind function and a listen function, so we can call the bind function before forking. Also, waitpid() at the end so we don't make zombies. commit 1b28a5ad13f2b8b212f771d77c47c6f49cac4bed Author: H. Peter Anvin Date: Thu Jun 17 07:40:58 2004 +0000 How to do nfslocking with nfs root... commit 78d542ef895c83edc738c8cd5108bfbe6aa92826 Author: H. Peter Anvin Date: Thu Jun 17 07:30:36 2004 +0000 0.144 released, next version is 0.145 commit 4274cf268f055e0e0a9b3f6b036426e8982837b8 Author: H. Peter Anvin Date: Thu Jun 17 04:46:38 2004 +0000 Add the ability to spoof portmap, and put out a file that then should get fed to pmap_set when starting the real portmapper. This allows for nfsroot with lockd enabled. commit 30a7b06b2560f415b958ce446412e13ee6d1ddf7 Author: H. Peter Anvin Date: Thu Jun 17 04:46:38 2004 +0000 Add test for strto* commit 9d67e1c171a7d34f7b1352296406b88c064002cc Author: H. Peter Anvin Date: Thu Jun 17 01:34:07 2004 +0000 0.143 released, next version is 0.144 commit 9be1ce2dce8350b5d692bb8ed3bd4c065d8d2c66 Author: H. Peter Anvin Date: Wed Jun 16 22:56:46 2004 +0000 Add missing *'s commit 990a805827c26a4b6509a928da61c9faf675c300 Author: H. Peter Anvin Date: Wed Jun 16 22:56:46 2004 +0000 0.142 released, next version is 0.143 commit 9b86c69c0bf66e6a9085ef4e3b51b213eba5780e Author: H. Peter Anvin Date: Wed Jun 16 22:54:26 2004 +0000 Start at port 768 to make the number of ports available to bindresvport() a power of 2. commit e59d7661489e6a86c0ef722cdd10ecd5c5589a3b Author: H. Peter Anvin Date: Wed Jun 16 22:54:26 2004 +0000 Fix bindresvport() - multiple bugs commit f0573650d1e86a7aea61108e7b0d273a90942e9a Author: H. Peter Anvin Date: Wed Jun 16 22:12:39 2004 +0000 0.141 released, next version is 0.142 commit 4f31185121dcafaccc49a39711d91d98c9fb6588 Author: H. Peter Anvin Date: Wed Jun 16 18:31:32 2004 +0000 sin_port -> sin_family commit c7f979e760d873998ca9f51777af98f8e29f5f19 Author: H. Peter Anvin Date: Wed Jun 16 18:31:32 2004 +0000 0.140 released, next version is 0.141 commit 373ad245f9695cf0293aa2243896c79c4f3963be Author: H. Peter Anvin Date: Sun Jun 13 06:19:41 2004 +0000 If we receieve an MTU option through BOOTP/DHCP, accept it; this is critical on GigE networks on which jumbo frames are used - until we do this we can't handle large IP datagrams. commit 2757e4b63b5ed5e8ee503858732dd29ee7a42bfc Author: H. Peter Anvin Date: Sun Jun 13 06:19:41 2004 +0000 0.139 released, next version is 0.140 commit d02da14f1a2841840d647fadfd3ad3915d850367 Author: H. Peter Anvin Date: Sun Jun 13 06:07:46 2004 +0000 Add ; fix pread/pwrite commit 3791deb96de1e5132b7cbe53c37206e7b3628d09 Author: H. Peter Anvin Date: Sun Jun 13 06:07:46 2004 +0000 0.138 released, next version is 0.139 commit 2a5a39841091d5c741806ad10f815aaa614455d6 Author: H. Peter Anvin Date: Thu Jun 10 21:00:58 2004 +0000 Support building the syslinux installer with klibc. commit b8a39ec4987df32fe311097fdc56f5d3ad11fc56 Author: H. Peter Anvin Date: Thu Jun 10 21:00:58 2004 +0000 First cut at updating the sh port to the new syscall stuff commit c3356786409316b2d573c760842c9462f664cf9b Author: H. Peter Anvin Date: Thu Jun 10 18:32:31 2004 +0000 0.137 released, next version is 0.138 commit 0389745eb3047f020129012c143a44cc1f48d230 Author: H. Peter Anvin Date: Thu Jun 10 08:06:51 2004 +0000 setjmp() needs to return zero commit 02886b9846835fc83958ee2193350bfb133c4b62 Author: H. Peter Anvin Date: Thu Jun 10 08:06:51 2004 +0000 0.136 released, next version is 0.137 commit 2a666037ee9be7d0079c0167311bc04f0026e70d Author: H. Peter Anvin Date: Thu Jun 10 06:59:46 2004 +0000 More cris tweaks - need to specify the start address slightly differently commit 9ee2b8e6fe57fb641206c76c135ebc7c919274ae Author: H. Peter Anvin Date: Thu Jun 10 06:59:46 2004 +0000 0.135 released, next version is 0.136 commit 39fb2d94eafcb877c22a9b2571d56cd71d330f60 Author: H. Peter Anvin Date: Thu Jun 10 05:30:21 2004 +0000 More work on the cris architecture, but apparently it needs multiply/divide helper functions, and might have some problem with ld? commit 16cef1d7c2db3a5cc3bf7f2262eb1335be8dd0fe Author: H. Peter Anvin Date: Thu Jun 10 05:30:21 2004 +0000 Fix handling of non-nsec stat commit c0d58c208263a3ebc890264d4c6abc6a6da39b37 Author: H. Peter Anvin Date: Thu Jun 10 04:36:11 2004 +0000 0.134 released, next version is 0.135 commit 7d059205357bd05137f6ab787c658d197b44fe7d Author: H. Peter Anvin Date: Thu Jun 10 04:30:27 2004 +0000 First attempt at completing the cris port commit 1079a28483118b6594511ac45842630c5e2cb520 Author: H. Peter Anvin Date: Thu Jun 10 04:30:27 2004 +0000 Remove vestigial definition (we don't use *.lo anymore) commit a1a3f47d8db526059a216d2e8413f9efcfe83c38 Author: H. Peter Anvin Date: Thu Jun 10 04:27:34 2004 +0000 Mark cris as "untested" commit 9961b2619429b8fd009e47dad3986505a0e80ce5 Author: H. Peter Anvin Date: Thu Jun 10 04:26:55 2004 +0000 Flesh out what I hope is all we need for the cris port commit 9738852fba88ee25b34ec00e52c1fb02bd191f23 Author: H. Peter Anvin Date: Thu Jun 10 03:35:12 2004 +0000 Initial attempt at syscall support for the cris architecture commit e13ef69be85f131ecc03cccfd4b8034f52322d85 Author: H. Peter Anvin Date: Wed Jun 9 19:53:42 2004 +0000 0.133 released, next version is 0.134 commit d0c4c83fb0105a0cc5f22dfe7f1b4a3ed44b848e Author: H. Peter Anvin Date: Wed Jun 9 19:38:48 2004 +0000 Fix statfs/fstatfs on systems which have statfs64/fstatfs64 commit 85bb33c1101198ec427ce9a781bf2e6c5877d6c0 Author: H. Peter Anvin Date: Wed Jun 9 19:38:48 2004 +0000 Add tests for stat and statfs commit 8bd7338d034369a42170d3dbf4932abe8d4bf5d7 Author: H. Peter Anvin Date: Wed Jun 9 19:28:33 2004 +0000 Make int64_t match uint64_t commit f36aac4795d9677658628c682577d0a60cc519a3 Author: H. Peter Anvin Date: Wed Jun 9 05:03:08 2004 +0000 0.132 released, next version is 0.133 commit f4a766a22e736a25bd323fd07c709ff63207583e Author: H. Peter Anvin Date: Wed Jun 9 04:35:05 2004 +0000 0.131 released, next version is 0.132 commit 4ce3f25ba3f0cf5c2398b05f3a05301071fa6336 Author: H. Peter Anvin Date: Wed Jun 9 04:35:05 2004 +0000 Update status of architectures commit d98fcd713e77a510f9624e58b7963302ac8f61ec Author: H. Peter Anvin Date: Wed Jun 9 04:35:05 2004 +0000 Document the need for it to be "a" commit d9904943e0e78e69ebffecc8ee1698e27901e93e Author: H. Peter Anvin Date: Wed Jun 9 04:34:22 2004 +0000 The interp section really needs to be "a" commit c694df00615d54d50047f2ba110e4d2cd69aeb3d Author: H. Peter Anvin Date: Wed Jun 9 03:45:41 2004 +0000 klibc now works on MIPS at least in static mode commit d2f8c96d15319a357b94f27d7ec17b676152e052 Author: H. Peter Anvin Date: Wed Jun 9 02:51:58 2004 +0000 Use MS_MOVE rather than MS_BIND commit 219287656678d724562bbf6c8395d0b2a15b6f45 Author: H. Peter Anvin Date: Wed Jun 9 00:30:28 2004 +0000 Add option to use sbrk for memory allocation rather than mmap. commit 91c8c7f39ff09b48df6833ca91290f5c52eedfe9 Author: H. Peter Anvin Date: Tue Jun 8 20:25:45 2004 +0000 0.130 released, next version is 0.131 commit cc0c0262446a10f69c10d5ddac3dd6536f2f9917 Author: H. Peter Anvin Date: Tue Jun 8 19:28:08 2004 +0000 Add more checks, add handling of console commit 34ebe698f9c52ca01bbe5ad5cea6fd4af591bb93 Author: H. Peter Anvin Date: Tue Jun 8 19:28:08 2004 +0000 s390/x updates from Arnd Bergmann commit 25044ce360dcda41b77c7eff8d498043c7071312 Author: H. Peter Anvin Date: Tue Jun 8 07:13:07 2004 +0000 0.129 released, next version is 0.130 commit c74f1dd23ed4018dea4a6f1bccf7dc7e7bde5c63 Author: H. Peter Anvin Date: Tue Jun 8 06:55:04 2004 +0000 Wrap open prototype to open.c doesn't go weird commit e65529d215db51b7ff7b567e03292a2311a1836a Author: H. Peter Anvin Date: Tue Jun 8 06:55:04 2004 +0000 0.128 released, next version is 0.129 commit 63d5b2d1f4818cb941318eccbe89b11263c689a3 Author: H. Peter Anvin Date: Tue Jun 8 06:53:14 2004 +0000 Fix O_LARGEFILE handling for i386 open commit b3bcff3c8122b553bdc5782f3661668be364c134 Author: H. Peter Anvin Date: Tue Jun 8 06:53:14 2004 +0000 0.127 released, next version is 0.128 commit 2b6ff890fe0e0e63e4f8ede3b0724d15ae587902 Author: H. Peter Anvin Date: Tue Jun 8 06:51:32 2004 +0000 Clean up whitespace commit 68f700808b35eb918ef15be89772e4af8a140afc Author: H. Peter Anvin Date: Tue Jun 8 06:51:32 2004 +0000 Fix added/missing files commit ff3a0a76074859999838118998f5a4a0d4a84001 Author: H. Peter Anvin Date: Tue Jun 8 06:44:23 2004 +0000 0.126 released, next version is 0.127 commit bd50ec0162ba98f759e50c5d91b28bb06f27d796 Author: H. Peter Anvin Date: Tue Jun 8 06:41:29 2004 +0000 open.S - special handling for open(2) for i386 commit 8204351ba5f9b837c8e358b931d996b8723281b5 Author: H. Peter Anvin Date: Tue Jun 8 06:41:29 2004 +0000 0.125 released, next version is 0.126 commit a1e2f3797263785722d3f74af447c1bb7593f45a Author: H. Peter Anvin Date: Tue Jun 8 06:39:44 2004 +0000 Remove duplicate definition of magic numbers commit daa33bad77443df8cdc240c9655680d26bd612d9 Author: H. Peter Anvin Date: Tue Jun 8 06:39:44 2004 +0000 Add list of filesystem types in ; Cleaner implementation of nuke(1); New utility run-init to finish a scripted initramfs. commit a6e53ad630a3a443cc07323221f0c714a0dfd335 Author: H. Peter Anvin Date: Tue Jun 8 05:34:15 2004 +0000 0.124 released, next version is 0.125 commit 7f7844381ac47c2cde38c13ed90003508a271bd6 Author: H. Peter Anvin Date: Tue Jun 8 03:01:49 2004 +0000 Change to using new stat and statfs system calls; move minips to utils. commit b1d7cb3a178fee1298700637276b47bcbb726046 Author: H. Peter Anvin Date: Tue Jun 8 03:01:49 2004 +0000 Make sure we include the "error " portion! commit dac0892ba8e7ad5da76267e07793d486cb421d21 Author: H. Peter Anvin Date: Tue Jun 8 02:58:27 2004 +0000 Set 'program' in main() commit 8e10e5d0b190d634b2383e7a22888242c1b3e6a2 Author: H. Peter Anvin Date: Tue Jun 8 02:44:54 2004 +0000 Use dup2() rather than fcntl() commit 8e3dacd70b061712f60a81b5bc91220cc59b64b8 Author: H. Peter Anvin Date: Mon Jun 7 21:43:14 2004 +0000 0.123 released, next version is 0.124 commit b5ef57cfa844ee3fa3099209be8903fdd9d054da Author: H. Peter Anvin Date: Mon Jun 7 20:41:52 2004 +0000 Clean libutils.a commit 691bbdf2bae34128f8d70aa2602ba05b36df5b1b Author: H. Peter Anvin Date: Mon Jun 7 20:41:52 2004 +0000 0.122 released, next version is 0.123 commit 0b2f8a06771c57475178910d3bc8d891b3ddce91 Author: H. Peter Anvin Date: Mon Jun 7 19:57:29 2004 +0000 Add "nuke" program; save non-stripped versions in .g directories commit 0386dda2b9e6e6f8b901d56ec9be08c8404f52dd Author: H. Peter Anvin Date: Mon Jun 7 19:57:29 2004 +0000 Reinstate stripping, but save unstripped versions as *.g commit 84e34e076a4e25a17a1582636e2c2765c0ca51fb Author: H. Peter Anvin Date: Mon Jun 7 19:49:36 2004 +0000 Use %rip-relative addressing for errno. commit dc1da848eee27650d6a6a399a12b111c4c3c5aae Author: H. Peter Anvin Date: Mon Jun 7 10:25:08 2004 +0000 0.121 released, next version is 0.122 commit 53b7c91cf73ba75160fc30e363daecbc87adeda3 Author: H. Peter Anvin Date: Mon Jun 7 08:43:00 2004 +0000 Make alpha actually work. commit 6a2d7ce26a0f67971b6526d02abe1f90b20bee62 Author: H. Peter Anvin Date: Mon Jun 7 08:43:00 2004 +0000 0.120 released, next version is 0.121 commit 64ebf2bd0f6393d271312af8aa264dd2297285ec Author: H. Peter Anvin Date: Mon Jun 7 08:18:45 2004 +0000 Actually handle the gp correctly (needed to find errno, sigh; if pc was accessible we wouldn't have to do this in the fast path and replicate among each function. Oh well. It's a dead architecture anyway.) commit dfa23844ad5a19f4f9e542b52f5f5428f6afaa33 Author: H. Peter Anvin Date: Mon Jun 7 08:18:45 2004 +0000 One more attempt at getting the alpha stuff right... commit a919b8a7657d4bceaabb968c7331c15e0cbce0e8 Author: H. Peter Anvin Date: Mon Jun 7 08:17:47 2004 +0000 ppc/ppc64 should now work commit 9e9a5ff906034d2c2be09b2cfc51e398d9acf8aa Author: H. Peter Anvin Date: Mon Jun 7 08:16:58 2004 +0000 #include commit 0ab0a038303b7c99c4134ac97121947a07e3e50b Author: H. Peter Anvin Date: Mon Jun 7 06:56:00 2004 +0000 0.119 released, next version is 0.120 commit 9ab92250fc99fa9a2d7522c710818160ec1d7fdf Author: H. Peter Anvin Date: Mon Jun 7 03:05:52 2004 +0000 ppc/ppc64 support from Paul Mackerras commit f651d9292521bd8a8de7ff0fa26d03ffb00d001f Author: H. Peter Anvin Date: Mon Jun 7 03:05:52 2004 +0000 0.118 released, next version is 0.119 commit 9b1e05361d419a144ec5d100f91197ae5772d866 Author: H. Peter Anvin Date: Mon Jun 7 01:53:43 2004 +0000 Something closer to how I *think* things are supposed to work... commit e736fc1c6d148002aa0a9b33d666b0a53b5c81be Author: H. Peter Anvin Date: Mon Jun 7 01:53:43 2004 +0000 Implement new system call architecture for alpha commit f4c5c8b4dc5206e83b58018e5a49d06ee7502a78 Author: H. Peter Anvin Date: Sun Jun 6 22:04:29 2004 +0000 0.117 released, next version is 0.118 commit 74ad706be412c00adb8ecfc0244479ea1121b1ec Author: H. Peter Anvin Date: Sun Jun 6 10:12:50 2004 +0000 Update status commit 17cd7f557ed59ca9c92f0e02148c84b16656d1ab Author: H. Peter Anvin Date: Sun Jun 6 10:12:50 2004 +0000 Minor cleanup commit 08046f3e42d0436a7af8d72016b19176272715b8 Author: H. Peter Anvin Date: Sun Jun 6 09:55:46 2004 +0000 We might not have forkish system calls on sparc64... commit 6321e7a96c6438e9510d1b86083441d40b088db5 Author: H. Peter Anvin Date: Sun Jun 6 09:51:15 2004 +0000 Handle "forkish" system calls on sparc64 commit 7dec8f8a23d43e92503a24309bafe9ede682cd23 Author: H. Peter Anvin Date: Sun Jun 6 09:49:22 2004 +0000 Add LDFLAGS, even though this is somewhat nonstandard usage commit b436d51840cabeda294dd219596f39455c52d88b Author: H. Peter Anvin Date: Sun Jun 6 09:43:27 2004 +0000 Add common stub for sparc "forkish" syscalls commit 3adf666de4550a85e96b26a8b09f0b51a0410c73 Author: H. Peter Anvin Date: Sun Jun 6 09:21:38 2004 +0000 Fix test crap that slank in by mistake commit f927b7c598274273d74ad445e5d666b2bae5cff5 Author: H. Peter Anvin Date: Sun Jun 6 09:18:03 2004 +0000 Make sparc work (damned branch delay slots...) except for fork/vfork commit a9efea64f41c5cfc10631e83aa42c3fbc19a4563 Author: H. Peter Anvin Date: Sun Jun 6 08:58:50 2004 +0000 SPARC64 system call stub generator commit ecea8185d10384417535f09679dd2b9f98afedb0 Author: H. Peter Anvin Date: Sun Jun 6 08:53:52 2004 +0000 Sparc64 porting - doesn't quite work yet commit 019eba37ffbdb69c62f2acdc5f92c6af91634cae Author: H. Peter Anvin Date: Sun Jun 6 05:33:19 2004 +0000 Make ARM work again with the new system call stub setup commit eb7347635bfa4462dcc15d45ae2a9a9734f866c1 Author: H. Peter Anvin Date: Sun Jun 6 05:31:13 2004 +0000 Very simple test for open(2) commit 73bf3563df4ad26a559ce39fdb81a4a104ad0edd Author: H. Peter Anvin Date: Sun Jun 6 02:46:18 2004 +0000 Need syscall.o on x86-64 commit 0fd01b86a233d05d87aafc8f6c2f14e283bece2d Author: H. Peter Anvin Date: Sun Jun 6 02:45:00 2004 +0000 Remove send and recv for good commit f37bd870dff6652cf9026e5aadacc802d296cddf Author: H. Peter Anvin Date: Sun Jun 6 02:43:55 2004 +0000 Fix the logic when to use mmap(2), when to use mmap2(2) commit cc98d0e031f1447378657f3641c7f066b735c82d Author: H. Peter Anvin Date: Sun Jun 6 02:41:18 2004 +0000 Deal with empty socketcall/*.o commit 07a37015eaea6b2c382c3d77a0e7ec402c34d454 Author: H. Peter Anvin Date: Sun Jun 6 02:26:31 2004 +0000 Initial set of changes for new syscall infrastructure. This probably breaks all non-i386 architectures; need to fix them one by one. commit c3ccd3cc02cb4d46998106898bb3c1ea6e53bc75 Author: H. Peter Anvin Date: Sat Jun 5 19:53:55 2004 +0000 Put the open() prototype in as well, to make it harder to miss. commit 4872ff24991627bbf7ee062c941b25141d7ebf68 Author: H. Peter Anvin Date: Sat Jun 5 19:47:45 2004 +0000 Add to any file which needs open(). commit afa83d5b67538238e400360e65d6a84e548fb729 Author: H. Peter Anvin Date: Sat Jun 5 03:03:08 2004 +0000 ARM changes to use function calls for syscalls commit c4e862f48d7ae689d615159496dd46e195642f97 Author: H. Peter Anvin Date: Fri Jun 4 06:50:23 2004 +0000 Change i386 to using a function-call-based syscall interface; this means (unlike the stock syscall macros) that it's 64-bit-argument safe. The goal is for all 32-bit architectures to do this, so we can change off_t to 64 bits. commit 8d6f90fd13a309369956177502352ee88170dbfa Author: H. Peter Anvin Date: Wed Apr 14 18:36:48 2004 +0000 0.116 released, next version is 0.117 commit 33aff92988cea3a6c6e57f2fc0eb9c6a55bc073b Author: H. Peter Anvin Date: Fri Apr 9 20:25:24 2004 +0000 sysinfo() support [for udev] - from Kay Sievers commit be067bf4d41a40b601f6f84c06b2f7b0d1858812 Author: H. Peter Anvin Date: Fri Apr 9 20:25:24 2004 +0000 PA-RISC support from Kyle McMartin commit 7d5ca1181249fe0f108f6860c59ab4bfc168ac33 Author: H. Peter Anvin Date: Mon Feb 23 00:35:39 2004 +0000 0.115 released, next version is 0.116 commit 80a6119e6d7bee9709a7a632983a4e06e94a7401 Author: H. Peter Anvin Date: Sun Feb 22 01:01:12 2004 +0000 open() is a weird function; treat it with care. commit 28fe3b9fdfe50384461193ba3fded999978d0256 Author: H. Peter Anvin Date: Sun Feb 22 01:01:12 2004 +0000 0.114 released, next version is 0.115 commit 7cbeca45c9008726aed1bda442f5fc7a8459749a Author: H. Peter Anvin Date: Sun Feb 22 00:58:27 2004 +0000 Use an automatic array instead of malloc() commit 629be76497daab98e5c4ca902239056756668f39 Author: H. Peter Anvin Date: Sun Feb 22 00:58:27 2004 +0000 0.113 released, next version is 0.114 commit 8753d01689cabd5c746406ec606c02ba6fdafa79 Author: H. Peter Anvin Date: Sun Feb 22 00:57:32 2004 +0000 Actually add the ln file commit 7a0c2b1960d01add73723524ef53ff6303806be3 Author: H. Peter Anvin Date: Sun Feb 22 00:57:32 2004 +0000 ln utility from Olaf commit 08cc55149ae9993e05a45ff7fda333a2643384d0 Author: H. Peter Anvin Date: Sat Feb 21 22:50:42 2004 +0000 0.112 released, next version is 0.113 commit 3f2eeb9d2bb1dccc272a3edc7808cf53ac1a72e4 Author: H. Peter Anvin Date: Sat Feb 21 08:44:07 2004 +0000 Add sleep utility (from Olaf); build both shared and static versions of the utilities. commit 400b285b76c2752ded710861268620058084d7ee Author: H. Peter Anvin Date: Sat Feb 21 08:44:07 2004 +0000 Remove useless ud2a commit 47f1091ea72b7f5db66b1d822f7c17561cad6ca4 Author: H. Peter Anvin Date: Sat Feb 21 08:38:43 2004 +0000 0.111 released, next version is 0.112 commit b07de37b0f0cb4aafa3daea3b9591afd36aa9b65 Author: H. Peter Anvin Date: Sat Feb 21 08:28:01 2004 +0000 Add missing prototype for getpgid() commit e588bebc623bd8f38c22b729dfb6e280b3310d82 Author: H. Peter Anvin Date: Sat Feb 21 08:28:01 2004 +0000 Add getpt(). Although it's a GNU extension, it's useful for portability, and people should be encouraged to use it. Besides, it's a whopping 30 bytes. commit f349fb8a9195b7e3965920608c246342a9cf286d Author: H. Peter Anvin Date: Tue Feb 17 21:11:11 2004 +0000 0.110 released, next version is 0.111 commit cc13e976f7b344f8b4271f079d2722b5d42a1317 Author: H. Peter Anvin Date: Tue Feb 17 21:09:13 2004 +0000 Add commit 5423ef74f55d0baadb32f85e07d361879289e0e9 Author: H. Peter Anvin Date: Tue Feb 17 21:09:13 2004 +0000 0.109 released, next version is 0.110 commit e3381b56e953cfd71a52679408932e3bf048fc25 Author: H. Peter Anvin Date: Fri Feb 13 02:53:47 2004 +0000 Use getpgid() to emulate getpgrp() since the latter isn't available on ia64 commit c459b3e45e13b4f3b524c3788bb036bbed023e85 Author: H. Peter Anvin Date: Fri Feb 13 02:53:47 2004 +0000 0.108 released, next version is 0.109 commit 319db49f17251c015670e81ab74215a88887ae38 Author: H. Peter Anvin Date: Thu Feb 12 02:19:51 2004 +0000 Fix offsetof() commit 364e6530ab507c0c2d8a059a3ec7d7954bb2f368 Author: H. Peter Anvin Date: Thu Feb 12 02:19:51 2004 +0000 0.107 released, next version is 0.108 commit 06765402ccfb517d757c5b8d3fce4c7421f1fd4a Author: H. Peter Anvin Date: Tue Feb 10 02:06:18 2004 +0000 Update to deal with attribute handling in recent kernels commit c98da2cb895cfeaba2639ab37caac616926f1ef8 Author: H. Peter Anvin Date: Tue Feb 10 02:06:18 2004 +0000 0.106 released, next version is 0.107 commit 0c3b964eceac1cffb3547e84f0294e4e4ed18bcc Author: H. Peter Anvin Date: Mon Feb 9 23:09:09 2004 +0000 Rename signal() to sysv_signal() to keep people from getting confused Centralize makefile rules to new MRULES file commit 98dc4d6da5760d35b7b747a9029aba80400d927b Author: H. Peter Anvin Date: Mon Feb 9 23:09:09 2004 +0000 Declarations are supposed to be first in a { } group (unless C99) commit ebd64686f416edee886612ebe94e64405d2eeedb Author: H. Peter Anvin Date: Mon Feb 9 06:20:53 2004 +0000 0.105 released, next version is 0.106 commit d3dde00040cc139c8c8d10b63985f298bdbb6c23 Author: H. Peter Anvin Date: Mon Feb 9 06:03:41 2004 +0000 Add the appropriate inline functions for dev_t manipulation commit 655e50eec1a29d3e18cda0abc3b25c1009e0e2c6 Author: H. Peter Anvin Date: Mon Feb 9 06:03:41 2004 +0000 Update headers to fix problems with integer types, wait() and access() commit 2a81588ca6ce0a03c70bf4fb5753df6fcb786e66 Author: H. Peter Anvin Date: Mon Feb 9 05:43:47 2004 +0000 0.104 released, next version is 0.105 commit 92c73cf855af1f0b4834ef2d05d214392e380760 Author: H. Peter Anvin Date: Fri Jan 30 22:57:55 2004 +0000 Fix setenv/putenv commit ec59c8be22d941eaee1b35b34f45c7f651b2f4b8 Author: H. Peter Anvin Date: Fri Jan 30 22:57:55 2004 +0000 0.103 released, next version is 0.104 commit ea1a9be1658d8d4eb2d07f185a37e8e0b4535631 Author: H. Peter Anvin Date: Fri Jan 30 21:46:12 2004 +0000 Much better x86-64 syscall macros commit 7e68ba9e00f2836001cd948a7f65765dfd392787 Author: H. Peter Anvin Date: Fri Jan 30 21:46:12 2004 +0000 0.102 released, next version is 0.103 commit b5c2595e2d0b22f15110bd3d89fab74303e4cfdf Author: H. Peter Anvin Date: Thu Jan 29 22:51:10 2004 +0000 Don't use , use our own commit da8343d5211b513b39c4e5ed25c06d46fd021d24 Author: H. Peter Anvin Date: Thu Jan 29 22:51:10 2004 +0000 Update build instructions for 2.6 commit 001eef5a19219e5b0601068a3d13874b88c0653e Author: H. Peter Anvin Date: Thu Jan 29 21:18:08 2004 +0000 0.101 released, next version is 0.102 commit 50425c8f4fd0630aa9652bd07a428321140716d5 Author: H. Peter Anvin Date: Wed Jan 28 08:12:02 2004 +0000 Doc updates commit 47b7d2f79fb456f7198b377b5c0d1ae6aab5521f Author: H. Peter Anvin Date: Wed Jan 28 08:12:02 2004 +0000 ppc32 fixes: use SYS_mmap not SYS_mmap2; fix the _syscall6() macro commit 2bab75df13eb30e275fb1cd7e1f1fb391de2f9c9 Author: H. Peter Anvin Date: Wed Jan 28 01:43:29 2004 +0000 0.100 released, next version is 0.101 commit 656ea57b2160547c909f7f7b9d63a59100f1c01c Author: H. Peter Anvin Date: Wed Jan 28 01:21:33 2004 +0000 Add getpagesize() as a real function -- it's a system call on some platforms and not others. commit 173d724734f81b3245a41822fc27f7556509d826 Author: H. Peter Anvin Date: Wed Jan 28 01:21:33 2004 +0000 Don't strip when building host binaries; it just makes debugging hard commit bae716f920e0aec449896e0e0cc32eb9e3ec6cd6 Author: H. Peter Anvin Date: Wed Jan 28 01:20:13 2004 +0000 Fix memory-trashing bug commit db200a085b78b58343ad02b670a25288861aed70 Author: H. Peter Anvin Date: Wed Jan 28 00:55:38 2004 +0000 0.99 released, next version is 0.100 commit 81cec7bde4ff55a28d3a9e3c71b5d488378eeac4 Author: H. Peter Anvin Date: Wed Jan 28 00:53:52 2004 +0000 Correct the definition of stdin, stdout, stderr; make __create_file() a macro so it can be used in static initializers commit 66ddaafef221825f3affff6fdc8b65a2e9bb944d Author: H. Peter Anvin Date: Wed Jan 28 00:53:52 2004 +0000 Correct the handling of DIR in dependency analysis -- we weren't actually picking up any dependencies at all! commit 325cd8e262ebbb12414bf4a31e5d1abcb0ae5b44 Author: H. Peter Anvin Date: Wed Jan 28 00:45:24 2004 +0000 Dependency fix from Olaf Hering commit 55650420952e7afc73f966332c45c57018011a1c Author: H. Peter Anvin Date: Mon Jan 26 20:01:15 2004 +0000 0.98 released, next version is 0.99 commit 8bb0e67a8035060886b838a0792f373748692c51 Author: H. Peter Anvin Date: Sun Jan 25 07:49:39 2004 +0000 Add getpagesize() commit da153eda8ba5149a5a612b5ebbc8df1a9b1a2586 Author: H. Peter Anvin Date: Sun Jan 25 07:49:39 2004 +0000 Correction: return __v not return v commit 4074472a965caeee45d740b41f2db0717d939fae Author: H. Peter Anvin Date: Sun Jan 25 01:36:03 2004 +0000 0.97 released, next version is 0.98 commit dd83e842761f6e938373fa015b9fa79c16560e94 Author: H. Peter Anvin Date: Thu Jan 22 21:07:54 2004 +0000 i386, x86_64: add basic I/O operations commit 421ff35c0f20ad784d834f51343582e5d9c3fe0b Author: H. Peter Anvin Date: Thu Jan 22 21:07:54 2004 +0000 Update path to the errno files commit 048400dd3de43328700a228831ad3c1feff2fe15 Author: H. Peter Anvin Date: Thu Jan 22 20:58:48 2004 +0000 0.96 released, next version is 0.97 commit b773ab16a84acfc6b0d47a96c9c4d46d878be016 Author: H. Peter Anvin Date: Wed Jan 7 01:17:11 2004 +0000 Change the mapping of file descriptors to FILE * commit 80c2ed5478b86e465312a81f603d0178cdd94298 Author: H. Peter Anvin Date: Wed Jan 7 01:17:11 2004 +0000 Add true, false commit 8ce4e158c4ee01c81469e5b50ba8f56dc582b206 Author: H. Peter Anvin Date: Sat Dec 27 07:44:24 2003 +0000 0.95 released, next version is 0.96 commit cf2f55a458b15fa26fad265e224f3a2a9978c837 Author: H. Peter Anvin Date: Sat Dec 13 21:14:14 2003 +0000 Add fchmod() commit 02c5b9219ab48dda18e37ccd4c531cea19ca858c Author: H. Peter Anvin Date: Sat Dec 13 21:14:14 2003 +0000 0.94 released, next version is 0.95 commit a30e5de49f79d1d04f83747c6cf70c3b4e45ea29 Author: H. Peter Anvin Date: Sat Dec 13 21:11:26 2003 +0000 s390 needs libgcc substitute, apparently commit 5f9c7ad4868bfec110868557d8acfdbda9293544 Author: H. Peter Anvin Date: Sat Dec 13 21:11:26 2003 +0000 Cosmetic fix commit edbc85b5bc151aa208aaa68f8943fe1c9cb63109 Author: H. Peter Anvin Date: Sat Dec 13 03:44:22 2003 +0000 0.93 released, next version is 0.94 commit 5e8b3b3925583e4a698d61fef7d57b5609000856 Author: H. Peter Anvin Date: Sat Dec 13 03:39:13 2003 +0000 Make sig_atomic_t() a global declaration commit 567e2850389caa7b06974b7c940fb418c2c9f524 Author: H. Peter Anvin Date: Sat Dec 13 03:39:13 2003 +0000 ppc64 support from Marcus Meissner and Olaf Hering commit de5afac259923bcdc1f7b820e4c4cff1a999d693 Author: H. Peter Anvin Date: Mon Dec 8 19:38:38 2003 +0000 0.92 released, next version is 0.93 commit 6a29c3559cb89c1cafb35495b03e548f10b165ac Author: H. Peter Anvin Date: Mon Dec 8 19:35:38 2003 +0000 Use our own libgcc intrinsics on IA64 commit 75e74b48204e0967ca151aa681641c1dff498888 Author: H. Peter Anvin Date: Mon Dec 8 19:35:38 2003 +0000 Pass r7 as the onexit pointer to __libc_init commit 04b918c70d2d29524885c5c9e8bb18f144a63dff Author: H. Peter Anvin Date: Mon Dec 8 19:34:20 2003 +0000 Use our own libgcc elements on ppc (Olaf Hering) commit 6ef5677dd776b1b4d0859d8460e029461597de1e Author: H. Peter Anvin Date: Mon Dec 8 01:47:36 2003 +0000 0.91 released, next version is 0.92 commit 17ad9c6d7879ef4ff20dbcd96af96a67ca98d400 Author: H. Peter Anvin Date: Mon Dec 8 01:44:27 2003 +0000 Don't define ntoa() unless we're debugging commit 6798b7a2fb43c03a04ce31c9cc82200cbe25ec68 Author: H. Peter Anvin Date: Mon Dec 8 01:44:27 2003 +0000 Suppress nuisance warnings for testvsnp.c commit 1f487befbb2fcd9e7c1cbae3d613c0fda1562ab7 Author: H. Peter Anvin Date: Mon Dec 8 01:40:15 2003 +0000 Add constipation to avoid nuisance warnings commit c3de6a0ed97fcff3a74ca632b7ef18a607c841b5 Author: H. Peter Anvin Date: Mon Dec 8 01:36:50 2003 +0000 Kill off nuisance warning commit 770bd4975bc5ba83a9d8f38561e8d91463fe7cd4 Author: H. Peter Anvin Date: Mon Dec 8 01:33:24 2003 +0000 Add missing typecast to quiet warning commit 9aeefe83407e7cc8bc1faf18febbe4353842e693 Author: H. Peter Anvin Date: Mon Dec 8 00:56:28 2003 +0000 Remove unused variable commit fcc114e69cb6299dc87b6c3069a859c775c98961 Author: H. Peter Anvin Date: Mon Dec 8 00:53:56 2003 +0000 Fix strncmp() and strncasecmp() so it returns the same values as strcmp() and strcasecmp() str[n]casecmp() don't need to make a copy of the target string!!! commit a371b8ef33899546b6f2a736d9817c2c05c8ad12 Author: H. Peter Anvin Date: Mon Dec 8 00:40:01 2003 +0000 Shut up warnings. commit dbc9d0629db300a6db37ad9ae32fbf17b5f329b3 Author: H. Peter Anvin Date: Mon Dec 8 00:37:07 2003 +0000 Add an __unusedfunc compiler directive commit 98f57671bc2e11149e65d25944ce9e96afdf32d0 Author: H. Peter Anvin Date: Mon Dec 8 00:36:33 2003 +0000 fread() and fwrite() are present in the library, so they should be extern inline, not static inline commit 7565568dc79f1fa3ec7ea349c4b0170bdcb3b3c4 Author: H. Peter Anvin Date: Mon Dec 8 00:06:08 2003 +0000 0.90 released, next version is 0.91 commit 2fc1d1fb6217b8485d0dac47abe78c3822e8e3f5 Author: H. Peter Anvin Date: Mon Dec 1 18:58:46 2003 +0000 From Olaf Hering: I should have looked earlier at this spec. This patch is required to not overwrite the argv[0]. The stack is linked and a new function will write its address into the previous frame. If _start doesnt adjust the stack, __libc_init will write its address to elfdata+4 which is argv[0]. This patch allocates just one frame to avoid this corruption. commit 801adce33d992bb7aab2c4372d0c1df4bbae2358 Author: H. Peter Anvin Date: Mon Dec 1 18:58:46 2003 +0000 0.89 released, next version is 0.90 commit 4b61bce76a88e136e2e8eb430a2beca90239586b Author: H. Peter Anvin Date: Mon Dec 1 18:48:12 2003 +0000 rpm -ba doesn't work because we don't have a "real" source distro commit a392be18509499c01b8a73ad6796f20b8050cb88 Author: H. Peter Anvin Date: Mon Dec 1 18:48:12 2003 +0000 Auto-incorporate the version number when building an RPM commit 5ca8c5b5aef0ae00f8601d5bded1d5bf21cedced Author: Bryan O'Sullivan Date: Sun Nov 30 06:38:56 2003 +0000 RPM packaging. commit 7243c02ed8acc6b31e035951bacd7468b43fab2b Author: Bryan O'Sullivan Date: Sun Nov 30 03:17:05 2003 +0000 From: Olaf Hering Subject: Re: [klibc] [PATCH] ash not make -j safe, make spotless updates > > here is a better patch. > > It adds the kinit dependency, and another one to sh.shared. > > These patches don't apply against CVS or BK head, presumably because of > earlier patches you sent in. This patch fits on the current bk. commit b0c0e3960c8b867cbe48a7daef063f6dc4efc0ed Author: H. Peter Anvin Date: Sun Nov 30 01:11:17 2003 +0000 0.88 released, next version is 0.89 commit accaee150add27c65011d77328cc09524fa67ccc Author: Bryan O'Sullivan Date: Sat Nov 29 06:17:07 2003 +0000 From: Olaf Hering Subject: [klibc] [PATCH] update crt0.S on ppc32 The _start stuff was changed some time ago, but ppc was not updated. This fixes klibc for me. I'm not sure what to do with the second arg to __libc_init, so I set it to 0.. However, looking at other static binaries, there is more stuff todo. commit a9f93546d6151c1a82c88ad3a68a4dfb3cf8e01a Author: Bryan O'Sullivan Date: Sat Nov 29 06:17:07 2003 +0000 From: Olaf Hering Subject: [klibc] [PATCH] Makefile dependencies ash/sh depends on crt0.o, but it has no dependency, so it will not see updates to the changed file. commit cda211b6a1536407d05c6f918b71ffbddc02bc8e Author: H. Peter Anvin Date: Wed Nov 26 19:05:34 2003 +0000 Use rm -f for cleanup commit ae14230a6c059e8398be656033d77778a1373bbe Author: H. Peter Anvin Date: Wed Nov 26 19:04:19 2003 +0000 Actually include the generated dependencies commit d2ac830f4a6feb5651c235e6b064fc6843cc611e Author: H. Peter Anvin Date: Wed Nov 26 19:03:11 2003 +0000 Don't use early-binding := unless absolutely required. ESPECIALLY don't use it for MAKEDEPS and CFLAGS, since they embed a late-binding construct ($*). commit c2cd7a938c5c245eb6f943dd8fa401fcb88bf7ba Author: H. Peter Anvin Date: Wed Nov 26 18:58:41 2003 +0000 Add "make spotless" target. commit 904f907010a9e71a46d37e3c3f3503f1ecec6a9c Author: H. Peter Anvin Date: Wed Nov 26 17:10:30 2003 +0000 0.87 released, next version is 0.88 commit 94a47c241fe5f4d00a14b5fc45c3d07cb99603ea Author: H. Peter Anvin Date: Mon Nov 24 22:09:04 2003 +0000 Switch to new 2.6 module interface -- much cleaner commit 2c7dabc54464a513a4dd13ccb7958597fded231d Author: H. Peter Anvin Date: Mon Nov 24 22:09:04 2003 +0000 0.86 released, next version is 0.87 commit 79b071e5acba1a3bc6e6e4c8e354e0b1630676fb Author: H. Peter Anvin Date: Mon Nov 24 22:07:26 2003 +0000 Add pipe.c missing from previous checkin commit 8fede992df66061c37671ed1e7b44e5321837c65 Author: H. Peter Anvin Date: Mon Nov 24 22:07:26 2003 +0000 0.85 released, next version is 0.86 commit 3b213efa33b27691785da9bde1a5e5a4d23892a8 Author: H. Peter Anvin Date: Mon Nov 24 20:15:30 2003 +0000 Fix pipe() for IA64 commit 2f9816c7278c43b53428fdb84949620b35610bee Author: H. Peter Anvin Date: Mon Nov 24 20:15:30 2003 +0000 0.84 released, next version is 0.85 commit 807b63b96df949811450086ff12b466dd007bdd1 Author: H. Peter Anvin Date: Mon Nov 24 20:09:35 2003 +0000 Fix ia64 mismerge commit 97851bcd0cd6696694ec35859ed46bb724400be4 Author: H. Peter Anvin Date: Mon Nov 24 20:09:35 2003 +0000 Add library functions for the benefit of udev commit c9d0f7d53970e01e428f977c7e4e2f296e144bea Author: H. Peter Anvin Date: Mon Nov 24 20:06:38 2003 +0000 Add sig_atomic_t (from mort) commit eb182225ce97b0eff3c28760f8e00eab6afe5d99 Author: H. Peter Anvin Date: Mon Nov 24 00:41:03 2003 +0000 0.83 released, next version is 0.84 commit 3357167cd5e4c92c104f2c30c3cf97ca9455098f Author: H. Peter Anvin Date: Sun Nov 23 21:47:34 2003 +0000 Add IA64 support from Martin Hicks commit b1ad4c0b8a2c876ae2270e5ad4b1cffbb7eb28b8 Author: H. Peter Anvin Date: Sun Nov 23 21:47:34 2003 +0000 0.82 released, next version is 0.83 commit 6ffe26a3fda44ebecee6b18cc5fb363bbdb1a381 Author: H. Peter Anvin Date: Wed Nov 19 20:32:08 2003 +0000 Add ftruncate() and vsyslog() from gregkh via mort commit 5b8b6534e42c3937d92cc80da9d959e7bc9a8b70 Author: H. Peter Anvin Date: Wed Nov 19 20:32:08 2003 +0000 Specify mode when opening a file using dd [Martin Hicks] commit 7befbd91f394ecfe340a5a3958b14eef9d80bf01 Author: H. Peter Anvin Date: Wed Nov 12 07:55:25 2003 +0000 Fix incorrect promotion to unsigned commit c342d1190a999cc0bd6558a421b5fae144ad7966 Author: H. Peter Anvin Date: Wed Nov 12 07:47:40 2003 +0000 Add missing control character to ctypes.c -- fix alignment of array commit c78943c673114cf6014d79be658894155246b11d Author: H. Peter Anvin Date: Thu Oct 16 05:42:42 2003 +0000 0.81 released, next version is 0.82 commit 426623eb9cecff8c912057fd4c432e9b7cf217e6 Author: Bryan O'Sullivan Date: Tue Jun 10 04:28:46 2003 +0000 Fix build with kernel 2.6.0-test7. commit ffbf23cd3f42d03528bff4a254ac0187695561cb Author: Bryan O'Sullivan Date: Tue Jun 10 04:28:46 2003 +0000 Pass appropriate arguments to gcc 2 and 3. commit bce244a43b3e2352b8d6f644c46a4da32808b0db Author: Bryan O'Sullivan Date: Mon Jun 2 22:21:58 2003 +0000 SH support, from Paul Mundt. commit 7c02fedaeaa82c9d095346d83f24b22ba8167230 Author: Bryan O'Sullivan Date: Sun Jun 1 06:21:09 2003 +0000 God, I hate using CVS. New file. commit 308f343a79e3996b10514f2bb17f141591e17f8a Author: Bryan O'Sullivan Date: Sun Jun 1 06:18:41 2003 +0000 Bring kinit up to the point of being able to moutn all filesystem types, not just nfs. It's now a replacement for linux/init/do_mounts.c. Much new code based on Kai Germaschewski's earlier work. commit 64e2291331291e6e2d8a28d5a69098f9f3cd7a4e Author: Bryan O'Sullivan Date: Sun Jun 1 06:16:49 2003 +0000 Add common definitions to unistd.h. commit 44d82ce4f423df5142fb22ecf37116f60c7a50f1 Author: Bryan O'Sullivan Date: Sun Jun 1 06:16:12 2003 +0000 Bring sanity to OPTFLAGS. Turn off -fomit-frame-pointer, which is worse than useless, and use new names for other directives. commit e50ddd4b25eda109447c4d12dfdb1ff733f2f976 Author: Bryan O'Sullivan Date: Thu May 22 22:26:16 2003 +0000 Mount /proc and /sys. commit 9f41bf182181bf1f431a3181f30e63889071a948 Author: Bryan O'Sullivan Date: Thu May 22 20:24:51 2003 +0000 This file somehow never got committed. commit 8602596a412c4cfec366a0c34d99e5ec7eb72a81 Author: Bryan O'Sullivan Date: Mon May 5 22:15:09 2003 +0000 Get kinit working for nfsroot replacement. commit ac66c4621f710fec4ec71ef21bb9c3d92a78298c Author: Bryan O'Sullivan Date: Mon May 5 06:06:50 2003 +0000 Get client working with NFSv3, UDP and TCP. commit 3aa92aad328346c13f9909ce5b3f03eb8ff9a956 Author: Bryan O'Sullivan Date: Fri May 2 23:41:51 2003 +0000 kinit commit d88bef5bb32dc0d24fc5835faccb73563e4c7062 Author: Bryan O'Sullivan Date: Fri May 2 23:37:39 2003 +0000 nfsmount: v2/tcp commit c766ac9a8a53bc86e852a7bc556821534909f46d Author: Bryan O'Sullivan Date: Fri May 2 23:36:37 2003 +0000 Added nfsmount. Works with NFSv2 over TCP right now. commit 81397c3b1e77928b75bf2bd8d4cc59b9966592e3 Author: Bryan O'Sullivan Date: Fri May 2 22:15:18 2003 +0000 Added bindresvport. commit 7fb384f312b4528f47d00b6f39b205c7582c8d97 Author: Bryan O'Sullivan Date: Thu May 1 19:10:35 2003 +0000 Allow ipconfig to configure all interfaces, and to run as part of another statically linked executable (yes, through a gross hack). commit 4f754b6d02a703863f0fb4ed9086307b0695e208 Author: Bryan O'Sullivan Date: Wed Apr 30 22:13:02 2003 +0000 Rusty CVS user forgets to add file. Film at 11. commit cbfabbe1dbc0f1ed7da67c4e1d94bf7983c7406a Author: Bryan O'Sullivan Date: Wed Apr 30 22:12:09 2003 +0000 Fix erroneous definition of bootp/dhcp xid. commit 13d0582902e295e704d49871eaf7ede23324a038 Author: Bryan O'Sullivan Date: Wed Apr 30 21:34:30 2003 +0000 Major surgery on ipconfig: get static configuration working, and accept the same kinds of command line parameters as the kernel. We now build ipconfig as part of the regular build. Make the Perl stub generators complain when they encounter problems, instead of dying silently. The ipconfig README now reflects the current state of ipconfig properly. commit 7255ac1c2f70d2db86b0fc2793de59468b68ae0a Author: H. Peter Anvin Date: Tue Apr 29 23:44:26 2003 +0000 Remove blank line in order to test klibc-cvs mailing list commit 280c2c5c0e7e9f83c9f177d72572d567c7cef3df Author: H. Peter Anvin Date: Mon Apr 28 22:30:46 2003 +0000 Fix ipconfig typo; patch from Bryan O'Sullivan commit 12c0ffb5ea4b52fff011867a950644ffb5890c87 Author: H. Peter Anvin Date: Sat Apr 26 04:58:43 2003 +0000 0.80 released, next version is 0.81 commit 8877601a6d76fe3d67a2d0fc34a1b7927dbe662b Author: H. Peter Anvin Date: Wed Mar 5 05:39:26 2003 +0000 Fix for include/sys/types.h due to posix timers being added to kernel. commit 6f9da1d766e698ea94ca0d13bb915b11f3bacab6 Author: H. Peter Anvin Date: Wed Mar 5 05:39:26 2003 +0000 0.79 released, next version is 0.80 commit 8bbed43af3db1d241095d9735e41ad1610bc6da1 Author: H. Peter Anvin Date: Fri Feb 28 06:18:39 2003 +0000 License description file commit 81356bd45232889c72dce4bace9a0706207e6843 Author: H. Peter Anvin Date: Fri Feb 28 06:18:39 2003 +0000 Set CLOEXEC flag on syslog file descriptor commit ce48432f72a6e1cc24d0e0ebdc7229fff22eaa60 Author: H. Peter Anvin Date: Fri Feb 28 05:32:20 2003 +0000 0.78 released, next version is 0.79 commit 1c6bf555158e0a3ea31401d1164b717b4f1f2445 Author: H. Peter Anvin Date: Fri Feb 28 05:18:55 2003 +0000 Add system() commit 0ff2032c6186ac00f1f63f30f88643c48d46bbd8 Author: H. Peter Anvin Date: Fri Feb 28 05:18:55 2003 +0000 Alpha setjmp() fix: save/restore the saved FP registers commit 533f4e2daaf7ca677b93f53c5c53626ee7783a79 Author: H. Peter Anvin Date: Mon Feb 10 11:05:21 2003 +0000 Build a shared version -- still rather hacky, need to clean up the Makefileage for shared stuff. commit 45390140a066eb150df3db638cfc0b36ca659053 Author: H. Peter Anvin Date: Fri Feb 7 05:58:33 2003 +0000 0.77 released, next version is 0.78 commit f125ff756292325533b0f61508652e1ba4f5becc Author: H. Peter Anvin Date: Fri Feb 7 05:56:35 2003 +0000 Define __KLIBC__ only if it's not already defined commit 5da1c2f1b55e5f2849679b8dcb91b7ffe74893f2 Author: H. Peter Anvin Date: Fri Feb 7 05:56:35 2003 +0000 Add -D__KLIBC__ commit 32962f1dadf7dacd565a48db8a2a8af3745a43c2 Author: H. Peter Anvin Date: Wed Feb 5 04:12:43 2003 +0000 0.76 released, next version is 0.77 commit 2d429f7fa4fbc369b3207d395effb28cd6de0a30 Author: H. Peter Anvin Date: Wed Feb 5 03:00:38 2003 +0000 Don't rely on Digest::MD5, instead use a local implementation of SHA-1. commit c705349b61be10db19ba9f71cd2b65c449fddee7 Author: H. Peter Anvin Date: Wed Feb 5 03:00:38 2003 +0000 0.75 released, next version is 0.76 commit a5853a69dc4ac1c5b7bd7691715c25413787fa4d Author: H. Peter Anvin Date: Tue Jan 28 04:52:41 2003 +0000 Null-terminate the result of a %[..] format commit a9d4ee0def5ce30b7b7e6662cabc15da7ab3db9e Author: H. Peter Anvin Date: Tue Jan 28 04:52:41 2003 +0000 0.74 released, next version is 0.75 commit ee8b6e2236c74b39d07b8d6fb2761ac08a17ebdf Author: H. Peter Anvin Date: Tue Jan 28 04:14:23 2003 +0000 Update information for how to port to a new architecture commit 2b2952fdbd76978cc864a870758b79ae33a20048 Author: H. Peter Anvin Date: Tue Jan 28 04:14:23 2003 +0000 0.73 released, next version is 0.74 commit 5fc07e76452fcdd18c8b3bc9eb52dc9cd9e092a7 Author: H. Peter Anvin Date: Tue Jan 7 05:38:41 2003 +0000 Correct old bogosity commit c463163248d42b6142538416007905c71e28356d Author: H. Peter Anvin Date: Tue Jan 7 05:38:41 2003 +0000 0.72 released, next version is 0.73 commit d55a12d59a7f5318a69a90f75f49a0e91cd08b3a Author: H. Peter Anvin Date: Tue Jan 7 05:21:24 2003 +0000 Add [f]getc() and fgets() commit c81f84914c27722423ea4fc336bdea7f7e437331 Author: H. Peter Anvin Date: Tue Jan 7 05:21:24 2003 +0000 0.71 released, next version is 0.72 commit 99f7621951a63681f478bd28a518924829f77054 Author: H. Peter Anvin Date: Fri Nov 15 07:33:51 2002 +0000 Clean up signal handling slightly commit 75fc627977994868206aa366caa98daf904a16dc Author: H. Peter Anvin Date: Fri Nov 15 07:33:51 2002 +0000 0.70 released, next version is 0.71 commit e67d0c90d75edf1aecdd9b8f4ec0bfa3d5141f86 Author: H. Peter Anvin Date: Fri Nov 15 05:07:50 2002 +0000 x86_64 now works (with kernel patch) commit c4dff5a61da1b2a0b7aba4c3b108eac53940789e Author: H. Peter Anvin Date: Fri Nov 15 05:07:50 2002 +0000 Changes to support x86-64 commit bcf13fe8d93f123f99a2732f5bb2fc750c07261a Author: H. Peter Anvin Date: Fri Nov 15 04:23:33 2002 +0000 likely() and unlikely() commit 221ae2a73dc11d812c41c2939bb1a4f77b6144b8 Author: H. Peter Anvin Date: Tue Oct 22 00:48:36 2002 +0000 0.69 released, next version is 0.70 commit 02e98d346659daab6d94bceea3a63a4e9b7a42f1 Author: Russell King Date: Mon Oct 21 23:43:53 2002 +0000 Add a file which contains the klibc version number commit 7a3251a72df48b7daaed95dd93219f29800e5af4 Author: Russell King Date: Mon Oct 21 23:43:53 2002 +0000 Add ipconfig (dhcp/bootp network configuration) commit 8517858e43f52e771521cce7c0e59e055a69447b Author: Russell King Date: Mon Oct 21 23:17:38 2002 +0000 Fix fstype for 2.5.44; supply our own ext3_fs.h commit 816c747146609cad639feb845dc66019e9674c4c Author: Russell King Date: Mon Oct 21 23:15:10 2002 +0000 Add netinet/ip.h and netinet/udp.h commit 83340626d895e3117d0e3d8a42cdec83ca8ab441 Author: Russell King Date: Mon Oct 21 23:11:06 2002 +0000 Add net/if.h, net/if_arp.h, net/if_ether.h, net/if_packet.h commit 4aa8c54c1ee7beb93e724449c0311b430b48111a Author: Russell King Date: Mon Sep 16 16:47:55 2002 +0000 Add gcc support functions for 32-bit and 64-bit mod/div. commit dc816d513710554a8f16bac79c4ed015e3999144 Author: Russell King Date: Mon Sep 16 16:45:47 2002 +0000 Add gcc support functions for 32-bit mod/div commit 7599d58d8487bc608b6f15b81dda6fa5e1a7bcad Author: H. Peter Anvin Date: Wed Sep 11 05:00:58 2002 +0000 Be a little more anal about the definition of these... commit 320a6e99b10998fe3e0eff31b7ac81a65abdf9e9 Author: H. Peter Anvin Date: Wed Sep 11 05:00:58 2002 +0000 Move setresuid/setresgid to explicit definition due to SPARC commit df8f8eb3f0db378b288ede9f3cdf36ad70644766 Author: H. Peter Anvin Date: Tue Sep 3 01:02:29 2002 +0000 Update sparc/sparc64 status: shared works with a fixed binutils commit 7fe50dedf74e27b0bdb658a6614e4086383df2f6 Author: H. Peter Anvin Date: Tue Sep 3 01:02:29 2002 +0000 S/390 shared support; remove redundant Makefile include commit aff3e6d104bb092b1072988932e3a06383d1faad Author: H. Peter Anvin Date: Tue Sep 3 01:02:29 2002 +0000 Make it a specifiable option where the shared klibc lives. Update information on working platforms (Alpha works 100% including shared) commit 615a4e7cfe1f9a70605e699cff3f3812b8c5e30a Author: H. Peter Anvin Date: Tue Sep 3 01:02:29 2002 +0000 Comments are more useful when they're correct commit e768df62b90c9136b556a3b222c6874ddbce662a Author: Russell King Date: Mon Sep 2 22:44:13 2002 +0000 Make dd close both in and out fds when done, reporting any errors found commit d721822e5a0f3d3ccfbd63f57db1cb2b50b017b9 Author: Russell King Date: Mon Sep 2 22:44:13 2002 +0000 Fix mount_opts parsing (since strcmp changed) commit 3bc33a6ba0f56965b61f9f5d20000b301ef38281 Author: H. Peter Anvin Date: Mon Sep 2 22:43:54 2002 +0000 Disable regparm on i386 since old compilers don't work right with it commit 76b7c3631ef23d4da727ac001661474a07d2f7f3 Author: H. Peter Anvin Date: Sat Aug 31 04:12:57 2002 +0000 Fix inverted return value from memcmp/strcmp commit dab0d3a353c07cd89914ae324c4ca1108bcb6d4d Author: H. Peter Anvin Date: Sat Aug 31 04:12:57 2002 +0000 s390/s390x updates commit 201b17fa1d3e96f5a069a8bd25951484c8980192 Author: H. Peter Anvin Date: Sat Aug 31 04:12:57 2002 +0000 Use C-style comments commit 72778083c83dd780b8ef5d854118acb84951fbd7 Author: H. Peter Anvin Date: Wed Aug 28 07:04:38 2002 +0000 Assign a reasonable address for klibc.so on SPARC32 commit fe8156a35dd54e4757fb3aa8d869632deeba3565 Author: H. Peter Anvin Date: Wed Aug 28 07:04:38 2002 +0000 A better place for the shared klibc... commit f0f207c8e0a38e63b27438f89ba9aa316fea9bae Author: H. Peter Anvin Date: Wed Aug 28 06:41:47 2002 +0000 Save space by misaligning the .so address commit 39fb71aacd88aaba7e54df7b6556a04a979b54d2 Author: H. Peter Anvin Date: Wed Aug 28 06:41:11 2002 +0000 Misalign .so addresses to save space commit 4576e58550d556b3db83bf8bd959dc28d4d62c6e Author: H. Peter Anvin Date: Wed Aug 28 06:28:24 2002 +0000 Alpha fixes: crt0 update; Alpha doesn't have a utime() syscall commit 9d67d9e331729553af87ad83c1dd34d2b8cc119a Author: H. Peter Anvin Date: Wed Aug 28 05:35:49 2002 +0000 setjmp() is supposed to actually return a value commit 4ab3adaa11ca887d20705a3672609bc8425f1e63 Author: H. Peter Anvin Date: Wed Aug 28 05:21:43 2002 +0000 Don't disable libgcc. commit 161d57e4f38337d5c9191d73eb295cd5704634d3 Author: H. Peter Anvin Date: Wed Aug 28 05:21:43 2002 +0000 i386 fixes commit e01e0124002f1e6ff0fb41888013fda03a2e34f2 Author: H. Peter Anvin Date: Wed Aug 28 05:18:24 2002 +0000 __divide_error() definition commit a504f14207713de63fd0bed97eb76442788281d1 Author: H. Peter Anvin Date: Wed Aug 28 05:17:37 2002 +0000 Link address for sparc64 dynamic. commit 674a21437d4fec33ac7bad584f4a2c7c26d0e83b Author: H. Peter Anvin Date: Wed Aug 28 05:16:13 2002 +0000 Make klibc (at least static) work on MIPS. Dynamic doesn't work due to ld problem. commit e54dec13541ab9ce32f49e4daacb6a96dd419ef2 Author: H. Peter Anvin Date: Tue Aug 27 23:30:01 2002 +0000 Fix support for i386 REGPARM commit a18aea3b9c7bb1557d352493249bf73e13511013 Author: H. Peter Anvin Date: Tue Aug 27 23:04:43 2002 +0000 Add libgcc replacement functions. commit 2f6cd4633e623c29bbcb793eff76c8c08c2c0f9c Author: H. Peter Anvin Date: Tue Aug 27 23:04:29 2002 +0000 libgcc replacement functions. commit f66431fb805793fab2459647a935f16b398684c3 Author: H. Peter Anvin Date: Mon Aug 26 20:59:30 2002 +0000 *ATTEMPT* to get regparm compilation to work for i386 commit 2bb6987a3046c7c5170725adba3c2cf7f15b02f8 Author: H. Peter Anvin Date: Mon Aug 26 20:24:25 2002 +0000 More function attribute support; prepare for regparm support (i386) commit 38f661038aceae7f371f12589de1ad7c492bac2e Author: H. Peter Anvin Date: Mon Aug 26 15:10:52 2002 +0000 Add reboot.o commit 57db86e0fa754393e3be2e7f6b43ec95d14b9f51 Author: H. Peter Anvin Date: Mon Aug 26 06:00:34 2002 +0000 Change config options: the i686 optimization option adds code size. commit a85e07743a0dd0c1de0e5650c259b4d34e8b9236 Author: Russell King Date: Fri Aug 23 23:11:01 2002 +0000 gcc 3.2 issues. asm fixes. Make sure we clean up when we make a new hash. commit 7c07997dd59d9b3fab322f0ab00459d9456b613c Author: Russell King Date: Fri Aug 23 23:11:01 2002 +0000 MIPS updates. commit e3f2c66d03c136c2b96c01c03303ade741b68b74 Author: Russell King Date: Fri Aug 23 23:11:01 2002 +0000 Shared klibc updates commit 4f0bc18bb037ae04d74c64ed708946738238e09b Author: H. Peter Anvin Date: Fri Aug 23 23:04:14 2002 +0000 Make sure we don't end up with slashes in the filename commit ad837bebbb5c0be68b51f74283a0e467780f2113 Author: H. Peter Anvin Date: Fri Aug 23 22:59:07 2002 +0000 Modify the starting point for the shared version commit 98905712c2143d830782f782fb8dfb3ecc4e168e Author: H. Peter Anvin Date: Fri Aug 23 22:53:05 2002 +0000 Add commit 8e2ea873c50f93900de396d2230de0fb3008153f Author: H. Peter Anvin Date: Fri Aug 23 22:40:10 2002 +0000 Added ... needed by the gcc includes commit 199c581253c4a44f2eb11578b1a69dc340f809c7 Author: H. Peter Anvin Date: Fri Aug 23 22:34:17 2002 +0000 Add setjmp.S commit 088ea15c743d2082fd355e92186a2a6ef0a29112 Author: H. Peter Anvin Date: Fri Aug 23 22:07:43 2002 +0000 Update MIPS crt0.S to the new passing convention commit f7c95e4992ab4306468dc8a03f292fa9a3a5b278 Author: H. Peter Anvin Date: Fri Aug 23 21:39:22 2002 +0000 The entrypoint isn't _start on all architectures. Go with the default. commit a112ae7f18f9a09ac2d50cf4820619f2850c9442 Author: H. Peter Anvin Date: Fri Aug 23 21:38:13 2002 +0000 Add commit b17a5299c30db2a996a22dea24489786eb79d717 Author: H. Peter Anvin Date: Fri Aug 23 05:44:48 2002 +0000 Make SRCROOT the basis for relative paths, and let there be where the "linux" link goes. commit 6de81f89dd48e0e89900d4e49c7a0dec8ffdfd28 Author: H. Peter Anvin Date: Fri Aug 23 05:44:48 2002 +0000 Change the x86-64 runtime to the new interface commit 2f500086632f9b4714b3d54a0d96029128c82e0f Author: H. Peter Anvin Date: Fri Aug 23 05:38:54 2002 +0000 Remove unused variable; port the SPARC initialization code. commit 4b11006fe95ec6e85899d618b1d19ebc3e79a222 Author: H. Peter Anvin Date: Thu Aug 22 23:53:51 2002 +0000 "Shared but not dynamic" klibc checkin -- breaks all arches but i386 until crt0.S has been updated to match... commit bdddc6ef48ec5b1a5208d06af58163ae8fa487e6 Author: H. Peter Anvin Date: Thu Aug 22 23:44:44 2002 +0000 Shared-but-not-static klibc (for i386 only so far...) commit a208472f9535ab629aa2f7b6c0575f389a0d0863 Author: H. Peter Anvin Date: Wed Aug 21 18:44:44 2002 +0000 Clean up setjmp/longjmp bogosity. commit 011529d0afff7706a97c78d94118b572f1ac2c07 Author: H. Peter Anvin Date: Wed Aug 21 18:44:44 2002 +0000 Add "const" and "unsigned" where needed commit 8b158b7aef1174687c90ec3b985c79baa8236c59 Author: Russell King Date: Wed Aug 21 14:12:10 2002 +0000 Add ARM setjmp and exits.S support. Add Thumb equvalents. commit a346a45f0e1f853a3e0c06a650db918b51696bcd Author: Russell King Date: Wed Aug 21 10:40:08 2002 +0000 Add memmove.o to klibc object lists. commit 6048ccaf8126b55c100249e54aed9e98ab5c6745 Author: Russell King Date: Wed Aug 21 08:43:35 2002 +0000 Add couple of extra utilities - dd and fstype. dd supports most of POSIX bits except for block/unblock conversions. fstype detects the type and size of the filesystem passed on its stdin, emitting a couple of expressions suitable for use in eval to set shell variables. This allows us to automatically detect the filesystem type when rootfstype= isn't specified, and when we're loading a ramdisk (via my load_ramdisk script) we can work out if we need to gunzip it first, and in the case that we don't, we know how many 1K blocks to ask dd to copy for us. commit 70cb087c66d29b965ffe65011e5d878bed5a6687 Author: Russell King Date: Wed Aug 21 08:38:07 2002 +0000 Add dependency generation and use to {ash,gzip,utils}/Makefile commit 1df584edc344050d881c40f854e01a5eae033bc0 Author: Russell King Date: Wed Aug 21 08:27:29 2002 +0000 If we're going to have separate mount/nfsmount commands, I guess we should re-use the option parsing we have for our mount command. So, this patch splits the mount option parsing code from mount.c MS_MOVE is now in sys/mount.h, so remove it, and add MS_DIRSYNC option. Add dirsync mount option to mount_opts.c commit 581a5b5e6b3938dfc8aad30e4faa0eee616dfb4b Author: H. Peter Anvin Date: Wed Aug 21 07:56:58 2002 +0000 Test of memset() and memcpy() commit b6f9894387ff511d7a03d7ae601c28330fc9881b Author: H. Peter Anvin Date: Wed Aug 21 07:55:31 2002 +0000 Greatly clean up the i386/x86_64 assembly versions of memset/memcpy commit 4590fea82c3bba1d3ebd6dd35d86a68436beba9e Author: H. Peter Anvin Date: Mon Aug 19 03:24:47 2002 +0000 Lots of fixes from rmk. x86-64 fixes from Mats Petersson. commit a661dd750337971c837cdadb45ac8e92b82bf43a Author: H. Peter Anvin Date: Mon Aug 19 03:24:47 2002 +0000 Add missing backslashes commit aa62551b4db9dd218251d6e5d5bae4f36f229821 Author: H. Peter Anvin Date: Mon Aug 19 03:24:47 2002 +0000 The ABI document is correct w.r.t. _syscall5(). commit 069a8afdaaf23414e7c5c5325f20fd4a7b80b1cf Author: H. Peter Anvin Date: Mon Aug 19 03:24:47 2002 +0000 Make sigsetjmp() a macro, and siglongjmp() a function commit 64db70cc9b2de953138927adc58da429536c83ec Author: H. Peter Anvin Date: Mon Aug 19 00:04:02 2002 +0000 rmk: Correct digit detection. commit fd8b7acb898445bfd0b9a78705a62562ac7fd5c9 Author: H. Peter Anvin Date: Sun Aug 18 22:24:38 2002 +0000 Add commit b2c404ea503f5712a59c34ec6ae1e5acb781b28b Author: H. Peter Anvin Date: Sun Aug 18 20:48:12 2002 +0000 rmk: Patches for some old utilities. commit 1f72ddea76da0143e93f4e0fc794c6dac11603f2 Author: H. Peter Anvin Date: Sun Aug 18 20:48:12 2002 +0000 Add script to make sys_errlist[], but don't actually compile it for the time being. commit 95e88a4354f7ea509e5ad3154b9e8ce2906e9fa1 Author: H. Peter Anvin Date: Sun Aug 18 20:47:44 2002 +0000 Slight correctness fix to siglist.c; add strerror.c but don't actually compile it in at the moment. commit 1f659ba37b108a722661fda429c063b7156878d3 Author: H. Peter Anvin Date: Sun Aug 18 10:11:34 2002 +0000 [rmk]: Warn if we are trying to build against a stale library commit 59fbee96e188686327b120d7a07f37ed57a27871 Author: H. Peter Anvin Date: Sun Aug 18 08:39:24 2002 +0000 Remove reference to %sp which wasn't meant to have been checked in. commit 6bc31836167da03249d92afe398f10665eae55be Author: H. Peter Anvin Date: Sun Aug 18 06:01:48 2002 +0000 Update the state of various ports commit 5d65a65a65af0291bde3aac3f3983545f228b0f5 Author: H. Peter Anvin Date: Sun Aug 18 06:01:48 2002 +0000 Portability improvements; SPARC64 fixes commit 603b4fc5b1bf6e418726abf2f277fce7b973be6b Author: H. Peter Anvin Date: Sun Aug 18 02:58:57 2002 +0000 More SPARC porting work commit 84e5ba6d561186149d6c84739a92bbe92791f8f3 Author: H. Peter Anvin Date: Sun Aug 18 01:36:55 2002 +0000 Add README file commit 871402a08b2a559d636a9ce3b0a9b96d0291e079 Author: H. Peter Anvin Date: Sun Aug 18 01:36:55 2002 +0000 Reverse an accidentally reverse merge :-/ commit 57393b28db831797f7cc433d72a23e2503329885 Author: H. Peter Anvin Date: Sun Aug 18 01:34:31 2002 +0000 Handle SPARC "forkish" syscalls (fork, vfork) commit a1f4443e79da99494c76da3b83a76171b80aefec Author: H. Peter Anvin Date: Sun Aug 18 00:59:21 2002 +0000 Makefile modifications; add root Makefiles commit 61e816644326151754534b57174a00687adf2c3a Author: H. Peter Anvin Date: Sun Aug 18 00:59:21 2002 +0000 From Russell King: gzip ported to klibc commit ec9d2ca469a0a2382a8a1c92b6373ada2ed64295 Author: H. Peter Anvin Date: Sun Aug 18 00:54:50 2002 +0000 Add prototype for perror() commit df8c7338f8d8612868cdb70b7824666ff7f04aa7 Author: H. Peter Anvin Date: Sun Aug 18 00:46:57 2002 +0000 Kill dead function xioctl(). Since we're using SA_RESTART on all signals it shouldn't be needed. commit 331a25bda29b2426f4090e21314b1c711d554ec4 Author: H. Peter Anvin Date: Sun Aug 18 00:40:35 2002 +0000 From Russell King: basic klibc-based utilities commit 1302804a3cdaec896e760e19bd55b7393de294e5 Author: H. Peter Anvin Date: Sun Aug 18 00:39:42 2002 +0000 Fix from Russell King: kill mksyntax.c commit 66d0cc7c4c1fc419c3a87ed5e583af8a8341548c Author: H. Peter Anvin Date: Sun Aug 18 00:37:19 2002 +0000 From Russel King: fix strsep(), add perror() commit 7057210ec6aeb6898c6d3336127624adbd5bd1e0 Author: H. Peter Anvin Date: Sat Aug 17 12:05:55 2002 +0000 Use a standard mnemonic for copying a register. commit 4f11b640e88024ddb34a6bb7e65efe3bec25229d Author: H. Peter Anvin Date: Sat Aug 17 12:01:31 2002 +0000 One more caveat... no protection against longjmp(...,0); commit 156eb2a65dd14820c58b0e35f7cf1a7ecda85a50 Author: H. Peter Anvin Date: Sat Aug 17 07:18:33 2002 +0000 SPARC fixes: fork/vfork are special; crt0 needs to reserve more space; define NSIG to _NSIG if the former does not exist. commit e2d728a3d0c60a1aa72dcb785027abd38918ced8 Author: H. Peter Anvin Date: Sat Aug 17 07:18:33 2002 +0000 Create own bsd_signal() stub. commit a794998b4bcd3fe5c956d0ddb81156433443a8d0 Author: H. Peter Anvin Date: Sat Aug 17 07:18:33 2002 +0000 We really need to use the trap method for doing stack unwind on SPARC. commit 8c48bdd16532c797d6541d3e1da71a164b5786ab Author: H. Peter Anvin Date: Sat Aug 17 03:07:48 2002 +0000 Remove intermediate file which got accidentally checked in. commit 56df17a094f4a1b8e2e02e5be2dcd60afd52e764 Author: H. Peter Anvin Date: Sat Aug 17 03:04:46 2002 +0000 Caveats for programmers. commit 6ce345a4a0ee58897e2ff9a00c406ab75085de0c Author: H. Peter Anvin Date: Sat Aug 17 03:04:46 2002 +0000 Change __fread() and __fwrite() to _fread() and _fwrite() commit 110ece518bac322465939b7161a88d5ba117a583 Author: H. Peter Anvin Date: Sat Aug 17 01:36:06 2002 +0000 Import ash into the klibc repository commit 9a5f1458ca3d1113f79dc21798dc4d135b7cccc8 Author: H. Peter Anvin Date: Sat Aug 17 01:36:06 2002 +0000 Initial revision commit d1a480f1e259fd9f43c4ef650831644344bdde4c Author: H. Peter Anvin Date: Sat Aug 17 01:30:26 2002 +0000 Generate sys_siglist automatically commit 11ba73ebcb763a8068eb9aa6c3f34da577851295 Author: H. Peter Anvin Date: Sat Aug 17 01:00:41 2002 +0000 %g0 is the zero register, don't use it commit 7a0440c14fd8693a16bc86b0fb61812e2828faf0 Author: H. Peter Anvin Date: Sat Aug 17 00:54:27 2002 +0000 Add setjmp/longjmp implementation commit ef0653fbd3296b67c1d65af0448b416995dd4690 Author: H. Peter Anvin Date: Sat Aug 17 00:43:02 2002 +0000 setjmp/longjmp implementation for SPARC commit 0f7a5dd944c885114b539805c97e325cbbea9b6b Author: H. Peter Anvin Date: Fri Aug 16 23:13:12 2002 +0000 Don't use rt_sig*() calls on architectures which have the standard system calls. commit 23705b823838ac7191269eb49147d6f0c472340d Author: H. Peter Anvin Date: Fri Aug 16 23:13:12 2002 +0000 Add isatty.c commit e7b9fc45f6903dc55e502f9bfbaffa9877609436 Author: H. Peter Anvin Date: Fri Aug 16 23:12:50 2002 +0000 Use sys_sigaction if available; some architectures export an sigset_t that rt_sigaction doesn't like! Add test for setjmp/longjmp commit 79386f27ab4f3157dee08f5d7f1e55f3b678f6f3 Author: H. Peter Anvin Date: Fri Aug 16 23:06:29 2002 +0000 Tidy up the various archsetjmp.h implementations; add setjmp.S for x86-64 commit d3f88816f3dd65222e995f657e071230ed58ae12 Author: H. Peter Anvin Date: Fri Aug 16 22:41:35 2002 +0000 Make setjmp/longjmp for alpha actually work commit 7c3f0dab928c423df95874ef89a43d07c1c0ee34 Author: H. Peter Anvin Date: Fri Aug 16 22:37:28 2002 +0000 Add setjmp implementation for Alpha commit fdb029fe6e59443431eb5cc83d7dd3ab52abccc8 Author: H. Peter Anvin Date: Fri Aug 16 22:31:32 2002 +0000 Add missing #endif commit 62d5ef16fc11b5e46e41ee4c0a5df5c7cb6aa89a Author: H. Peter Anvin Date: Fri Aug 16 22:28:23 2002 +0000 include file fixes; add the i386 implementation of setjmp() commit 005d4313bacd704099976d451a880551dcd77d3d Author: H. Peter Anvin Date: Thu Aug 15 07:02:01 2002 +0000 Fix bugs in ; add basic pty functionality commit 65b8258ec2450938e930ad2fb5993f034dd64c79 Author: H. Peter Anvin Date: Thu Aug 15 07:02:01 2002 +0000 Add missing semicolon :%) commit 774b2eb5a81602d4a4563381a95df3070fa8fc19 Author: H. Peter Anvin Date: Thu Aug 15 07:02:01 2002 +0000 Add a few missing termios functions; correct some casts commit 21d243929559c0f1711bfef02defe023394a823e Author: H. Peter Anvin Date: Thu Aug 15 07:02:01 2002 +0000 Add support for as a bunch of inline wrappers around ioctl() commit 22c4e36ce45d60b9c8f40869100822b390de2c6e Author: H. Peter Anvin Date: Thu Aug 15 07:02:01 2002 +0000 Apparently some architectures have a signed off_t. Sigh. commit 189e42ffa56430f6b2728a3b8ccf41a11383e36e Author: H. Peter Anvin Date: Thu Aug 15 06:48:46 2002 +0000 More accurate instructions... commit bb7ed697de40e0f6b16974dd8ffdbe8886695929 Author: H. Peter Anvin Date: Thu Aug 15 06:48:46 2002 +0000 Add options to make klibc build for sparc64 commit 94c9a6d798a25e2c629eede015435e8facf91ae7 Author: H. Peter Anvin Date: Thu Aug 15 06:36:11 2002 +0000 The multiply .S files are *not* generated commit 3cbc56d7565bc94adcf341ebd9674bb9be83bc8a Author: H. Peter Anvin Date: Thu Aug 15 06:34:25 2002 +0000 Redesign the syscall interface so arch-specific macros are moved to an arch-specific include file commit 6db6026624b16d99205120b466e894d43eefe4bb Author: H. Peter Anvin Date: Thu Aug 15 06:12:04 2002 +0000 Fix routines to they actually work on SPARC. commit 3254a66bb5dade0a09bfd6a2f73a90bfe5eb31ed Author: H. Peter Anvin Date: Thu Aug 15 06:03:43 2002 +0000 Add as needed by assembly code; might be useful in general commit b0200be7f61f1399d90cbb40357c453eaa5c304e Author: H. Peter Anvin Date: Thu Aug 15 05:50:55 2002 +0000 Add div/rem/mul subroutines. commit 8d49440f371b5cfce7ed4f61d9cbabec3a923415 Author: H. Peter Anvin Date: Thu Aug 15 02:05:08 2002 +0000 Add missing SA_* flag aliases commit 36271df72aa65ee913093018f617f5fc6a11d8ec Author: H. Peter Anvin Date: Wed Aug 14 19:55:17 2002 +0000 More MIPS fixes. commit 95f42db3797e2e1c845b6de49437bf4bf623e165 Author: H. Peter Anvin Date: Wed Aug 14 19:55:17 2002 +0000 MIPS patches. commit 6332fe7d2abffbdfb8f256c642a16450ccf9868c Author: H. Peter Anvin Date: Wed Aug 14 11:30:37 2002 +0000 Add memswap(), mostly for the benefit of qsort() commit a328d0df33b16f3fd63b973d60fbedfbc0998d32 Author: H. Peter Anvin Date: Wed Aug 14 11:26:31 2002 +0000 Sizes are size_t; make a comment about the desirability of memswap() commit 2639d4f836beac844bc28ec71e2ec0583c4068e9 Author: H. Peter Anvin Date: Wed Aug 14 11:21:03 2002 +0000 We now only need to set ARCH if we're cross-compiling... commit 17e139e8f5bd5b60bddb43247b52a2df48dec6f5 Author: H. Peter Anvin Date: Wed Aug 14 10:55:38 2002 +0000 Various bug fixes than didn't happen on i386. commit 5e1d1d885969db05444a9d9bfe1bde3fa2ffaaa9 Author: H. Peter Anvin Date: Wed Aug 14 10:55:38 2002 +0000 Special handling of pipe() on alpha commit e6fa6d99ae268af8686eead516adc6087adc0f51 Author: H. Peter Anvin Date: Wed Aug 14 10:45:45 2002 +0000 MIPS fixes; move i386-specific and x86-64-specific files into their respective arch directories. commit 6e3546670779f29d56f8885fa52342b9a983a789 Author: H. Peter Anvin Date: Wed Aug 14 10:01:24 2002 +0000 Make sure the tests .o files end up in the tests directory commit f3b8d9fe6b9bfe9d6467b1b96c3fe3613674ca4e Author: H. Peter Anvin Date: Wed Aug 14 06:00:22 2002 +0000 Add a hlt just in case _exit() would ever return -- it's free because of alignment. commit 947da5fc534cb2c7465a52f507b0f1d6eb936346 Author: H. Peter Anvin Date: Wed Aug 14 05:29:19 2002 +0000 Add fallback to stderr should /dev/kmsg be unavailable commit a48921e396a4c6bcf8ca96d8e735bc94c402efed Author: H. Peter Anvin Date: Wed Aug 14 05:29:19 2002 +0000 New syslog(3) implementation which uses the /dev/kmsg kernel interface commit a904ad39f04952c483c3cd1e0f578392d2bf9d61 Author: H. Peter Anvin Date: Wed Aug 14 04:28:35 2002 +0000 File missing from previous checkin commit c30eb33d8bae133d193d2597faa979687853a7fd Author: H. Peter Anvin Date: Wed Aug 14 04:28:35 2002 +0000 Create syslog() interface to klogctl() commit 8f3ef965346802e1df6cd3c4f1b2f8bb6e3c77d0 Author: H. Peter Anvin Date: Wed Aug 14 02:18:55 2002 +0000 Improve "make clean" commit 2a2d19d07c19369d02b3b16967c945589cc5f6ed Author: H. Peter Anvin Date: Wed Aug 14 00:09:43 2002 +0000 Need for this one commit 86a04e85b7460357cebfdd103a3c9e6d6550e01f Author: H. Peter Anvin Date: Wed Aug 14 00:09:43 2002 +0000 Add -> commit a1c347b720ca003d56bedb3eca04207d0b18c242 Author: H. Peter Anvin Date: Tue Aug 13 22:32:25 2002 +0000 Insert an (untested) SPARC version commit cfaeed5924fdb2bff5efc7412952c4ab12795749 Author: H. Peter Anvin Date: Tue Aug 13 17:51:30 2002 +0000 Special-case socketcalls on i386, esp. since i386 is possibly the only architecture still using socketcalls. It also lends itself to a particular optimization. commit ff1b5f868918563dd89dca9e3682494d1e7bff8a Author: H. Peter Anvin Date: Tue Aug 13 17:51:30 2002 +0000 More warnings cleanups, some of which were actually real... commit d91fd498a9342d1f97f1259052e2844aceb7b8b5 Author: H. Peter Anvin Date: Tue Aug 13 17:51:30 2002 +0000 Add NFS-mouting example. Fix a couple of warnings, and reinstate -Wall. commit 518d17145117caf0dffcc757905e62f603094bec Author: H. Peter Anvin Date: Tue Aug 13 05:09:18 2002 +0000 Add the klogctl ("syslog") system call commit ac323a2d2e69bbb051c9cf81f22a10b2f38350b2 Author: H. Peter Anvin Date: Tue Aug 13 05:09:18 2002 +0000 Define fopen() in terms of fdopen(); define fdopen() as a macro commit e77ea6f04eb774ef5b3fd480980a0d200829a754 Author: H. Peter Anvin Date: Tue Aug 13 05:09:18 2002 +0000 Fix some warnings; improve the stdio emulation. commit 1fe2a686111e246cf9e2189e99e523c68cccfb78 Author: H. Peter Anvin Date: Tue Aug 13 05:09:18 2002 +0000 Files missing from previous checkin... commit dae0fbea1ba63709e39f07e44676cdc249e721c3 Author: H. Peter Anvin Date: Tue Aug 13 05:09:18 2002 +0000 A few more of the inet-address-parsing functions... commit 4c4c0255f2a1c8507ea1ad2d3bab0847383c8e30 Author: H. Peter Anvin Date: Tue Aug 13 03:58:57 2002 +0000 Reorganize: separate Makefile and MCONFIG; move test files to separate directory; fix some minor bugs like no EOF in commit cd89c9bbeb7ca0941b1ee0670b31c269efe99809 Author: H. Peter Anvin Date: Tue Aug 13 03:58:57 2002 +0000 Move tests to a subdirectory commit 6129fd10c2ddae8d673a499819c3542b307db042 Author: H. Peter Anvin Date: Tue Aug 13 03:37:05 2002 +0000 Make sure the rand48 implementation is strictly compliant, even on 64-bit platforms. commit ab0aedb11a3d1710460e004facbadfbcf93b8cc9 Author: H. Peter Anvin Date: Tue Aug 13 01:31:08 2002 +0000 Add the rand48() functions -- needed by zcip commit 9c015e5aacb8f0426f994c5861483a7e0598b2a0 Author: H. Peter Anvin Date: Tue Aug 13 01:31:08 2002 +0000 Make the newgap() operation in combsort an inline. commit fd555e92fe81c33907dea2806c96c84930ad90eb Author: H. Peter Anvin Date: Tue Aug 13 01:19:22 2002 +0000 Add qsort() -- actually a combsort implementation. commit c9bd865c640c7861eb03e5141e5a4c3a7225f718 Author: H. Peter Anvin Date: Mon Aug 12 23:45:27 2002 +0000 Begin to add in functions commit 1230090a12146333c8b362e3ba66eeb4a484cebf Author: H. Peter Anvin Date: Mon Aug 12 22:48:08 2002 +0000 Correct memcmp(), commit 4631d7357fdffd744808959f4505c730dc978bab Author: H. Peter Anvin Date: Mon Aug 12 22:48:08 2002 +0000 Update assembly versions for x86-64 commit 13ae658495538f1f2164654c49656b20355cb967 Author: H. Peter Anvin Date: Mon Aug 12 21:01:31 2002 +0000 Better handling of nice(); add setpriority() getpriority() sched_setscheduler() sched_yield() commit 4eda8fcc9c7e4d209445756e81454e19e3adb3c8 Author: H. Peter Anvin Date: Mon Aug 12 21:01:31 2002 +0000 Add (envp == environ) test to getenvtest commit 6f034c4e310e89791dd65cd0ea1f997019f4e7e0 Author: H. Peter Anvin Date: Mon Aug 12 05:50:49 2002 +0000 S390(x) additions; use _newselect() if available rather than select() commit 2435704db44896a8b4c8f8fec419e43b334f01f5 Author: H. Peter Anvin Date: Mon Aug 12 05:50:49 2002 +0000 README file for porting commit 1322aeac5fa07d2219e3ca5b0fca834b1ae04620 Author: H. Peter Anvin Date: Mon Aug 12 05:50:49 2002 +0000 Add to commit d580c2d25ede73d4a8568e5d3672080082d52246 Author: H. Peter Anvin Date: Mon Aug 12 01:30:55 2002 +0000 The kernels endian handing is better than ours -- use the kernel. commit 4122764ace9a7548677a28ae921a592727a6345a Author: H. Peter Anvin Date: Mon Aug 12 01:30:55 2002 +0000 Add llseek() support -- needed to support things like partition scanning. commit ad6cb3fea7ce96aec76b3d147a43fb330a7ccf93 Author: H. Peter Anvin Date: Mon Aug 12 01:30:55 2002 +0000 Add "idtest" as a test; add missing getgid() prototype to commit 56d3f7016cb23e201efaa8e707bcfab95b30ed95 Author: H. Peter Anvin Date: Mon Aug 12 01:30:55 2002 +0000 Correct the definition of the alpha divide register usages. commit bf5552d0b72ea656ca0a7223fc68e6c66a827c10 Author: H. Peter Anvin Date: Sun Aug 11 10:15:28 2002 +0000 Make the default readdir buffer larger. commit 1eb16e832fa5e2fb74c1a3cc76c0a83d06cd386e Author: H. Peter Anvin Date: Sun Aug 11 05:08:58 2002 +0000 Find the bitsize includes automatically; document new build procedure. commit 45896bdb0fd200046d267cdb3de8520922e469d3 Author: H. Peter Anvin Date: Sun Aug 11 05:08:58 2002 +0000 Move the bitsize definitions down a subdirectory, so we can use an automatic include path to find them. commit 11306fe0139e03a97f5a7a000e39cbbfd8845d1b Author: H. Peter Anvin Date: Sun Aug 11 05:03:37 2002 +0000 Move arch-specific include files before the nonspecific include files commit 29cf68401ed5707d041064ce1addc91a4b3eeca9 Author: H. Peter Anvin Date: Sun Aug 11 04:50:38 2002 +0000 Correct the handling of the byte order macros in netinet/in.h commit 13c7a3fd2452e1806c99105e180385a5fc543244 Author: H. Peter Anvin Date: Sun Aug 11 04:50:38 2002 +0000 Add for hton/ntoh macros commit 5d5d05fc89ebe38c4712367bbc7e617690a87af6 Author: H. Peter Anvin Date: Sun Aug 11 04:50:38 2002 +0000 Move to ; add commit 1518b426ed9ed55087273003b7afbf6b36cae51e Author: H. Peter Anvin Date: Sun Aug 11 04:35:43 2002 +0000 Move to commit 85a0225a5993180b0a57ec6fc949b46547ddcc35 Author: H. Peter Anvin Date: Sun Aug 11 04:30:27 2002 +0000 #define __KLIBC__ 1 commit f2066ea1963a57ae61aacc80f5f2ca29c1a52ec3 Author: H. Peter Anvin Date: Sun Aug 11 04:23:52 2002 +0000 Remove redundant definition of _syscall_clobbers commit 404c996f3d74c1ff0427b43ff9df91e83e0b6d68 Author: H. Peter Anvin Date: Sun Aug 11 04:00:26 2002 +0000 Be more specific about CROSS. commit 771018892e6464363d010a3139fe2026dd40902f Author: H. Peter Anvin Date: Sun Aug 11 04:00:26 2002 +0000 Each architecture needs a Makefile.inc; don't call it Makefile though commit 1960ca321e8bca2bbb114cf565264b32c4808165 Author: H. Peter Anvin Date: Sun Aug 11 03:49:16 2002 +0000 Actually make the weird alpha syscalls to work... commit d3ecf48fed30d5e7a1599fcdec7246898f894491 Author: H. Peter Anvin Date: Sun Aug 11 03:38:06 2002 +0000 Handle dual-return system calls on Alpha. commit 5a92f4e2f09a204c2867644185c7d79c93d05533 Author: H. Peter Anvin Date: Sun Aug 11 02:06:18 2002 +0000 Make the alpha crt0.S actually work. commit ae5b366289bb52e66491691f0de0f4a1c51741ab Author: H. Peter Anvin Date: Sun Aug 11 01:28:58 2002 +0000 More special rules for the divide functions commit aedf4293c7062e9d0446ad318b874e1c70db1507 Author: H. Peter Anvin Date: Sun Aug 11 01:05:36 2002 +0000 Do the $16 <-> $24 swap *correctly* commit 3d1ef8af0498ec05d0b7743f14e958c6ccc1b8af Author: H. Peter Anvin Date: Sun Aug 11 01:00:21 2002 +0000 Handle flags a bit differently. commit dc2d163af5cbdc47a7d8835fcb6fe80b691524ad Author: H. Peter Anvin Date: Sun Aug 11 00:48:04 2002 +0000 Add archclean target commit 9b77021d2d1859ec177ab663a71b619e560779ab Author: H. Peter Anvin Date: Sun Aug 11 00:47:01 2002 +0000 Learn to create .ls files from .lss commit b3b5319dbe7841ece4242186d54baf305690c086 Author: H. Peter Anvin Date: Sun Aug 11 00:44:41 2002 +0000 Fix names and types of divide subroutines commit 8df05562416544cb8522e5b749aaa7e30cefa4c4 Author: H. Peter Anvin Date: Sun Aug 11 00:41:40 2002 +0000 $'s need to be escaped in makefiles commit 801257eef95ab0ec25f06ff1ef6e74726535f368 Author: H. Peter Anvin Date: Sun Aug 11 00:41:00 2002 +0000 Correct the definition of ARCHOBJS et al commit 72b60a3cb1fa5c1a12f1824186c27cbaad9395ec Author: H. Peter Anvin Date: Sun Aug 11 00:38:30 2002 +0000 "all" must be the first target commit fdd498b1179d63b700ae0bc057bebb9d014dabe2 Author: H. Peter Anvin Date: Sun Aug 11 00:37:06 2002 +0000 Attempt at getting alpha divide subroutines... commit a5fd632b6e7bb56ae765969bba2284564930bf74 Author: H. Peter Anvin Date: Sat Aug 10 21:19:58 2002 +0000 Handle both arm and thumb in arm/crt0.S commit bfaec8719e6de79949b8ba5b518f94d350d24435 Author: H. Peter Anvin Date: Sat Aug 10 21:19:58 2002 +0000 Add "spotless" Makefile target commit 9e2ed7f9f431de5b996610f512f4e0ed0d20a8c4 Author: H. Peter Anvin Date: Sat Aug 10 21:19:58 2002 +0000 Makefile improvements from rmk commit 39a50344963ee70b11c5f22e9612d945faf42079 Author: H. Peter Anvin Date: Sat Aug 10 11:32:24 2002 +0000 Add a default if GETOPTTEST isn't set commit 2f8c60c97821a886bf7aa35b67ef3f8916e362da Author: H. Peter Anvin Date: Sat Aug 10 10:55:55 2002 +0000 Yet another victim of the bizarre ELF startup format... commit e8fb582477a0806e6dfa44e2d98bd60b5888eebd Author: H. Peter Anvin Date: Sat Aug 10 10:55:55 2002 +0000 Add ppc64 startup file commit 69d9cddf564734c3730fa44344b74d6b29722988 Author: H. Peter Anvin Date: Sat Aug 10 10:40:39 2002 +0000 Actually implement fileno() commit c905cc3d98ded943bfc090de0710dc976cc034a3 Author: H. Peter Anvin Date: Sat Aug 10 10:40:39 2002 +0000 Portability fixes for Alpha commit f971ca25a65262c80f8557fda12397e3f7a45e59 Author: H. Peter Anvin Date: Sat Aug 10 10:15:01 2002 +0000 More assembly hacking nasty... commit f4e905542dcf7b8669085f92b21f45d7d55d5ee1 Author: H. Peter Anvin Date: Sat Aug 10 09:53:41 2002 +0000 Use assembly version of crt0; the C version just didn't work right commit 3425620ce0c3e1ef38e3f86569a1a505ba4028fb Author: H. Peter Anvin Date: Sat Aug 10 09:53:22 2002 +0000 Stub to invoke __main if crt0.S doesn't do that... commit f7063dcd67dd441dd3575b97bd96a13372444f3c Author: H. Peter Anvin Date: Sat Aug 10 09:48:38 2002 +0000 Begin the work of creating crt0.S stubs for all architectures commit 203d299ce7dcfe846766ed3e8d35ec32452a10ae Author: H. Peter Anvin Date: Sat Aug 10 08:01:55 2002 +0000 Make gcc3-compatible. Call fread() and fwrite() by their proper names. commit fe6d77d3a3d59bcab3d13be98b1280522db49531 Author: H. Peter Anvin Date: Sat Aug 10 08:01:55 2002 +0000 #include in vsscanf.c so we don't have to worry about prototype mismatch! commit 977d3a6eb6f5001d3baceaba0bc57804b6abdd3e Author: H. Peter Anvin Date: Sat Aug 10 07:59:19 2002 +0000 We can make malloc() better by sharing the code for free(). Since they are usually used together, there is no point left in breaking them into separate modules. commit 0c11ad9d3546f6eed9cfb0bf3843fdd47ac0646e Author: H. Peter Anvin Date: Sat Aug 10 07:08:22 2002 +0000 A few more architectures for crt0.c commit cc1819cfb2df0055a0156025f648f74500bd5f15 Author: H. Peter Anvin Date: Sat Aug 10 02:56:35 2002 +0000 Various bug fixes. minips now seems to work! commit aafcf61aac69be7e38344c934b4f2c6d25774572 Author: H. Peter Anvin Date: Sat Aug 10 02:56:35 2002 +0000 Add minips -- useful test program. commit 10be0fca9f7f22fb884895b82370d5329317dbff Author: H. Peter Anvin Date: Sat Aug 10 00:35:24 2002 +0000 Bug fixes; add readdir() and friends commit 1d5c01ba8676528624b4a49c6410a57f75a53cfd Author: H. Peter Anvin Date: Sat Aug 10 00:35:24 2002 +0000 a) Clean up crt0.c somewhat b) Support $(CROSS) in the makefile c) Compile with -nostdinc -iwithprefix include commit e098aa6c1a9983f6f5e88ed65112bb965bb2fb49 Author: H. Peter Anvin Date: Sat Aug 10 00:35:24 2002 +0000 crt0.c has basically been completely rewritten, so kill Werner's note... Add sparc64 handling commit 3a957ffcb0c2a0fe39fac7770606fba85597e9a9 Author: H. Peter Anvin Date: Fri Aug 9 23:36:40 2002 +0000 Add sscan(); add sscanf() and vsscanf() to commit c51c17701c881be01070085a622b9feb31bbff12 Author: H. Peter Anvin Date: Fri Aug 9 23:36:40 2002 +0000 Add missing include files commit 95fda95ff69d945f6713bc55cd74f82d23950e61 Author: H. Peter Anvin Date: Fri Aug 9 23:05:27 2002 +0000 At least *try* to support a few more architectures... commit 0ee6a26999b7ab605af0eff17facd0a3153ce26e Author: H. Peter Anvin Date: Fri Aug 9 23:05:27 2002 +0000 Make more correct/architecture-specific on architectures which don't pass its arguments on the stack. commit b7612dbb2fd7b5be4ed90b7210e960a71cb55f76 Author: H. Peter Anvin Date: Fri Aug 9 23:04:33 2002 +0000 Add 6-argument stubs for PowerPC and S/390 commit d439dc8824e903ae7cd159c86277cbd10b9e2648 Author: H. Peter Anvin Date: Fri Aug 9 22:48:35 2002 +0000 Add missing _syscall6() for PowerPC commit c5985ed13ca2df128d3894bafc3a07f13efb2dde Author: H. Peter Anvin Date: Fri Aug 9 20:44:50 2002 +0000 Add workaround handling for missing alarm() and pause() commit 5f1d11bf0263e8ab25431730822db651bc925d46 Author: H. Peter Anvin Date: Fri Aug 9 20:44:50 2002 +0000 Handle more platform braindamage commit 3175765c0ee6bd8edffd6af71e1a414648132565 Author: H. Peter Anvin Date: Fri Aug 9 20:44:50 2002 +0000 Fix the definition of *int_fast*_t on 64-bit platforms. commit 890774f71952def5d1ae2844c927d1f87ae60f77 Author: H. Peter Anvin Date: Fri Aug 9 19:22:18 2002 +0000 Add a few more system-specific dependencies. commit 33e448b2d1c411f5a0f24f671432f098138f8cc5 Author: H. Peter Anvin Date: Fri Aug 9 19:22:18 2002 +0000 Handle fork() separately -- IA64 apparently only has clone() commit 4c3cf352ba2ad969fbfac0ab64d43640677e53a8 Author: H. Peter Anvin Date: Fri Aug 9 06:46:07 2002 +0000 Add fprintf() and vfprintf(), implement printf() vprintf() in terms of those, and create a rather iffy hack to make our "stdio" functions use FILE * rather than int commit 103d725dfbe9e252cf1b1f1471331b067fb42ee5 Author: H. Peter Anvin Date: Fri Aug 9 06:27:31 2002 +0000 Add poll(); add ; fix the prototypes of execv family functions commit dfadab9e174f64729ed24729b6ca12b303042774 Author: H. Peter Anvin Date: Fri Aug 9 06:12:49 2002 +0000 Improve the error handling commit 059bf42ac68df3be2b2803f001ac044a2c446237 Author: H. Peter Anvin Date: Fri Aug 9 05:16:34 2002 +0000 Add exec*p*() family of functions commit 3dfc8c42757b501f37fed13cb47c9eb660636698 Author: H. Peter Anvin Date: Fri Aug 9 03:16:39 2002 +0000 Re-enable optimization commit afbe5c98d40922e685dec1294379dcab50ca9f29 Author: H. Peter Anvin Date: Fri Aug 9 02:27:37 2002 +0000 Change malloc() so that it actually works. Fix mmap(). Make malloc() use mmap() instead of sbrk(). Add test for malloc()/free(). commit fa53216ffad4ce59a352e5dd5b4c2aeca8be03d7 Author: H. Peter Anvin Date: Fri Aug 9 00:03:22 2002 +0000 Fix a couple of getopt() bugs; fix printf(); add getopt test case commit b201f6336bb4b48d332642d79be1ee5f84586424 Author: H. Peter Anvin Date: Thu Aug 8 22:58:11 2002 +0000 Add getopt() prototype commit dd72874de02369ec899ff430678d0931358906f5 Author: H. Peter Anvin Date: Thu Aug 8 22:57:09 2002 +0000 Add getopt() commit a842d91942ba32ef92462d27724c7a3e4089afe9 Author: H. Peter Anvin Date: Thu Aug 8 21:23:18 2002 +0000 Another microoptimization in _exit() commit 41f0f7781a193a19458876cae13b058860351813 Author: H. Peter Anvin Date: Thu Aug 8 21:23:01 2002 +0000 Add strstr() and memmem() commit 8990f58174bc4498e410050839630348cd34a253 Author: H. Peter Anvin Date: Thu Aug 8 18:37:28 2002 +0000 Special-case exit() and _exit(), and merge the two commit 04fa24c5b945177ad80c59e6189fe92b7076638d Author: H. Peter Anvin Date: Thu Aug 8 07:26:47 2002 +0000 Add reboot, and __brk() commit 46d900837f91c7ae43704a97bb79580edf5e0067 Author: H. Peter Anvin Date: Thu Aug 8 01:36:14 2002 +0000 Make it possible to support assembly syscall stubs. commit e07fcac9191164aa1e5f35dfb1acb4a221b881e1 Author: H. Peter Anvin Date: Wed Aug 7 21:53:24 2002 +0000 Save some space by not adding the on_exit() link parse unless on_exit() is actually called. commit 6d20d4b184458a7a47a0b7e7c2d89b404abc7833 Author: H. Peter Anvin Date: Wed Aug 7 21:18:05 2002 +0000 Add support for execle() and lay the groundwork for execlp() commit c759937a94640de8861d6c461b963429055d2e27 Author: H. Peter Anvin Date: Wed Aug 7 20:52:23 2002 +0000 Note about asm symlink commit 9337e295bb5deeffdddb91a9fd352398b236187c Author: H. Peter Anvin Date: Wed Aug 7 20:40:49 2002 +0000 Add getenv() setenv() putenv() unsetenv() commit 0fb032f2fde83fcb83bc22892b207e151fbb514a Author: H. Peter Anvin Date: Wed Aug 7 05:40:39 2002 +0000 A whole bunch of work... commit 90937acdaf7f7fb206907a9d7f92a2034dcaff15 Author: H. Peter Anvin Date: Wed Aug 7 04:55:19 2002 +0000 Add msync() commit 5b232fad9742e77b8a57271961d92f79673496da Author: H. Peter Anvin Date: Wed Aug 7 04:52:44 2002 +0000 Add setfsuid() setfsgid() commit 738e113afa5c4d239fe9f104c10e6076f32c2bc6 Author: H. Peter Anvin Date: Wed Aug 7 04:49:40 2002 +0000 Add mmap() munmap() mremap() support. commit 16bd278be10e99b6915d57a0dd0491168893e5e2 Author: H. Peter Anvin Date: Wed Aug 7 01:54:47 2002 +0000 Use rt_* signal system calls instead of the old ones, create emulation routines for the old calls. commit 07523435cccbbe1291b9668aeb46a8807d153e6f Author: H. Peter Anvin Date: Tue Aug 6 19:37:42 2002 +0000 Tweak optimizations somewhat. Implement wait() in terms of wait4(). commit 5e38a4c2f64a90a7e5756200de9f0e566ecfd772 Author: H. Peter Anvin Date: Tue Aug 6 19:23:14 2002 +0000 Add missing seteuid() file commit 7cc8bce890e7e72e62ef8c46488947320099f503 Author: H. Peter Anvin Date: Tue Aug 6 18:16:42 2002 +0000 Add a "microhello" version; strip test programs, and build with -Os commit 5157b95fd029620ab601e51041d9fd03ff495190 Author: H. Peter Anvin Date: Tue Aug 6 18:01:06 2002 +0000 Implement signal() and waitpid() in terms of sigaction() and wait4() commit 14014d62d4fff03f9e30bec5473a205541a36bef Author: H. Peter Anvin Date: Tue Aug 6 04:29:47 2002 +0000 Add missing header files. commit 7ed7255a4fc95cf651ce46066160eec1e98280ce Author: H. Peter Anvin Date: Tue Aug 6 04:28:41 2002 +0000 Add additional system calls; add module support commit b36df0c6ce1a6c17cea8238a87c83446e0336705 Author: H. Peter Anvin Date: Tue Aug 6 03:55:39 2002 +0000 Add a whole bunch more syscalls to the pot. commit 441b6e128d318837913191f8147ac6f3e0ef5727 Author: H. Peter Anvin Date: Tue Aug 6 01:50:51 2002 +0000 Add headers for all the socket system calls. commit d232bd93a334e191d6d498aeded92ff9667bf2af Author: H. Peter Anvin Date: Tue Aug 6 01:48:39 2002 +0000 Infrastructure for generating socketcall stubs commit 74b67d34871be80a0ed5ef636f5d3ec9d97c0b99 Author: H. Peter Anvin Date: Tue Aug 6 00:25:09 2002 +0000 Add calloc() and realloc() commit 1b20b39d14c1bf37f011453a23a8d8306036b096 Author: H. Peter Anvin Date: Mon Aug 5 23:27:23 2002 +0000 Implement strtok(); remove strxfrm() (locale-related) commit 14990dab6394560c3692d275ef8a515315ce6a49 Author: H. Peter Anvin Date: Mon Aug 5 23:12:01 2002 +0000 Name-related system calls... commit 805da19fe47ba0ab5478ec725534abd0a4414dba Author: H. Peter Anvin Date: Mon Aug 5 23:03:09 2002 +0000 More work, more missing pieces added... commit f7c065304156b3fdf30a8db96c1bafc5ded3d904 Author: H. Peter Anvin Date: Mon Aug 5 21:41:38 2002 +0000 Clean up and fix execl(), add header which creates va_copy(), add which invokes the gcc builtin. commit 1f6294e92b7d3d874c1d88142535c1e0d0ae364d Author: H. Peter Anvin Date: Mon Aug 5 20:45:51 2002 +0000 Make __xread() actually compile commit 55abe2d108402de9b6ded4293cf83422cd0517b3 Author: H. Peter Anvin Date: Mon Aug 5 20:45:02 2002 +0000 Add __xread() support, include in xwrite.c commit 3a9c641f9b0e37c810ef59f83c8e055eda83493f Author: H. Peter Anvin Date: Mon Aug 5 20:33:37 2002 +0000 Add minihello to the list of programs to try. commit 34f64118ad7ecb83282b3193b7147c6517bbb298 Author: H. Peter Anvin Date: Mon Aug 5 20:33:07 2002 +0000 Add miniature Hello, World! that doesn't use printf(), just to demo the size advantage. commit ab5d7e61f389cfcb495ba55b67c3679802d05b68 Author: H. Peter Anvin Date: Mon Aug 5 20:21:09 2002 +0000 Add prototype for strsep() commit 10768713863d40d39824baaf7cbbfcca3c76c79c Author: H. Peter Anvin Date: Mon Aug 5 20:20:24 2002 +0000 More string functions; fix a couple of broken ones commit 22abc7d775f231a0d471f112f06a1ab532917803 Author: H. Peter Anvin Date: Mon Aug 5 19:22:03 2002 +0000 More string functions; updated README commit ff804863a13bb1c4fa2146c0cf397ee2814632d3 Author: H. Peter Anvin Date: Mon Aug 5 11:32:27 2002 +0000 Add pivot_root() commit 4c1255e39eff242f5782c664fc4dd3d2f0bd9b34 Author: H. Peter Anvin Date: Mon Aug 5 11:30:16 2002 +0000 Add README file commit e798577c03891bea9802d56b10bfa8939a188bf8 Author: H. Peter Anvin Date: Mon Aug 5 11:26:29 2002 +0000 Add mount() umount() umount2() commit 305c309ae556f59609b5a454b2e1410469a7c22b Author: H. Peter Anvin Date: Mon Aug 5 11:11:00 2002 +0000 Add fputs() as a general way to send a string to an output. commit 5f3a2e83aa6464d21af96b52a13d61f4c3fbe56e Author: H. Peter Anvin Date: Mon Aug 5 10:55:36 2002 +0000 Add strlen() commit da79e83a401d6953627b88ef32fe4363c56b5161 Author: H. Peter Anvin Date: Mon Aug 5 10:51:50 2002 +0000 memset() commit ec2c5a32afba539ebef23045f5f84f5051a6dc86 Author: H. Peter Anvin Date: Mon Aug 5 10:47:40 2002 +0000 Watch out for dangerous promotions... commit 36d7747dc7e3533336763496aac391e9e5a7bbf3 Author: H. Peter Anvin Date: Mon Aug 5 10:07:42 2002 +0000 More functionality. We can now link and run testvsnp.c and hello.c against klibc. commit dd3f499d5aa167043a72def24989030ec6c5b3ea Author: H. Peter Anvin Date: Mon Aug 5 07:55:01 2002 +0000 Basic system call support, malloc/free commit f3119f3a18429b7c1a623314488635821bd2a3cd Author: H. Peter Anvin Date: Mon Aug 5 04:20:14 2002 +0000 crt0 -- the initialization function. commit 951d816bb393aa24aed70893284458e13e0beeab Author: H. Peter Anvin Date: Mon Aug 5 04:19:57 2002 +0000 exit() and friends commit 4040802221cac33c1177e886e12b497f5e03b719 Author: H. Peter Anvin Date: Mon Aug 5 01:14:58 2002 +0000 , more or less complete commit fd485dc5da866516eef5567a5dd2c30164b3f4c8 Author: H. Peter Anvin Date: Mon Aug 5 01:14:40 2002 +0000 Beginnings of commit c2c192e517327bc9e8a229b45d7bf0b42df5f906 Author: H. Peter Anvin Date: Sun Aug 4 23:16:38 2002 +0000 Add support for generating .i and .s files in Makefile. Add strntoimax(). Handle _Exit() better. commit 5ad45492bdb311b996f3c5e10dd62d74a7a91a40 Author: H. Peter Anvin Date: Sun Aug 4 23:06:53 2002 +0000 Add commit 4e047e9353ba880f0090091e50838675e2337fa7 Author: H. Peter Anvin Date: Sun Aug 4 23:06:31 2002 +0000 Beginning of implementation commit e311d261657e4c3f89e25cf96eca40f795cfb579 Author: H. Peter Anvin Date: Sun Aug 4 23:06:08 2002 +0000 Use __extern commit 9fd06dc6d600519e8b8379571da7ca2c931fff47 Author: H. Peter Anvin Date: Sun Aug 4 23:05:53 2002 +0000 Support __extern commit 89048dd6bb1012849ad2629dbc11d659281f615c Author: H. Peter Anvin Date: Sun Aug 4 23:05:40 2002 +0000 Update commit a947171f05d67f99e1980db08c39e1c99b0536c4 Author: H. Peter Anvin Date: Sun Aug 4 23:05:04 2002 +0000 Unify ato*() functions, add atoll() commit add1ce8f1f6ee9461ce80b46fa889d6a823903b8 Author: H. Peter Anvin Date: Sun Aug 4 22:39:17 2002 +0000 definition commit a0d566165dd58918fbfe1a673a56c401107fe5b6 Author: H. Peter Anvin Date: Sun Aug 4 22:38:06 2002 +0000 Add commit 9d81021c07320089bad223382bba232769fee506 Author: H. Peter Anvin Date: Sun Aug 4 22:13:28 2002 +0000 Build a shared-library version too. commit 70e226a867374b78b495c2fe622d7842bf934b4d Author: H. Peter Anvin Date: Sun Aug 4 22:13:11 2002 +0000 Compile cleanly, without warnings. commit 18ff33e9d389a9b5db270802c7094fa5692e1f52 Author: H. Peter Anvin Date: Sun Aug 4 21:36:01 2002 +0000 strto*() and ato*() functions commit b8a50070dedee453cf389c8104a4aa44fc967fb1 Author: H. Peter Anvin Date: Sun Aug 4 21:35:32 2002 +0000 Initial implementation commit ed9028671146061f437854f0aa63e087b0021638 Author: H. Peter Anvin Date: Sun Aug 4 18:47:05 2002 +0000 Add include directory commit d77c36b96f258334fa641b3e55764cb6105c214a Author: H. Peter Anvin Date: Thu Jul 25 05:49:34 2002 +0000 A potentially fully-featured version of vsscanf(). commit b0a58b02a90a8d481cd52e17539b233044beeb26 Author: H. Peter Anvin Date: Thu Jul 25 03:44:25 2002 +0000 Initial revision commit ba85063f3fd1086982a610776c67be2814057f41 Author: H. Peter Anvin Date: Thu Jul 25 03:44:14 2002 +0000 Add vsscanf.o commit 1bbe2922853c64a9c32853817dd4ea7ba69eb0f0 Author: H. Peter Anvin Date: Tue Jul 23 06:54:37 2002 +0000 Include (for CHAR_BIT) commit bb2586383f9e709bf5461110dea8f63e3b36e6fb Author: H. Peter Anvin Date: Tue Jul 23 06:54:20 2002 +0000 Use CHAR_BIT instead of assuming 8-bit bytes commit 56c67217c2257cc3f380aec3e47db7e07bef7a45 Author: H. Peter Anvin Date: Tue Jul 23 06:41:30 2002 +0000 Initial revision --- Signed-off-by: Andrew Morton --- MAINTAINERS | 7 Makefile | 32 arch/i386/kernel/setup.c | 8 arch/powerpc/Makefile | 1 arch/s390/Makefile | 4 arch/sparc/kernel/setup.c | 40 arch/sparc64/kernel/setup.c | 92 arch/um/Makefile | 2 arch/x86_64/kernel/setup.c | 7 fs/Kconfig | 14 fs/nfs/Makefile | 1 fs/nfs/mount_clnt.c | 191 fs/nfs/nfsroot.c | 525 -- include/linux/mount.h | 1 init/Makefile | 8 init/do_mounts.c | 437 - init/do_mounts.h | 91 init/do_mounts_devfs.c | 137 init/do_mounts_initrd.c | 125 init/do_mounts_md.c | 286 - init/do_mounts_rd.c | 429 - init/initramfs.c | 3 init/main.c | 45 kernel/power/disk.c | 45 net/ipv4/Makefile | 1 net/ipv4/ipconfig.c | 1510 ------ scripts/Kbuild.include | 5 scripts/Kbuild.klibc | 358 + scripts/gen_initramfs_list.sh | 51 usr/Kbuild | 75 usr/Kconfig | 21 usr/Makefile | 47 usr/dash/Kbuild | 146 usr/dash/README.klibc | 7 usr/dash/TOUR | 356 + usr/dash/alias.c | 227 usr/dash/alias.h | 52 usr/dash/arith.y | 155 usr/dash/arith_yylex.c | 163 usr/dash/bltin/bltin.h | 89 usr/dash/bltin/echo.1 | 109 usr/dash/bltin/printf.1 | 354 + usr/dash/bltin/printf.c | 476 ++ usr/dash/bltin/test.1 | 309 + usr/dash/bltin/test.c | 500 ++ usr/dash/builtins.def.in | 92 usr/dash/cd.c | 303 + usr/dash/cd.h | 35 usr/dash/config.h | 85 usr/dash/error.c | 233 + usr/dash/error.h | 145 usr/dash/eval.c | 1100 ++++ usr/dash/eval.h | 62 usr/dash/exec.c | 869 +++ usr/dash/exec.h | 77 usr/dash/expand.c | 1744 +++++++ usr/dash/expand.h | 83 usr/dash/funcs/cmv | 47 usr/dash/funcs/dirs | 71 usr/dash/funcs/kill | 47 usr/dash/funcs/login | 36 usr/dash/funcs/newgrp | 35 usr/dash/funcs/popd | 71 usr/dash/funcs/pushd | 71 usr/dash/funcs/suspend | 39 usr/dash/gendeps.pl | 38 usr/dash/hetio.c | 397 + usr/dash/hetio.h | 22 usr/dash/histedit.c | 492 ++ usr/dash/init.h | 39 usr/dash/input.c | 563 ++ usr/dash/input.h | 68 usr/dash/jobs.c | 1499 ++++++ usr/dash/jobs.h | 109 usr/dash/machdep.h | 53 usr/dash/mail.c | 112 usr/dash/mail.h | 38 usr/dash/main.c | 349 + usr/dash/main.h | 54 usr/dash/memalloc.c | 329 + usr/dash/memalloc.h | 97 usr/dash/miscbltin.c | 457 + usr/dash/miscbltin.h | 31 usr/dash/mkbuiltins | 101 usr/dash/mkinit.c | 476 ++ usr/dash/mknodes.c | 448 + usr/dash/mksyntax.c | 315 + usr/dash/mktokens | 92 usr/dash/myhistedit.h | 45 usr/dash/mystring.c | 209 usr/dash/mystring.h | 58 usr/dash/nodes.c.pat | 166 usr/dash/nodetypes | 144 usr/dash/options.c | 547 ++ usr/dash/options.h | 86 usr/dash/output.c | 385 + usr/dash/output.h | 112 usr/dash/parser.c | 1556 ++++++ usr/dash/parser.h | 96 usr/dash/redir.c | 475 ++ usr/dash/redir.h | 49 usr/dash/sh.1 | 2332 ++++++++++ usr/dash/shell.h | 94 usr/dash/show.c | 403 + usr/dash/show.h | 45 usr/dash/system.c | 191 usr/dash/system.h | 91 usr/dash/trap.c | 443 + usr/dash/trap.h | 52 usr/dash/var.c | 676 ++ usr/dash/var.h | 146 usr/gzip/COPYING | 339 + usr/gzip/Kbuild | 25 usr/gzip/README | 144 usr/gzip/bits.c | 200 usr/gzip/deflate.c | 759 +++ usr/gzip/gzip.c | 1214 +++++ usr/gzip/gzip.h | 298 + usr/gzip/inflate.c | 950 ++++ usr/gzip/revision.h | 11 usr/gzip/tailor.h | 50 usr/gzip/trees.c | 1075 ++++ usr/gzip/unzip.c | 77 usr/gzip/util.c | 372 + usr/gzip/zip.c | 110 usr/include/Kbuild | 11 usr/include/alloca.h | 12 usr/include/arch/alpha/klibc/archconfig.h | 15 usr/include/arch/alpha/klibc/archsetjmp.h | 33 usr/include/arch/alpha/klibc/archsignal.h | 14 usr/include/arch/alpha/klibc/archstat.h | 28 usr/include/arch/alpha/machine/asm.h | 44 usr/include/arch/arm/klibc/archconfig.h | 14 usr/include/arch/arm/klibc/archsetjmp.h | 14 usr/include/arch/arm/klibc/archsignal.h | 14 usr/include/arch/arm/klibc/archstat.h | 40 usr/include/arch/arm/klibc/asmmacros.h | 30 usr/include/arch/cris/klibc/archconfig.h | 15 usr/include/arch/cris/klibc/archsetjmp.h | 24 usr/include/arch/cris/klibc/archsignal.h | 14 usr/include/arch/cris/klibc/archstat.h | 39 usr/include/arch/i386/klibc/archconfig.h | 19 usr/include/arch/i386/klibc/archsetjmp.h | 19 usr/include/arch/i386/klibc/archsignal.h | 114 usr/include/arch/i386/klibc/archstat.h | 38 usr/include/arch/i386/klibc/diverr.h | 15 usr/include/arch/i386/sys/io.h | 127 usr/include/arch/i386/sys/vm86.h | 40 usr/include/arch/ia64/klibc/archconfig.h | 17 usr/include/arch/ia64/klibc/archsetjmp.h | 17 usr/include/arch/ia64/klibc/archsignal.h | 32 usr/include/arch/ia64/klibc/archstat.h | 26 usr/include/arch/ia64/klibc/archsys.h | 217 usr/include/arch/m32r/klibc/archconfig.h | 14 usr/include/arch/m32r/klibc/archsetjmp.h | 21 usr/include/arch/m32r/klibc/archsignal.h | 14 usr/include/arch/m32r/klibc/archstat.h | 39 usr/include/arch/m68k/klibc/archconfig.h | 15 usr/include/arch/m68k/klibc/archsetjmp.h | 26 usr/include/arch/m68k/klibc/archsignal.h | 14 usr/include/arch/m68k/klibc/archstat.h | 38 usr/include/arch/mips/klibc/archconfig.h | 15 usr/include/arch/mips/klibc/archfcntl.h | 86 usr/include/arch/mips/klibc/archsetjmp.h | 39 usr/include/arch/mips/klibc/archsignal.h | 14 usr/include/arch/mips/klibc/archstat.h | 40 usr/include/arch/mips/machine/asm.h | 11 usr/include/arch/mips/sgidefs.h | 20 usr/include/arch/mips/spaces.h | 1 usr/include/arch/mips64/klibc/archconfig.h | 14 usr/include/arch/mips64/klibc/archsignal.h | 14 usr/include/arch/mips64/klibc/archstat.h | 33 usr/include/arch/parisc/klibc/archconfig.h | 14 usr/include/arch/parisc/klibc/archsetjmp.h | 14 usr/include/arch/parisc/klibc/archsignal.h | 25 usr/include/arch/parisc/klibc/archstat.h | 29 usr/include/arch/ppc/klibc/archconfig.h | 14 usr/include/arch/ppc/klibc/archsetjmp.h | 36 usr/include/arch/ppc/klibc/archsignal.h | 14 usr/include/arch/ppc/klibc/archstat.h | 30 usr/include/arch/ppc64/klibc/archconfig.h | 12 usr/include/arch/ppc64/klibc/archsetjmp.h | 36 usr/include/arch/ppc64/klibc/archsignal.h | 14 usr/include/arch/ppc64/klibc/archstat.h | 27 usr/include/arch/s390/klibc/archconfig.h | 15 usr/include/arch/s390/klibc/archsetjmp.h | 26 usr/include/arch/s390/klibc/archsignal.h | 14 usr/include/arch/s390/klibc/archstat.h | 56 usr/include/arch/sh/klibc/archconfig.h | 14 usr/include/arch/sh/klibc/archsetjmp.h | 22 usr/include/arch/sh/klibc/archsignal.h | 14 usr/include/arch/sh/klibc/archstat.h | 38 usr/include/arch/sparc/klibc/archconfig.h | 14 usr/include/arch/sparc/klibc/archsetjmp.h | 16 usr/include/arch/sparc/klibc/archsignal.h | 24 usr/include/arch/sparc/klibc/archstat.h | 37 usr/include/arch/sparc/machine/asm.h | 191 usr/include/arch/sparc/machine/frame.h | 146 usr/include/arch/sparc/machine/trap.h | 140 usr/include/arch/sparc64/klibc/archconfig.h | 15 usr/include/arch/sparc64/klibc/archsetjmp.h | 16 usr/include/arch/sparc64/klibc/archsignal.h | 17 usr/include/arch/sparc64/klibc/archstat.h | 30 usr/include/arch/x86_64/klibc/archconfig.h | 15 usr/include/arch/x86_64/klibc/archsetjmp.h | 21 usr/include/arch/x86_64/klibc/archsignal.h | 18 usr/include/arch/x86_64/klibc/archstat.h | 28 usr/include/arch/x86_64/sys/io.h | 127 usr/include/arpa/inet.h | 22 usr/include/assert.h | 22 usr/include/bits32/bitsize.h | 3 usr/include/bits32/bitsize/limits.h | 14 usr/include/bits32/bitsize/stddef.h | 18 usr/include/bits32/bitsize/stdint.h | 34 usr/include/bits32/bitsize/stdintconst.h | 18 usr/include/bits32/bitsize/stdintlimits.h | 22 usr/include/bits64/bitsize.h | 3 usr/include/bits64/bitsize/limits.h | 14 usr/include/bits64/bitsize/stddef.h | 13 usr/include/bits64/bitsize/stdint.h | 34 usr/include/bits64/bitsize/stdintconst.h | 18 usr/include/bits64/bitsize/stdintlimits.h | 22 usr/include/byteswap.h | 15 usr/include/ctype.h | 140 usr/include/dirent.h | 33 usr/include/elf.h | 11 usr/include/endian.h | 15 usr/include/errno.h | 13 usr/include/fcntl.h | 47 usr/include/grp.h | 13 usr/include/inttypes.h | 226 usr/include/klibc/compiler.h | 123 usr/include/klibc/diverr.h | 15 usr/include/klibc/endian.h | 39 usr/include/klibc/extern.h | 16 usr/include/klibc/stathelp.h | 24 usr/include/klibc/sysconfig.h | 166 usr/include/limits.h | 40 usr/include/malloc.h | 21 usr/include/net/if.h | 7 usr/include/net/if_arp.h | 1 usr/include/net/if_packet.h | 1 usr/include/net/route.h | 1 usr/include/netinet/if_ether.h | 1 usr/include/netinet/in.h | 39 usr/include/netinet/in6.h | 10 usr/include/netinet/ip.h | 13 usr/include/netinet/tcp.h | 11 usr/include/netinet/udp.h | 19 usr/include/netpacket/packet.h | 1 usr/include/paths.h | 74 usr/include/poll.h | 1 usr/include/sched.h | 36 usr/include/setjmp.h | 43 usr/include/signal.h | 97 usr/include/stdarg.h | 14 usr/include/stddef.h | 24 usr/include/stdint.h | 116 usr/include/stdio.h | 128 usr/include/stdlib.h | 94 usr/include/string.h | 47 usr/include/sys/dirent.h | 32 usr/include/sys/elf32.h | 113 usr/include/sys/elf64.h | 113 usr/include/sys/elfcommon.h | 187 usr/include/sys/fsuid.h | 14 usr/include/sys/inotify.h | 16 usr/include/sys/ioctl.h | 14 usr/include/sys/klog.h | 24 usr/include/sys/md.h | 32 usr/include/sys/mman.h | 24 usr/include/sys/mount.h | 71 usr/include/sys/param.h | 11 usr/include/sys/poll.h | 20 usr/include/sys/reboot.h | 25 usr/include/sys/resource.h | 15 usr/include/sys/select.h | 17 usr/include/sys/sendfile.h | 14 usr/include/sys/socket.h | 44 usr/include/sys/socketcalls.h | 28 usr/include/sys/splice.h | 19 usr/include/sys/stat.h | 33 usr/include/sys/statfs.h | 1 usr/include/sys/syscall.h | 13 usr/include/sys/sysinfo.h | 12 usr/include/sys/sysmacros.h | 34 usr/include/sys/time.h | 18 usr/include/sys/times.h | 14 usr/include/sys/types.h | 111 usr/include/sys/uio.h | 15 usr/include/sys/un.h | 10 usr/include/sys/utime.h | 10 usr/include/sys/utsname.h | 23 usr/include/sys/vfs.h | 115 usr/include/sys/wait.h | 28 usr/include/syslog.h | 62 usr/include/termios.h | 91 usr/include/time.h | 18 usr/include/unistd.h | 159 usr/include/utime.h | 14 usr/include/zconf.h | 332 + usr/include/zlib.h | 1357 +++++ usr/initramfs.default | 9 usr/kinit/Kbuild | 28 usr/kinit/README | 9 usr/kinit/devname.c | 114 usr/kinit/do_mounts.c | 221 usr/kinit/do_mounts.h | 48 usr/kinit/do_mounts_md.c | 398 + usr/kinit/do_mounts_mtd.c | 44 usr/kinit/fstype/Kbuild | 25 usr/kinit/fstype/cramfs_fs.h | 85 usr/kinit/fstype/ext2_fs.h | 79 usr/kinit/fstype/ext3_fs.h | 92 usr/kinit/fstype/fstype.c | 296 + usr/kinit/fstype/fstype.h | 23 usr/kinit/fstype/jfs_superblock.h | 114 usr/kinit/fstype/luks_fs.h | 44 usr/kinit/fstype/lvm2_sb.h | 18 usr/kinit/fstype/main.c | 58 usr/kinit/fstype/minix_fs.h | 85 usr/kinit/fstype/reiserfs_fs.h | 69 usr/kinit/fstype/romfs_fs.h | 56 usr/kinit/fstype/swap_fs.h | 18 usr/kinit/fstype/xfs_sb.h | 16 usr/kinit/getarg.c | 57 usr/kinit/getintfile.c | 30 usr/kinit/initrd.c | 199 usr/kinit/ipconfig/Kbuild | 31 usr/kinit/ipconfig/README | 103 usr/kinit/ipconfig/bootp_packet.h | 34 usr/kinit/ipconfig/bootp_proto.c | 213 usr/kinit/ipconfig/bootp_proto.h | 8 usr/kinit/ipconfig/dhcp_proto.c | 212 usr/kinit/ipconfig/dhcp_proto.h | 18 usr/kinit/ipconfig/ipconfig.h | 35 usr/kinit/ipconfig/main.c | 758 +++ usr/kinit/ipconfig/netdev.c | 251 + usr/kinit/ipconfig/netdev.h | 83 usr/kinit/ipconfig/packet.c | 286 + usr/kinit/ipconfig/packet.h | 9 usr/kinit/kinit.c | 330 + usr/kinit/kinit.h | 73 usr/kinit/name_to_dev.c | 202 usr/kinit/nfsmount/Kbuild | 27 usr/kinit/nfsmount/README.locking | 26 usr/kinit/nfsmount/dummypmap.c | 188 usr/kinit/nfsmount/dummypmap.h | 13 usr/kinit/nfsmount/dummypmap_test.c | 2 usr/kinit/nfsmount/main.c | 263 + usr/kinit/nfsmount/mount.c | 357 + usr/kinit/nfsmount/nfsmount.h | 39 usr/kinit/nfsmount/portmap.c | 73 usr/kinit/nfsmount/sunrpc.c | 253 + usr/kinit/nfsmount/sunrpc.h | 99 usr/kinit/nfsroot.c | 113 usr/kinit/open.c | 18 usr/kinit/ramdisk_load.c | 271 + usr/kinit/readfile.c | 86 usr/kinit/resume.c | 75 usr/kinit/run-init/Kbuild | 25 usr/kinit/run-init/run-init.c | 95 usr/kinit/run-init/run-init.h | 38 usr/kinit/run-init/runinitlib.c | 216 usr/kinit/xpio.c | 51 usr/kinit/xpio.h | 11 usr/klibc/CAVEATS | 60 usr/klibc/Kbuild | 186 usr/klibc/LICENSE | 73 usr/klibc/README | 80 usr/klibc/SOCKETCALLS.def | 21 usr/klibc/SYSCALLS.def | 260 + usr/klibc/__put_env.c | 74 usr/klibc/__shared_init.c | 2 usr/klibc/__signal.c | 20 usr/klibc/__static_init.c | 2 usr/klibc/abort.c | 18 usr/klibc/alarm.c | 25 usr/klibc/arch/README | 81 usr/klibc/arch/alpha/MCONFIG | 16 usr/klibc/arch/alpha/Makefile.inc | 60 usr/klibc/arch/alpha/README-gcc | 22 usr/klibc/arch/alpha/crt0.S | 22 usr/klibc/arch/alpha/divide.c | 59 usr/klibc/arch/alpha/pipe.S | 38 usr/klibc/arch/alpha/setjmp.S | 75 usr/klibc/arch/alpha/syscall.S | 26 usr/klibc/arch/alpha/sysdual.S | 33 usr/klibc/arch/alpha/sysstub.ph | 37 usr/klibc/arch/arm/MCONFIG | 36 usr/klibc/arch/arm/Makefile.inc | 23 usr/klibc/arch/arm/__muldi3.c | 15 usr/klibc/arch/arm/aeabi_nonsense.S | 9 usr/klibc/arch/arm/crt0.S | 23 usr/klibc/arch/arm/setjmp.S | 102 usr/klibc/arch/arm/syscall.S | 61 usr/klibc/arch/arm/sysstub.ph | 58 usr/klibc/arch/arm/vfork.S | 60 usr/klibc/arch/cris/MCONFIG | 26 usr/klibc/arch/cris/Makefile.inc | 34 usr/klibc/arch/cris/__negdi2.S | 25 usr/klibc/arch/cris/crt0.S | 27 usr/klibc/arch/cris/divide.c | 99 usr/klibc/arch/cris/setjmp.S | 37 usr/klibc/arch/cris/syscall.S | 30 usr/klibc/arch/cris/sysstub.ph | 29 usr/klibc/arch/cris/vfork.S | 29 usr/klibc/arch/i386/MCONFIG | 33 usr/klibc/arch/i386/Makefile.inc | 30 usr/klibc/arch/i386/crt0.S | 31 usr/klibc/arch/i386/libgcc/__ashldi3.S | 29 usr/klibc/arch/i386/libgcc/__ashrdi3.S | 29 usr/klibc/arch/i386/libgcc/__lshrdi3.S | 29 usr/klibc/arch/i386/libgcc/__muldi3.S | 34 usr/klibc/arch/i386/libgcc/__negdi2.S | 21 usr/klibc/arch/i386/open.S | 29 usr/klibc/arch/i386/openat.S | 26 usr/klibc/arch/i386/setjmp.S | 58 usr/klibc/arch/i386/sigreturn.S | 15 usr/klibc/arch/i386/socketcall.S | 55 usr/klibc/arch/i386/syscall.S | 69 usr/klibc/arch/i386/sysstub.ph | 26 usr/klibc/arch/i386/varsyscall.S | 36 usr/klibc/arch/i386/vfork.S | 26 usr/klibc/arch/ia64/MCONFIG | 11 usr/klibc/arch/ia64/Makefile.inc | 26 usr/klibc/arch/ia64/crt0.S | 27 usr/klibc/arch/ia64/pipe.c | 41 usr/klibc/arch/ia64/setjmp.S | 343 + usr/klibc/arch/ia64/syscall.S | 20 usr/klibc/arch/ia64/sysstub.ph | 29 usr/klibc/arch/ia64/vfork.S | 42 usr/klibc/arch/m32r/MCONFIG | 18 usr/klibc/arch/m32r/Makefile.inc | 19 usr/klibc/arch/m32r/crt0.S | 24 usr/klibc/arch/m32r/setjmp.S | 47 usr/klibc/arch/m32r/syscall.S | 29 usr/klibc/arch/m32r/sysstub.ph | 25 usr/klibc/arch/m68k/MCONFIG | 11 usr/klibc/arch/m68k/Makefile.inc | 25 usr/klibc/arch/m68k/crt0.S | 27 usr/klibc/arch/m68k/setjmp.S | 43 usr/klibc/arch/m68k/syscall.S | 27 usr/klibc/arch/m68k/sysstub.ph | 26 usr/klibc/arch/m68k/vfork.S | 28 usr/klibc/arch/mips/MCONFIG | 15 usr/klibc/arch/mips/Makefile.inc | 29 usr/klibc/arch/mips/crt0.S | 25 usr/klibc/arch/mips/klibc.ld | 214 usr/klibc/arch/mips/pipe.S | 16 usr/klibc/arch/mips/setjmp.S | 80 usr/klibc/arch/mips/syscall.S | 16 usr/klibc/arch/mips/sysstub.ph | 30 usr/klibc/arch/mips/vfork.S | 16 usr/klibc/arch/mips64/MCONFIG | 11 usr/klibc/arch/mips64/Makefile.inc | 10 usr/klibc/arch/parisc/MCONFIG | 12 usr/klibc/arch/parisc/Makefile.inc | 16 usr/klibc/arch/parisc/crt0.S | 37 usr/klibc/arch/parisc/setjmp.S | 88 usr/klibc/arch/parisc/syscall.S | 36 usr/klibc/arch/parisc/sysstub.ph | 28 usr/klibc/arch/ppc/MCONFIG | 29 usr/klibc/arch/ppc/Makefile.inc | 22 usr/klibc/arch/ppc/crt0.S | 23 usr/klibc/arch/ppc/setjmp.S | 34 usr/klibc/arch/ppc/syscall.S | 16 usr/klibc/arch/ppc/sysstub.ph | 25 usr/klibc/arch/ppc64/MCONFIG | 26 usr/klibc/arch/ppc64/Makefile.inc | 25 usr/klibc/arch/ppc64/crt0.S | 32 usr/klibc/arch/ppc64/setjmp.S | 85 usr/klibc/arch/ppc64/syscall.c | 14 usr/klibc/arch/ppc64/sysstub.ph | 31 usr/klibc/arch/s390/MCONFIG | 23 usr/klibc/arch/s390/Makefile.inc | 38 usr/klibc/arch/s390/crt0.S | 35 usr/klibc/arch/s390/mmap.c | 75 usr/klibc/arch/s390/setjmp.S | 66 usr/klibc/arch/s390/syscall.c | 16 usr/klibc/arch/s390/sysstub.ph | 40 usr/klibc/arch/sh/MCONFIG | 18 usr/klibc/arch/sh/Makefile.inc | 15 usr/klibc/arch/sh/crt0.S | 27 usr/klibc/arch/sh/setjmp.S | 64 usr/klibc/arch/sh/syscall.S | 35 usr/klibc/arch/sh/sysstub.ph | 34 usr/klibc/arch/sparc/MCONFIG | 19 usr/klibc/arch/sparc/Makefile.inc | 48 usr/klibc/arch/sparc/__muldi3.S | 27 usr/klibc/arch/sparc/crt0.S | 2 usr/klibc/arch/sparc/crt0i.S | 100 usr/klibc/arch/sparc/divrem.m4 | 276 + usr/klibc/arch/sparc/pipe.S | 30 usr/klibc/arch/sparc/setjmp.S | 38 usr/klibc/arch/sparc/smul.S | 160 usr/klibc/arch/sparc/syscall.S | 19 usr/klibc/arch/sparc/sysfork.S | 25 usr/klibc/arch/sparc/sysstub.ph | 25 usr/klibc/arch/sparc/umul.S | 193 usr/klibc/arch/sparc64/MCONFIG | 21 usr/klibc/arch/sparc64/Makefile.inc | 16 usr/klibc/arch/sparc64/crt0.S | 2 usr/klibc/arch/sparc64/pipe.S | 30 usr/klibc/arch/sparc64/setjmp.S | 55 usr/klibc/arch/sparc64/syscall.S | 18 usr/klibc/arch/sparc64/sysfork.S | 26 usr/klibc/arch/sparc64/sysstub.ph | 25 usr/klibc/arch/x86_64/MCONFIG | 35 usr/klibc/arch/x86_64/Makefile.inc | 18 usr/klibc/arch/x86_64/crt0.S | 22 usr/klibc/arch/x86_64/setjmp.S | 54 usr/klibc/arch/x86_64/sigreturn.S | 15 usr/klibc/arch/x86_64/syscall.S | 28 usr/klibc/arch/x86_64/sysstub.ph | 23 usr/klibc/arch/x86_64/vfork.S | 26 usr/klibc/asprintf.c | 30 usr/klibc/assert.c | 14 usr/klibc/atexit.c | 10 usr/klibc/atexit.h | 18 usr/klibc/atoi.c | 3 usr/klibc/atol.c | 3 usr/klibc/atoll.c | 3 usr/klibc/atox.c | 14 usr/klibc/brk.c | 24 usr/klibc/bsd_signal.c | 11 usr/klibc/bsearch.c | 26 usr/klibc/calloc.c | 20 usr/klibc/clearenv.c | 17 usr/klibc/closelog.c | 18 usr/klibc/creat.c | 12 usr/klibc/ctype/ctypefunc.h | 13 usr/klibc/ctype/isalnum.c | 2 usr/klibc/ctype/isalpha.c | 2 usr/klibc/ctype/isascii.c | 2 usr/klibc/ctype/isblank.c | 2 usr/klibc/ctype/iscntrl.c | 2 usr/klibc/ctype/isdigit.c | 2 usr/klibc/ctype/isgraph.c | 2 usr/klibc/ctype/islower.c | 2 usr/klibc/ctype/isprint.c | 2 usr/klibc/ctype/ispunct.c | 2 usr/klibc/ctype/isspace.c | 2 usr/klibc/ctype/isupper.c | 2 usr/klibc/ctype/isxdigit.c | 2 usr/klibc/ctype/tolower.c | 2 usr/klibc/ctype/toupper.c | 2 usr/klibc/ctypes.c | 284 + usr/klibc/daemon.c | 35 usr/klibc/env.h | 10 usr/klibc/exec_l.c | 59 usr/klibc/execl.c | 8 usr/klibc/execle.c | 8 usr/klibc/execlp.c | 8 usr/klibc/execlpe.c | 8 usr/klibc/execv.c | 11 usr/klibc/execvp.c | 11 usr/klibc/execvpe.c | 75 usr/klibc/exit.c | 30 usr/klibc/fgetc.c | 19 usr/klibc/fgets.c | 31 usr/klibc/fopen.c | 39 usr/klibc/fork.c | 21 usr/klibc/fprintf.c | 19 usr/klibc/fputc.c | 14 usr/klibc/fputs.c | 15 usr/klibc/fread.c | 33 usr/klibc/fread2.c | 13 usr/klibc/fstatfs.c | 19 usr/klibc/fwrite.c | 33 usr/klibc/fwrite2.c | 13 usr/klibc/getcwd.c | 15 usr/klibc/getdomainname.c | 25 usr/klibc/getenv.c | 24 usr/klibc/gethostname.c | 25 usr/klibc/getopt.c | 97 usr/klibc/getpgrp.c | 10 usr/klibc/getpriority.c | 23 usr/klibc/getpt.c | 17 usr/klibc/globals.c | 10 usr/klibc/inet/bindresvport.c | 46 usr/klibc/inet/inet_addr.c | 14 usr/klibc/inet/inet_aton.c | 22 usr/klibc/inet/inet_ntoa.c | 16 usr/klibc/inet/inet_ntop.c | 53 usr/klibc/inet/inet_pton.c | 78 usr/klibc/interp.S | 13 usr/klibc/isatty.c | 20 usr/klibc/jrand48.c | 24 usr/klibc/libc_init.c | 107 usr/klibc/libgcc/__ashldi3.c | 23 usr/klibc/libgcc/__ashrdi3.c | 23 usr/klibc/libgcc/__clzsi2.c | 36 usr/klibc/libgcc/__divdi3.c | 29 usr/klibc/libgcc/__divsi3.c | 29 usr/klibc/libgcc/__lshrdi3.c | 23 usr/klibc/libgcc/__moddi3.c | 29 usr/klibc/libgcc/__modsi3.c | 29 usr/klibc/libgcc/__udivdi3.c | 13 usr/klibc/libgcc/__udivmoddi4.c | 32 usr/klibc/libgcc/__udivmodsi4.c | 32 usr/klibc/libgcc/__udivsi3.c | 13 usr/klibc/libgcc/__umoddi3.c | 16 usr/klibc/libgcc/__umodsi3.c | 16 usr/klibc/llseek.c | 30 usr/klibc/lrand48.c | 13 usr/klibc/makeerrlist.pl | 98 usr/klibc/malloc.c | 200 usr/klibc/malloc.h | 47 usr/klibc/memccpy.c | 23 usr/klibc/memchr.c | 19 usr/klibc/memcmp.c | 19 usr/klibc/memcpy.c | 29 usr/klibc/memmem.c | 52 usr/klibc/memmove.c | 36 usr/klibc/memrchr.c | 19 usr/klibc/memset.c | 30 usr/klibc/memswap.c | 24 usr/klibc/mmap.c | 40 usr/klibc/mrand48.c | 13 usr/klibc/nice.c | 19 usr/klibc/nrand48.c | 11 usr/klibc/nullenv.c | 8 usr/klibc/onexit.c | 23 usr/klibc/open.c | 22 usr/klibc/openat.c | 22 usr/klibc/pause.c | 17 usr/klibc/perror.c | 13 usr/klibc/ppoll.c | 19 usr/klibc/printf.c | 19 usr/klibc/pselect.c | 42 usr/klibc/pty.c | 31 usr/klibc/putchar.c | 15 usr/klibc/putenv.c | 37 usr/klibc/puts.c | 13 usr/klibc/qsort.c | 42 usr/klibc/raise.c | 11 usr/klibc/readdir.c | 57 usr/klibc/realloc.c | 48 usr/klibc/reboot.c | 15 usr/klibc/recv.c | 11 usr/klibc/remove.c | 18 usr/klibc/sbrk.c | 45 usr/klibc/seed48.c | 18 usr/klibc/send.c | 11 usr/klibc/setegid.c | 10 usr/klibc/setenv.c | 42 usr/klibc/seteuid.c | 10 usr/klibc/setpgrp.c | 10 usr/klibc/sha1hash.c | 317 + usr/klibc/sigabbrev.c | 121 usr/klibc/sigaction.c | 60 usr/klibc/siglist.c | 121 usr/klibc/siglongjmp.c | 15 usr/klibc/sigpending.c | 18 usr/klibc/sigprocmask.c | 18 usr/klibc/sigsuspend.c | 18 usr/klibc/sleep.c | 20 usr/klibc/snprintf.c | 16 usr/klibc/socketcalls.pl | 88 usr/klibc/socketcalls/Kbuild | 50 usr/klibc/socketcalls/socketcommon.h | 16 usr/klibc/sprintf.c | 18 usr/klibc/srand48.c | 15 usr/klibc/sscanf.c | 17 usr/klibc/statfs.c | 19 usr/klibc/strcasecmp.c | 24 usr/klibc/strcat.c | 11 usr/klibc/strchr.c | 19 usr/klibc/strcmp.c | 21 usr/klibc/strcpy.c | 20 usr/klibc/strcspn.c | 10 usr/klibc/strdup.c | 17 usr/klibc/strerror.c | 33 usr/klibc/strlcat.c | 31 usr/klibc/strlcpy.c | 27 usr/klibc/strlen.c | 13 usr/klibc/strncasecmp.c | 24 usr/klibc/strncat.c | 22 usr/klibc/strncmp.c | 21 usr/klibc/strncpy.c | 24 usr/klibc/strndup.c | 17 usr/klibc/strnlen.c | 18 usr/klibc/strntoimax.c | 13 usr/klibc/strntoumax.c | 76 usr/klibc/strpbrk.c | 12 usr/klibc/strrchr.c | 21 usr/klibc/strsep.c | 21 usr/klibc/strsignal.c | 26 usr/klibc/strspn.c | 10 usr/klibc/strstr.c | 11 usr/klibc/strtoimax.c | 3 usr/klibc/strtok.c | 15 usr/klibc/strtol.c | 3 usr/klibc/strtoll.c | 3 usr/klibc/strtotimespec.c | 5 usr/klibc/strtotimeval.c | 5 usr/klibc/strtotimex.c | 39 usr/klibc/strtoul.c | 3 usr/klibc/strtoull.c | 3 usr/klibc/strtoumax.c | 3 usr/klibc/strtox.c | 13 usr/klibc/strxspn.c | 29 usr/klibc/strxspn.h | 12 usr/klibc/syscalls.pl | 286 + usr/klibc/syscalls/Kbuild | 94 usr/klibc/syscalls/syscommon.h | 33 usr/klibc/syslog.c | 89 usr/klibc/system.c | 61 usr/klibc/sysv_signal.c | 11 usr/klibc/tests/Kbuild | 47 usr/klibc/tests/environ.c | 24 usr/klibc/tests/fcntl.c | 50 usr/klibc/tests/getopttest.c | 32 usr/klibc/tests/getpagesize.c | 10 usr/klibc/tests/hello.c | 7 usr/klibc/tests/idtest.c | 14 usr/klibc/tests/malloctest.c | 4146 ++++++++++++++++++ usr/klibc/tests/malloctest2.c | 62 usr/klibc/tests/memstrtest.c | 28 usr/klibc/tests/microhello.c | 9 usr/klibc/tests/minihello.c | 7 usr/klibc/tests/mmaptest.c | 73 usr/klibc/tests/opentest.c | 15 usr/klibc/tests/pipetest.c | 39 usr/klibc/tests/rtsig.c | 12 usr/klibc/tests/setenvtest.c | 39 usr/klibc/tests/setjmptest.c | 38 usr/klibc/tests/sigint.c | 53 usr/klibc/tests/stat.c | 63 usr/klibc/tests/statfs.c | 42 usr/klibc/tests/strlcpycat.c | 111 usr/klibc/tests/strtoimax.c | 23 usr/klibc/tests/strtotime.c | 25 usr/klibc/tests/testrand48.c | 19 usr/klibc/tests/testvsnp.c | 119 usr/klibc/tests/vfork.c | 45 usr/klibc/time.c | 23 usr/klibc/umount.c | 12 usr/klibc/unsetenv.c | 44 usr/klibc/usleep.c | 15 usr/klibc/utime.c | 24 usr/klibc/vasprintf.c | 25 usr/klibc/version | 1 usr/klibc/vfork.c | 13 usr/klibc/vfprintf.c | 26 usr/klibc/vprintf.c | 11 usr/klibc/vsnprintf.c | 488 ++ usr/klibc/vsprintf.c | 11 usr/klibc/vsscanf.c | 378 + usr/klibc/wait.c | 12 usr/klibc/wait3.c | 12 usr/klibc/waitpid.c | 12 usr/klibc/zlib/FAQ | 339 + usr/klibc/zlib/INDEX | 51 usr/klibc/zlib/README | 125 usr/klibc/zlib/adler32.c | 149 usr/klibc/zlib/algorithm.txt | 209 usr/klibc/zlib/compress.c | 79 usr/klibc/zlib/crc32.c | 423 + usr/klibc/zlib/crc32.h | 441 + usr/klibc/zlib/deflate.c | 1736 +++++++ usr/klibc/zlib/deflate.h | 331 + usr/klibc/zlib/gzio.c | 1029 ++++ usr/klibc/zlib/infback.c | 623 ++ usr/klibc/zlib/inffast.c | 318 + usr/klibc/zlib/inffast.h | 11 usr/klibc/zlib/inffixed.h | 94 usr/klibc/zlib/inflate.c | 1368 +++++ usr/klibc/zlib/inflate.h | 115 usr/klibc/zlib/inftrees.c | 329 + usr/klibc/zlib/inftrees.h | 55 usr/klibc/zlib/trees.c | 1219 +++++ usr/klibc/zlib/trees.h | 127 usr/klibc/zlib/uncompr.c | 61 usr/klibc/zlib/zconf.in.h | 332 + usr/klibc/zlib/zlib.3 | 159 usr/klibc/zlib/zutil.c | 318 + usr/klibc/zlib/zutil.h | 269 + usr/utils/Kbuild | 62 usr/utils/cat.c | 329 + usr/utils/chroot.c | 25 usr/utils/dd.c | 533 ++ usr/utils/false.c | 4 usr/utils/file_mode.c | 143 usr/utils/file_mode.h | 1 usr/utils/halt.c | 55 usr/utils/insmod.c | 140 usr/utils/ln.c | 77 usr/utils/minips.c | 508 ++ usr/utils/mkdir.c | 150 usr/utils/mkfifo.c | 71 usr/utils/mknod.c | 58 usr/utils/mount_main.c | 105 usr/utils/mount_opts.c | 94 usr/utils/mount_opts.h | 21 usr/utils/nuke.c | 134 usr/utils/pivot_root.c | 19 usr/utils/sleep.c | 25 usr/utils/true.c | 4 usr/utils/umount.c | 45 usr/utils/uname.c | 154 802 files changed, 75696 insertions(+), 3959 deletions(-) diff -puN arch/i386/kernel/setup.c~git-klibc arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c~git-klibc +++ a/arch/i386/kernel/setup.c @@ -150,7 +150,6 @@ struct e820map e820; extern void early_cpu_init(void); extern void generic_apic_probe(char *); -extern int root_mountflags; unsigned long saved_videomode; @@ -1468,11 +1467,6 @@ void __init setup_arch(char **cmdline_p) } bootloader_type = LOADER_TYPE; -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif ARCH_SETUP if (efi_enabled) efi_init(); @@ -1483,8 +1477,6 @@ void __init setup_arch(char **cmdline_p) copy_edd(); - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; init_mm.start_code = (unsigned long) _text; init_mm.end_code = (unsigned long) _etext; init_mm.end_data = (unsigned long) _edata; diff -puN arch/powerpc/Makefile~git-klibc arch/powerpc/Makefile --- a/arch/powerpc/Makefile~git-klibc +++ a/arch/powerpc/Makefile @@ -51,6 +51,7 @@ SZ := 32 endif UTS_MACHINE := $(OLDARCH) +KLIBCARCH := $(OLDARCH) ifeq ($(HAS_BIARCH),y) override AS += -a$(SZ) diff -puN arch/s390/Makefile~git-klibc arch/s390/Makefile --- a/arch/s390/Makefile~git-klibc +++ a/arch/s390/Makefile @@ -20,6 +20,7 @@ AFLAGS += -m31 UTS_MACHINE := s390 STACK_SIZE := 8192 CHECKFLAGS += -D__s390__ +KLIBCARCH := s390 else LDFLAGS := -m elf64_s390 MODFLAGS += -fpic -D__PIC__ @@ -28,8 +29,11 @@ AFLAGS += -m64 UTS_MACHINE := s390x STACK_SIZE := 16384 CHECKFLAGS += -D__s390__ -D__s390x__ +KLIBCARCH := s390x endif +KLIBCARCHDIR := s390 + cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5) cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900) cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) diff -puN arch/sparc64/kernel/setup.c~git-klibc arch/sparc64/kernel/setup.c --- a/arch/sparc64/kernel/setup.c~git-klibc +++ a/arch/sparc64/kernel/setup.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -102,7 +103,7 @@ int obp_system_intr(void) return 0; } -/* +/* * Process kernel command line switches that are specific to the * SPARC or that require special low-level processing. */ @@ -214,8 +215,6 @@ extern unsigned short ram_flags; #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 -extern int root_mountflags; - char reboot_command[COMMAND_LINE_SIZE]; static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; @@ -315,6 +314,64 @@ void __init sun4v_patch(void) } } +/* + * Platform-specific configuration commands which don't come from + * the actual kernel command line. Write them into a file in rootfs + * so kinit can pick them up. + */ +static int __init set_arch_init_commands(void) +{ + int fd = sys_open("/arch.cmd", O_WRONLY|O_CREAT|O_APPEND, 0666); + int chosen; + u32 cl, sv, gw; + char buffer[256]; + int len = 0; + + if (fd < 0) + return fd; + + buffer[0] = 'r'; + buffer[1] = root_flags ? 'o' : 'w'; + buffer[2] = '\n'; + len = 3; + +#ifdef CONFIG_BLK_DEV_RAM + len += min((int)(sizeof buffer - 1 - len), + snprintf(buffer+len, sizeof buffer - len, + "ramdisk_start=%u\n" + "prompt_ramdisk=%d\n" + "load_ramdisk=%d\n", + ram_flags & RAMDISK_IMAGE_START_MASK, + !!(ram_flags & RAMDISK_PROMPT_FLAG), + !!(ram_flags & RAMDISK_LOAD_FLAG))); +#endif + + chosen = prom_finddevice("/chosen"); + cl = prom_getintdefault(chosen, "client-ip", 0); + sv = prom_getintdefault(chosen, "server-ip", 0); + gw = prom_getintdefault(chosen, "gateway-ip", 0); + + if (cl && sv) { + len += min((int)(sizeof buffer - 1 - len), + snprintf(buffer+len, sizeof buffer - len, + "ip=%u.%u.%u.%u:%u.%u.%u.%u:" + "%u.%u.%u.%u\n", + (u8)(cl >> 24), (u8)(cl >> 16), + (u8)(cl >> 8), (u8)cl, + (u8)(sv >> 24), (u8)(sv >> 16), + (u8)(sv >> 8), (u8)sv, + (u8)(gw >> 24), (u8)(gw >> 16), + (u8)(gw >> 8), (u8)gw)); + } + + sys_write(fd, buffer, len); + sys_close(fd); + + return 0; +} + +late_initcall(set_arch_init_commands); + #ifdef CONFIG_SMP void __init boot_cpu_id_too_large(int cpu) { @@ -345,37 +402,10 @@ void __init setup_arch(char **cmdline_p) idprom_init(); - if (!root_flags) - root_mountflags &= ~MS_RDONLY; ROOT_DEV = old_decode_dev(root_dev); -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); -#endif task_thread_info(&init_task)->kregs = &fake_swapper_regs; -#ifdef CONFIG_IP_PNP - if (!ic_set_manually) { - int chosen = prom_finddevice ("/chosen"); - u32 cl, sv, gw; - - cl = prom_getintdefault (chosen, "client-ip", 0); - sv = prom_getintdefault (chosen, "server-ip", 0); - gw = prom_getintdefault (chosen, "gateway-ip", 0); - if (cl && sv) { - ic_myaddr = cl; - ic_servaddr = sv; - if (gw) - ic_gateway = gw; -#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) - ic_proto_enabled = 0; -#endif - } - } -#endif - /* Get boot processor trap_block[] setup. */ init_cur_cpu_trap(current_thread_info()); @@ -438,7 +468,7 @@ static int ncpus_probed; static int show_cpuinfo(struct seq_file *m, void *__unused) { - seq_printf(m, + seq_printf(m, "cpu\t\t: %s\n" "fpu\t\t: %s\n" "prom\t\t: %s\n" diff -puN arch/sparc/kernel/setup.c~git-klibc arch/sparc/kernel/setup.c --- a/arch/sparc/kernel/setup.c~git-klibc +++ a/arch/sparc/kernel/setup.c @@ -241,8 +241,6 @@ extern unsigned short ram_flags; #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 -extern int root_mountflags; - char reboot_command[COMMAND_LINE_SIZE]; enum sparc_cpu sparc_cpu_model; @@ -389,6 +387,44 @@ static int __init set_preferred_console( } console_initcall(set_preferred_console); +/* + * Platform-specific configuration commands which don't come from + * the actual kernel command line. Write them into a file in rootfs + * so kinit can pick them up. + */ +static int __init set_arch_init_commands(void) +{ + int fd = sys_open("/arch.cmd", O_WRONLY|O_CREAT|O_APPEND, 0666); + char buffer[256]; + int len = 0; + + if (fd < 0) + return fd; + + buffer[0] = 'r'; + buffer[1] = root_flags ? 'o' : 'w'; + buffer[2] = '\n'; + len = 3; + +#ifdef CONFIG_BLK_DEV_RAM + len += min((int)(sizeof buffer - 1 - len), + snprintf(buffer+len, sizeof buffer - len, + "ramdisk_start=%u\n" + "prompt_ramdisk=%d\n" + "load_ramdisk=%d\n", + ram_flags & RAMDISK_IMAGE_START_MASK, + !!(ram_flags & RAMDISK_PROMPT_FLAG), + !!(ram_flags & RAMDISK_LOAD_FLAG))); +#endif + + sys_write(fd, buffer, len); + sys_close(fd); + + return 0; +} + +late_initcall(set_arch_init_commands); + extern char *sparc_cpu_type; extern char *sparc_fpu_type; diff -puN arch/um/Makefile~git-klibc arch/um/Makefile --- a/arch/um/Makefile~git-klibc +++ a/arch/um/Makefile @@ -50,6 +50,8 @@ ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR) endif SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) +KLIBCARCH := $(SUBARCH) + # -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so # named - it's a common symbol in libpcap, so we get a binary which crashes. # diff -puN arch/x86_64/kernel/setup.c~git-klibc arch/x86_64/kernel/setup.c --- a/arch/x86_64/kernel/setup.c~git-klibc +++ a/arch/x86_64/kernel/setup.c @@ -530,16 +530,9 @@ void __init setup_arch(char **cmdline_p) saved_video_mode = SAVED_VIDEO_MODE; bootloader_type = LOADER_TYPE; -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif setup_memory_region(); copy_edd(); - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; init_mm.start_code = (unsigned long) &_text; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; diff -puN fs/Kconfig~git-klibc fs/Kconfig --- a/fs/Kconfig~git-klibc +++ a/fs/Kconfig @@ -1558,20 +1558,6 @@ config NFSD_TCP TCP connections usually perform better than the default UDP when the network is lossy or congested. If unsure, say Y. -config ROOT_NFS - bool "Root file system on NFS" - depends on NFS_FS=y && IP_PNP - help - If you want your Linux box to mount its whole root file system (the - one containing the directory /) from some other computer over the - net via NFS (presumably because your box doesn't have a hard disk), - say Y. Read for details. It is - likely that in this case, you also want to say Y to "Kernel level IP - autoconfiguration" so that your box can discover its network address - at boot time. - - Most people say N here. - config LOCKD tristate diff -puN fs/nfs/Makefile~git-klibc fs/nfs/Makefile --- a/fs/nfs/Makefile~git-klibc +++ a/fs/nfs/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_NFS_FS) += nfs.o nfs-y := dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \ proc.o read.o symlink.o unlink.o write.o \ namespace.o -nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ diff -puN fs/nfs/mount_clnt.c~git-klibc /dev/null --- a/fs/nfs/mount_clnt.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * linux/fs/nfs/mount_clnt.c - * - * MOUNT client to support NFSroot. - * - * Copyright (C) 1997, Olaf Kirch - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef RPC_DEBUG -# define NFSDBG_FACILITY NFSDBG_ROOT -#endif - -/* -#define MOUNT_PROGRAM 100005 -#define MOUNT_VERSION 1 -#define MOUNT_MNT 1 -#define MOUNT_UMNT 3 - */ - -static struct rpc_clnt * mnt_create(char *, struct sockaddr_in *, - int, int); -static struct rpc_program mnt_program; - -struct mnt_fhstatus { - unsigned int status; - struct nfs_fh * fh; -}; - -/* - * Obtain an NFS file handle for the given host and path - */ -int -nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh, - int version, int protocol) -{ - struct rpc_clnt *mnt_clnt; - struct mnt_fhstatus result = { - .fh = fh - }; - struct rpc_message msg = { - .rpc_argp = path, - .rpc_resp = &result, - }; - char hostname[32]; - int status; - - dprintk("NFS: nfs_mount(%08x:%s)\n", - (unsigned)ntohl(addr->sin_addr.s_addr), path); - - sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr)); - mnt_clnt = mnt_create(hostname, addr, version, protocol); - if (IS_ERR(mnt_clnt)) - return PTR_ERR(mnt_clnt); - - if (version == NFS_MNT3_VERSION) - msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT]; - else - msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT]; - - status = rpc_call_sync(mnt_clnt, &msg, 0); - return status < 0? status : (result.status? -EACCES : 0); -} - -static struct rpc_clnt * -mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, - int protocol) -{ - struct rpc_xprt *xprt; - struct rpc_clnt *clnt; - - xprt = xprt_create_proto(protocol, srvaddr, NULL); - if (IS_ERR(xprt)) - return (struct rpc_clnt *)xprt; - - clnt = rpc_create_client(xprt, hostname, - &mnt_program, version, - RPC_AUTH_UNIX); - if (!IS_ERR(clnt)) { - clnt->cl_softrtry = 1; - clnt->cl_oneshot = 1; - clnt->cl_intr = 1; - } - return clnt; -} - -/* - * XDR encode/decode functions for MOUNT - */ -static int -xdr_encode_dirpath(struct rpc_rqst *req, u32 *p, const char *path) -{ - p = xdr_encode_string(p, path); - - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - return 0; -} - -static int -xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) -{ - struct nfs_fh *fh = res->fh; - - if ((res->status = ntohl(*p++)) == 0) { - fh->size = NFS2_FHSIZE; - memcpy(fh->data, p, NFS2_FHSIZE); - } - return 0; -} - -static int -xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) -{ - struct nfs_fh *fh = res->fh; - - if ((res->status = ntohl(*p++)) == 0) { - int size = ntohl(*p++); - if (size <= NFS3_FHSIZE) { - fh->size = size; - memcpy(fh->data, p, size); - } else - res->status = -EBADHANDLE; - } - return 0; -} - -#define MNT_dirpath_sz (1 + 256) -#define MNT_fhstatus_sz (1 + 8) - -static struct rpc_procinfo mnt_procedures[] = { -[MNTPROC_MNT] = { - .p_proc = MNTPROC_MNT, - .p_encode = (kxdrproc_t) xdr_encode_dirpath, - .p_decode = (kxdrproc_t) xdr_decode_fhstatus, - .p_bufsiz = MNT_dirpath_sz << 2, - .p_statidx = MNTPROC_MNT, - .p_name = "MOUNT", - }, -}; - -static struct rpc_procinfo mnt3_procedures[] = { -[MOUNTPROC3_MNT] = { - .p_proc = MOUNTPROC3_MNT, - .p_encode = (kxdrproc_t) xdr_encode_dirpath, - .p_decode = (kxdrproc_t) xdr_decode_fhstatus3, - .p_bufsiz = MNT_dirpath_sz << 2, - .p_statidx = MOUNTPROC3_MNT, - .p_name = "MOUNT", - }, -}; - - -static struct rpc_version mnt_version1 = { - .number = 1, - .nrprocs = 2, - .procs = mnt_procedures -}; - -static struct rpc_version mnt_version3 = { - .number = 3, - .nrprocs = 2, - .procs = mnt3_procedures -}; - -static struct rpc_version * mnt_version[] = { - NULL, - &mnt_version1, - NULL, - &mnt_version3, -}; - -static struct rpc_stat mnt_stats; - -static struct rpc_program mnt_program = { - .name = "mount", - .number = NFS_MNT_PROGRAM, - .nrvers = ARRAY_SIZE(mnt_version), - .version = mnt_version, - .stats = &mnt_stats, -}; diff -puN fs/nfs/nfsroot.c~git-klibc /dev/null --- a/fs/nfs/nfsroot.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * $Id: nfsroot.c,v 1.45 1998/03/07 10:44:46 mj Exp $ - * - * Copyright (C) 1995, 1996 Gero Kuhlmann - * - * Allow an NFS filesystem to be mounted as root. The way this works is: - * (1) Use the IP autoconfig mechanism to set local IP addresses and routes. - * (2) Handle RPC negotiation with the system which replied to RARP or - * was reported as a boot server by BOOTP or manually. - * (3) The actual mounting is done later, when init() is running. - * - * - * Changes: - * - * Alan Cox : Removed get_address name clash with FPU. - * Alan Cox : Reformatted a bit. - * Gero Kuhlmann : Code cleanup - * Michael Rausch : Fixed recognition of an incoming RARP answer. - * Martin Mares : (2.0) Auto-configuration via BOOTP supported. - * Martin Mares : Manual selection of interface & BOOTP/RARP. - * Martin Mares : Using network routes instead of host routes, - * allowing the default configuration to be used - * for normal operation of the host. - * Martin Mares : Randomized timer with exponential backoff - * installed to minimize network congestion. - * Martin Mares : Code cleanup. - * Martin Mares : (2.1) BOOTP and RARP made configuration options. - * Martin Mares : Server hostname generation fixed. - * Gerd Knorr : Fixed wired inode handling - * Martin Mares : (2.2) "0.0.0.0" addresses from command line ignored. - * Martin Mares : RARP replies not tested for server address. - * Gero Kuhlmann : (2.3) Some bug fixes and code cleanup again (please - * send me your new patches _before_ bothering - * Linus so that I don' always have to cleanup - * _afterwards_ - thanks) - * Gero Kuhlmann : Last changes of Martin Mares undone. - * Gero Kuhlmann : RARP replies are tested for specified server - * again. However, it's now possible to have - * different RARP and NFS servers. - * Gero Kuhlmann : "0.0.0.0" addresses from command line are - * now mapped to INADDR_NONE. - * Gero Kuhlmann : Fixed a bug which prevented BOOTP path name - * from being used (thanks to Leo Spiekman) - * Andy Walker : Allow to specify the NFS server in nfs_root - * without giving a path name - * Swen Thümmler : Allow to specify the NFS options in nfs_root - * without giving a path name. Fix BOOTP request - * for domainname (domainname is NIS domain, not - * DNS domain!). Skip dummy devices for BOOTP. - * Jacek Zapala : Fixed a bug which prevented server-ip address - * from nfsroot parameter from being used. - * Olaf Kirch : Adapted to new NFS code. - * Jakub Jelinek : Free used code segment. - * Marko Kohtala : Fixed some bugs. - * Martin Mares : Debug message cleanup - * Martin Mares : Changed to use the new generic IP layer autoconfig - * code. BOOTP and RARP moved there. - * Martin Mares : Default path now contains host name instead of - * host IP address (but host name defaults to IP - * address anyway). - * Martin Mares : Use root_server_addr appropriately during setup. - * Martin Mares : Rewrote parameter parsing, now hopefully giving - * correct overriding. - * Trond Myklebust : Add in preliminary support for NFSv3 and TCP. - * Fix bug in root_nfs_addr(). nfs_data.namlen - * is NOT for the length of the hostname. - * Hua Qin : Support for mounting root file system via - * NFS over TCP. - * Fabian Frederick: Option parser rebuilt (using parser lib) -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Define this to allow debugging output */ -#undef NFSROOT_DEBUG -#define NFSDBG_FACILITY NFSDBG_ROOT - -/* Default path we try to mount. "%s" gets replaced by our IP address */ -#define NFS_ROOT "/tftpboot/%s" - -/* Parameters passed from the kernel command line */ -static char nfs_root_name[256] __initdata = ""; - -/* Address of NFS server */ -static __u32 servaddr __initdata = 0; - -/* Name of directory to mount */ -static char nfs_path[NFS_MAXPATHLEN] __initdata = { 0, }; - -/* NFS-related data */ -static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */ -static int nfs_port __initdata = 0; /* Port to connect to for NFS */ -static int mount_port __initdata = 0; /* Mount daemon port number */ - - -/*************************************************************************** - - Parsing of options - - ***************************************************************************/ - -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rsize, Opt_wsize, Opt_timeo, Opt_retrans, Opt_acregmin, - Opt_acregmax, Opt_acdirmin, Opt_acdirmax, - /* Options that take no arguments */ - Opt_soft, Opt_hard, Opt_intr, - Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, - Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp, - Opt_acl, Opt_noacl, - /* Error token */ - Opt_err -}; - -static match_table_t __initdata tokens = { - {Opt_port, "port=%u"}, - {Opt_rsize, "rsize=%u"}, - {Opt_wsize, "wsize=%u"}, - {Opt_timeo, "timeo=%u"}, - {Opt_retrans, "retrans=%u"}, - {Opt_acregmin, "acregmin=%u"}, - {Opt_acregmax, "acregmax=%u"}, - {Opt_acdirmin, "acdirmin=%u"}, - {Opt_acdirmax, "acdirmax=%u"}, - {Opt_soft, "soft"}, - {Opt_hard, "hard"}, - {Opt_intr, "intr"}, - {Opt_nointr, "nointr"}, - {Opt_posix, "posix"}, - {Opt_noposix, "noposix"}, - {Opt_cto, "cto"}, - {Opt_nocto, "nocto"}, - {Opt_ac, "ac"}, - {Opt_noac, "noac"}, - {Opt_lock, "lock"}, - {Opt_nolock, "nolock"}, - {Opt_v2, "nfsvers=2"}, - {Opt_v2, "v2"}, - {Opt_v3, "nfsvers=3"}, - {Opt_v3, "v3"}, - {Opt_udp, "proto=udp"}, - {Opt_udp, "udp"}, - {Opt_tcp, "proto=tcp"}, - {Opt_tcp, "tcp"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, - {Opt_err, NULL} - -}; - -/* - * Parse option string. - */ - -static int __init root_nfs_parse(char *name, char *buf) -{ - - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - - if (!name) - return 1; - - /* Set the NFS remote path */ - p = strsep(&name, ","); - if (p[0] != '\0' && strcmp(p, "default") != 0) - strlcpy(buf, p, NFS_MAXPATHLEN); - - while ((p = strsep (&name, ",")) != NULL) { - int token; - if (!*p) - continue; - token = match_token(p, tokens, args); - - /* %u tokens only. Beware if you add new tokens! */ - if (token < Opt_soft && match_int(&args[0], &option)) - return 0; - switch (token) { - case Opt_port: - nfs_port = option; - break; - case Opt_rsize: - nfs_data.rsize = option; - break; - case Opt_wsize: - nfs_data.wsize = option; - break; - case Opt_timeo: - nfs_data.timeo = option; - break; - case Opt_retrans: - nfs_data.retrans = option; - break; - case Opt_acregmin: - nfs_data.acregmin = option; - break; - case Opt_acregmax: - nfs_data.acregmax = option; - break; - case Opt_acdirmin: - nfs_data.acdirmin = option; - break; - case Opt_acdirmax: - nfs_data.acdirmax = option; - break; - case Opt_soft: - nfs_data.flags |= NFS_MOUNT_SOFT; - break; - case Opt_hard: - nfs_data.flags &= ~NFS_MOUNT_SOFT; - break; - case Opt_intr: - nfs_data.flags |= NFS_MOUNT_INTR; - break; - case Opt_nointr: - nfs_data.flags &= ~NFS_MOUNT_INTR; - break; - case Opt_posix: - nfs_data.flags |= NFS_MOUNT_POSIX; - break; - case Opt_noposix: - nfs_data.flags &= ~NFS_MOUNT_POSIX; - break; - case Opt_cto: - nfs_data.flags &= ~NFS_MOUNT_NOCTO; - break; - case Opt_nocto: - nfs_data.flags |= NFS_MOUNT_NOCTO; - break; - case Opt_ac: - nfs_data.flags &= ~NFS_MOUNT_NOAC; - break; - case Opt_noac: - nfs_data.flags |= NFS_MOUNT_NOAC; - break; - case Opt_lock: - nfs_data.flags &= ~NFS_MOUNT_NONLM; - break; - case Opt_nolock: - nfs_data.flags |= NFS_MOUNT_NONLM; - break; - case Opt_v2: - nfs_data.flags &= ~NFS_MOUNT_VER3; - break; - case Opt_v3: - nfs_data.flags |= NFS_MOUNT_VER3; - break; - case Opt_udp: - nfs_data.flags &= ~NFS_MOUNT_TCP; - break; - case Opt_tcp: - nfs_data.flags |= NFS_MOUNT_TCP; - break; - case Opt_acl: - nfs_data.flags &= ~NFS_MOUNT_NOACL; - break; - case Opt_noacl: - nfs_data.flags |= NFS_MOUNT_NOACL; - break; - default: - printk(KERN_WARNING "Root-NFS: unknown " - "option: %s\n", p); - return 0; - } - } - - return 1; -} - -/* - * Prepare the NFS data structure and parse all options. - */ -static int __init root_nfs_name(char *name) -{ - static char buf[NFS_MAXPATHLEN] __initdata; - char *cp; - - /* Set some default values */ - memset(&nfs_data, 0, sizeof(nfs_data)); - nfs_port = -1; - nfs_data.version = NFS_MOUNT_VERSION; - nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */ - nfs_data.rsize = NFS_DEF_FILE_IO_SIZE; - nfs_data.wsize = NFS_DEF_FILE_IO_SIZE; - nfs_data.acregmin = 3; - nfs_data.acregmax = 60; - nfs_data.acdirmin = 30; - nfs_data.acdirmax = 60; - strcpy(buf, NFS_ROOT); - - /* Process options received from the remote server */ - root_nfs_parse(root_server_path, buf); - - /* Override them by options set on kernel command-line */ - root_nfs_parse(name, buf); - - cp = system_utsname.nodename; - if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) { - printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n"); - return -1; - } - sprintf(nfs_path, buf, cp); - - return 1; -} - - -/* - * Get NFS server address. - */ -static int __init root_nfs_addr(void) -{ - if ((servaddr = root_server_addr) == INADDR_NONE) { - printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n"); - return -1; - } - - snprintf(nfs_data.hostname, sizeof(nfs_data.hostname), - "%u.%u.%u.%u", NIPQUAD(servaddr)); - return 0; -} - -/* - * Tell the user what's going on. - */ -#ifdef NFSROOT_DEBUG -static void __init root_nfs_print(void) -{ - printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n", - nfs_path, nfs_data.hostname); - printk(KERN_NOTICE "Root-NFS: rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", - nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans); - printk(KERN_NOTICE "Root-NFS: acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n", - nfs_data.acregmin, nfs_data.acregmax, - nfs_data.acdirmin, nfs_data.acdirmax); - printk(KERN_NOTICE "Root-NFS: nfsd port = %d, mountd port = %d, flags = %08x\n", - nfs_port, mount_port, nfs_data.flags); -} -#endif - - -static int __init root_nfs_init(void) -{ -#ifdef NFSROOT_DEBUG - nfs_debug |= NFSDBG_ROOT; -#endif - - /* - * Decode the root directory path name and NFS options from - * the kernel command line. This has to go here in order to - * be able to use the client IP address for the remote root - * directory (necessary for pure RARP booting). - */ - if (root_nfs_name(nfs_root_name) < 0 || - root_nfs_addr() < 0) - return -1; - -#ifdef NFSROOT_DEBUG - root_nfs_print(); -#endif - - return 0; -} - - -/* - * Parse NFS server and directory information passed on the kernel - * command line. - */ -static int __init nfs_root_setup(char *line) -{ - ROOT_DEV = Root_NFS; - if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) { - strlcpy(nfs_root_name, line, sizeof(nfs_root_name)); - } else { - int n = strlen(line) + sizeof(NFS_ROOT) - 1; - if (n >= sizeof(nfs_root_name)) - line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0'; - sprintf(nfs_root_name, NFS_ROOT, line); - } - root_server_addr = root_nfs_parse_addr(nfs_root_name); - return 1; -} - -__setup("nfsroot=", nfs_root_setup); - -/*************************************************************************** - - Routines to actually mount the root directory - - ***************************************************************************/ - -/* - * Construct sockaddr_in from address and port number. - */ -static inline void -set_sockaddr(struct sockaddr_in *sin, __u32 addr, __u16 port) -{ - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = addr; - sin->sin_port = port; -} - -/* - * Query server portmapper for the port of a daemon program. - */ -static int __init root_nfs_getport(int program, int version, int proto) -{ - struct sockaddr_in sin; - - printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n", - program, version, NIPQUAD(servaddr)); - set_sockaddr(&sin, servaddr, 0); - return rpc_getport_external(&sin, program, version, proto); -} - - -/* - * Use portmapper to find mountd and nfsd port numbers if not overriden - * by the user. Use defaults if portmapper is not available. - * XXX: Is there any nfs server with no portmapper? - */ -static int __init root_nfs_ports(void) -{ - int port; - int nfsd_ver, mountd_ver; - int nfsd_port, mountd_port; - int proto; - - if (nfs_data.flags & NFS_MOUNT_VER3) { - nfsd_ver = NFS3_VERSION; - mountd_ver = NFS_MNT3_VERSION; - nfsd_port = NFS_PORT; - mountd_port = NFS_MNT_PORT; - } else { - nfsd_ver = NFS2_VERSION; - mountd_ver = NFS_MNT_VERSION; - nfsd_port = NFS_PORT; - mountd_port = NFS_MNT_PORT; - } - - proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; - - if (nfs_port < 0) { - if ((port = root_nfs_getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) { - printk(KERN_ERR "Root-NFS: Unable to get nfsd port " - "number from server, using default\n"); - port = nfsd_port; - } - nfs_port = port; - dprintk("Root-NFS: Portmapper on server returned %d " - "as nfsd port\n", port); - } - nfs_port = htons(nfs_port); - - if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) { - printk(KERN_ERR "Root-NFS: Unable to get mountd port " - "number from server, using default\n"); - port = mountd_port; - } - mount_port = htons(port); - dprintk("Root-NFS: mountd port is %d\n", port); - - return 0; -} - - -/* - * Get a file handle from the server for the directory which is to be - * mounted. - */ -static int __init root_nfs_get_handle(void) -{ - struct nfs_fh fh; - struct sockaddr_in sin; - int status; - int protocol = (nfs_data.flags & NFS_MOUNT_TCP) ? - IPPROTO_TCP : IPPROTO_UDP; - int version = (nfs_data.flags & NFS_MOUNT_VER3) ? - NFS_MNT3_VERSION : NFS_MNT_VERSION; - - set_sockaddr(&sin, servaddr, mount_port); - status = nfsroot_mount(&sin, nfs_path, &fh, version, protocol); - if (status < 0) - printk(KERN_ERR "Root-NFS: Server returned error %d " - "while mounting %s\n", status, nfs_path); - else { - nfs_data.root.size = fh.size; - memcpy(nfs_data.root.data, fh.data, fh.size); - } - - return status; -} - -/* - * Get the NFS port numbers and file handle, and return the prepared 'data' - * argument for mount() if everything went OK. Return NULL otherwise. - */ -void * __init nfs_root_data(void) -{ - if (root_nfs_init() < 0 - || root_nfs_ports() < 0 - || root_nfs_get_handle() < 0) - return NULL; - set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, nfs_port); - return (void*)&nfs_data; -} diff -puN include/linux/mount.h~git-klibc include/linux/mount.h --- a/include/linux/mount.h~git-klibc +++ a/include/linux/mount.h @@ -94,7 +94,6 @@ extern void mark_mounts_for_expiry(struc extern void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts); extern spinlock_t vfsmount_lock; -extern dev_t name_to_dev_t(char *name); #endif #endif /* _LINUX_MOUNT_H */ diff -puN init/do_mounts.c~git-klibc /dev/null --- a/init/do_mounts.c +++ /dev/null @@ -1,437 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "do_mounts.h" - -extern int get_filesystem_list(char * buf); - -int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ - -int root_mountflags = MS_RDONLY | MS_SILENT; -char * __initdata root_device_name; -static char __initdata saved_root_name[64]; - -dev_t ROOT_DEV; - -static int __init load_ramdisk(char *str) -{ - rd_doload = simple_strtol(str,NULL,0) & 3; - return 1; -} -__setup("load_ramdisk=", load_ramdisk); - -static int __init readonly(char *str) -{ - if (*str) - return 0; - root_mountflags |= MS_RDONLY; - return 1; -} - -static int __init readwrite(char *str) -{ - if (*str) - return 0; - root_mountflags &= ~MS_RDONLY; - return 1; -} - -__setup("ro", readonly); -__setup("rw", readwrite); - -static dev_t try_name(char *name, int part) -{ - char path[64]; - char buf[32]; - int range; - dev_t res; - char *s; - int len; - int fd; - unsigned int maj, min; - - /* read device number from .../dev */ - - sprintf(path, "/sys/block/%s/dev", name); - fd = sys_open(path, 0, 0); - if (fd < 0) - goto fail; - len = sys_read(fd, buf, 32); - sys_close(fd); - if (len <= 0 || len == 32 || buf[len - 1] != '\n') - goto fail; - buf[len - 1] = '\0'; - if (sscanf(buf, "%u:%u", &maj, &min) == 2) { - /* - * Try the %u:%u format -- see print_dev_t() - */ - res = MKDEV(maj, min); - if (maj != MAJOR(res) || min != MINOR(res)) - goto fail; - } else { - /* - * Nope. Try old-style "0321" - */ - res = new_decode_dev(simple_strtoul(buf, &s, 16)); - if (*s) - goto fail; - } - - /* if it's there and we are not looking for a partition - that's it */ - if (!part) - return res; - - /* otherwise read range from .../range */ - sprintf(path, "/sys/block/%s/range", name); - fd = sys_open(path, 0, 0); - if (fd < 0) - goto fail; - len = sys_read(fd, buf, 32); - sys_close(fd); - if (len <= 0 || len == 32 || buf[len - 1] != '\n') - goto fail; - buf[len - 1] = '\0'; - range = simple_strtoul(buf, &s, 10); - if (*s) - goto fail; - - /* if partition is within range - we got it */ - if (part < range) - return res + part; -fail: - return 0; -} - -/* - * Convert a name into device number. We accept the following variants: - * - * 1) device number in hexadecimal represents itself - * 2) /dev/nfs represents Root_NFS (0xff) - * 3) /dev/ represents the device number of disk - * 4) /dev/ represents the device number - * of partition - device number of disk plus the partition number - * 5) /dev/p - same as the above, that form is - * used when disk name of partitioned disk ends on a digit. - * - * If name doesn't have fall into the categories above, we return 0. - * Sysfs is used to check if something is a disk name - it has - * all known disks under bus/block/devices. If the disk name - * contains slashes, name of sysfs node has them replaced with - * bangs. try_name() does the actual checks, assuming that sysfs - * is mounted on rootfs /sys. - */ - -dev_t name_to_dev_t(char *name) -{ - char s[32]; - char *p; - dev_t res = 0; - int part; - -#ifdef CONFIG_SYSFS - int mkdir_err = sys_mkdir("/sys", 0700); - if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0) - goto out; -#endif - - if (strncmp(name, "/dev/", 5) != 0) { - unsigned maj, min; - - if (sscanf(name, "%u:%u", &maj, &min) == 2) { - res = MKDEV(maj, min); - if (maj != MAJOR(res) || min != MINOR(res)) - goto fail; - } else { - res = new_decode_dev(simple_strtoul(name, &p, 16)); - if (*p) - goto fail; - } - goto done; - } - name += 5; - res = Root_NFS; - if (strcmp(name, "nfs") == 0) - goto done; - res = Root_RAM0; - if (strcmp(name, "ram") == 0) - goto done; - - if (strlen(name) > 31) - goto fail; - strcpy(s, name); - for (p = s; *p; p++) - if (*p == '/') - *p = '!'; - res = try_name(s, 0); - if (res) - goto done; - - while (p > s && isdigit(p[-1])) - p--; - if (p == s || !*p || *p == '0') - goto fail; - part = simple_strtoul(p, NULL, 10); - *p = '\0'; - res = try_name(s, part); - if (res) - goto done; - - if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') - goto fail; - p[-1] = '\0'; - res = try_name(s, part); -done: -#ifdef CONFIG_SYSFS - sys_umount("/sys", 0); -out: - if (!mkdir_err) - sys_rmdir("/sys"); -#endif - return res; -fail: - res = 0; - goto done; -} - -static int __init root_dev_setup(char *line) -{ - strlcpy(saved_root_name, line, sizeof(saved_root_name)); - return 1; -} - -__setup("root=", root_dev_setup); - -static char * __initdata root_mount_data; -static int __init root_data_setup(char *str) -{ - root_mount_data = str; - return 1; -} - -static char * __initdata root_fs_names; -static int __init fs_names_setup(char *str) -{ - root_fs_names = str; - return 1; -} - -static unsigned int __initdata root_delay; -static int __init root_delay_setup(char *str) -{ - root_delay = simple_strtoul(str, NULL, 0); - return 1; -} - -__setup("rootflags=", root_data_setup); -__setup("rootfstype=", fs_names_setup); -__setup("rootdelay=", root_delay_setup); - -static void __init get_fs_names(char *page) -{ - char *s = page; - - if (root_fs_names) { - strcpy(page, root_fs_names); - while (*s++) { - if (s[-1] == ',') - s[-1] = '\0'; - } - } else { - int len = get_filesystem_list(page); - char *p, *next; - - page[len] = '\0'; - for (p = page-1; p; p = next) { - next = strchr(++p, '\n'); - if (*p++ != '\t') - continue; - while ((*s++ = *p++) != '\n') - ; - s[-1] = '\0'; - } - } - *s = '\0'; -} - -static int __init do_mount_root(char *name, char *fs, int flags, void *data) -{ - int err = sys_mount(name, "/root", fs, flags, data); - if (err) - return err; - - sys_chdir("/root"); - ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; - printk("VFS: Mounted root (%s filesystem)%s.\n", - current->fs->pwdmnt->mnt_sb->s_type->name, - current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY ? - " readonly" : ""); - return 0; -} - -void __init mount_block_root(char *name, int flags) -{ - char *fs_names = __getname(); - char *p; - char b[BDEVNAME_SIZE]; - - get_fs_names(fs_names); -retry: - for (p = fs_names; *p; p += strlen(p)+1) { - int err = do_mount_root(name, p, flags, root_mount_data); - switch (err) { - case 0: - goto out; - case -EACCES: - flags |= MS_RDONLY; - goto retry; - case -EINVAL: - continue; - } - /* - * Allow the user to distinguish between failed sys_open - * and bad superblock on root device. - */ - __bdevname(ROOT_DEV, b); - printk("VFS: Cannot open root device \"%s\" or %s\n", - root_device_name, b); - printk("Please append a correct \"root=\" boot option\n"); - - panic("VFS: Unable to mount root fs on %s", b); - } - - printk("No filesystem could mount root, tried: "); - for (p = fs_names; *p; p += strlen(p)+1) - printk(" %s", p); - printk("\n"); - panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b)); -out: - putname(fs_names); -} - -#ifdef CONFIG_ROOT_NFS -static int __init mount_nfs_root(void) -{ - void *data = nfs_root_data(); - - create_dev("/dev/root", ROOT_DEV, NULL); - if (data && - do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0) - return 1; - return 0; -} -#endif - -#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) -void __init change_floppy(char *fmt, ...) -{ - struct termios termios; - char buf[80]; - char c; - int fd; - va_list args; - va_start(args, fmt); - vsprintf(buf, fmt, args); - va_end(args); - fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); - if (fd >= 0) { - sys_ioctl(fd, FDEJECT, 0); - sys_close(fd); - } - printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); - fd = sys_open("/dev/console", O_RDWR, 0); - if (fd >= 0) { - sys_ioctl(fd, TCGETS, (long)&termios); - termios.c_lflag &= ~ICANON; - sys_ioctl(fd, TCSETSF, (long)&termios); - sys_read(fd, &c, 1); - termios.c_lflag |= ICANON; - sys_ioctl(fd, TCSETSF, (long)&termios); - sys_close(fd); - } -} -#endif - -void __init mount_root(void) -{ -#ifdef CONFIG_ROOT_NFS - if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { - if (mount_nfs_root()) - return; - - printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); - ROOT_DEV = Root_FD0; - } -#endif -#ifdef CONFIG_BLK_DEV_FD - if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { - /* rd_doload is 2 for a dual initrd/ramload setup */ - if (rd_doload==2) { - if (rd_load_disk(1)) { - ROOT_DEV = Root_RAM1; - root_device_name = NULL; - } - } else - change_floppy("root floppy"); - } -#endif - create_dev("/dev/root", ROOT_DEV, root_device_name); - mount_block_root("/dev/root", root_mountflags); -} - -/* - * Prepare the namespace - decide what/where to mount, load ramdisks, etc. - */ -void __init prepare_namespace(void) -{ - int is_floppy; - - mount_devfs(); - - if (root_delay) { - printk(KERN_INFO "Waiting %dsec before mounting root device...\n", - root_delay); - ssleep(root_delay); - } - - md_run_setup(); - - if (saved_root_name[0]) { - root_device_name = saved_root_name; - if (!strncmp(root_device_name, "mtd", 3)) { - mount_block_root(root_device_name, root_mountflags); - goto out; - } - ROOT_DEV = name_to_dev_t(root_device_name); - if (strncmp(root_device_name, "/dev/", 5) == 0) - root_device_name += 5; - } - - is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; - - if (initrd_load()) - goto out; - - if (is_floppy && rd_doload && rd_load_disk(0)) - ROOT_DEV = Root_RAM0; - - mount_root(); -out: - umount_devfs("/dev"); - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); - security_sb_post_mountroot(); - mount_devfs_fs (); -} - diff -puN init/do_mounts_devfs.c~git-klibc /dev/null --- a/init/do_mounts_devfs.c +++ /dev/null @@ -1,137 +0,0 @@ - -#include -#include -#include - -#include "do_mounts.h" - -void __init mount_devfs(void) -{ - sys_mount("devfs", "/dev", "devfs", 0, NULL); -} - -void __init umount_devfs(char *path) -{ - sys_umount(path, 0); -} - -/* - * If the dir will fit in *buf, return its length. If it won't fit, return - * zero. Return -ve on error. - */ -static int __init do_read_dir(int fd, void *buf, int len) -{ - long bytes, n; - char *p = buf; - sys_lseek(fd, 0, 0); - - for (bytes = 0; bytes < len; bytes += n) { - n = sys_getdents64(fd, (struct linux_dirent64 *)(p + bytes), - len - bytes); - if (n < 0) - return n; - if (n == 0) - return bytes; - } - return 0; -} - -/* - * Try to read all of a directory. Returns the contents at *p, which - * is kmalloced memory. Returns the number of bytes read at *len. Returns - * NULL on error. - */ -static void * __init read_dir(char *path, int *len) -{ - int size; - int fd = sys_open(path, 0, 0); - - *len = 0; - if (fd < 0) - return NULL; - - for (size = 1 << 9; size <= (PAGE_SIZE << MAX_ORDER); size <<= 1) { - void *p = kmalloc(size, GFP_KERNEL); - int n; - if (!p) - break; - n = do_read_dir(fd, p, size); - if (n > 0) { - sys_close(fd); - *len = n; - return p; - } - kfree(p); - if (n == -EINVAL) - continue; /* Try a larger buffer */ - if (n < 0) - break; - } - sys_close(fd); - return NULL; -} - -/* - * recursively scan , looking for a device node of type - */ -static int __init find_in_devfs(char *path, unsigned dev) -{ - char *end = path + strlen(path); - int rest = path + 64 - end; - int size; - char *p = read_dir(path, &size); - char *s; - - if (!p) - return -1; - for (s = p; s < p + size; s += ((struct linux_dirent64 *)s)->d_reclen) { - struct linux_dirent64 *d = (struct linux_dirent64 *)s; - if (strlen(d->d_name) + 2 > rest) - continue; - switch (d->d_type) { - case DT_BLK: - sprintf(end, "/%s", d->d_name); - if (bstat(path) != dev) - break; - kfree(p); - return 0; - case DT_DIR: - if (strcmp(d->d_name, ".") == 0) - break; - if (strcmp(d->d_name, "..") == 0) - break; - sprintf(end, "/%s", d->d_name); - if (find_in_devfs(path, dev) < 0) - break; - kfree(p); - return 0; - } - } - kfree(p); - return -1; -} - -/* - * create a device node called which points to - * if possible, otherwise find a device node - * which matches and make a symlink pointing to it. - */ -int __init create_dev(char *name, dev_t dev, char *devfs_name) -{ - char path[64]; - - sys_unlink(name); - if (devfs_name && devfs_name[0]) { - if (strncmp(devfs_name, "/dev/", 5) == 0) - devfs_name += 5; - sprintf(path, "/dev/%s", devfs_name); - if (sys_access(path, 0) == 0) - return sys_symlink(devfs_name, name); - } - if (!dev) - return -1; - strcpy(path, "/dev"); - if (find_in_devfs(path, new_encode_dev(dev)) < 0) - return -1; - return sys_symlink(path + 5, name); -} diff -puN init/do_mounts.h~git-klibc /dev/null --- a/init/do_mounts.h +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void change_floppy(char *fmt, ...); -void mount_block_root(char *name, int flags); -void mount_root(void); -extern int root_mountflags; -extern char *root_device_name; - -#ifdef CONFIG_DEVFS_FS - -void mount_devfs(void); -void umount_devfs(char *path); -int create_dev(char *name, dev_t dev, char *devfs_name); - -#else - -static inline void mount_devfs(void) {} -static inline void umount_devfs(const char *path) {} - -static inline int create_dev(char *name, dev_t dev, char *devfs_name) -{ - sys_unlink(name); - return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev)); -} - -#endif - -#if BITS_PER_LONG == 32 -static inline u32 bstat(char *name) -{ - struct stat64 stat; - if (sys_stat64(name, &stat) != 0) - return 0; - if (!S_ISBLK(stat.st_mode)) - return 0; - if (stat.st_rdev != (u32)stat.st_rdev) - return 0; - return stat.st_rdev; -} -#else -static inline u32 bstat(char *name) -{ - struct stat stat; - if (sys_newstat(name, &stat) != 0) - return 0; - if (!S_ISBLK(stat.st_mode)) - return 0; - return stat.st_rdev; -} -#endif - -#ifdef CONFIG_BLK_DEV_RAM - -int __init rd_load_disk(int n); -int __init rd_load_image(char *from); - -#else - -static inline int rd_load_disk(int n) { return 0; } -static inline int rd_load_image(char *from) { return 0; } - -#endif - -#ifdef CONFIG_BLK_DEV_INITRD - -int __init initrd_load(void); - -#else - -static inline int initrd_load(void) { return 0; } - -#endif - -#ifdef CONFIG_BLK_DEV_MD - -void md_run_setup(void); - -#else - -static inline void md_run_setup(void) {} - -#endif diff -puN init/do_mounts_initrd.c~git-klibc /dev/null --- a/init/do_mounts_initrd.c +++ /dev/null @@ -1,125 +0,0 @@ -#define __KERNEL_SYSCALLS__ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "do_mounts.h" - -unsigned long initrd_start, initrd_end; -int initrd_below_start_ok; -unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ -static int __initdata old_fd, root_fd; -static int __initdata mount_initrd = 1; - -static int __init no_initrd(char *str) -{ - mount_initrd = 0; - return 1; -} - -__setup("noinitrd", no_initrd); - -static int __init do_linuxrc(void * shell) -{ - static char *argv[] = { "linuxrc", NULL, }; - extern char * envp_init[]; - - sys_close(old_fd);sys_close(root_fd); - sys_close(0);sys_close(1);sys_close(2); - sys_setsid(); - (void) sys_open("/dev/console",O_RDWR,0); - (void) sys_dup(0); - (void) sys_dup(0); - return execve(shell, argv, envp_init); -} - -static void __init handle_initrd(void) -{ - int error; - int pid; - - real_root_dev = new_encode_dev(ROOT_DEV); - create_dev("/dev/root.old", Root_RAM0, NULL); - /* mount initrd on rootfs' /root */ - mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); - sys_mkdir("/old", 0700); - root_fd = sys_open("/", 0, 0); - old_fd = sys_open("/old", 0, 0); - /* move initrd over / and chdir/chroot in initrd root */ - sys_chdir("/root"); - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); - mount_devfs_fs (); - - current->flags |= PF_NOFREEZE; - pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); - if (pid > 0) { - while (pid != sys_wait4(-1, NULL, 0, NULL)) - yield(); - } - - /* move initrd to rootfs' /old */ - sys_fchdir(old_fd); - sys_mount("/", ".", NULL, MS_MOVE, NULL); - /* switch root and cwd back to / of rootfs */ - sys_fchdir(root_fd); - sys_chroot("."); - sys_close(old_fd); - sys_close(root_fd); - umount_devfs("/old/dev"); - - if (new_decode_dev(real_root_dev) == Root_RAM0) { - sys_chdir("/old"); - return; - } - - ROOT_DEV = new_decode_dev(real_root_dev); - mount_root(); - - printk(KERN_NOTICE "Trying to move old root to /initrd ... "); - error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); - if (!error) - printk("okay\n"); - else { - int fd = sys_open("/dev/root.old", O_RDWR, 0); - if (error == -ENOENT) - printk("/initrd does not exist. Ignored.\n"); - else - printk("failed\n"); - printk(KERN_NOTICE "Unmounting old root\n"); - sys_umount("/old", MNT_DETACH); - printk(KERN_NOTICE "Trying to free ramdisk memory ... "); - if (fd < 0) { - error = fd; - } else { - error = sys_ioctl(fd, BLKFLSBUF, 0); - sys_close(fd); - } - printk(!error ? "okay\n" : "failed\n"); - } -} - -int __init initrd_load(void) -{ - if (mount_initrd) { - create_dev("/dev/ram", Root_RAM0, NULL); - /* - * Load the initrd data into /dev/ram0. Execute it as initrd - * unless /dev/ram0 is supposed to be our actual root device, - * in that case the ram disk is just set up here, and gets - * mounted in the normal path. - */ - if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) { - sys_unlink("/initrd.image"); - handle_initrd(); - return 1; - } - } - sys_unlink("/initrd.image"); - return 0; -} diff -puN init/do_mounts_md.c~git-klibc /dev/null --- a/init/do_mounts_md.c +++ /dev/null @@ -1,286 +0,0 @@ - -#include - -#include "do_mounts.h" - -/* - * When md (and any require personalities) are compiled into the kernel - * (not a module), arrays can be assembles are boot time using with AUTODETECT - * where specially marked partitions are registered with md_autodetect_dev(), - * and with MD_BOOT where devices to be collected are given on the boot line - * with md=..... - * The code for that is here. - */ - -static int __initdata raid_noautodetect, raid_autopart; - -static struct { - int minor; - int partitioned; - int level; - int chunk; - char *device_names; -} md_setup_args[MAX_MD_DEVS] __initdata; - -static int md_setup_ents __initdata; - -extern int mdp_major; -/* - * Parse the command-line parameters given our kernel, but do not - * actually try to invoke the MD device now; that is handled by - * md_setup_drive after the low-level disk drivers have initialised. - * - * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which - * assigns the task of parsing integer arguments to the - * invoked program now). Added ability to initialise all - * the MD devices (by specifying multiple "md=" lines) - * instead of just one. -- KTK - * 18May2000: Added support for persistent-superblock arrays: - * md=n,0,factor,fault,device-list uses RAID0 for device n - * md=n,-1,factor,fault,device-list uses LINEAR for device n - * md=n,device-list reads a RAID superblock from the devices - * elements in device-list are read by name_to_kdev_t so can be - * a hex number or something like /dev/hda1 /dev/sdb - * 2001-06-03: Dave Cinege - * Shifted name_to_kdev_t() and related operations to md_set_drive() - * for later execution. Rewrote section to make devfs compatible. - */ -static int __init md_setup(char *str) -{ - int minor, level, factor, fault, partitioned = 0; - char *pername = ""; - char *str1; - int ent; - - if (*str == 'd') { - partitioned = 1; - str++; - } - if (get_option(&str, &minor) != 2) { /* MD Number */ - printk(KERN_WARNING "md: Too few arguments supplied to md=.\n"); - return 0; - } - str1 = str; - if (minor >= MAX_MD_DEVS) { - printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor); - return 0; - } - for (ent=0 ; ent< md_setup_ents ; ent++) - if (md_setup_args[ent].minor == minor && - md_setup_args[ent].partitioned == partitioned) { - printk(KERN_WARNING "md: md=%s%d, Specified more than once. " - "Replacing previous definition.\n", partitioned?"d":"", minor); - break; - } - if (ent >= MAX_MD_DEVS) { - printk(KERN_WARNING "md: md=%s%d - too many md initialisations\n", partitioned?"d":"", minor); - return 0; - } - if (ent >= md_setup_ents) - md_setup_ents++; - switch (get_option(&str, &level)) { /* RAID level */ - case 2: /* could be 0 or -1.. */ - if (level == 0 || level == LEVEL_LINEAR) { - if (get_option(&str, &factor) != 2 || /* Chunk Size */ - get_option(&str, &fault) != 2) { - printk(KERN_WARNING "md: Too few arguments supplied to md=.\n"); - return 0; - } - md_setup_args[ent].level = level; - md_setup_args[ent].chunk = 1 << (factor+12); - if (level == LEVEL_LINEAR) - pername = "linear"; - else - pername = "raid0"; - break; - } - /* FALL THROUGH */ - case 1: /* the first device is numeric */ - str = str1; - /* FALL THROUGH */ - case 0: - md_setup_args[ent].level = LEVEL_NONE; - pername="super-block"; - } - - printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n", - minor, pername, str); - md_setup_args[ent].device_names = str; - md_setup_args[ent].partitioned = partitioned; - md_setup_args[ent].minor = minor; - - return 1; -} - -#define MdpMinorShift 6 - -static void __init md_setup_drive(void) -{ - int minor, i, ent, partitioned; - dev_t dev; - dev_t devices[MD_SB_DISKS+1]; - - for (ent = 0; ent < md_setup_ents ; ent++) { - int fd; - int err = 0; - char *devname; - mdu_disk_info_t dinfo; - char name[16], devfs_name[16]; - - minor = md_setup_args[ent].minor; - partitioned = md_setup_args[ent].partitioned; - devname = md_setup_args[ent].device_names; - - sprintf(name, "/dev/md%s%d", partitioned?"_d":"", minor); - sprintf(devfs_name, "/dev/md/%s%d", partitioned?"d":"", minor); - if (partitioned) - dev = MKDEV(mdp_major, minor << MdpMinorShift); - else - dev = MKDEV(MD_MAJOR, minor); - create_dev(name, dev, devfs_name); - for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { - char *p; - char comp_name[64]; - u32 rdev; - - p = strchr(devname, ','); - if (p) - *p++ = 0; - - dev = name_to_dev_t(devname); - if (strncmp(devname, "/dev/", 5) == 0) - devname += 5; - snprintf(comp_name, 63, "/dev/%s", devname); - rdev = bstat(comp_name); - if (rdev) - dev = new_decode_dev(rdev); - if (!dev) { - printk(KERN_WARNING "md: Unknown device name: %s\n", devname); - break; - } - - devices[i] = dev; - - devname = p; - } - devices[i] = 0; - - if (!i) - continue; - - printk(KERN_INFO "md: Loading md%s%d: %s\n", - partitioned ? "_d" : "", minor, - md_setup_args[ent].device_names); - - fd = sys_open(name, 0, 0); - if (fd < 0) { - printk(KERN_ERR "md: open failed - cannot start " - "array %s\n", name); - continue; - } - if (sys_ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) { - printk(KERN_WARNING - "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n", - minor); - sys_close(fd); - continue; - } - - if (md_setup_args[ent].level != LEVEL_NONE) { - /* non-persistent */ - mdu_array_info_t ainfo; - ainfo.level = md_setup_args[ent].level; - ainfo.size = 0; - ainfo.nr_disks =0; - ainfo.raid_disks =0; - while (devices[ainfo.raid_disks]) - ainfo.raid_disks++; - ainfo.md_minor =minor; - ainfo.not_persistent = 1; - - ainfo.state = (1 << MD_SB_CLEAN); - ainfo.layout = 0; - ainfo.chunk_size = md_setup_args[ent].chunk; - err = sys_ioctl(fd, SET_ARRAY_INFO, (long)&ainfo); - for (i = 0; !err && i <= MD_SB_DISKS; i++) { - dev = devices[i]; - if (!dev) - break; - dinfo.number = i; - dinfo.raid_disk = i; - dinfo.state = (1<= 0) { - sys_ioctl(fd, RAID_AUTORUN, raid_autopart); - sys_close(fd); - } - } - md_setup_drive(); -} diff -puN init/do_mounts_rd.c~git-klibc /dev/null --- a/init/do_mounts_rd.c +++ /dev/null @@ -1,429 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "do_mounts.h" - -#define BUILD_CRAMDISK - -int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ - -static int __init prompt_ramdisk(char *str) -{ - rd_prompt = simple_strtol(str,NULL,0) & 1; - return 1; -} -__setup("prompt_ramdisk=", prompt_ramdisk); - -int __initdata rd_image_start; /* starting block # of image */ - -static int __init ramdisk_start_setup(char *str) -{ - rd_image_start = simple_strtol(str,NULL,0); - return 1; -} -__setup("ramdisk_start=", ramdisk_start_setup); - -static int __init crd_load(int in_fd, int out_fd); - -/* - * This routine tries to find a RAM disk image to load, and returns the - * number of blocks to read for a non-compressed image, 0 if the image - * is a compressed image, and -1 if an image with the right magic - * numbers could not be found. - * - * We currently check for the following magic numbers: - * minix - * ext2 - * romfs - * cramfs - * gzip - */ -static int __init -identify_ramdisk_image(int fd, int start_block) -{ - const int size = 512; - struct minix_super_block *minixsb; - struct ext2_super_block *ext2sb; - struct romfs_super_block *romfsb; - struct cramfs_super *cramfsb; - int nblocks = -1; - unsigned char *buf; - - buf = kmalloc(size, GFP_KERNEL); - if (buf == 0) - return -1; - - minixsb = (struct minix_super_block *) buf; - ext2sb = (struct ext2_super_block *) buf; - romfsb = (struct romfs_super_block *) buf; - cramfsb = (struct cramfs_super *) buf; - memset(buf, 0xe5, size); - - /* - * Read block 0 to test for gzipped kernel - */ - sys_lseek(fd, start_block * BLOCK_SIZE, 0); - sys_read(fd, buf, size); - - /* - * If it matches the gzip magic numbers, return -1 - */ - if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { - printk(KERN_NOTICE - "RAMDISK: Compressed image found at block %d\n", - start_block); - nblocks = 0; - goto done; - } - - /* romfs is at block zero too */ - if (romfsb->word0 == ROMSB_WORD0 && - romfsb->word1 == ROMSB_WORD1) { - printk(KERN_NOTICE - "RAMDISK: romfs filesystem found at block %d\n", - start_block); - nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; - goto done; - } - - if (cramfsb->magic == CRAMFS_MAGIC) { - printk(KERN_NOTICE - "RAMDISK: cramfs filesystem found at block %d\n", - start_block); - nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; - goto done; - } - - /* - * Read block 1 to test for minix and ext2 superblock - */ - sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0); - sys_read(fd, buf, size); - - /* Try minix */ - if (minixsb->s_magic == MINIX_SUPER_MAGIC || - minixsb->s_magic == MINIX_SUPER_MAGIC2) { - printk(KERN_NOTICE - "RAMDISK: Minix filesystem found at block %d\n", - start_block); - nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; - goto done; - } - - /* Try ext2 */ - if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { - printk(KERN_NOTICE - "RAMDISK: ext2 filesystem found at block %d\n", - start_block); - nblocks = le32_to_cpu(ext2sb->s_blocks_count) << - le32_to_cpu(ext2sb->s_log_block_size); - goto done; - } - - printk(KERN_NOTICE - "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", - start_block); - -done: - sys_lseek(fd, start_block * BLOCK_SIZE, 0); - kfree(buf); - return nblocks; -} - -int __init rd_load_image(char *from) -{ - int res = 0; - int in_fd, out_fd; - unsigned long rd_blocks, devblocks; - int nblocks, i, disk; - char *buf = NULL; - unsigned short rotate = 0; -#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) - char rotator[4] = { '|' , '/' , '-' , '\\' }; -#endif - - out_fd = sys_open("/dev/ram", O_RDWR, 0); - if (out_fd < 0) - goto out; - - in_fd = sys_open(from, O_RDONLY, 0); - if (in_fd < 0) - goto noclose_input; - - nblocks = identify_ramdisk_image(in_fd, rd_image_start); - if (nblocks < 0) - goto done; - - if (nblocks == 0) { -#ifdef BUILD_CRAMDISK - if (crd_load(in_fd, out_fd) == 0) - goto successful_load; -#else - printk(KERN_NOTICE - "RAMDISK: Kernel does not support compressed " - "RAM disk images\n"); -#endif - goto done; - } - - /* - * NOTE NOTE: nblocks is not actually blocks but - * the number of kibibytes of data to load into a ramdisk. - * So any ramdisk block size that is a multiple of 1KiB should - * work when the appropriate ramdisk_blocksize is specified - * on the command line. - * - * The default ramdisk_blocksize is 1KiB and it is generally - * silly to use anything else, so make sure to use 1KiB - * blocksize while generating ext2fs ramdisk-images. - */ - if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) - rd_blocks = 0; - else - rd_blocks >>= 1; - - if (nblocks > rd_blocks) { - printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n", - nblocks, rd_blocks); - goto done; - } - - /* - * OK, time to copy in the data - */ - if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0) - devblocks = 0; - else - devblocks >>= 1; - - if (strcmp(from, "/initrd.image") == 0) - devblocks = nblocks; - - if (devblocks == 0) { - printk(KERN_ERR "RAMDISK: could not determine device size\n"); - goto done; - } - - buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); - if (buf == 0) { - printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); - goto done; - } - - printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ", - nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); - for (i = 0, disk = 1; i < nblocks; i++) { - if (i && (i % devblocks == 0)) { - printk("done disk #%d.\n", disk++); - rotate = 0; - if (sys_close(in_fd)) { - printk("Error closing the disk.\n"); - goto noclose_input; - } - change_floppy("disk #%d", disk); - in_fd = sys_open(from, O_RDONLY, 0); - if (in_fd < 0) { - printk("Error opening disk.\n"); - goto noclose_input; - } - printk("Loading disk #%d... ", disk); - } - sys_read(in_fd, buf, BLOCK_SIZE); - sys_write(out_fd, buf, BLOCK_SIZE); -#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) - if (!(i % 16)) { - printk("%c\b", rotator[rotate & 0x3]); - rotate++; - } -#endif - } - printk("done.\n"); - -successful_load: - res = 1; -done: - sys_close(in_fd); -noclose_input: - sys_close(out_fd); -out: - kfree(buf); - sys_unlink("/dev/ram"); - return res; -} - -int __init rd_load_disk(int n) -{ - if (rd_prompt) - change_floppy("root floppy disk to be loaded into RAM disk"); - create_dev("/dev/root", ROOT_DEV, root_device_name); - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); - return rd_load_image("/dev/root"); -} - -#ifdef BUILD_CRAMDISK - -/* - * gzip declarations - */ - -#define OF(args) args - -#ifndef memzero -#define memzero(s, n) memset ((s), 0, (n)) -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INBUFSIZ 4096 -#define WSIZE 0x8000 /* window size--must be a power of two, and */ - /* at least 32K for zip's deflate method */ - -static uch *inbuf; -static uch *window; - -static unsigned insize; /* valid bytes in inbuf */ -static unsigned inptr; /* index of next byte to be processed in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ -static int exit_code; -static int unzip_error; -static long bytes_out; -static int crd_infd, crd_outfd; - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions (stubbed out) */ -#define Assert(cond,msg) -#define Trace(x) -#define Tracev(x) -#define Tracevv(x) -#define Tracec(c,x) -#define Tracecv(c,x) - -#define STATIC static -#define INIT __init - -static int __init fill_inbuf(void); -static void __init flush_window(void); -static void __init *malloc(size_t size); -static void __init free(void *where); -static void __init error(char *m); -static void __init gzip_mark(void **); -static void __init gzip_release(void **); - -#include "../lib/inflate.c" - -static void __init *malloc(size_t size) -{ - return kmalloc(size, GFP_KERNEL); -} - -static void __init free(void *where) -{ - kfree(where); -} - -static void __init gzip_mark(void **ptr) -{ -} - -static void __init gzip_release(void **ptr) -{ -} - - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - * Returning -1 does not guarantee that gunzip() will ever return. - */ -static int __init fill_inbuf(void) -{ - if (exit_code) return -1; - - insize = sys_read(crd_infd, inbuf, INBUFSIZ); - if (insize == 0) { - error("RAMDISK: ran out of compressed data"); - return -1; - } - - inptr = 1; - - return inbuf[0]; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void __init flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n, written; - uch *in, ch; - - written = sys_write(crd_outfd, window, outcnt); - if (written != outcnt && unzip_error == 0) { - printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n", - written, outcnt, bytes_out); - unzip_error = 1; - } - in = window; - for (n = 0; n < outcnt; n++) { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; -} - -static void __init error(char *x) -{ - printk(KERN_ERR "%s\n", x); - exit_code = 1; - unzip_error = 1; -} - -static int __init crd_load(int in_fd, int out_fd) -{ - int result; - - insize = 0; /* valid bytes in inbuf */ - inptr = 0; /* index of next byte to be processed in inbuf */ - outcnt = 0; /* bytes in output buffer */ - exit_code = 0; - bytes_out = 0; - crc = (ulg)0xffffffffL; /* shift register contents */ - - crd_infd = in_fd; - crd_outfd = out_fd; - inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); - if (inbuf == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); - return -1; - } - window = kmalloc(WSIZE, GFP_KERNEL); - if (window == 0) { - printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); - kfree(inbuf); - return -1; - } - makecrc(); - result = gunzip(); - if (unzip_error) - result = 1; - kfree(inbuf); - kfree(window); - return result; -} - -#endif /* BUILD_CRAMDISK */ diff -puN init/initramfs.c~git-klibc init/initramfs.c --- a/init/initramfs.c~git-klibc +++ a/init/initramfs.c @@ -7,6 +7,9 @@ #include #include +unsigned long __initdata initrd_start, initrd_end; +int __initdata initrd_below_start_ok; + static __initdata char *message; static void __init error(char *x) { diff -puN init/main.c~git-klibc init/main.c --- a/init/main.c~git-klibc +++ a/init/main.c @@ -7,6 +7,8 @@ * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 * Simplified starting of init: Michael A. Griffith + * + * 2006-02-12 H. Peter Anvin: Eliminated in-kernel root mounting. */ #define __KERNEL_SYSCALLS__ @@ -47,6 +49,7 @@ #include #include #include +#include #include #include @@ -125,6 +128,11 @@ static char *ramdisk_execute_command; /* Setup configured maximum number of CPUs to activate */ static unsigned int max_cpus = NR_CPUS; +/* ROOT_DEV contains any architecture-specific default root device. */ +/* real_root_dev is used (via sysctl) to communicate ROOT_DEV to kinit. */ +dev_t ROOT_DEV; +unsigned int real_root_dev; + /* * Setup routine for controlling SMP activation * @@ -683,6 +691,12 @@ static int init(void * unused) do_basic_setup(); /* + * If we have a root device set by architecture-specific means, + * let kinit know about it. + */ + real_root_dev = new_encode_dev(ROOT_DEV); + + /* * check if there is an early userspace init. If yes, let it do all * the work */ @@ -690,11 +704,6 @@ static int init(void * unused) if (!ramdisk_execute_command) ramdisk_execute_command = "/init"; - if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { - ramdisk_execute_command = NULL; - prepare_namespace(); - } - /* * Ok, we have completed the initial bootup, and * we're essentially up and running. Get rid of the @@ -706,33 +715,13 @@ static int init(void * unused) system_state = SYSTEM_RUNNING; numa_default_policy(); + /* This could be done by (k)init as well... */ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING "Warning: unable to open an initial console.\n"); (void) sys_dup(0); (void) sys_dup(0); - if (ramdisk_execute_command) { - run_init_process(ramdisk_execute_command); - printk(KERN_WARNING "Failed to execute %s\n", - ramdisk_execute_command); - } - - /* - * We try each of these until one succeeds. - * - * The Bourne shell can be used instead of init if we are - * trying to recover a really broken machine. - */ - if (execute_command) { - run_init_process(execute_command); - printk(KERN_WARNING "Failed to execute %s. Attempting " - "defaults...\n", execute_command); - } - run_init_process("/sbin/init"); - run_init_process("/etc/init"); - run_init_process("/bin/init"); - run_init_process("/bin/sh"); - - panic("No init found. Try passing init= option to kernel."); + run_init_process(ramdisk_execute_command); + panic("Failed to execute %s", ramdisk_execute_command); } diff -puN init/Makefile~git-klibc init/Makefile --- a/init/Makefile~git-klibc +++ a/init/Makefile @@ -2,15 +2,9 @@ # Makefile for the linux kernel. # -obj-y := main.o version.o mounts.o initramfs.o +obj-y := main.o version.o initramfs.o obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o -mounts-y := do_mounts.o -mounts-$(CONFIG_DEVFS_FS) += do_mounts_devfs.o -mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o -mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o -mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o - # files to be removed upon make clean clean-files := ../include/linux/compile.h diff -puN kernel/power/disk.c~git-klibc kernel/power/disk.c --- a/kernel/power/disk.c~git-klibc +++ a/kernel/power/disk.c @@ -22,8 +22,6 @@ #include "power.h" -static int noresume = 0; -char resume_file[256] = CONFIG_PM_STD_PARTITION; dev_t swsusp_resume_device; /** @@ -166,26 +164,13 @@ static int software_resume(void) down(&pm_sem); if (!swsusp_resume_device) { - if (!strlen(resume_file)) { - up(&pm_sem); - return -ENOENT; - } - swsusp_resume_device = name_to_dev_t(resume_file); - pr_debug("swsusp: Resume From Partition %s\n", resume_file); - } else { - pr_debug("swsusp: Resume From Partition %d:%d\n", - MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); - } - - if (noresume) { - /** - * FIXME: If noresume is specified, we need to find the partition - * and reset it back to normal swap space. - */ - up(&pm_sem); + pr_debug("swsusp: No device given!\n"); return 0; } + pr_debug("swsusp: Resume From Partition %d:%d\n", + MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device)); + pr_debug("PM: Checking swsusp image.\n"); if ((error = swsusp_check())) @@ -228,8 +213,6 @@ static int software_resume(void) return 0; } -late_initcall(software_resume); - static const char * const pm_disk_modes[] = { [PM_DISK_FIRMWARE] = "firmware", @@ -333,7 +316,6 @@ static ssize_t resume_store(struct subsy swsusp_resume_device = res; up(&pm_sem); printk("Attempting manual resume\n"); - noresume = 0; software_resume(); ret = n; out: @@ -380,22 +362,3 @@ static int __init pm_disk_init(void) } core_initcall(pm_disk_init); - - -static int __init resume_setup(char *str) -{ - if (noresume) - return 1; - - strncpy( resume_file, str, 255 ); - return 1; -} - -static int __init noresume_setup(char *str) -{ - noresume = 1; - return 1; -} - -__setup("noresume", noresume_setup); -__setup("resume=", resume_setup); diff -puN MAINTAINERS~git-klibc MAINTAINERS --- a/MAINTAINERS~git-klibc +++ a/MAINTAINERS @@ -1669,6 +1669,13 @@ L: linux-kernel@vger.kernel.org L: fastboot@osdl.org S: Maintained +KLIBC/KINIT +P: H. Peter Anvin +M: hpa@zytor.com +L: klibc@zytor.com +T: git kernel.org:pub/scm/linux/kernel/git/hpa/linux-2.6-klibc.git +S: Maintained + KPROBES P: Prasanna S Panchamukhi M: prasanna@in.ibm.com diff -puN Makefile~git-klibc Makefile --- a/Makefile~git-klibc +++ a/Makefile @@ -176,7 +176,16 @@ ARCH ?= $(SUBARCH) CROSS_COMPILE ?= # Architecture as present in compile.h -UTS_MACHINE := $(ARCH) +UTS_MACHINE := $(ARCH) + +# Architecture used to compile user-space code +KLIBCARCH ?= $(ARCH) +KLIBCARCHDIR ?= $(KLIBCARCH) + +# klibc definitions +export KLIBCINC := usr/include +export KLIBCSRC := $(srctree)/usr/klibc +export KLIBCOBJ := $(objtree)/usr/klibc KCONFIG_CONFIG ?= .config @@ -278,6 +287,7 @@ LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc CPP = $(CC) -E AR = $(CROSS_COMPILE)ar +RANLIB = $(CROSS_COMPILE)ranlib NM = $(CROSS_COMPILE)nm STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy @@ -318,6 +328,7 @@ export VERSION PATCHLEVEL SUBLEVEL KERNE export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS +export RANLIB KLIBCARCH KLIBCARCHDIR export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE @@ -1303,41 +1314,44 @@ kernelversion: # - build whith mixed source and output # - build with separate output dir 'make O=...' # - external modules +# - klibc library and klibc programs (everything under usr/) # # target-dir => where to store outputfile # build-dir => directory in kernel source tree to use ifeq ($(KBUILD_EXTMOD),) + singlebld = $(if $(filter usr/%,$(dir $@)),$(klibc),$(build)) build-dir = $(patsubst %/,%,$(dir $@)) target-dir = $(dir $@) else + singlebld = $(build) zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@))) build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash)) target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@)) endif %.s: %.c prepare scripts FORCE - $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + $(Q)$(MAKE) $(singlebld)=$(build-dir) $(target-dir)$(notdir $@) %.i: %.c prepare scripts FORCE - $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + $(Q)$(MAKE) $(singlebld)=$(build-dir) $(target-dir)$(notdir $@) %.o: %.c prepare scripts FORCE - $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + $(Q)$(MAKE) $(singlebld)=$(build-dir) $(target-dir)$(notdir $@) %.lst: %.c prepare scripts FORCE - $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + $(Q)$(MAKE) $(singlebld)=$(build-dir) $(target-dir)$(notdir $@) %.s: %.S prepare scripts FORCE - $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + $(Q)$(MAKE) $(singlebld)=$(build-dir) $(target-dir)$(notdir $@) %.o: %.S prepare scripts FORCE - $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + $(Q)$(MAKE) $(singlebld)=$(build-dir) $(target-dir)$(notdir $@) %.symtypes: %.c prepare scripts FORCE $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) # Modules / %/: prepare scripts FORCE $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ - $(build)=$(build-dir) + $(singlebld)=$(build-dir) %.ko: prepare scripts FORCE $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ - $(build)=$(build-dir) $(@:.ko=.o) + $(singlebld)=$(build-dir) $(@:.ko=.o) $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost # FIXME Should go into a make.lib or something diff -puN net/ipv4/ipconfig.c~git-klibc /dev/null --- a/net/ipv4/ipconfig.c +++ /dev/null @@ -1,1510 +0,0 @@ -/* - * $Id: ipconfig.c,v 1.46 2002/02/01 22:01:04 davem Exp $ - * - * Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or - * user-supplied information to configure own IP address and routes. - * - * Copyright (C) 1996-1998 Martin Mares - * - * Derived from network configuration code in fs/nfs/nfsroot.c, - * originally Copyright (C) 1995, 1996 Gero Kuhlmann and me. - * - * BOOTP rewritten to construct and analyse packets itself instead - * of misusing the IP layer. num_bugs_causing_wrong_arp_replies--; - * -- MJ, December 1998 - * - * Fixed ip_auto_config_setup calling at startup in the new "Linker Magic" - * initialization scheme. - * - Arnaldo Carvalho de Melo , 08/11/1999 - * - * DHCP support added. To users this looks like a whole separate - * protocol, but we know it's just a bag on the side of BOOTP. - * -- Chip Salzenberg , May 2000 - * - * Ported DHCP support from 2.2.16 to 2.4.0-test4 - * -- Eric Biederman , 30 Aug 2000 - * - * Merged changes from 2.2.19 into 2.4.3 - * -- Eric Biederman , 22 April Aug 2001 - * - * Multiple Nameservers in /proc/net/pnp - * -- Josef Siemes , Aug 2002 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Define this to allow debugging output */ -#undef IPCONFIG_DEBUG - -#ifdef IPCONFIG_DEBUG -#define DBG(x) printk x -#else -#define DBG(x) do { } while(0) -#endif - -#if defined(CONFIG_IP_PNP_DHCP) -#define IPCONFIG_DHCP -#endif -#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_DHCP) -#define IPCONFIG_BOOTP -#endif -#if defined(CONFIG_IP_PNP_RARP) -#define IPCONFIG_RARP -#endif -#if defined(IPCONFIG_BOOTP) || defined(IPCONFIG_RARP) -#define IPCONFIG_DYNAMIC -#endif - -/* Define the friendly delay before and after opening net devices */ -#define CONF_PRE_OPEN 500 /* Before opening: 1/2 second */ -#define CONF_POST_OPEN 1 /* After opening: 1 second */ - -/* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */ -#define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */ -#define CONF_SEND_RETRIES 6 /* Send six requests per open */ -#define CONF_INTER_TIMEOUT (HZ/2) /* Inter-device timeout: 1/2 second */ -#define CONF_BASE_TIMEOUT (HZ*2) /* Initial timeout: 2 seconds */ -#define CONF_TIMEOUT_RANDOM (HZ) /* Maximum amount of randomization */ -#define CONF_TIMEOUT_MULT *7/4 /* Rate of timeout growth */ -#define CONF_TIMEOUT_MAX (HZ*30) /* Maximum allowed timeout */ -#define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers - - '3' from resolv.h */ - - -/* - * Public IP configuration - */ - -/* This is used by platforms which might be able to set the ipconfig - * variables using firmware environment vars. If this is set, it will - * ignore such firmware variables. - */ -int ic_set_manually __initdata = 0; /* IPconfig parameters set manually */ - -static int ic_enable __initdata = 0; /* IP config enabled? */ - -/* Protocol choice */ -int ic_proto_enabled __initdata = 0 -#ifdef IPCONFIG_BOOTP - | IC_BOOTP -#endif -#ifdef CONFIG_IP_PNP_DHCP - | IC_USE_DHCP -#endif -#ifdef IPCONFIG_RARP - | IC_RARP -#endif - ; - -static int ic_host_name_set __initdata = 0; /* Host name set by us? */ - -u32 ic_myaddr = INADDR_NONE; /* My IP address */ -static u32 ic_netmask = INADDR_NONE; /* Netmask for local subnet */ -u32 ic_gateway = INADDR_NONE; /* Gateway IP address */ - -u32 ic_servaddr = INADDR_NONE; /* Boot server IP address */ - -u32 root_server_addr = INADDR_NONE; /* Address of NFS server */ -u8 root_server_path[256] = { 0, }; /* Path to mount as root */ - -/* Persistent data: */ - -static int ic_proto_used; /* Protocol used, if any */ -static u32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ -static u8 ic_domain[64]; /* DNS (not NIS) domain name */ - -/* - * Private state. - */ - -/* Name of user-selected boot device */ -static char user_dev_name[IFNAMSIZ] __initdata = { 0, }; - -/* Protocols supported by available interfaces */ -static int ic_proto_have_if __initdata = 0; - -#ifdef IPCONFIG_DYNAMIC -static DEFINE_SPINLOCK(ic_recv_lock); -static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */ -#endif -#ifdef IPCONFIG_DHCP -static int ic_dhcp_msgtype __initdata = 0; /* DHCP msg type received */ -#endif - - -/* - * Network devices - */ - -struct ic_device { - struct ic_device *next; - struct net_device *dev; - unsigned short flags; - short able; - u32 xid; -}; - -static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ -static struct net_device *ic_dev __initdata = NULL; /* Selected device */ - -static int __init ic_open_devs(void) -{ - struct ic_device *d, **last; - struct net_device *dev; - unsigned short oflags; - - last = &ic_first_dev; - rtnl_lock(); - - /* bring loopback device up first */ - if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0) - printk(KERN_ERR "IP-Config: Failed to open %s\n", loopback_dev.name); - - for (dev = dev_base; dev; dev = dev->next) { - if (dev == &loopback_dev) - continue; - if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : - (!(dev->flags & IFF_LOOPBACK) && - (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && - strncmp(dev->name, "dummy", 5))) { - int able = 0; - if (dev->mtu >= 364) - able |= IC_BOOTP; - else - printk(KERN_WARNING "DHCP/BOOTP: Ignoring device %s, MTU %d too small", dev->name, dev->mtu); - if (!(dev->flags & IFF_NOARP)) - able |= IC_RARP; - able &= ic_proto_enabled; - if (ic_proto_enabled && !able) - continue; - oflags = dev->flags; - if (dev_change_flags(dev, oflags | IFF_UP) < 0) { - printk(KERN_ERR "IP-Config: Failed to open %s\n", dev->name); - continue; - } - if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { - rtnl_unlock(); - return -1; - } - d->dev = dev; - *last = d; - last = &d->next; - d->flags = oflags; - d->able = able; - if (able & IC_BOOTP) - get_random_bytes(&d->xid, sizeof(u32)); - else - d->xid = 0; - ic_proto_have_if |= able; - DBG(("IP-Config: %s UP (able=%d, xid=%08x)\n", - dev->name, able, d->xid)); - } - } - rtnl_unlock(); - - *last = NULL; - - if (!ic_first_dev) { - if (user_dev_name[0]) - printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name); - else - printk(KERN_ERR "IP-Config: No network devices available.\n"); - return -1; - } - return 0; -} - -static void __init ic_close_devs(void) -{ - struct ic_device *d, *next; - struct net_device *dev; - - rtnl_lock(); - next = ic_first_dev; - while ((d = next)) { - next = d->next; - dev = d->dev; - if (dev != ic_dev) { - DBG(("IP-Config: Downing %s\n", dev->name)); - dev_change_flags(dev, d->flags); - } - kfree(d); - } - rtnl_unlock(); -} - -/* - * Interface to various network functions. - */ - -static inline void -set_sockaddr(struct sockaddr_in *sin, u32 addr, u16 port) -{ - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = addr; - sin->sin_port = port; -} - -static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) -{ - int res; - - mm_segment_t oldfs = get_fs(); - set_fs(get_ds()); - res = devinet_ioctl(cmd, (struct ifreq __user *) arg); - set_fs(oldfs); - return res; -} - -static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg) -{ - int res; - - mm_segment_t oldfs = get_fs(); - set_fs(get_ds()); - res = ip_rt_ioctl(cmd, (void __user *) arg); - set_fs(oldfs); - return res; -} - -/* - * Set up interface addresses and routes. - */ - -static int __init ic_setup_if(void) -{ - struct ifreq ir; - struct sockaddr_in *sin = (void *) &ir.ifr_ifru.ifru_addr; - int err; - - memset(&ir, 0, sizeof(ir)); - strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name); - set_sockaddr(sin, ic_myaddr, 0); - if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err); - return -1; - } - set_sockaddr(sin, ic_netmask, 0); - if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err); - return -1; - } - set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); - if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err); - return -1; - } - return 0; -} - -static int __init ic_setup_routes(void) -{ - /* No need to setup device routes, only the default route... */ - - if (ic_gateway != INADDR_NONE) { - struct rtentry rm; - int err; - - memset(&rm, 0, sizeof(rm)); - if ((ic_gateway ^ ic_myaddr) & ic_netmask) { - printk(KERN_ERR "IP-Config: Gateway not on directly connected network.\n"); - return -1; - } - set_sockaddr((struct sockaddr_in *) &rm.rt_dst, 0, 0); - set_sockaddr((struct sockaddr_in *) &rm.rt_genmask, 0, 0); - set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0); - rm.rt_flags = RTF_UP | RTF_GATEWAY; - if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) { - printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err); - return -1; - } - } - - return 0; -} - -/* - * Fill in default values for all missing parameters. - */ - -static int __init ic_defaults(void) -{ - /* - * At this point we have no userspace running so need not - * claim locks on system_utsname - */ - - if (!ic_host_name_set) - sprintf(system_utsname.nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr)); - - if (root_server_addr == INADDR_NONE) - root_server_addr = ic_servaddr; - - if (ic_netmask == INADDR_NONE) { - if (IN_CLASSA(ntohl(ic_myaddr))) - ic_netmask = htonl(IN_CLASSA_NET); - else if (IN_CLASSB(ntohl(ic_myaddr))) - ic_netmask = htonl(IN_CLASSB_NET); - else if (IN_CLASSC(ntohl(ic_myaddr))) - ic_netmask = htonl(IN_CLASSC_NET); - else { - printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n", - NIPQUAD(ic_myaddr)); - return -1; - } - printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask)); - } - - return 0; -} - -/* - * RARP support. - */ - -#ifdef IPCONFIG_RARP - -static int ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); - -static struct packet_type rarp_packet_type __initdata = { - .type = __constant_htons(ETH_P_RARP), - .func = ic_rarp_recv, -}; - -static inline void ic_rarp_init(void) -{ - dev_add_pack(&rarp_packet_type); -} - -static inline void ic_rarp_cleanup(void) -{ - dev_remove_pack(&rarp_packet_type); -} - -/* - * Process received RARP packet. - */ -static int __init -ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) -{ - struct arphdr *rarp; - unsigned char *rarp_ptr; - unsigned long sip, tip; - unsigned char *sha, *tha; /* s for "source", t for "target" */ - struct ic_device *d; - - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - return NET_RX_DROP; - - if (!pskb_may_pull(skb, sizeof(struct arphdr))) - goto drop; - - /* Basic sanity checks can be done without the lock. */ - rarp = (struct arphdr *)skb->h.raw; - - /* If this test doesn't pass, it's not IP, or we should - * ignore it anyway. - */ - if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)) - goto drop; - - /* If it's not a RARP reply, delete it. */ - if (rarp->ar_op != htons(ARPOP_RREPLY)) - goto drop; - - /* If it's not Ethernet, delete it. */ - if (rarp->ar_pro != htons(ETH_P_IP)) - goto drop; - - if (!pskb_may_pull(skb, - sizeof(struct arphdr) + - (2 * dev->addr_len) + - (2 * 4))) - goto drop; - - /* OK, it is all there and looks valid, process... */ - rarp = (struct arphdr *)skb->h.raw; - rarp_ptr = (unsigned char *) (rarp + 1); - - /* One reply at a time, please. */ - spin_lock(&ic_recv_lock); - - /* If we already have a reply, just drop the packet */ - if (ic_got_reply) - goto drop_unlock; - - /* Find the ic_device that the packet arrived on */ - d = ic_first_dev; - while (d && d->dev != dev) - d = d->next; - if (!d) - goto drop_unlock; /* should never happen */ - - /* Extract variable-width fields */ - sha = rarp_ptr; - rarp_ptr += dev->addr_len; - memcpy(&sip, rarp_ptr, 4); - rarp_ptr += 4; - tha = rarp_ptr; - rarp_ptr += dev->addr_len; - memcpy(&tip, rarp_ptr, 4); - - /* Discard packets which are not meant for us. */ - if (memcmp(tha, dev->dev_addr, dev->addr_len)) - goto drop_unlock; - - /* Discard packets which are not from specified server. */ - if (ic_servaddr != INADDR_NONE && ic_servaddr != sip) - goto drop_unlock; - - /* We have a winner! */ - ic_dev = dev; - if (ic_myaddr == INADDR_NONE) - ic_myaddr = tip; - ic_servaddr = sip; - ic_got_reply = IC_RARP; - -drop_unlock: - /* Show's over. Nothing to see here. */ - spin_unlock(&ic_recv_lock); - -drop: - /* Throw the packet out. */ - kfree_skb(skb); - return 0; -} - - -/* - * Send RARP request packet over a single interface. - */ -static void __init ic_rarp_send_if(struct ic_device *d) -{ - struct net_device *dev = d->dev; - arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL, - dev->dev_addr, dev->dev_addr); -} -#endif - -/* - * DHCP/BOOTP support. - */ - -#ifdef IPCONFIG_BOOTP - -struct bootp_pkt { /* BOOTP packet format */ - struct iphdr iph; /* IP header */ - struct udphdr udph; /* UDP header */ - u8 op; /* 1=request, 2=reply */ - u8 htype; /* HW address type */ - u8 hlen; /* HW address length */ - u8 hops; /* Used only by gateways */ - u32 xid; /* Transaction ID */ - u16 secs; /* Seconds since we started */ - u16 flags; /* Just what it says */ - u32 client_ip; /* Client's IP address if known */ - u32 your_ip; /* Assigned IP address */ - u32 server_ip; /* (Next, e.g. NFS) Server's IP address */ - u32 relay_ip; /* IP address of BOOTP relay */ - u8 hw_addr[16]; /* Client's HW address */ - u8 serv_name[64]; /* Server host name */ - u8 boot_file[128]; /* Name of boot file */ - u8 exten[312]; /* DHCP options / BOOTP vendor extensions */ -}; - -/* packet ops */ -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 - -/* DHCP message types */ -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 -#define DHCPINFORM 8 - -static int ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); - -static struct packet_type bootp_packet_type __initdata = { - .type = __constant_htons(ETH_P_IP), - .func = ic_bootp_recv, -}; - - -/* - * Initialize DHCP/BOOTP extension fields in the request. - */ - -static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 }; - -#ifdef IPCONFIG_DHCP - -static void __init -ic_dhcp_init_options(u8 *options) -{ - u8 mt = ((ic_servaddr == INADDR_NONE) - ? DHCPDISCOVER : DHCPREQUEST); - u8 *e = options; - -#ifdef IPCONFIG_DEBUG - printk("DHCP: Sending message type %d\n", mt); -#endif - - memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ - e += 4; - - *e++ = 53; /* DHCP message type */ - *e++ = 1; - *e++ = mt; - - if (mt == DHCPREQUEST) { - *e++ = 54; /* Server ID (IP address) */ - *e++ = 4; - memcpy(e, &ic_servaddr, 4); - e += 4; - - *e++ = 50; /* Requested IP address */ - *e++ = 4; - memcpy(e, &ic_myaddr, 4); - e += 4; - } - - /* always? */ - { - static const u8 ic_req_params[] = { - 1, /* Subnet mask */ - 3, /* Default gateway */ - 6, /* DNS server */ - 12, /* Host name */ - 15, /* Domain name */ - 17, /* Boot path */ - 40, /* NIS domain name */ - }; - - *e++ = 55; /* Parameter request list */ - *e++ = sizeof(ic_req_params); - memcpy(e, ic_req_params, sizeof(ic_req_params)); - e += sizeof(ic_req_params); - } - - *e++ = 255; /* End of the list */ -} - -#endif /* IPCONFIG_DHCP */ - -static void __init ic_bootp_init_ext(u8 *e) -{ - memcpy(e, ic_bootp_cookie, 4); /* RFC1048 Magic Cookie */ - e += 4; - *e++ = 1; /* Subnet mask request */ - *e++ = 4; - e += 4; - *e++ = 3; /* Default gateway request */ - *e++ = 4; - e += 4; - *e++ = 5; /* Name server request */ - *e++ = 8; - e += 8; - *e++ = 12; /* Host name request */ - *e++ = 32; - e += 32; - *e++ = 40; /* NIS Domain name request */ - *e++ = 32; - e += 32; - *e++ = 17; /* Boot path */ - *e++ = 40; - e += 40; - - *e++ = 57; /* set extension buffer size for reply */ - *e++ = 2; - *e++ = 1; /* 128+236+8+20+14, see dhcpd sources */ - *e++ = 150; - - *e++ = 255; /* End of the list */ -} - - -/* - * Initialize the DHCP/BOOTP mechanism. - */ -static inline void ic_bootp_init(void) -{ - int i; - - for (i = 0; i < CONF_NAMESERVERS_MAX; i++) - ic_nameservers[i] = INADDR_NONE; - - dev_add_pack(&bootp_packet_type); -} - - -/* - * DHCP/BOOTP cleanup. - */ -static inline void ic_bootp_cleanup(void) -{ - dev_remove_pack(&bootp_packet_type); -} - - -/* - * Send DHCP/BOOTP request to single interface. - */ -static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_diff) -{ - struct net_device *dev = d->dev; - struct sk_buff *skb; - struct bootp_pkt *b; - int hh_len = LL_RESERVED_SPACE(dev); - struct iphdr *h; - - /* Allocate packet */ - skb = alloc_skb(sizeof(struct bootp_pkt) + hh_len + 15, GFP_KERNEL); - if (!skb) - return; - skb_reserve(skb, hh_len); - b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt)); - memset(b, 0, sizeof(struct bootp_pkt)); - - /* Construct IP header */ - skb->nh.iph = h = &b->iph; - h->version = 4; - h->ihl = 5; - h->tot_len = htons(sizeof(struct bootp_pkt)); - h->frag_off = htons(IP_DF); - h->ttl = 64; - h->protocol = IPPROTO_UDP; - h->daddr = INADDR_BROADCAST; - h->check = ip_fast_csum((unsigned char *) h, h->ihl); - - /* Construct UDP header */ - b->udph.source = htons(68); - b->udph.dest = htons(67); - b->udph.len = htons(sizeof(struct bootp_pkt) - sizeof(struct iphdr)); - /* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */ - - /* Construct DHCP/BOOTP header */ - b->op = BOOTP_REQUEST; - if (dev->type < 256) /* check for false types */ - b->htype = dev->type; - else if (dev->type == ARPHRD_IEEE802_TR) /* fix for token ring */ - b->htype = ARPHRD_IEEE802; - else if (dev->type == ARPHRD_FDDI) - b->htype = ARPHRD_ETHER; - else { - printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name); - b->htype = dev->type; /* can cause undefined behavior */ - } - b->hlen = dev->addr_len; - b->your_ip = INADDR_NONE; - b->server_ip = INADDR_NONE; - memcpy(b->hw_addr, dev->dev_addr, dev->addr_len); - b->secs = htons(jiffies_diff / HZ); - b->xid = d->xid; - - /* add DHCP options or BOOTP extensions */ -#ifdef IPCONFIG_DHCP - if (ic_proto_enabled & IC_USE_DHCP) - ic_dhcp_init_options(b->exten); - else -#endif - ic_bootp_init_ext(b->exten); - - /* Chain packet down the line... */ - skb->dev = dev; - skb->protocol = htons(ETH_P_IP); - if ((dev->hard_header && - dev->hard_header(skb, dev, ntohs(skb->protocol), dev->broadcast, dev->dev_addr, skb->len) < 0) || - dev_queue_xmit(skb) < 0) - printk("E"); -} - - -/* - * Copy BOOTP-supplied string if not already set. - */ -static int __init ic_bootp_string(char *dest, char *src, int len, int max) -{ - if (!len) - return 0; - if (len > max-1) - len = max-1; - memcpy(dest, src, len); - dest[len] = '\0'; - return 1; -} - - -/* - * Process BOOTP extensions. - */ -static void __init ic_do_bootp_ext(u8 *ext) -{ - u8 servers; - int i; - -#ifdef IPCONFIG_DEBUG - u8 *c; - - printk("DHCP/BOOTP: Got extension %d:",*ext); - for(c=ext+2; c CONF_NAMESERVERS_MAX) - servers = CONF_NAMESERVERS_MAX; - for (i = 0; i < servers; i++) { - if (ic_nameservers[i] == INADDR_NONE) - memcpy(&ic_nameservers[i], ext+1+4*i, 4); - } - break; - case 12: /* Host name */ - ic_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN); - ic_host_name_set = 1; - break; - case 15: /* Domain name (DNS) */ - ic_bootp_string(ic_domain, ext+1, *ext, sizeof(ic_domain)); - break; - case 17: /* Root path */ - if (!root_server_path[0]) - ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path)); - break; - case 40: /* NIS Domain name (_not_ DNS) */ - ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN); - break; - } -} - - -/* - * Receive BOOTP reply. - */ -static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) -{ - struct bootp_pkt *b; - struct iphdr *h; - struct ic_device *d; - int len, ext_len; - - /* Perform verifications before taking the lock. */ - if (skb->pkt_type == PACKET_OTHERHOST) - goto drop; - - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - return NET_RX_DROP; - - if (!pskb_may_pull(skb, - sizeof(struct iphdr) + - sizeof(struct udphdr))) - goto drop; - - b = (struct bootp_pkt *) skb->nh.iph; - h = &b->iph; - - if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP) - goto drop; - - /* Fragments are not supported */ - if (h->frag_off & htons(IP_OFFSET | IP_MF)) { - if (net_ratelimit()) - printk(KERN_ERR "DHCP/BOOTP: Ignoring fragmented " - "reply.\n"); - goto drop; - } - - if (skb->len < ntohs(h->tot_len)) - goto drop; - - if (ip_fast_csum((char *) h, h->ihl)) - goto drop; - - if (b->udph.source != htons(67) || b->udph.dest != htons(68)) - goto drop; - - if (ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr)) - goto drop; - - len = ntohs(b->udph.len) - sizeof(struct udphdr); - ext_len = len - (sizeof(*b) - - sizeof(struct iphdr) - - sizeof(struct udphdr) - - sizeof(b->exten)); - if (ext_len < 0) - goto drop; - - /* Ok the front looks good, make sure we can get at the rest. */ - if (!pskb_may_pull(skb, skb->len)) - goto drop; - - b = (struct bootp_pkt *) skb->nh.iph; - h = &b->iph; - - /* One reply at a time, please. */ - spin_lock(&ic_recv_lock); - - /* If we already have a reply, just drop the packet */ - if (ic_got_reply) - goto drop_unlock; - - /* Find the ic_device that the packet arrived on */ - d = ic_first_dev; - while (d && d->dev != dev) - d = d->next; - if (!d) - goto drop_unlock; /* should never happen */ - - /* Is it a reply to our BOOTP request? */ - if (b->op != BOOTP_REPLY || - b->xid != d->xid) { - if (net_ratelimit()) - printk(KERN_ERR "DHCP/BOOTP: Reply not for us, " - "op[%x] xid[%x]\n", - b->op, b->xid); - goto drop_unlock; - } - - /* Parse extensions */ - if (ext_len >= 4 && - !memcmp(b->exten, ic_bootp_cookie, 4)) { /* Check magic cookie */ - u8 *end = (u8 *) b + ntohs(b->iph.tot_len); - u8 *ext; - -#ifdef IPCONFIG_DHCP - if (ic_proto_enabled & IC_USE_DHCP) { - u32 server_id = INADDR_NONE; - int mt = 0; - - ext = &b->exten[4]; - while (ext < end && *ext != 0xff) { - u8 *opt = ext++; - if (*opt == 0) /* Padding */ - continue; - ext += *ext + 1; - if (ext >= end) - break; - switch (*opt) { - case 53: /* Message type */ - if (opt[1]) - mt = opt[2]; - break; - case 54: /* Server ID (IP address) */ - if (opt[1] >= 4) - memcpy(&server_id, opt + 2, 4); - break; - }; - } - -#ifdef IPCONFIG_DEBUG - printk("DHCP: Got message type %d\n", mt); -#endif - - switch (mt) { - case DHCPOFFER: - /* While in the process of accepting one offer, - * ignore all others. - */ - if (ic_myaddr != INADDR_NONE) - goto drop_unlock; - - /* Let's accept that offer. */ - ic_myaddr = b->your_ip; - ic_servaddr = server_id; -#ifdef IPCONFIG_DEBUG - printk("DHCP: Offered address %u.%u.%u.%u", - NIPQUAD(ic_myaddr)); - printk(" by server %u.%u.%u.%u\n", - NIPQUAD(ic_servaddr)); -#endif - /* The DHCP indicated server address takes - * precedence over the bootp header one if - * they are different. - */ - if ((server_id != INADDR_NONE) && - (b->server_ip != server_id)) - b->server_ip = ic_servaddr; - break; - - case DHCPACK: - if (memcmp(dev->dev_addr, b->hw_addr, dev->addr_len) != 0) - goto drop_unlock; - - /* Yeah! */ - break; - - default: - /* Urque. Forget it*/ - ic_myaddr = INADDR_NONE; - ic_servaddr = INADDR_NONE; - goto drop_unlock; - }; - - ic_dhcp_msgtype = mt; - - } -#endif /* IPCONFIG_DHCP */ - - ext = &b->exten[4]; - while (ext < end && *ext != 0xff) { - u8 *opt = ext++; - if (*opt == 0) /* Padding */ - continue; - ext += *ext + 1; - if (ext < end) - ic_do_bootp_ext(opt); - } - } - - /* We have a winner! */ - ic_dev = dev; - ic_myaddr = b->your_ip; - ic_servaddr = b->server_ip; - if (ic_gateway == INADDR_NONE && b->relay_ip) - ic_gateway = b->relay_ip; - if (ic_nameservers[0] == INADDR_NONE) - ic_nameservers[0] = ic_servaddr; - ic_got_reply = IC_BOOTP; - -drop_unlock: - /* Show's over. Nothing to see here. */ - spin_unlock(&ic_recv_lock); - -drop: - /* Throw the packet out. */ - kfree_skb(skb); - - return 0; -} - - -#endif - - -/* - * Dynamic IP configuration -- DHCP, BOOTP, RARP. - */ - -#ifdef IPCONFIG_DYNAMIC - -static int __init ic_dynamic(void) -{ - int retries; - struct ic_device *d; - unsigned long start_jiffies, timeout, jiff; - int do_bootp = ic_proto_have_if & IC_BOOTP; - int do_rarp = ic_proto_have_if & IC_RARP; - - /* - * If none of DHCP/BOOTP/RARP was selected, return with an error. - * This routine gets only called when some pieces of information - * are missing, and without DHCP/BOOTP/RARP we are unable to get it. - */ - if (!ic_proto_enabled) { - printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n"); - return -1; - } - -#ifdef IPCONFIG_BOOTP - if ((ic_proto_enabled ^ ic_proto_have_if) & IC_BOOTP) - printk(KERN_ERR "DHCP/BOOTP: No suitable device found.\n"); -#endif -#ifdef IPCONFIG_RARP - if ((ic_proto_enabled ^ ic_proto_have_if) & IC_RARP) - printk(KERN_ERR "RARP: No suitable device found.\n"); -#endif - - if (!ic_proto_have_if) - /* Error message already printed */ - return -1; - - /* - * Setup protocols - */ -#ifdef IPCONFIG_BOOTP - if (do_bootp) - ic_bootp_init(); -#endif -#ifdef IPCONFIG_RARP - if (do_rarp) - ic_rarp_init(); -#endif - - /* - * Send requests and wait, until we get an answer. This loop - * seems to be a terrible waste of CPU time, but actually there is - * only one process running at all, so we don't need to use any - * scheduler functions. - * [Actually we could now, but the nothing else running note still - * applies.. - AC] - */ - printk(KERN_NOTICE "Sending %s%s%s requests .", - do_bootp - ? ((ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP") : "", - (do_bootp && do_rarp) ? " and " : "", - do_rarp ? "RARP" : ""); - - start_jiffies = jiffies; - d = ic_first_dev; - retries = CONF_SEND_RETRIES; - get_random_bytes(&timeout, sizeof(timeout)); - timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM); - for(;;) { -#ifdef IPCONFIG_BOOTP - if (do_bootp && (d->able & IC_BOOTP)) - ic_bootp_send_if(d, jiffies - start_jiffies); -#endif -#ifdef IPCONFIG_RARP - if (do_rarp && (d->able & IC_RARP)) - ic_rarp_send_if(d); -#endif - - jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout); - while (time_before(jiffies, jiff) && !ic_got_reply) - schedule_timeout_uninterruptible(1); -#ifdef IPCONFIG_DHCP - /* DHCP isn't done until we get a DHCPACK. */ - if ((ic_got_reply & IC_BOOTP) - && (ic_proto_enabled & IC_USE_DHCP) - && ic_dhcp_msgtype != DHCPACK) - { - ic_got_reply = 0; - printk(","); - continue; - } -#endif /* IPCONFIG_DHCP */ - - if (ic_got_reply) { - printk(" OK\n"); - break; - } - - if ((d = d->next)) - continue; - - if (! --retries) { - printk(" timed out!\n"); - break; - } - - d = ic_first_dev; - - timeout = timeout CONF_TIMEOUT_MULT; - if (timeout > CONF_TIMEOUT_MAX) - timeout = CONF_TIMEOUT_MAX; - - printk("."); - } - -#ifdef IPCONFIG_BOOTP - if (do_bootp) - ic_bootp_cleanup(); -#endif -#ifdef IPCONFIG_RARP - if (do_rarp) - ic_rarp_cleanup(); -#endif - - if (!ic_got_reply) { - ic_myaddr = INADDR_NONE; - return -1; - } - - printk("IP-Config: Got %s answer from %u.%u.%u.%u, ", - ((ic_got_reply & IC_RARP) ? "RARP" - : (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"), - NIPQUAD(ic_servaddr)); - printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr)); - - return 0; -} - -#endif /* IPCONFIG_DYNAMIC */ - -#ifdef CONFIG_PROC_FS - -static int pnp_seq_show(struct seq_file *seq, void *v) -{ - int i; - - if (ic_proto_used & IC_PROTO) - seq_printf(seq, "#PROTO: %s\n", - (ic_proto_used & IC_RARP) ? "RARP" - : (ic_proto_used & IC_USE_DHCP) ? "DHCP" : "BOOTP"); - else - seq_puts(seq, "#MANUAL\n"); - - if (ic_domain[0]) - seq_printf(seq, - "domain %s\n", ic_domain); - for (i = 0; i < CONF_NAMESERVERS_MAX; i++) { - if (ic_nameservers[i] != INADDR_NONE) - seq_printf(seq, - "nameserver %u.%u.%u.%u\n", - NIPQUAD(ic_nameservers[i])); - } - if (ic_servaddr != INADDR_NONE) - seq_printf(seq, - "bootserver %u.%u.%u.%u\n", - NIPQUAD(ic_servaddr)); - return 0; -} - -static int pnp_seq_open(struct inode *indoe, struct file *file) -{ - return single_open(file, pnp_seq_show, NULL); -} - -static struct file_operations pnp_seq_fops = { - .owner = THIS_MODULE, - .open = pnp_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_PROC_FS */ - -/* - * Extract IP address from the parameter string if needed. Note that we - * need to have root_server_addr set _before_ IPConfig gets called as it - * can override it. - */ -u32 __init root_nfs_parse_addr(char *name) -{ - u32 addr; - int octets = 0; - char *cp, *cq; - - cp = cq = name; - while (octets < 4) { - while (*cp >= '0' && *cp <= '9') - cp++; - if (cp == cq || cp - cq > 3) - break; - if (*cp == '.' || octets == 3) - octets++; - if (octets < 4) - cp++; - cq = cp; - } - if (octets == 4 && (*cp == ':' || *cp == '\0')) { - if (*cp == ':') - *cp++ = '\0'; - addr = in_aton(name); - memmove(name, cp, strlen(cp) + 1); - } else - addr = INADDR_NONE; - - return addr; -} - -/* - * IP Autoconfig dispatcher. - */ - -static int __init ip_auto_config(void) -{ - u32 addr; - -#ifdef CONFIG_PROC_FS - proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops); -#endif /* CONFIG_PROC_FS */ - - if (!ic_enable) - return 0; - - DBG(("IP-Config: Entered.\n")); -#ifdef IPCONFIG_DYNAMIC - try_try_again: -#endif - /* Give hardware a chance to settle */ - msleep(CONF_PRE_OPEN); - - /* Setup all network devices */ - if (ic_open_devs() < 0) - return -1; - - /* Give drivers a chance to settle */ - ssleep(CONF_POST_OPEN); - - /* - * If the config information is insufficient (e.g., our IP address or - * IP address of the boot server is missing or we have multiple network - * interfaces and no default was set), use BOOTP or RARP to get the - * missing values. - */ - if (ic_myaddr == INADDR_NONE || -#ifdef CONFIG_ROOT_NFS - (MAJOR(ROOT_DEV) == UNNAMED_MAJOR - && root_server_addr == INADDR_NONE - && ic_servaddr == INADDR_NONE) || -#endif - ic_first_dev->next) { -#ifdef IPCONFIG_DYNAMIC - - int retries = CONF_OPEN_RETRIES; - - if (ic_dynamic() < 0) { - ic_close_devs(); - - /* - * I don't know why, but sometimes the - * eepro100 driver (at least) gets upset and - * doesn't work the first time it's opened. - * But then if you close it and reopen it, it - * works just fine. So we need to try that at - * least once before giving up. - * - * Also, if the root will be NFS-mounted, we - * have nowhere to go if DHCP fails. So we - * just have to keep trying forever. - * - * -- Chip - */ -#ifdef CONFIG_ROOT_NFS - if (ROOT_DEV == Root_NFS) { - printk(KERN_ERR - "IP-Config: Retrying forever (NFS root)...\n"); - goto try_try_again; - } -#endif - - if (--retries) { - printk(KERN_ERR - "IP-Config: Reopening network devices...\n"); - goto try_try_again; - } - - /* Oh, well. At least we tried. */ - printk(KERN_ERR "IP-Config: Auto-configuration of network failed.\n"); - return -1; - } -#else /* !DYNAMIC */ - printk(KERN_ERR "IP-Config: Incomplete network configuration information.\n"); - ic_close_devs(); - return -1; -#endif /* IPCONFIG_DYNAMIC */ - } else { - /* Device selected manually or only one device -> use it */ - ic_dev = ic_first_dev->dev; - } - - addr = root_nfs_parse_addr(root_server_path); - if (root_server_addr == INADDR_NONE) - root_server_addr = addr; - - /* - * Use defaults whereever applicable. - */ - if (ic_defaults() < 0) - return -1; - - /* - * Close all network devices except the device we've - * autoconfigured and set up routes. - */ - ic_close_devs(); - if (ic_setup_if() < 0 || ic_setup_routes() < 0) - return -1; - - /* - * Record which protocol was actually used. - */ -#ifdef IPCONFIG_DYNAMIC - ic_proto_used = ic_got_reply | (ic_proto_enabled & IC_USE_DHCP); -#endif - -#ifndef IPCONFIG_SILENT - /* - * Clue in the operator. - */ - printk("IP-Config: Complete:"); - printk("\n device=%s", ic_dev->name); - printk(", addr=%u.%u.%u.%u", NIPQUAD(ic_myaddr)); - printk(", mask=%u.%u.%u.%u", NIPQUAD(ic_netmask)); - printk(", gw=%u.%u.%u.%u", NIPQUAD(ic_gateway)); - printk(",\n host=%s, domain=%s, nis-domain=%s", - system_utsname.nodename, ic_domain, system_utsname.domainname); - printk(",\n bootserver=%u.%u.%u.%u", NIPQUAD(ic_servaddr)); - printk(", rootserver=%u.%u.%u.%u", NIPQUAD(root_server_addr)); - printk(", rootpath=%s", root_server_path); - printk("\n"); -#endif /* !SILENT */ - - return 0; -} - -late_initcall(ip_auto_config); - - -/* - * Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel - * command line parameter. It consists of option fields separated by colons in - * the following order: - * - * :::::: - * - * Any of the fields can be empty which means to use a default value: - * - address given by BOOTP or RARP - * - address of host returning BOOTP or RARP packet - * - none, or the address returned by BOOTP - * - automatically determined from , or the - * one returned by BOOTP - * - in ASCII notation, or the name returned - * by BOOTP - * - use all available devices - * : - * off|none - don't do autoconfig at all (DEFAULT) - * on|any - use any configured protocol - * dhcp|bootp|rarp - use only the specified protocol - * both - use both BOOTP and RARP (not DHCP) - */ -static int __init ic_proto_name(char *name) -{ - if (!strcmp(name, "on") || !strcmp(name, "any")) { - return 1; - } -#ifdef CONFIG_IP_PNP_DHCP - else if (!strcmp(name, "dhcp")) { - ic_proto_enabled &= ~IC_RARP; - return 1; - } -#endif -#ifdef CONFIG_IP_PNP_BOOTP - else if (!strcmp(name, "bootp")) { - ic_proto_enabled &= ~(IC_RARP | IC_USE_DHCP); - return 1; - } -#endif -#ifdef CONFIG_IP_PNP_RARP - else if (!strcmp(name, "rarp")) { - ic_proto_enabled &= ~(IC_BOOTP | IC_USE_DHCP); - return 1; - } -#endif -#ifdef IPCONFIG_DYNAMIC - else if (!strcmp(name, "both")) { - ic_proto_enabled &= ~IC_USE_DHCP; /* backward compat :-( */ - return 1; - } -#endif - return 0; -} - -static int __init ip_auto_config_setup(char *addrs) -{ - char *cp, *ip, *dp; - int num = 0; - - ic_set_manually = 1; - - ic_enable = (*addrs && - (strcmp(addrs, "off") != 0) && - (strcmp(addrs, "none") != 0)); - if (!ic_enable) - return 1; - - if (ic_proto_name(addrs)) - return 1; - - /* Parse the whole string */ - ip = addrs; - while (ip && *ip) { - if ((cp = strchr(ip, ':'))) - *cp++ = '\0'; - if (strlen(ip) > 0) { - DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip)); - switch (num) { - case 0: - if ((ic_myaddr = in_aton(ip)) == INADDR_ANY) - ic_myaddr = INADDR_NONE; - break; - case 1: - if ((ic_servaddr = in_aton(ip)) == INADDR_ANY) - ic_servaddr = INADDR_NONE; - break; - case 2: - if ((ic_gateway = in_aton(ip)) == INADDR_ANY) - ic_gateway = INADDR_NONE; - break; - case 3: - if ((ic_netmask = in_aton(ip)) == INADDR_ANY) - ic_netmask = INADDR_NONE; - break; - case 4: - if ((dp = strchr(ip, '.'))) { - *dp++ = '\0'; - strlcpy(system_utsname.domainname, dp, - sizeof(system_utsname.domainname)); - } - strlcpy(system_utsname.nodename, ip, - sizeof(system_utsname.nodename)); - ic_host_name_set = 1; - break; - case 5: - strlcpy(user_dev_name, ip, sizeof(user_dev_name)); - break; - case 6: - ic_proto_name(ip); - break; - } - } - ip = cp; - num++; - } - - return 1; -} - -static int __init nfsaddrs_config_setup(char *addrs) -{ - return ip_auto_config_setup(addrs); -} - -__setup("ip=", ip_auto_config_setup); -__setup("nfsaddrs=", nfsaddrs_config_setup); diff -puN net/ipv4/Makefile~git-klibc net/ipv4/Makefile --- a/net/ipv4/Makefile~git-klibc +++ a/net/ipv4/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_ obj-$(CONFIG_INET_TUNNEL) += tunnel4.o obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o -obj-$(CONFIG_IP_PNP) += ipconfig.o obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o diff -puN scripts/gen_initramfs_list.sh~git-klibc scripts/gen_initramfs_list.sh --- a/scripts/gen_initramfs_list.sh~git-klibc +++ a/scripts/gen_initramfs_list.sh @@ -15,7 +15,7 @@ set -e usage() { cat << EOF Usage: -$0 [-o ] [-u ] [-g ] {-d | } ... +$0 [-o ] [-u ] [-g ] ... -o Create gzipped initramfs file named using gen_init_cpio and gzip -u User ID to map to user ID 0 (root). @@ -27,7 +27,6 @@ $0 [-o ] [-u ] [-g ] {-d File list or directory for cpio archive. If is a .cpio file it will be used as direct input to initramfs. - -d Output the default cpio list. All options except -o and -l may be repeated and are interpreted sequentially and immediately. -u and -g states are preserved across @@ -36,23 +35,6 @@ to reset the root/group mapping. EOF } -list_default_initramfs() { - # echo usr/kinit/kinit - : -} - -default_initramfs() { - cat <<-EOF >> ${output} - # This is a very simple, default initramfs - - dir /dev 0755 0 0 - nod /dev/console 0600 0 0 c 5 1 - dir /root 0700 0 0 - # file /kinit usr/kinit/kinit 0755 0 0 - # slink /init kinit 0755 0 0 - EOF -} - filetype() { local argv1="$1" @@ -167,8 +149,6 @@ header() { # process one directory (incl sub-directories) dir_filelist() { - ${dep_list}header "$1" - srcdir=$(echo "$1" | sed -e 's://*:/:g') dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null) @@ -187,9 +167,7 @@ dir_filelist() { # if a directory is specified then add all files in given direcotry to fs # if a regular file is specified assume it is in gen_initramfs format input_file() { - source="$1" if [ -f "$1" ]; then - ${dep_list}header "$1" is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')" if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then cpio_file=$1 @@ -214,6 +192,15 @@ input_file() { fi } +# input file/dir - process it +process_file() { + if [ -z ${print_header} ]; then + ${dep_list}header "$1" + fi + print_header=y + input_file "$1" "$2" +} + prog=$0 root_uid=0 root_gid=0 @@ -249,27 +236,29 @@ while [ $# -gt 0 ]; do root_gid="$1" shift ;; - "-d") # display default initramfs list - default_list="$arg" - ${dep_list}default_initramfs - ;; "-h") usage exit 0 ;; *) case "$arg" in - "-"*) - unknown_option + "-"*) unknown_option ;; - *) # input file/dir - process it - input_file "$arg" "$#" + *) process_file "$arg" "$#" ;; esac ;; esac done +# trailer of dependency list +if [ ! -z ${dep_list} ]; then + echo "" + echo "initramfs: \$(deps_initramfs)" + echo "\$(deps_initramfs): ;" + echo "" +fi + # If output_file is set we will generate cpio archive and gzip it # we are carefull to delete tmp files if [ ! -z ${output_file} ]; then diff -puN scripts/Kbuild.include~git-klibc scripts/Kbuild.include --- a/scripts/Kbuild.include~git-klibc +++ a/scripts/Kbuild.include @@ -87,6 +87,11 @@ cc-ifversion = $(shell if [ $(call cc-ve # $(Q)$(MAKE) $(build)=dir build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj +# Shorthand for $(Q)$(MAKE) -f scripts/Kbuild.klibc obj= +# Usage: +# $(Q)$(MAKE) $(klibc)=dir +klibc := -f $(srctree)/scripts/Kbuild.klibc obj + # Prefix -I with $(srctree) if it is not an absolute path addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1) # Find all -I options and call addtree diff -puN /dev/null scripts/Kbuild.klibc --- /dev/null +++ a/scripts/Kbuild.klibc @@ -0,0 +1,358 @@ +# ========================================================================== +# Support for building klibc and related programs +# ========================================================================== +# +# To create a kbuild file for a userspace program do the following: +# +# Kbuild: +# +# static-y := cat +# # This will compile a file named cat.c -> the executable 'cat' +# # The executable will be linked statically +# +# shared-y := cats +# # This will compile a file named cats.c -> the executable 'cats' +# # The executable will be linked shared +# +# If the userspace program consist of more files do the following: +# Kbuild: +# +# static-y := ipconfig +# ipconfig-y := main.o netdev.c +# So ipconfig will be linked statically using the two .o files +# specified with ipconfig-y. +# +# To set directory wide CFLAGS use: +# EXTRA_KLIBCCFLAGS := -DDEBUG +# To set directory wide AFLAGS use: +# EXTRA_KLIBCAFLAGS := -DDEBUG +# +# To set target specific CFLAGS (for .c files) use +# KLIBCCFLAGS-main.o := -DDEBUG=3 +# To set target specific AFLAGS (for .s files) use +# KLIBCAFLAGS-main.o := -DDEBUG=3 + +src := $(obj) +# Preset target and make sure it is a ':=' variable +targets := + +.phony: __build +__build: + +# Read .config if it exist, otherwise ignore +-include .config + +# Generic Kbuild routines +include $(srctree)/scripts/Kbuild.include + +# Defines used when compiling early userspace (klibc programs) +# --------------------------------------------------------------------------- + +KLIBCREQFLAGS := +KLIBCARCHREQFLAGS := +KLIBCOPTFLAGS := +KLIBCWARNFLAGS := -W -Wall -Wno-sign-compare -Wno-unused-parameter +KLIBCSHAREDFLAGS := +KLIBCBITSIZE := +KLIBCLDFLAGS := +KLIBCCFLAGS := + +# Arch specific definitions for klibc +include $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/MCONFIG + +# include/asm-* architecture +KLIBCASMARCH ?= $(KLIBCARCH) + +# klibc version +KLIBCMAJOR := $(shell cut -d. -f1 $(srctree)/usr/klibc/version) +KLIBCMINOR := $(shell cut -d. -f2 $(srctree)/usr/klibc/version) + +# binutils +KLIBCLD := $(LD) +KLIBCCC := $(CC) +KLIBCAR := $(AR) +KLIBCRANLIB := $(RANLIB) +KLIBCSTRIP := $(STRIP) +KLIBCNM := $(NM) +KLIBCOBJCOPY := $(OBJCOPY) +KLIBCOBJDUMP := $(OBJDUMP) + +# klibc include paths +KLIBCCPPFLAGS := -I$(KLIBCINC)/arch/$(KLIBCARCHDIR) \ + -I$(KLIBCINC)/bits$(KLIBCBITSIZE) \ + -I$(KLIBCOBJ)/../include \ + -I$(KLIBCINC) +# kernel include paths +KLIBCKERNELSRC ?= $(srctree)/ +KLIBCCPPFLAGS += -I$(KLIBCKERNELSRC)include \ + $(if $(KBUILD_SRC),-I$(KLIBCKERNELOBJ)include2 -I$(KLIBCKERNELOBJ)include -I$(srctree)/include) \ + $(KLIBCARCHINCFLAGS) + +# klibc definitions +KLIBCDEFS += -D__KLIBC__=$(KLIBCMAJOR) \ + -D__KLIBC_MINOR__=$(KLIBCMINOR) \ + -D_BITSIZE=$(KLIBCBITSIZE) +KLIBCCPPFLAGS += $(KLIBCDEFS) +KLIBCCFLAGS += $(KLIBCCPPFLAGS) $(KLIBCREQFLAGS) $(KLIBCARCHREQFLAGS) \ + $(KLIBCOPTFLAGS) $(KLIBCWARNFLAGS) +KLIBCAFLAGS += -D__ASSEMBLY__ $(KLIBCCFLAGS) +KLIBCSTRIPFLAGS += --strip-all -R .comment -R .note + +KLIBCLIBGCC_DEF := $(shell $(KLIBCCC) $(KLIBCCFLAGS) --print-libgcc) +KLIBCLIBGCC ?= $(KLIBCLIBGCC_DEF) +KLIBCCRT0 := $(KLIBCOBJ)/arch/$(KLIBCARCHDIR)/crt0.o +KLIBCLIBC := $(KLIBCOBJ)/libc.a +KLIBCCRTSHARED := $(KLIBCOBJ)/interp.o +KLIBCLIBCSHARED := $(KLIBCOBJ)/libc.so +# How to tell the linker main() is the entrypoint +KLIBCEMAIN ?= -e main + +# +# This indicates the location of the final version of the shared library. +# THIS MUST BE AN ABSOLUTE PATH WITH NO FINAL SLASH. +# Leave this empty to make it the root. +# +SHLIBDIR = /lib + +export KLIBCLD KLIBCCC KLIBCAR KLIBCSTRIP KLIBCNM +export KLIBCCFLAGS KLIBCAFLAGS KLIBCLIBGCC KLIBCSHAREDFLAGS KLIBCSTRIPFLAGS +export KLIBCCRT0 KLIBCLIBC SHLIBDIR + +# kernel configuration +include .config + +# Add $(obj)/ for paths that is not absolute +objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) + +# Kbuild file in the directory that is being build +include $(obj)/Kbuild + +##### +# static-y + shared-y handling +klibc-progs := $(static-y) $(shared-y) +# klibc-progs based on a single .o file (with same name + .o) +klibc-objs := $(foreach p, $(klibc-progs), $(if $($(p)-y),,$(p))) +klibc-objs := $(addsuffix .o, $(klibc-objs)) +# klibc-progs which is based on several .o files +klibc-multi := $(foreach p, $(klibc-progs), $(if $($(p)-y),$(p))) +# objects used for klibc-progs with more then one .o file +klibc-objs += $(foreach p, $(klibc-multi), $($(p)-y)) +# objects build in this dir +klibc-real-objs := $(patsubst %/,,$(klibc-objs)) +# Directories we need to visit before klibc-objs are up-to-date +klibc-dirs := $(patsubst %/,%,$(filter %/, $(klibc-objs))) +# replace all dir/ with dir/lib.a +klibc-objs := $(patsubst %/, %/lib.a, $(klibc-objs)) + +targets += $(static-y) $(shared-y) + +# $(output-dirs) are a list of directories that contain object files +output-dirs := $(dir $(klibc-dirs) $(klibc-objs)) +output-dirs += $(foreach f, $(hostprogs-y) $(targets), \ + $(if $(dir $(f)), $(dir $(f)))) +output-dirs := $(strip $(sort $(filter-out ./,$(output-dirs)))) + +# prefix so we get full dir +static-y := $(addprefix $(obj)/,$(static-y)) +shared-y := $(addprefix $(obj)/,$(shared-y)) +klibc-objs := $(addprefix $(obj)/,$(klibc-objs)) +klibc-real-objs := $(addprefix $(obj)/,$(klibc-real-objs)) +output-dirs := $(addprefix $(obj)/,$(output-dirs)) +klibc-dirs := $(addprefix $(obj)/,$(klibc-dirs)) +subdir-y := $(addprefix $(obj)/,$(subdir-y)) +lib-y := $(addprefix $(obj)/,$(lib-y)) +always := $(addprefix $(obj)/,$(always)) +targets := $(addprefix $(obj)/,$(targets)) + +##### +# Handle options to gcc. Support building with separate output directory + +__klibccflags = $(KLIBCCFLAGS) $(EXTRA_KLIBCCFLAGS) $(KLIBCCFLAGS_$(*F).o) +__klibcaflags = $(KLIBCAFLAGS) $(EXTRA_KLIBCAFLAGS) $(KLIBCAFLAGS_$(*F).o) + +ifeq ($(KBUILD_SRC),) +_klibccflags = $(__klibccflags) +_klibcaflags = $(__klibcaflags) +else +_klibccflags = $(call flags,__klibccflags) +_klibcaflags = $(call flags,__klibcaflags) +endif + +klibccflags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(_klibccflags) +klibcaflags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(_klibcaflags) + +# Create output directory if not already present +_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) + +# Create directories for object files if directory does not exist +# Needed when lib-y := dir/file.o syntax is used +_dummy := $(foreach d,$(output-dirs), $(shell [ -d $(d) ] || mkdir -p $(d))) + +# Do we have to make a lib.a in this dir? +ifneq ($(strip $(lib-y) $(lib-n) $(lib-)),) +lib-target := $(obj)/lib.a +endif + +__build: $(subdir-y) $(lib-target) $(always) + @: + +# Compile C sources (.c) +# --------------------------------------------------------------------------- + +quiet_cmd_cc_s_c = KLIBCCC $@ + cmd_cc_s_c = $(KLIBCCC) $(klibccflags) -S -o $@ $< + +%.s: %.c FORCE + $(call if_changed_dep,cc_s_c) + +quiet_cmd_cc_o_c = KLIBCCC $@ + cmd_cc_o_c = $(KLIBCCC) $(klibccflags) -c -o $@ $< + +%.o: %.c FORCE + $(call if_changed_dep,cc_o_c) + +quiet_cmd_cc_i_c = CPP $@ + cmd_cc_i_c = $(KLIBCCC) -E $(klibccflags) -o $@ $< +%.i: %.c FORCE + $(call if_changed_dep,cc_i_c) + +# Compile assembler sources (.S) +# --------------------------------------------------------------------------- + +quiet_cmd_as_o_S = KLIBCAS $@ + cmd_as_o_S = $(KLIBCCC) $(klibcaflags) -c -o $@ $< + +%.o: %.S FORCE + $(call if_changed_dep,as_o_S) + +targets += $(real-objs-y) + +# +# Rule to compile a set of .o files into one .o file +# +ifdef lib-target +quiet_cmd_link_o_target = LD $@ +# If the list of objects to link is empty, just create an empty lib.a +cmd_link_o_target = $(if $(strip $(lib-y)),\ + rm -f $@; $(KLIBCAR) cru $@ $(filter $(lib-y), $^),\ + rm -f $@; $(KLIBCAR) crs $@) + +$(lib-target): $(lib-y) FORCE + $(call if_changed,link_o_target) +targets += $(lib-target) $(lib-y) +endif # lib-target + + +ifdef klibc-progs +# Compile klibcspace programs for the target +# =========================================================================== + +__build : $(klibc-dirs) $(static-y) $(shared-y) + +# Descend if needed +$(sort $(addsuffix /lib.a,$(klibc-dirs))): $(klibc-dirs) ; + +# Define dependencies for link of progs +# For the simple program: +# file.o => file +# A program with multiple objects +# filea.o, fileb.o => file +# A program with .o files in another dir +# dir/lib.a filea.o => file + +stripobj = $(subst $(obj)/,,$@) +addliba = $(addprefix $(obj)/, $(patsubst %/, %/lib.a, $(1))) +link-deps = $(if $($(stripobj)-y), $(call addliba, $($(stripobj)-y)), $@.o) + +quiet_cmd_ld-static = KLIBCLD $@ + cmd_ld-static = $(KLIBCLD) $(KLIBCLDFLAGS) -o $@ \ + $(EXTRA_KLIBCLDFLAGS) \ + $(KLIBCCRT0) \ + $(link-deps) \ + --start-group $(KLIBCLIBC) \ + $(KLIBCLIBGCC) --end-group ; \ + cp -f $@ $@.g ; \ + $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@ + + +$(static-y): $(klibc-objs) $(lib-target) $(KLIBCCRT0) $(KLIBCLIBC) FORCE + $(call if_changed,ld-static) + +quiet_cmd_ld-shared = KLIBCLD $@ + cmd_ld-shared = $(KLIBCLD) $(KLIBCLDFLAGS) -o $@ \ + $(EXTRA_KLIBCLDFLAGS) \ + $(KLIBCEMAIN) $(KLIBCCRTSHARED) \ + $(link-deps) \ + --start-group -R $(KLIBCLIBCSHARED) \ + $(KLIBCLIBGCC) --end-group ; \ + cp -f $@ $@.g ; \ + $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@ + + +$(shared-y): $(klibc-objs) $(lib-target) $(KLIBCCRTSHARED) \ + $(KLIBCLIBCSHARED) FORCE + $(call if_changed,ld-shared) + +# Do not try to build KLIBC libaries if we are building klibc +ifeq ($(klibc-build),) +$(KLIBCCRT0) $(KLIBCLIBC): ; +$(KLIBCCRTSHARED) $(KLIBCLIBCSHARED): ; +endif + +targets += $(klibc-real-objs) +endif + +# Compile programs on the host +# =========================================================================== +ifdef hostprogs-y +include $(srctree)/scripts/Makefile.host +endif + +# Descending +# --------------------------------------------------------------------------- + +.PHONY: $(subdir-y) $(klibc-dirs) +$(subdir-y) $(klibc-dirs): + $(Q)$(MAKE) $(klibc)=$@ + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +.PHONY: FORCE + +FORCE: + +# Linking +# Create a reloctable composite object file +# --------------------------------------------------------------------------- +quiet_cmd_klibcld = KLIBCLD $@ + cmd_klibcld = $(KLIBCLD) -r $(KLIBCLDFLAGS) \ + $(EXTRA_KLIBCLDFLAGS) $(KLIBCLDFLAGS_$(@F)) \ + $(filter-out FORCE,$^) -o $@ + + +# Link target to a new name +# --------------------------------------------------------------------------- +quiet_cmd_ln = LN $@ + cmd_ln = rm -f $@ && ln $< $@ + +# Strip target (remove all debugging info) +quiet_cmd_strip = STRIP $@ + cmd_strip = $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $< -o $@ + + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif + +# Shorthand for $(Q)$(MAKE) -f scripts/Kbuild.klibc obj +# Usage: +# $(Q)$(MAKE) $(klibc)=dir +klibc := -rR -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Kbuild.klibc obj diff -puN /dev/null usr/dash/alias.c --- /dev/null +++ a/usr/dash/alias.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "shell.h" +#include "input.h" +#include "output.h" +#include "error.h" +#include "memalloc.h" +#include "mystring.h" +#include "alias.h" +#include "options.h" /* XXX for argptr (should remove?) */ + +#define ATABSIZE 39 + +struct alias *atab[ATABSIZE]; + +STATIC void setalias(const char *, const char *); +STATIC struct alias *freealias(struct alias *); +STATIC struct alias **__lookupalias(const char *); + +STATIC +void +setalias(const char *name, const char *val) +{ + struct alias *ap, **app; + + app = __lookupalias(name); + ap = *app; + INTOFF; + if (ap) { + if (!(ap->flag & ALIASINUSE)) { + ckfree(ap->val); + } + ap->val = savestr(val); + ap->flag &= ~ALIASDEAD; + } else { + /* not found */ + ap = ckmalloc(sizeof (struct alias)); + ap->name = savestr(name); + ap->val = savestr(val); + ap->flag = 0; + ap->next = 0; + *app = ap; + } + INTON; +} + +int +unalias(const char *name) +{ + struct alias **app; + + app = __lookupalias(name); + + if (*app) { + INTOFF; + *app = freealias(*app); + INTON; + return (0); + } + + return (1); +} + +void +rmaliases(void) +{ + struct alias *ap, **app; + int i; + + INTOFF; + for (i = 0; i < ATABSIZE; i++) { + app = &atab[i]; + for (ap = *app; ap; ap = *app) { + *app = freealias(*app); + if (ap == *app) { + app = &ap->next; + } + } + } + INTON; +} + +struct alias * +lookupalias(const char *name, int check) +{ + struct alias *ap = *__lookupalias(name); + + if (check && ap && (ap->flag & ALIASINUSE)) + return (NULL); + return (ap); +} + +/* + * TODO - sort output + */ +int +aliascmd(int argc, char **argv) +{ + char *n, *v; + int ret = 0; + struct alias *ap; + + if (argc == 1) { + int i; + + for (i = 0; i < ATABSIZE; i++) + for (ap = atab[i]; ap; ap = ap->next) { + printalias(ap); + } + return (0); + } + while ((n = *++argv) != NULL) { + if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */ + if ((ap = *__lookupalias(n)) == NULL) { + outfmt(out2, "%s: %s not found\n", "alias", n); + ret = 1; + } else + printalias(ap); + } else { + *v++ = '\0'; + setalias(n, v); + } + } + + return (ret); +} + +int +unaliascmd(int argc, char **argv) +{ + int i; + + while ((i = nextopt("a")) != '\0') { + if (i == 'a') { + rmaliases(); + return (0); + } + } + for (i = 0; *argptr; argptr++) { + if (unalias(*argptr)) { + outfmt(out2, "%s: %s not found\n", "unalias", *argptr); + i = 1; + } + } + + return (i); +} + +STATIC struct alias * +freealias(struct alias *ap) { + struct alias *next; + + if (ap->flag & ALIASINUSE) { + ap->flag |= ALIASDEAD; + return ap; + } + + next = ap->next; + ckfree(ap->name); + ckfree(ap->val); + ckfree(ap); + return next; +} + +void +printalias(const struct alias *ap) { + out1fmt("%s=%s\n", ap->name, single_quote(ap->val)); +} + +STATIC struct alias ** +__lookupalias(const char *name) { + unsigned int hashval; + struct alias **app; + const char *p; + unsigned int ch; + + p = name; + + ch = (unsigned char)*p; + hashval = ch << 4; + while (ch) { + hashval += ch; + ch = (unsigned char)*++p; + } + app = &atab[hashval % ATABSIZE]; + + for (; *app; app = &(*app)->next) { + if (equal(name, (*app)->name)) { + break; + } + } + + return app; +} diff -puN /dev/null usr/dash/alias.h --- /dev/null +++ a/usr/dash/alias.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)alias.h 8.2 (Berkeley) 5/4/95 + */ + +#define ALIASINUSE 1 +#define ALIASDEAD 2 + +struct alias { + struct alias *next; + char *name; + char *val; + int flag; +}; + +struct alias *lookupalias(const char *, int); +int aliascmd(int, char **); +int unaliascmd(int, char **); +void rmaliases(void); +int unalias(const char *); +void printalias(const struct alias *); diff -puN /dev/null usr/dash/arith.y --- /dev/null +++ a/usr/dash/arith.y @@ -0,0 +1,155 @@ +%{ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "expand.h" +#include "shell.h" +#include "error.h" +#include "output.h" +#include "memalloc.h" + +const char *arith_buf, *arith_startbuf; + +#ifndef YYBISON +int yyparse(void); +#endif +void yyerror(const char *); +#ifdef TESTARITH +int main(int , char *[]); +int sh_error(char *); +#endif + +%} +%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN + +%left ARITH_OR +%left ARITH_AND +%left ARITH_BOR +%left ARITH_BXOR +%left ARITH_BAND +%left ARITH_EQ ARITH_NE +%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE +%left ARITH_LSHIFT ARITH_RSHIFT +%left ARITH_ADD ARITH_SUB +%left ARITH_MUL ARITH_DIV ARITH_REM +%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT +%% + +exp: expr { + return ($1); + } + ; + + +expr: ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; } + | expr ARITH_OR expr { $$ = $1 || $3; } + | expr ARITH_AND expr { $$ = $1 && $3; } + | expr ARITH_BOR expr { $$ = $1 | $3; } + | expr ARITH_BXOR expr { $$ = $1 ^ $3; } + | expr ARITH_BAND expr { $$ = $1 & $3; } + | expr ARITH_EQ expr { $$ = $1 == $3; } + | expr ARITH_GT expr { $$ = $1 > $3; } + | expr ARITH_GE expr { $$ = $1 >= $3; } + | expr ARITH_LT expr { $$ = $1 < $3; } + | expr ARITH_LE expr { $$ = $1 <= $3; } + | expr ARITH_NE expr { $$ = $1 != $3; } + | expr ARITH_LSHIFT expr { $$ = $1 << $3; } + | expr ARITH_RSHIFT expr { $$ = $1 >> $3; } + | expr ARITH_ADD expr { $$ = $1 + $3; } + | expr ARITH_SUB expr { $$ = $1 - $3; } + | expr ARITH_MUL expr { $$ = $1 * $3; } + | expr ARITH_DIV expr { + if ($3 == 0) + yyerror("division by zero"); + $$ = $1 / $3; + } + | expr ARITH_REM expr { + if ($3 == 0) + yyerror("division by zero"); + $$ = $1 % $3; + } + | ARITH_NOT expr { $$ = !($2); } + | ARITH_BNOT expr { $$ = ~($2); } + | ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); } + | ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; } + | ARITH_NUM + ; +%% +int +arith(s) + const char *s; +{ + long result; + + arith_buf = arith_startbuf = s; + + INTOFF; + result = yyparse(); + arith_lex_reset(); /* reprime lex */ + INTON; + + return (result); +} + + +/*************************/ +#ifdef TEST_ARITH +#include +main(argc, argv) + char *argv[]; +{ + printf("%d\n", exp(argv[1])); +} +sh_error(s) + char *s; +{ + fprintf(stderr, "exp: %s\n", s); + exit(1); +} +#endif + +void +yyerror(s) + const char *s; +{ + +#ifndef YYBISON + yyerrok; +#endif + yyclearin; + arith_lex_reset(); /* reprime lex */ + sh_error("arithmetic expression: %s: \"%s\"", s, arith_startbuf); + /* NOTREACHED */ +} diff -puN /dev/null usr/dash/arith_yylex.c --- /dev/null +++ a/usr/dash/arith_yylex.c @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 2002 + * Herbert Xu. + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "arith.h" +#include "expand.h" +#include "error.h" + +extern int yylval; +extern const char *arith_buf, *arith_startbuf; + +int +yylex() +{ + int value; + const char *buf = arith_buf; + + for (;;) { + switch (*buf) { + case ' ': + case '\t': + case '\n': + buf++; + continue; + default: +err: + sh_error("arith: syntax error: \"%s\"", arith_startbuf); + /* NOTREACHED */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + yylval = strtoll(buf, (char **) &arith_buf, 0); + return ARITH_NUM; + case '=': + if (*++buf != '=') { + goto err; + } + value = ARITH_EQ; + break; + case '>': + switch (*++buf) { + case '=': + value = ARITH_GE; + break; + case '>': + value = ARITH_RSHIFT; + break; + default: + value = ARITH_GT; + goto out; + } + break; + case '<': + switch (*++buf) { + case '=': + value = ARITH_LE; + break; + case '<': + value = ARITH_LSHIFT; + break; + default: + value = ARITH_LT; + goto out; + } + break; + case '|': + if (*++buf != '|') { + value = ARITH_BOR; + goto out; + } + value = ARITH_OR; + break; + case '&': + if (*++buf != '&') { + value = ARITH_BAND; + goto out; + } + value = ARITH_AND; + break; + case '!': + if (*++buf != '=') { + value = ARITH_NOT; + goto out; + } + value = ARITH_NE; + break; + case 0: + value = 0; + goto out; + case '(': + value = ARITH_LPAREN; + break; + case ')': + value = ARITH_RPAREN; + break; + case '*': + value = ARITH_MUL; + break; + case '/': + value = ARITH_DIV; + break; + case '%': + value = ARITH_REM; + break; + case '+': + value = ARITH_ADD; + break; + case '-': + value = ARITH_SUB; + break; + case '~': + value = ARITH_BNOT; + break; + case '^': + value = ARITH_BXOR; + break; + } + break; + } + + buf++; +out: + arith_buf = buf; + return value; +} diff -puN /dev/null usr/dash/bltin/bltin.h --- /dev/null +++ a/usr/dash/bltin/bltin.h @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bltin.h 8.1 (Berkeley) 5/31/93 + */ + +/* + * This file is included by programs which are optionally built into the + * shell. If SHELL is defined, we try to map the standard UNIX library + * routines to ash routines using defines. + */ + +#include "../shell.h" +#include "../mystring.h" +#include "../options.h" +#ifdef SHELL +#include "../memalloc.h" +#include "../output.h" +#include "../error.h" +#ifndef USE_GLIBC_STDIO +#undef stdout +#undef stderr +#undef putc +#undef putchar +#undef fileno +#define stdout out1 +#define stderr out2 +#define printf out1fmt +#define putc(c, file) outc(c, file) +#define putchar(c) out1c(c) +#define FILE struct output +#define fprintf outfmt +#define fputs outstr +#define fflush flushout +#define fileno(f) ((f)->fd) +#define ferror outerr +#endif +#define INITARGS(argv) +#define error sh_error +#define warn sh_warn +#define warnx sh_warnx +#define exit sh_exit +#define setprogname(s) +#define getprogname() commandname +#define setlocate(l,s) 0 + +#define getenv(p) bltinlookup((p),0) + +#else +#undef NULL +#include +#undef main +#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else +#endif + +int echocmd(int, char **); + + +extern const char *commandname; diff -puN /dev/null usr/dash/bltin/echo.1 --- /dev/null +++ a/usr/dash/bltin/echo.1 @@ -0,0 +1,109 @@ +.\" Copyright (c) 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1997-2005 +.\" Herbert Xu . All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Kenneth Almquist. +.\" Copyright 1989 by Kenneth Almquist +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)echo.1 8.1 (Berkeley) 5/31/93 +.\" +.Dd May 31, 1993 +.Dt ECHO 1 +.Os +.Sh NAME +.Nm echo +.Nd produce message in a shell script +.Sh SYNOPSIS +.Nm +.Op Fl n | Fl e +.Ar args ... +.Sh DESCRIPTION +.Nm +prints its arguments on the standard output, separated by spaces. +Unless the +.Fl n +option is present, a newline is output following the arguments. +The +.Fl e +option causes +.Nm +to treat the escape sequences specially, as described in the following +paragraph. +The +.Fl e +option is the default, and is provided solely for compatibility with +other systems. +Only one of the options +.Fl n +and +.Fl e +may be given. +.Pp +If any of the following sequences of characters is encountered during +output, the sequence is not output. Instead, the specified action is +performed: +.Bl -tag -width indent +.It Li \eb +A backspace character is output. +.It Li \ec +Subsequent output is suppressed. This is normally used at the end of the +last argument to suppress the trailing newline that +.Nm +would otherwise output. +.It Li \ef +Output a form feed. +.It Li \en +Output a newline character. +.It Li \er +Output a carriage return. +.It Li \et +Output a (horizontal) tab character. +.It Li \ev +Output a vertical tab. +.It Li \e0 Ns Ar digits +Output the character whose value is given by zero to three digits. +If there are zero digits, a nul character is output. +.It Li \e\e +Output a backslash. +.El +.Sh HINTS +Remember that backslash is special to the shell and needs to be escaped. +To output a message to standard error, say +.Pp +.D1 echo message \*[Gt]\*[Am]2 +.Sh BUGS +The octal character escape mechanism +.Pq Li \e0 Ns Ar digits +differs from the +C language mechanism. +.Pp +There is no way to force +.Nm +to treat its arguments literally, rather than interpreting them as +options and escape sequences. diff -puN /dev/null usr/dash/bltin/printf.1 --- /dev/null +++ a/usr/dash/bltin/printf.1 @@ -0,0 +1,354 @@ +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1997-2005 +.\" Herbert Xu . All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)printf.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd November 5, 1993 +.Dt PRINTF 1 +.Os +.Sh NAME +.Nm printf +.Nd formatted output +.Sh SYNOPSIS +.Nm +.Ar format +.Op Ar arguments ... +.Sh DESCRIPTION +.Nm +formats and prints its arguments, after the first, under control +of the +.Ar format . +The +.Ar format +is a character string which contains three types of objects: plain characters, +which are simply copied to standard output, character escape sequences which +are converted and copied to the standard output, and format specifications, +each of which causes printing of the next successive +.Ar argument . +.Pp +The +.Ar arguments +after the first are treated as strings if the corresponding format is +either +.Cm b , +.Cm B , +.Cm c +or +.Cm s ; +otherwise it is evaluated as a C constant, with the following extensions: +.Pp +.Bl -bullet -offset indent -compact +.It +A leading plus or minus sign is allowed. +.It +If the leading character is a single or double quote, the value is the +.Tn ASCII +code of the next character. +.El +.Pp +The format string is reused as often as necessary to satisfy the +.Ar arguments . +Any extra format specifications are evaluated with zero or the null +string. +.Pp +Character escape sequences are in backslash notation as defined in +.St -ansiC . +The characters and their meanings are as follows: +.Bl -tag -width Ds -offset indent +.It Cm \ee +Write an \*[Lt]escape\*[Gt] character. +.It Cm \ea +Write a \*[Lt]bell\*[Gt] character. +.It Cm \eb +Write a \*[Lt]backspace\*[Gt] character. +.It Cm \ef +Write a \*[Lt]form-feed\*[Gt] character. +.It Cm \en +Write a \*[Lt]new-line\*[Gt] character. +.It Cm \er +Write a \*[Lt]carriage return\*[Gt] character. +.It Cm \et +Write a \*[Lt]tab\*[Gt] character. +.It Cm \ev +Write a \*[Lt]vertical tab\*[Gt] character. +.It Cm \e\' +Write a \*[Lt]single quote\*[Gt] character. +.It Cm \e" +Write a \*[Lt]double quote\*[Gt] character. +.It Cm \e\e +Write a backslash character. +.It Cm \e Ns Ar num +Write an 8\-bit character whose +.Tn ASCII +value is the 1\-, 2\-, or 3\-digit octal number +.Ar num . +.It Cm \ex Ns Ar xx +Write an 8\-bit character whose +.Tn ASCII +value is the 1\- or 2\-digit hexadecimal number +.Ar xx . +.El +.Pp +Each format specification is introduced by the percent character +(``%''). +The remainder of the format specification includes, +in the following order: +.Bl -tag -width Ds +.It "Zero or more of the following flags:" +.Bl -tag -width Ds +.It Cm # +A `#' character +specifying that the value should be printed in an ``alternative form''. +For +.Cm b , +.Cm c , +.Cm d , +and +.Cm s +formats, this option has no effect. +For the +.Cm o +format the precision of the number is increased to force the first +character of the output string to a zero. +For the +.Cm x +.Pq Cm X +format, a non-zero result has the string +.Li 0x +.Pq Li 0X +prepended to it. +For +.Cm e , +.Cm E , +.Cm f , +.Cm g , +and +.Cm G +formats, the result will always contain a decimal point, even if no +digits follow the point (normally, a decimal point only appears in the +results of those formats if a digit follows the decimal point). +For +.Cm g +and +.Cm G +formats, trailing zeros are not removed from the result as they +would otherwise be. +.\" I turned this off - decided it isn't a valid use of '#' +.\" For the +.\" .Cm B +.\" format, backslash-escape sequences are expanded first; +.It Cm \&\- +A minus sign `\-' which specifies +.Em left adjustment +of the output in the indicated field; +.It Cm \&+ +A `+' character specifying that there should always be +a sign placed before the number when using signed formats. +.It Sq \&\ \& +A space specifying that a blank should be left before a positive number +for a signed format. +A `+' overrides a space if both are used; +.It Cm \&0 +A zero `0' character indicating that zero-padding should be used +rather than blank-padding. +A `\-' overrides a `0' if both are used; +.El +.It "Field Width:" +An optional digit string specifying a +.Em field width ; +if the output string has fewer characters than the field width it will +be blank-padded on the left (or right, if the left-adjustment indicator +has been given) to make up the field width (note that a leading zero +is a flag, but an embedded zero is part of a field width); +.It Precision : +An optional period, +.Sq Cm \&.\& , +followed by an optional digit string giving a +.Em precision +which specifies the number of digits to appear after the decimal point, +for +.Cm e +and +.Cm f +formats, or the maximum number of characters to be printed +from a string +.Sm off +.Pf ( Cm b No , +.Sm on +.Cm B +and +.Cm s +formats); if the digit string is missing, the precision is treated +as zero; +.It Format : +A character which indicates the type of format to use (one of +.Cm diouxXfwEgGbBcs ) . +.El +.Pp +A field width or precision may be +.Sq Cm \&* +instead of a digit string. +In this case an +.Ar argument +supplies the field width or precision. +.Pp +The format characters and their meanings are: +.Bl -tag -width Fl +.It Cm diouXx +The +.Ar argument +is printed as a signed decimal (d or i), unsigned octal, unsigned decimal, +or unsigned hexadecimal (X or x), respectively. +.It Cm f +The +.Ar argument +is printed in the style +.Sm off +.Pf [\-]ddd Cm \&. No ddd +.Sm on +where the number of d's +after the decimal point is equal to the precision specification for +the argument. +If the precision is missing, 6 digits are given; if the precision +is explicitly 0, no digits and no decimal point are printed. +.It Cm eE +The +.Ar argument +is printed in the style +.Sm off +.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd +.Sm on +where there +is one digit before the decimal point and the number after is equal to +the precision specification for the argument; when the precision is +missing, 6 digits are produced. +An upper-case E is used for an `E' format. +.It Cm gG +The +.Ar argument +is printed in style +.Cm f +or in style +.Cm e +.Pq Cm E +whichever gives full precision in minimum space. +.It Cm b +Characters from the string +.Ar argument +are printed with backslash-escape sequences expanded. +.br +The following additional backslash-escape sequences are supported: +.Bl -tag -width Ds +.It Cm \ec +Causes +.Nm +to ignore any remaining characters in the string operand containing it, +any remaining string operands, and any additional characters in +the format operand. +.It Cm \e0 Ns Ar num +Write an 8\-bit character whose +.Tn ASCII +value is the 1\-, 2\-, or 3\-digit +octal number +.Ar num . +.It Cm \e^ Ns Ar c +Write the control character +.Ar c . +Generates characters `\e000' through `\e037`, and `\e177' (from `\e^?'). +.It Cm \eM\- Ns Ar c +Write the character +.Ar c +with the 8th bit set. +Generates characters `\e241' through `\e376`. +.It Cm \eM^ Ns Ar c +Write the control character +.Ar c +with the 8th bit set. +Generates characters `\e000' through `\e037`, and `\e177' (from `\eM^?'). +.El +.It Cm B +Characters from the string +.Ar argument +are printed with unprintable characters backslash-escaped using the +.Sm off +.Pf ` Cm \e Ar c No ', +.Pf ` Cm \e^ Ar c No ', +.Pf ` Cm \eM\- Ar c No ' +or +.Pf ` Cm \eM^ Ar c No ', +.Sm on +formats described above. +.It Cm c +The first character of +.Ar argument +is printed. +.It Cm s +Characters from the string +.Ar argument +are printed until the end is reached or until the number of characters +indicated by the precision specification is reached; if the +precision is omitted, all characters in the string are printed. +.It Cm \&% +Print a `%'; no argument is used. +.El +.Pp +In no case does a non-existent or small field width cause truncation of +a field; padding takes place only if the specified field width exceeds +the actual width. +.Sh EXIT STATUS +.Nm +exits 0 on success, 1 on failure. +.Sh SEE ALSO +.Xr echo 1 , +.Xr printf 3 , +.Xr printf 9 +.Xr vis 3 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.1-2001 . +.Pp +Support for the floating point formats and `*' as a field width and precision +are optional in POSIX. +.Pp +The behaviour of the %B format and the \e', \e", \exxx, \ee and +\e[M][\-|^]c escape sequences are undefined in POSIX. +.Sh BUGS +Since the floating point numbers are translated from +.Tn ASCII +to floating-point and +then back again, floating-point precision may be lost. +.Pp +Hexadecimal character constants are restricted to, and should be specified +as, two character constants. This is contrary to the ISO C standard but +does guarantee detection of the end of the constant. diff -puN /dev/null usr/dash/bltin/printf.c --- /dev/null +++ a/usr/dash/bltin/printf.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static char *conv_escape_str(char *); +static char *conv_escape(char *, int *); +static int getchr(void); +static intmax_t getintmax(void); +static uintmax_t getuintmax(void); +static char *getstr(void); +static char *mklong(const char *, const char *); +static void check_conversion(const char *, const char *); +#ifdef HAVE_STRTOD +static double getdouble(void); +#endif + +static int rval; +static char **gargv; + +#define isodigit(c) ((c) >= '0' && (c) <= '7') +#define octtobin(c) ((c) - '0') + +#include "bltin.h" +#include "system.h" + +#define PF(f, func) { \ + switch ((char *)param - (char *)array) { \ + default: \ + (void)printf(f, array[0], array[1], func); \ + break; \ + case sizeof(*param): \ + (void)printf(f, array[0], func); \ + break; \ + case 0: \ + (void)printf(f, func); \ + break; \ + } \ +} + +int printfcmd(int argc, char *argv[]) +{ + char *fmt; + char *format; + int ch; + + rval = 0; + + nextopt(nullstr); + + argv = argptr; + format = *argv; + + if (!format) { + warnx("usage: printf format [arg ...]"); + goto err; + } + + gargv = ++argv; + +#define SKIP1 "#-+ 0" +#define SKIP2 "*0123456789" + do { + /* + * Basic algorithm is to scan the format string for conversion + * specifications -- once one is found, find out if the field + * width or precision is a '*'; if it is, gather up value. + * Note, format strings are reused as necessary to use up the + * provided arguments, arguments of zero/null string are + * provided to use up the format string. + */ + + /* find next format specification */ + for (fmt = format; (ch = *fmt++) ;) { + char *start; + char nextch; + int array[2]; + int *param; + + if (ch == '\\') { + int c_ch; + fmt = conv_escape(fmt, &c_ch); + ch = c_ch; + goto pc; + } + if (ch != '%' || (*fmt == '%' && (++fmt || 1))) { +pc: + putchar(ch); + continue; + } + + /* Ok - we've found a format specification, + Save its address for a later printf(). */ + start = fmt - 1; + param = array; + + /* skip to field width */ + fmt += strspn(fmt, SKIP1); + if (*fmt == '*') + *param++ = getintmax(); + + /* skip to possible '.', get following precision */ + fmt += strspn(fmt, SKIP2); + if (*fmt == '.') + ++fmt; + if (*fmt == '*') + *param++ = getintmax(); + + fmt += strspn(fmt, SKIP2); + + ch = *fmt; + if (!ch) { + warnx("missing format character"); + goto err; + } + /* null terminate format string to we can use it + as an argument to printf. */ + nextch = fmt[1]; + fmt[1] = 0; + switch (ch) { + + case 'b': { + char *p = conv_escape_str(getstr()); + *fmt = 's'; + PF(start, p); + /* escape if a \c was encountered */ + if (rval & 0x100) + goto out; + *fmt = 'b'; + break; + } + case 'c': { + int p = getchr(); + PF(start, p); + break; + } + case 's': { + char *p = getstr(); + PF(start, p); + break; + } + case 'd': + case 'i': { + intmax_t p = getintmax(); + char *f = mklong(start, fmt); + PF(f, p); + break; + } + case 'o': + case 'u': + case 'x': + case 'X': { + uintmax_t p = getuintmax(); + char *f = mklong(start, fmt); + PF(f, p); + break; + } +#ifdef HAVE_STRTOD + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': { + double p = getdouble(); + PF(start, p); + break; + } +#endif + default: + warnx("%s: invalid directive", start); + goto err; + } + *++fmt = nextch; + } + } while (gargv != argv && *gargv); + +out: + return (rval & ~0x100); +err: + return 1; +} + + +/* + * Print SysV echo(1) style escape string + * Halts processing string if a \c escape is encountered. + */ +static char * +conv_escape_str(char *str) +{ + int ch; + char *cp; + + /* convert string into a temporary buffer... */ + STARTSTACKSTR(cp); + + do { + int c; + + ch = *str++; + if (ch != '\\') + continue; + + ch = *str++; + if (ch == 'c') { + /* \c as in SYSV echo - abort all processing.... */ + rval |= 0x100; + ch = 0; + continue; + } + + /* + * %b string octal constants are not like those in C. + * They start with a \0, and are followed by 0, 1, 2, + * or 3 octal digits. + */ + if (ch == '0') { + unsigned char i; + i = 3; + ch = 0; + do { + unsigned k = octtobin(*str); + if (k > 7) + break; + str++; + ch <<= 3; + ch += k; + } while (--i); + continue; + } + + /* Finally test for sequences valid in the format string */ + str = conv_escape(str - 1, &c); + ch = c; + } while (STPUTC(ch, cp), ch); + + return stackblock(); +} + +/* + * Print "standard" escape characters + */ +static char * +conv_escape(char *str, int *conv_ch) +{ + int value; + int ch; + + ch = *str; + + switch (ch) { + default: + case 0: + value = '\\'; + goto out; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + ch = 3; + value = 0; + do { + value <<= 3; + value += octtobin(*str++); + } while (isodigit(*str) && --ch); + goto out; + + case '\\': value = '\\'; break; /* backslash */ + case 'a': value = '\a'; break; /* alert */ + case 'b': value = '\b'; break; /* backspace */ + case 'f': value = '\f'; break; /* form-feed */ + case 'n': value = '\n'; break; /* newline */ + case 'r': value = '\r'; break; /* carriage-return */ + case 't': value = '\t'; break; /* tab */ + case 'v': value = '\v'; break; /* vertical-tab */ + } + + str++; +out: + *conv_ch = value; + return str; +} + +static char * +mklong(const char *str, const char *ch) +{ + char *copy; + size_t len; + + len = ch - str + 3; + STARTSTACKSTR(copy); + copy = makestrspace(len, copy); + memcpy(copy, str, len - 3); + copy[len - 3] = 'j'; + copy[len - 2] = *ch; + copy[len - 1] = '\0'; + return (copy); +} + +static int +getchr(void) +{ + int val = 0; + + if (*gargv) + val = **gargv++; + return val; +} + +static char * +getstr(void) +{ + char *val = nullstr; + + if (*gargv) + val = *gargv++; + return val; +} + +static intmax_t +getintmax(void) +{ + intmax_t val = 0; + char *cp, *ep; + + cp = *gargv; + if (cp == NULL) + goto out; + gargv++; + + val = (unsigned char) cp[1]; + if (*cp == '\"' || *cp == '\'') + goto out; + + errno = 0; + val = strtoimax(cp, &ep, 0); + check_conversion(cp, ep); +out: + return val; +} + +static uintmax_t +getuintmax(void) +{ + uintmax_t val = 0; + char *cp, *ep; + + cp = *gargv; + if (cp == NULL) + goto out; + gargv++; + + val = (unsigned char) cp[1]; + if (*cp == '\"' || *cp == '\'') + goto out; + + errno = 0; + val = strtoumax(cp, &ep, 0); + check_conversion(cp, ep); +out: + return val; +} + +#ifdef HAVE_STRTOD +static double +getdouble(void) +{ + double val; + char *cp, *ep; + + cp = *gargv; + if (cp == NULL) + return 0; + gargv++; + + if (*cp == '\"' || *cp == '\'') + return (unsigned char) cp[1]; + + errno = 0; + val = strtod(cp, &ep); + check_conversion(cp, ep); + return val; +} +#endif + +static void +check_conversion(const char *s, const char *ep) +{ + if (*ep) { + if (ep == s) + warnx("%s: expected numeric value", s); + else + warnx("%s: not completely converted", s); + rval = 1; + } else if (errno == ERANGE) { + warnx("%s: %s", s, strerror(ERANGE)); + rval = 1; + } +} + +int +echocmd(int argc, char **argv) +{ + int nonl = 0; + struct output *outs = out1; + + if (!*++argv) + goto end; + if (equal(*argv, "-n")) { + nonl = ~nonl; + if (!*++argv) + goto end; + } + + do { + char c; + + c = *(*argv)++; + if (!c) + goto next; + if (c != '\\') + goto print; + + outstr(conv_escape_str(*argv - 1), outs); + if (rval & 0x100) + break; +next: + c = ' '; + if (!*++argv) { +end: + if (nonl) { + break; + } + c = '\n'; + } +print: + outc(c, outs); + } while (*argv); + return 0; +} diff -puN /dev/null usr/dash/bltin/test.1 --- /dev/null +++ a/usr/dash/bltin/test.1 @@ -0,0 +1,309 @@ +.\" Copyright (c) 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1997-2005 +.\" Herbert Xu . All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)test.1 8.1 (Berkeley) 5/31/93 +.\" +.Dd May 31, 1993 +.Dt TEST 1 +.Os +.Sh NAME +.Nm test , +.Nm \&[ +.Nd condition evaluation utility +.Sh SYNOPSIS +.Nm test +.Ar expression +.Nm \&[ +.Ar expression Cm ] +.Sh DESCRIPTION +The +.Nm test +utility evaluates the expression and, if it evaluates +to true, returns a zero (true) exit status; otherwise +it returns 1 (false). +If there is no expression, test also +returns 1 (false). +.Pp +All operators and flags are separate arguments to the +.Nm test +utility. +.Pp +The following primaries are used to construct expression: +.Bl -tag -width Ar +.It Fl b Ar file +True if +.Ar file +exists and is a block special +file. +.It Fl c Ar file +True if +.Ar file +exists and is a character +special file. +.It Fl d Ar file +True if +.Ar file +exists and is a directory. +.It Fl e Ar file +True if +.Ar file +exists (regardless of type). +.It Fl f Ar file +True if +.Ar file +exists and is a regular file. +.It Fl g Ar file +True if +.Ar file +exists and its set group ID flag +is set. +.It Fl h Ar file +True if +.Ar file +exists and is a symbolic link. +.It Fl k Ar file +True if +.Ar file +exists and its sticky bit is set. +.It Fl n Ar string +True if the length of +.Ar string +is nonzero. +.It Fl p Ar file +True if +.Ar file +is a named pipe +.Po Tn FIFO Pc . +.It Fl r Ar file +True if +.Ar file +exists and is readable. +.It Fl s Ar file +True if +.Ar file +exists and has a size greater +than zero. +.It Fl t Ar file_descriptor +True if the file whose file descriptor number +is +.Ar file_descriptor +is open and is associated with a terminal. +.It Fl u Ar file +True if +.Ar file +exists and its set user ID flag +is set. +.It Fl w Ar file +True if +.Ar file +exists and is writable. +True +indicates only that the write flag is on. +The file is not writable on a read-only file +system even if this test indicates true. +.It Fl x Ar file +True if +.Ar file +exists and is executable. +True +indicates only that the execute flag is on. +If +.Ar file +is a directory, true indicates that +.Ar file +can be searched. +.It Fl z Ar string +True if the length of +.Ar string +is zero. +.It Fl L Ar file +True if +.Ar file +exists and is a symbolic link. +This operator is retained for compatibility with previous versions of +this program. +Do not rely on its existence; use +.Fl h +instead. +.It Fl O Ar file +True if +.Ar file +exists and its owner matches the effective user id of this process. +.It Fl G Ar file +True if +.Ar file +exists and its group matches the effective group id of this process. +.It Fl S Ar file +True if +.Ar file +exists and is a socket. +.It Ar file1 Fl nt Ar file2 +True if +.Ar file1 +exists and is newer than +.Ar file2 . +.It Ar file1 Fl ot Ar file2 +True if +.Ar file1 +exists and is older than +.Ar file2 . +.It Ar file1 Fl ef Ar file2 +True if +.Ar file1 +and +.Ar file2 +exist and refer to the same file. +.It Ar string +True if +.Ar string +is not the null +string. +.It Ar \&s\&1 Cm \&= Ar \&s\&2 +True if the strings +.Ar \&s\&1 +and +.Ar \&s\&2 +are identical. +.It Ar \&s\&1 Cm \&!= Ar \&s\&2 +True if the strings +.Ar \&s\&1 +and +.Ar \&s\&2 +are not identical. +.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2 +True if string +.Ar \&s\&1 +comes before +.Ar \&s\&2 +based on the ASCII value of their characters. +.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2 +True if string +.Ar \&s\&1 +comes after +.Ar \&s\&2 +based on the ASCII value of their characters. +.It Ar \&n\&1 Fl \&eq Ar \&n\&2 +True if the integers +.Ar \&n\&1 +and +.Ar \&n\&2 +are algebraically +equal. +.It Ar \&n\&1 Fl \&ne Ar \&n\&2 +True if the integers +.Ar \&n\&1 +and +.Ar \&n\&2 +are not +algebraically equal. +.It Ar \&n\&1 Fl \> Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically +greater than the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \&ge Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically +greater than or equal to the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \< Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically less +than the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \&le Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically less +than or equal to the integer +.Ar \&n\&2 . +.El +.Pp +These primaries can be combined with the following operators: +.Bl -tag -width Ar +.It Cm \&! Ar expression +True if +.Ar expression +is false. +.It Ar expression1 Fl a Ar expression2 +True if both +.Ar expression1 +and +.Ar expression2 +are true. +.It Ar expression1 Fl o Ar expression2 +True if either +.Ar expression1 +or +.Ar expression2 +are true. +.It Cm \&( Ns Ar expression Ns Cm \&) +True if expression is true. +.El +.Pp +The +.Fl a +operator has higher precedence than the +.Fl o +operator. +.Sh GRAMMAR AMBIGUITY +The +.Nm test +grammar is inherently ambiguous. +In order to assure a degree of consistency, the cases described in +.St -p1003.2 +section 4.62.4, +are evaluated consistently according to the rules specified in the +standards document. +All other cases are subject to the ambiguity in the command semantics. +.Sh EXIT STATUS +The +.Nm test +utility exits with one of the following values: +.Bl -tag -width Ds +.It 0 +expression evaluated to true. +.It 1 +expression evaluated to false or expression was +missing. +.It \*[Gt]1 +An error occurred. +.El +.Sh STANDARDS +The +.Nm test +utility implements a superset of the +.St -p1003.2 +specification. diff -puN /dev/null usr/dash/bltin/test.c --- /dev/null +++ a/usr/dash/bltin/test.c @@ -0,0 +1,500 @@ +/* + * test(1); version 7-like -- author Erik Baalbergen + * modified by Eric Gisin to be used as built-in. + * modified by Arnold Robbins to add SVR3 compatibility + * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). + * modified by J.T. Conklin for NetBSD. + * + * This program is in the Public Domain. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "bltin.h" + +/* test(1) accepts the following grammar: + oexpr ::= aexpr | aexpr "-o" oexpr ; + aexpr ::= nexpr | nexpr "-a" aexpr ; + nexpr ::= primary | "!" primary + primary ::= unary-operator operand + | operand binary-operator operand + | operand + | "(" oexpr ")" + ; + unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| + "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; + + binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| + "-nt"|"-ot"|"-ef"; + operand ::= +*/ + +enum token { + EOI, + FILRD, + FILWR, + FILEX, + FILEXIST, + FILREG, + FILDIR, + FILCDEV, + FILBDEV, + FILFIFO, + FILSOCK, + FILSYM, + FILGZ, + FILTT, + FILSUID, + FILSGID, + FILSTCK, + FILNT, + FILOT, + FILEQ, + FILUID, + FILGID, + STREZ, + STRNZ, + STREQ, + STRNE, + STRLT, + STRGT, + INTEQ, + INTNE, + INTGE, + INTGT, + INTLE, + INTLT, + UNOT, + BAND, + BOR, + LPAREN, + RPAREN, + OPERAND +}; + +enum token_types { + UNOP, + BINOP, + BUNOP, + BBINOP, + PAREN +}; + +static struct t_op { + const char *op_text; + short op_num, op_type; +} const ops [] = { + {"-r", FILRD, UNOP}, + {"-w", FILWR, UNOP}, + {"-x", FILEX, UNOP}, + {"-e", FILEXIST,UNOP}, + {"-f", FILREG, UNOP}, + {"-d", FILDIR, UNOP}, + {"-c", FILCDEV,UNOP}, + {"-b", FILBDEV,UNOP}, + {"-p", FILFIFO,UNOP}, + {"-u", FILSUID,UNOP}, + {"-g", FILSGID,UNOP}, + {"-k", FILSTCK,UNOP}, + {"-s", FILGZ, UNOP}, + {"-t", FILTT, UNOP}, + {"-z", STREZ, UNOP}, + {"-n", STRNZ, UNOP}, + {"-h", FILSYM, UNOP}, /* for backwards compat */ + {"-O", FILUID, UNOP}, + {"-G", FILGID, UNOP}, + {"-L", FILSYM, UNOP}, + {"-S", FILSOCK,UNOP}, + {"=", STREQ, BINOP}, + {"!=", STRNE, BINOP}, + {"<", STRLT, BINOP}, + {">", STRGT, BINOP}, + {"-eq", INTEQ, BINOP}, + {"-ne", INTNE, BINOP}, + {"-ge", INTGE, BINOP}, + {"-gt", INTGT, BINOP}, + {"-le", INTLE, BINOP}, + {"-lt", INTLT, BINOP}, + {"-nt", FILNT, BINOP}, + {"-ot", FILOT, BINOP}, + {"-ef", FILEQ, BINOP}, + {"!", UNOT, BUNOP}, + {"-a", BAND, BBINOP}, + {"-o", BOR, BBINOP}, + {"(", LPAREN, PAREN}, + {")", RPAREN, PAREN}, + {0, 0, 0} +}; + +static char **t_wp; +static struct t_op const *t_wp_op; + +static void syntax(const char *, const char *); +static int oexpr(enum token); +static int aexpr(enum token); +static int nexpr(enum token); +static int primary(enum token); +static int binop(void); +static int filstat(char *, enum token); +static enum token t_lex(char *); +static int isoperand(void); +static int getn(const char *); +static int newerf(const char *, const char *); +static int olderf(const char *, const char *); +static int equalf(const char *, const char *); +static int test_st_mode(const struct stat64 *, int); +static int bash_group_member(gid_t); + +int +testcmd(int argc, char **argv) +{ + int res; + + if (strcmp(argv[0], "[") == 0) { + if (strcmp(argv[--argc], "]")) + error("missing ]"); + argv[argc] = NULL; + } + + if (argc < 2) + return 1; + + t_wp = &argv[1]; + res = !oexpr(t_lex(*t_wp)); + + if (*t_wp != NULL && *++t_wp != NULL) + syntax(*t_wp, "unexpected operator"); + + return res; +} + +static void +syntax(const char *op, const char *msg) +{ + if (op && *op) + error("%s: %s", op, msg); + else + error("%s", msg); +} + +static int +oexpr(enum token n) +{ + int res; + + res = aexpr(n); + if (t_lex(*++t_wp) == BOR) + return oexpr(t_lex(*++t_wp)) || res; + t_wp--; + return res; +} + +static int +aexpr(enum token n) +{ + int res; + + res = nexpr(n); + if (t_lex(*++t_wp) == BAND) + return aexpr(t_lex(*++t_wp)) && res; + t_wp--; + return res; +} + +static int +nexpr(enum token n) +{ + if (n == UNOT) + return !nexpr(t_lex(*++t_wp)); + return primary(n); +} + +static int +primary(enum token n) +{ + enum token nn; + int res; + + if (n == EOI) + return 0; /* missing expression */ + if (n == LPAREN) { + if ((nn = t_lex(*++t_wp)) == RPAREN) + return 0; /* missing expression */ + res = oexpr(nn); + if (t_lex(*++t_wp) != RPAREN) + syntax(NULL, "closing paren expected"); + return res; + } + if (t_wp_op && t_wp_op->op_type == UNOP) { + /* unary expression */ + if (*++t_wp == NULL) + syntax(t_wp_op->op_text, "argument expected"); + switch (n) { + case STREZ: + return strlen(*t_wp) == 0; + case STRNZ: + return strlen(*t_wp) != 0; + case FILTT: + return isatty(getn(*t_wp)); + default: + return filstat(*t_wp, n); + } + } + + if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { + return binop(); + } + + return strlen(*t_wp) > 0; +} + +static int +binop(void) +{ + const char *opnd1, *opnd2; + struct t_op const *op; + + opnd1 = *t_wp; + (void) t_lex(*++t_wp); + op = t_wp_op; + + if ((opnd2 = *++t_wp) == (char *)0) + syntax(op->op_text, "argument expected"); + + switch (op->op_num) { + default: +#ifdef DEBUG + abort(); + /* NOTREACHED */ +#endif + case STREQ: + return strcmp(opnd1, opnd2) == 0; + case STRNE: + return strcmp(opnd1, opnd2) != 0; + case STRLT: + return strcmp(opnd1, opnd2) < 0; + case STRGT: + return strcmp(opnd1, opnd2) > 0; + case INTEQ: + return getn(opnd1) == getn(opnd2); + case INTNE: + return getn(opnd1) != getn(opnd2); + case INTGE: + return getn(opnd1) >= getn(opnd2); + case INTGT: + return getn(opnd1) > getn(opnd2); + case INTLE: + return getn(opnd1) <= getn(opnd2); + case INTLT: + return getn(opnd1) < getn(opnd2); + case FILNT: + return newerf (opnd1, opnd2); + case FILOT: + return olderf (opnd1, opnd2); + case FILEQ: + return equalf (opnd1, opnd2); + } +} + +static int +filstat(char *nm, enum token mode) +{ + struct stat64 s; + + if (mode == FILSYM ? lstat64(nm, &s) : stat64(nm, &s)) + return 0; + + switch (mode) { + case FILRD: + return test_st_mode(&s, R_OK); + case FILWR: + return test_st_mode(&s, W_OK); + case FILEX: + return test_st_mode(&s, X_OK); + case FILEXIST: + return 1; + case FILREG: + return S_ISREG(s.st_mode); + case FILDIR: + return S_ISDIR(s.st_mode); + case FILCDEV: + return S_ISCHR(s.st_mode); + case FILBDEV: + return S_ISBLK(s.st_mode); + case FILFIFO: + return S_ISFIFO(s.st_mode); + case FILSOCK: + return S_ISSOCK(s.st_mode); + case FILSYM: + return S_ISLNK(s.st_mode); + case FILSUID: + return (s.st_mode & S_ISUID) != 0; + case FILSGID: + return (s.st_mode & S_ISGID) != 0; + case FILSTCK: + return (s.st_mode & S_ISVTX) != 0; + case FILGZ: + return !!s.st_size; + case FILUID: + return s.st_uid == geteuid(); + case FILGID: + return s.st_gid == getegid(); + default: + return 1; + } +} + +static enum token +t_lex(char *s) +{ + struct t_op const *op; + + op = ops; + + if (s == 0) { + t_wp_op = (struct t_op *)0; + return EOI; + } + while (op->op_text) { + if (strcmp(s, op->op_text) == 0) { + if ((op->op_type == UNOP && isoperand()) || + (op->op_num == LPAREN && *(t_wp+1) == 0)) + break; + t_wp_op = op; + return op->op_num; + } + op++; + } + t_wp_op = (struct t_op *)0; + return OPERAND; +} + +static int +isoperand(void) +{ + struct t_op const *op; + char *s, *t; + + op = ops; + if ((s = *(t_wp+1)) == 0) + return 1; + if ((t = *(t_wp+2)) == 0) + return 0; + while (op->op_text) { + if (strcmp(s, op->op_text) == 0) + return op->op_type == BINOP && + (t[0] != ')' || t[1] != '\0'); + op++; + } + return 0; +} + +/* atoi with error detection */ +static int +getn(const char *s) +{ + char *p; + long r; + + errno = 0; + r = strtol(s, &p, 10); + + if (errno != 0) + error("%s: out of range", s); + + while (isspace((unsigned char)*p)) + p++; + + if (*p) + error("%s: bad number", s); + + return (int) r; +} + +static int +newerf (const char *f1, const char *f2) +{ + struct stat b1, b2; + + return (stat (f1, &b1) == 0 && + stat (f2, &b2) == 0 && + b1.st_mtime > b2.st_mtime); +} + +static int +olderf (const char *f1, const char *f2) +{ + struct stat b1, b2; + + return (stat (f1, &b1) == 0 && + stat (f2, &b2) == 0 && + b1.st_mtime < b2.st_mtime); +} + +static int +equalf (const char *f1, const char *f2) +{ + struct stat b1, b2; + + return (stat (f1, &b1) == 0 && + stat (f2, &b2) == 0 && + b1.st_dev == b2.st_dev && + b1.st_ino == b2.st_ino); +} + +/* + * Similar to what access(2) does, but uses the effective uid and gid. + * Doesn't make the mistake of telling root that any file is executable. + * Returns non-zero if the file is accessible. + */ +static int +test_st_mode(const struct stat64 *st, int mode) +{ + int euid = geteuid(); + + if (euid == 0) { + /* Root can read or write any file. */ + if (mode != X_OK) + return 1; + + /* Root can execute any file that has any one of the execute + bits set. */ + mode = S_IXUSR | S_IXGRP | S_IXOTH; + } else if (st->st_uid == euid) + mode <<= 6; + else if (bash_group_member(st->st_gid)) + mode <<= 3; + + return st->st_mode & mode; +} + +/* Return non-zero if GID is one that we have in our groups list. */ +static int +bash_group_member(gid_t gid) +{ + register int i; + gid_t *group_array; + int ngroups; + + /* Short-circuit if possible, maybe saving a call to getgroups(). */ + if (gid == getgid() || gid == getegid()) + return (1); + + ngroups = getgroups(0, NULL); + group_array = stalloc(ngroups * sizeof(gid_t)); + getgroups(ngroups, group_array); + + /* Search through the list looking for GID. */ + for (i = 0; i < ngroups; i++) + if (gid == group_array[i]) + return (1); + + return (0); +} diff -puN /dev/null usr/dash/builtins.def.in --- /dev/null +++ a/usr/dash/builtins.def.in @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)builtins.def 8.4 (Berkeley) 5/4/95 + */ + +/* + * This file lists all the builtin commands. The first column is the name + * of a C routine. + * The -a flag specifies that this is a posix 'assignment builtin' command. + * The -s flag specifies that this is a posix 'special builtin' command. + * The -u flag specifies that this is a posix 'standard utility'. + * The rest of the line specifies the command name or names used to run + * the command. + */ + +#ifndef JOBS +#define JOBS 1 +#endif + +#if JOBS +bgcmd -u bg +fgcmd -u fg +#endif + +#ifndef SMALL +histcmd -u fc +#endif + +breakcmd -s break -s continue +cdcmd -u cd chdir +commandcmd -u command +dotcmd -s . +echocmd echo +evalcmd -s eval +execcmd -s exec +exitcmd -s exit +exportcmd -as export -as readonly +falsecmd -u false +getoptscmd -u getopts +hashcmd hash +jobscmd -u jobs +localcmd -a local +printfcmd printf +pwdcmd pwd +readcmd -u read +returncmd -s return +setcmd -s set +shiftcmd -s shift +trapcmd -s trap +truecmd -s : -u true +typecmd type +umaskcmd -u umask +unaliascmd -u unalias +unsetcmd -s unset +waitcmd -u wait +aliascmd -au alias +#ifdef HAVE_GETRLIMIT +ulimitcmd ulimit +#endif +testcmd test [ +killcmd -u kill diff -puN /dev/null usr/dash/cd.c --- /dev/null +++ a/usr/dash/cd.c @@ -0,0 +1,303 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +/* + * The cd and pwd commands. + */ + +#include "shell.h" +#include "var.h" +#include "nodes.h" /* for jobs.h */ +#include "jobs.h" +#include "options.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "exec.h" +#include "redir.h" +#include "mystring.h" +#include "show.h" +#include "cd.h" + +#define CD_PHYSICAL 1 +#define CD_PRINT 2 + +STATIC int docd(const char *, int); +STATIC const char *updatepwd(const char *); +STATIC char *getpwd(void); +STATIC int cdopt(void); + +STATIC char *curdir = nullstr; /* current working directory */ +STATIC char *physdir = nullstr; /* physical working directory */ + +STATIC int +cdopt() +{ + int flags = 0; + int i, j; + + j = 'L'; + while ((i = nextopt("LP"))) { + if (i != j) { + flags ^= CD_PHYSICAL; + j = i; + } + } + + return flags; +} + +int +cdcmd(int argc, char **argv) +{ + const char *dest; + const char *path; + const char *p; + char c; + struct stat statb; + int flags; + + flags = cdopt(); + dest = *argptr; + if (!dest) + dest = bltinlookup(homestr); + else if (dest[0] == '-' && dest[1] == '\0') { + dest = bltinlookup("OLDPWD"); + flags |= CD_PRINT; + } + if (!dest) + dest = nullstr; + if (*dest == '/') + goto step7; + if (*dest == '.') { + c = dest[1]; +dotdot: + switch (c) { + case '\0': + case '/': + goto step6; + case '.': + c = dest[2]; + if (c != '.') + goto dotdot; + } + } + if (!*dest) + dest = "."; + if (!(path = bltinlookup("CDPATH"))) { +step6: +step7: + p = dest; + goto docd; + } + do { + c = *path; + p = padvance(&path, dest); + if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { + if (c && c != ':') + flags |= CD_PRINT; +docd: + if (!docd(p, flags)) + goto out; + break; + } + } while (path); + sh_error("can't cd to %s", dest); + /* NOTREACHED */ +out: + if (flags & CD_PRINT) + out1fmt(snlfmt, curdir); + return 0; +} + + +/* + * Actually do the chdir. We also call hashcd to let the routines in exec.c + * know that the current directory has changed. + */ + +STATIC int +docd(const char *dest, int flags) +{ + const char *dir = 0; + int err; + + TRACE(("docd(\"%s\", %d) called\n", dest, flags)); + + INTOFF; + if (!(flags & CD_PHYSICAL)) { + dir = updatepwd(dest); + if (dir) + dest = dir; + } + err = chdir(dest); + if (err) + goto out; + setpwd(dir, 1); + hashcd(); +out: + INTON; + return err; +} + + +/* + * Update curdir (the name of the current directory) in response to a + * cd command. + */ + +STATIC const char * +updatepwd(const char *dir) +{ + char *new; + char *p; + char *cdcomppath; + const char *lim; + + cdcomppath = sstrdup(dir); + STARTSTACKSTR(new); + if (*dir != '/') { + if (curdir == nullstr) + return 0; + new = stputs(curdir, new); + } + new = makestrspace(strlen(dir) + 2, new); + lim = stackblock() + 1; + if (*dir != '/') { + if (new[-1] != '/') + USTPUTC('/', new); + if (new > lim && *lim == '/') + lim++; + } else { + USTPUTC('/', new); + cdcomppath++; + if (dir[1] == '/' && dir[2] != '/') { + USTPUTC('/', new); + cdcomppath++; + lim++; + } + } + p = strtok(cdcomppath, "/"); + while (p) { + switch(*p) { + case '.': + if (p[1] == '.' && p[2] == '\0') { + while (new > lim) { + STUNPUTC(new); + if (new[-1] == '/') + break; + } + break; + } else if (p[1] == '\0') + break; + /* fall through */ + default: + new = stputs(p, new); + USTPUTC('/', new); + } + p = strtok(0, "/"); + } + if (new > lim) + STUNPUTC(new); + *new = 0; + return stackblock(); +} + + +#define MAXPWD 256 + +/* + * Find out what the current directory is. If we already know the current + * directory, this routine returns immediately. + */ +inline +STATIC char * +getpwd() +{ + char *dir = getcwd(0, 0); + return dir ? dir : nullstr; +} + +int +pwdcmd(int argc, char **argv) +{ + int flags; + const char *dir = curdir; + + flags = cdopt(); + if (flags) { + if (physdir == nullstr) + setpwd(dir, 0); + dir = physdir; + } + out1fmt(snlfmt, dir); + return 0; +} + +void +setpwd(const char *val, int setold) +{ + char *oldcur, *dir; + + oldcur = dir = curdir; + + if (setold) { + setvar("OLDPWD", oldcur, VEXPORT); + } + INTOFF; + if (physdir != nullstr) { + if (physdir != oldcur) + free(physdir); + physdir = nullstr; + } + if (oldcur == val || !val) { + char *s = getpwd(); + physdir = s; + if (!val) + dir = s; + } else + dir = savestr(val); + if (oldcur != dir && oldcur != nullstr) { + free(oldcur); + } + curdir = dir; + INTON; + setvar("PWD", dir, VEXPORT); +} diff -puN /dev/null usr/dash/cd.h --- /dev/null +++ a/usr/dash/cd.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 1995 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +int cdcmd(int, char **); +int pwdcmd(int, char **); +void setpwd(const char *, int); diff -puN /dev/null usr/dash/config.h --- /dev/null +++ a/usr/dash/config.h @@ -0,0 +1,85 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `bsearch' function. */ +#define HAVE_BSEARCH 1 + +/* Define to 1 if you have the `getpwnam' function. */ +/* #undef HAVE_GETPWNAM */ + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the `isalpha' function. */ +#define HAVE_ISALPHA 1 + +/* Define to 1 if you have the `killpg' function. */ +/* #undef HAVE_KILLPG */ + +/* Define to 1 if you have the `mempcpy' function. */ +/* #undef HAVE_MEMPCPY */ + +/* Define to 1 if you have the `sigsetmask' function. */ +/* #undef HAVE_SIGSETMASK */ + +/* Define to 1 if you have the `stpcpy' function. */ +/* #undef HAVE_STPCPY */ + +/* Define to 1 if you have the `strchrnul' function. */ +/* #undef HAVE_STRCHRNUL */ + +/* Define to 1 if you have the `strsignal' function. */ +#define HAVE_STRSIGNAL 1 + +/* Define to 1 if you have the `strtod' function. */ +/* #undef HAVE_STRTOD */ + +/* Define to 1 if you have the `strtoimax' function. */ +#define HAVE_STRTOIMAX 1 + +/* Define to 1 if you have the `strtoumax' function. */ +#define HAVE_STRTOUMAX 1 + +/* Define to 1 if you have the `sysconf' function. */ +/* #undef HAVE_SYSCONF */ + +/* Name of package */ +#define PACKAGE "dash" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "dash" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "dash 0.5.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "dash" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.5.2" + +/* Version number of package */ +#define VERSION "0.5.2" + +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +/* 64-bit operations are the same as 32-bit */ +#define fstat64 fstat + +/* 64-bit operations are the same as 32-bit */ +#define lstat64 lstat + +/* 64-bit operations are the same as 32-bit */ +#define open64 open + +/* klibc has bsd_signal instead of signal */ +#define signal bsd_signal + +/* 64-bit operations are the same as 32-bit */ +#define stat64 stat diff -puN /dev/null usr/dash/error.c --- /dev/null +++ a/usr/dash/error.c @@ -0,0 +1,233 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Errors and exceptions. + */ + +#include +#include +#include +#include +#include +#include + +#include "shell.h" +#include "main.h" +#include "options.h" +#include "output.h" +#include "error.h" +#include "show.h" +#include "eval.h" +#include "parser.h" +#include "trap.h" +#include "system.h" + + +/* + * Code to handle exceptions in C. + */ + +struct jmploc *handler; +int exception; +int suppressint; +volatile sig_atomic_t intpending; + + +static void exverror(int, const char *, va_list) + __attribute__((__noreturn__)); + +/* + * Called to raise an exception. Since C doesn't include exceptions, we + * just do a longjmp to the exception handler. The type of exception is + * stored in the global variable "exception". + */ + +void +exraise(int e) +{ +#ifdef DEBUG + if (handler == NULL) + abort(); +#endif + INTOFF; + + exception = e; + longjmp(handler->loc, 1); +} + + +/* + * Called from trap.c when a SIGINT is received. (If the user specifies + * that SIGINT is to be trapped or ignored using the trap builtin, then + * this routine is not called.) Suppressint is nonzero when interrupts + * are held using the INTOFF macro. (The test for iflag is just + * defensive programming.) + */ + +void +onint(void) { + int i; + + intpending = 0; + sigclearmask(); + i = EXSIG; + if (gotsig[SIGINT - 1] && !trap[SIGINT]) { + if (!(rootshell && iflag)) { + signal(SIGINT, SIG_DFL); + raise(SIGINT); + } + i = EXINT; + } + exraise(i); + /* NOTREACHED */ +} + +static void +exvwarning2(const char *msg, va_list ap) +{ + struct output *errs; + const char *name; + const char *fmt; + + errs = out2; + name = arg0; + fmt = "%s: "; + if (commandname) { + name = commandname; + fmt = "%s: %d: "; + } + outfmt(errs, fmt, name, startlinno); + doformat(errs, msg, ap); +#if FLUSHERR + outc('\n', errs); +#else + outcslow('\n', errs); +#endif +} + +#define exvwarning(a, b, c) exvwarning2(b, c) + +/* + * Exverror is called to raise the error exception. If the second argument + * is not NULL then error prints an error message using printf style + * formatting. It then raises the error exception. + */ +static void +exverror(int cond, const char *msg, va_list ap) +{ +#ifdef DEBUG + if (msg) { + TRACE(("exverror(%d, \"", cond)); + TRACEV((msg, ap)); + TRACE(("\") pid=%d\n", getpid())); + } else + TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); + if (msg) +#endif + exvwarning(-1, msg, ap); + + flushall(); + exraise(cond); + /* NOTREACHED */ +} + + +void +sh_error(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + exverror(EXERROR, msg, ap); + /* NOTREACHED */ + va_end(ap); +} + + +void +exerror(int cond, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + exverror(cond, msg, ap); + /* NOTREACHED */ + va_end(ap); +} + +/* + * error/warning routines for external builtins + */ + +void +sh_warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + exvwarning(-1, fmt, ap); + va_end(ap); +} + + +/* + * Return a string describing an error. The returned string may be a + * pointer to a static buffer that will be overwritten on the next call. + * Action describes the operation that got the error. + */ + +const char * +errmsg(int e, int action) +{ + if (e != ENOENT && e != ENOTDIR) + return strerror(e); + + if (action & E_OPEN) + return "No such file"; + else if (action & E_CREAT) + return "Directory nonexistent"; + else + return "not found"; +} + + +#ifdef REALLY_SMALL +void +__inton() { + if (--suppressint == 0 && intpending) { + onint(); + } +} +#endif diff -puN /dev/null usr/dash/error.h --- /dev/null +++ a/usr/dash/error.h @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)error.h 8.2 (Berkeley) 5/4/95 + */ + +#ifndef DASH_ERROR_H +#define DASH_ERROR_H + +#include +#include + +/* + * Types of operations (passed to the errmsg routine). + */ + +#define E_OPEN 01 /* opening a file */ +#define E_CREAT 02 /* creating a file */ +#define E_EXEC 04 /* executing a program */ + + +/* + * We enclose jmp_buf in a structure so that we can declare pointers to + * jump locations. The global variable handler contains the location to + * jump to when an exception occurs, and the global variable exception + * contains a code identifying the exeception. To implement nested + * exception handlers, the user should save the value of handler on entry + * to an inner scope, set handler to point to a jmploc structure for the + * inner scope, and restore handler on exit from the scope. + */ + +struct jmploc { + jmp_buf loc; +}; + +extern struct jmploc *handler; +extern int exception; + +/* exceptions */ +#define EXINT 0 /* SIGINT received */ +#define EXERROR 1 /* a generic error */ +#define EXSHELLPROC 2 /* execute a shell procedure */ +#define EXEXEC 3 /* command execution failed */ +#define EXEXIT 4 /* exit the shell */ +#define EXSIG 5 /* trapped signal in wait(1) */ + + +/* + * These macros allow the user to suspend the handling of interrupt signals + * over a period of time. This is similar to SIGHOLD to or sigblock, but + * much more efficient and portable. (But hacking the kernel is so much + * more fun than worrying about efficiency and portability. :-)) + */ + +extern int suppressint; +extern volatile sig_atomic_t intpending; +extern int exsig; + +#define barrier() ({ __asm__ __volatile__ ("": : :"memory"); }) +#define INTOFF \ + ({ \ + suppressint++; \ + barrier(); \ + 0; \ + }) +#ifdef REALLY_SMALL +void __inton(void); +#define INTON __inton() +#else +#define INTON \ + ({ \ + barrier(); \ + if (--suppressint == 0 && intpending) onint(); \ + 0; \ + }) +#endif +#define FORCEINTON \ + ({ \ + barrier(); \ + suppressint = 0; \ + if (intpending) onint(); \ + 0; \ + }) +#define SAVEINT(v) ((v) = suppressint) +#define RESTOREINT(v) \ + ({ \ + barrier(); \ + if ((suppressint = (v)) == 0 && intpending) onint(); \ + 0; \ + }) +#define CLEAR_PENDING_INT intpending = 0 +#define int_pending() intpending +#define EXSIGON() \ + ({ \ + exsig++; \ + barrier(); \ + if (pendingsigs) \ + exraise(EXSIG); \ + 0; \ + }) +/* EXSIG is turned off by evalbltin(). */ + +void exraise(int) __attribute__((__noreturn__)); +#ifdef USE_NORETURN +void onint(void) __attribute__((__noreturn__)); +#else +void onint(void); +#endif +void sh_error(const char *, ...) __attribute__((__noreturn__)); +void exerror(int, const char *, ...) __attribute__((__noreturn__)); +const char *errmsg(int, int); + +void sh_warnx(const char *, ...); + +#endif /* DASH_ERROR_H */ diff -puN /dev/null usr/dash/eval.c --- /dev/null +++ a/usr/dash/eval.c @@ -0,0 +1,1100 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Evaluate a command. + */ + +#include "shell.h" +#include "nodes.h" +#include "syntax.h" +#include "expand.h" +#include "parser.h" +#include "jobs.h" +#include "eval.h" +#include "builtins.h" +#include "options.h" +#include "exec.h" +#include "redir.h" +#include "input.h" +#include "output.h" +#include "trap.h" +#include "var.h" +#include "memalloc.h" +#include "error.h" +#include "show.h" +#include "mystring.h" +#ifndef SMALL +#include "myhistedit.h" +#endif + + +/* flags in argument to evaltree */ +#define EV_EXIT 01 /* exit after evaluating tree */ +#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ +#define EV_BACKCMD 04 /* command executing within back quotes */ + +int evalskip; /* set if we are skipping commands */ +STATIC int skipcount; /* number of levels to skip */ +MKINIT int loopnest; /* current loop nesting level */ +static int funcnest; /* depth of function calls */ + + +char *commandname; +struct strlist *cmdenviron; +int exitstatus; /* exit status of last command */ +int back_exitstatus; /* exit status of backquoted command */ + + +#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) +STATIC +#endif +void evaltreenr(union node *, int) __attribute__ ((__noreturn__)); +STATIC void evalloop(union node *, int); +STATIC void evalfor(union node *, int); +STATIC void evalcase(union node *, int); +STATIC void evalsubshell(union node *, int); +STATIC void expredir(union node *); +STATIC void evalpipe(union node *, int); +#ifdef notyet +STATIC void evalcommand(union node *, int, struct backcmd *); +#else +STATIC void evalcommand(union node *, int); +#endif +STATIC int evalbltin(const struct builtincmd *, int, char **); +STATIC int evalfun(struct funcnode *, int, char **, int); +STATIC void prehash(union node *); +STATIC int eprintlist(struct output *, struct strlist *, int); +STATIC int bltincmd(int, char **); + + +STATIC const struct builtincmd bltin = { + name: nullstr, + builtin: bltincmd +}; + + +/* + * Called to reset things after an exception. + */ + +#ifdef mkinit +INCLUDE "eval.h" + +RESET { + evalskip = 0; + loopnest = 0; +} +#endif + + + +/* + * The eval commmand. + */ + +int +evalcmd(int argc, char **argv) +{ + char *p; + char *concat; + char **ap; + + if (argc > 1) { + p = argv[1]; + if (argc > 2) { + STARTSTACKSTR(concat); + ap = argv + 2; + for (;;) { + concat = stputs(p, concat); + if ((p = *ap++) == NULL) + break; + STPUTC(' ', concat); + } + STPUTC('\0', concat); + p = grabstackstr(concat); + } + evalstring(p, ~SKIPEVAL); + + } + return exitstatus; +} + + +/* + * Execute a command or commands contained in a string. + */ + +int +evalstring(char *s, int mask) +{ + union node *n; + struct stackmark smark; + int skip; + + setinputstring(s); + setstackmark(&smark); + + skip = 0; + while ((n = parsecmd(0)) != NEOF) { + evaltree(n, 0); + popstackmark(&smark); + skip = evalskip; + if (skip) + break; + } + popfile(); + + skip &= mask; + evalskip = skip; + return skip; +} + + + +/* + * Evaluate a parse tree. The value is left in the global variable + * exitstatus. + */ + +void +evaltree(union node *n, int flags) +{ + int checkexit = 0; + void (*evalfn)(union node *, int); + unsigned isor; + int status; + if (n == NULL) { + TRACE(("evaltree(NULL) called\n")); + goto out; + } +#ifndef SMALL + displayhist = 1; /* show history substitutions done with fc */ +#endif + TRACE(("pid %d, evaltree(%p: %d, %d) called\n", + getpid(), n, n->type, flags)); + switch (n->type) { + default: +#ifdef DEBUG + out1fmt("Node type = %d\n", n->type); +#ifndef USE_GLIBC_STDIO + flushout(out1); +#endif + break; +#endif + case NNOT: + evaltree(n->nnot.com, EV_TESTED); + status = !exitstatus; + goto setstatus; + case NREDIR: + expredir(n->nredir.redirect); + status = redirectsafe(n->nredir.redirect, REDIR_PUSH); + if (!status) { + evaltree(n->nredir.n, flags & EV_TESTED); + status = exitstatus; + } + popredir(0); + goto setstatus; + case NCMD: +#ifdef notyet + if (eflag && !(flags & EV_TESTED)) + checkexit = ~0; + evalcommand(n, flags, (struct backcmd *)NULL); + break; +#else + evalfn = evalcommand; +checkexit: + if (eflag && !(flags & EV_TESTED)) + checkexit = ~0; + goto calleval; +#endif + case NFOR: + evalfn = evalfor; + goto calleval; + case NWHILE: + case NUNTIL: + evalfn = evalloop; + goto calleval; + case NSUBSHELL: + case NBACKGND: + evalfn = evalsubshell; + goto calleval; + case NPIPE: + evalfn = evalpipe; +#ifdef notyet + if (eflag && !(flags & EV_TESTED)) + checkexit = ~0; + goto calleval; +#else + goto checkexit; +#endif + case NCASE: + evalfn = evalcase; + goto calleval; + case NAND: + case NOR: + case NSEMI: +#if NAND + 1 != NOR +#error NAND + 1 != NOR +#endif +#if NOR + 1 != NSEMI +#error NOR + 1 != NSEMI +#endif + isor = n->type - NAND; + evaltree( + n->nbinary.ch1, + (flags | ((isor >> 1) - 1)) & EV_TESTED + ); + if (!exitstatus == isor) + break; + if (!evalskip) { + n = n->nbinary.ch2; +evaln: + evalfn = evaltree; +calleval: + evalfn(n, flags); + break; + } + break; + case NIF: + evaltree(n->nif.test, EV_TESTED); + if (evalskip) + break; + if (exitstatus == 0) { + n = n->nif.ifpart; + goto evaln; + } else if (n->nif.elsepart) { + n = n->nif.elsepart; + goto evaln; + } + goto success; + case NDEFUN: + defun(n->narg.text, n->narg.next); +success: + status = 0; +setstatus: + exitstatus = status; + break; + } +out: + if ((checkexit & exitstatus)) + evalskip |= SKIPEVAL; + else if (pendingsigs && dotrap()) + goto exexit; + + if (flags & EV_EXIT) { +exexit: + exraise(EXEXIT); + } +} + + +#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) +STATIC +#endif +void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"))); + + +STATIC void +evalloop(union node *n, int flags) +{ + int status; + + loopnest++; + status = 0; + flags &= EV_TESTED; + for (;;) { + int i; + + evaltree(n->nbinary.ch1, EV_TESTED); + if (evalskip) { +skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { + evalskip = 0; + continue; + } + if (evalskip == SKIPBREAK && --skipcount <= 0) + evalskip = 0; + break; + } + i = exitstatus; + if (n->type != NWHILE) + i = !i; + if (i != 0) + break; + evaltree(n->nbinary.ch2, flags); + status = exitstatus; + if (evalskip) + goto skipping; + } + loopnest--; + exitstatus = status; +} + + + +STATIC void +evalfor(union node *n, int flags) +{ + struct arglist arglist; + union node *argp; + struct strlist *sp; + struct stackmark smark; + + setstackmark(&smark); + arglist.lastp = &arglist.list; + for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { + expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD); + /* XXX */ + if (evalskip) + goto out; + } + *arglist.lastp = NULL; + + exitstatus = 0; + loopnest++; + flags &= EV_TESTED; + for (sp = arglist.list ; sp ; sp = sp->next) { + setvar(n->nfor.var, sp->text, 0); + evaltree(n->nfor.body, flags); + if (evalskip) { + if (evalskip == SKIPCONT && --skipcount <= 0) { + evalskip = 0; + continue; + } + if (evalskip == SKIPBREAK && --skipcount <= 0) + evalskip = 0; + break; + } + } + loopnest--; +out: + popstackmark(&smark); +} + + + +STATIC void +evalcase(union node *n, int flags) +{ + union node *cp; + union node *patp; + struct arglist arglist; + struct stackmark smark; + + setstackmark(&smark); + arglist.lastp = &arglist.list; + expandarg(n->ncase.expr, &arglist, EXP_TILDE); + exitstatus = 0; + for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { + for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { + if (casematch(patp, arglist.list->text)) { + if (evalskip == 0) { + evaltree(cp->nclist.body, flags); + } + goto out; + } + } + } +out: + popstackmark(&smark); +} + + + +/* + * Kick off a subshell to evaluate a tree. + */ + +STATIC void +evalsubshell(union node *n, int flags) +{ + struct job *jp; + int backgnd = (n->type == NBACKGND); + int status; + + expredir(n->nredir.redirect); + if (!backgnd && flags & EV_EXIT && !trap[0]) + goto nofork; + INTOFF; + jp = makejob(n, 1); + if (forkshell(jp, n, backgnd) == 0) { + INTON; + flags |= EV_EXIT; + if (backgnd) + flags &=~ EV_TESTED; +nofork: + redirect(n->nredir.redirect, 0); + evaltreenr(n->nredir.n, flags); + /* never returns */ + } + status = 0; + if (! backgnd) + status = waitforjob(jp); + exitstatus = status; + INTON; +} + + + +/* + * Compute the names of the files in a redirection list. + */ + +STATIC void +expredir(union node *n) +{ + union node *redir; + + for (redir = n ; redir ; redir = redir->nfile.next) { + struct arglist fn; + fn.lastp = &fn.list; + switch (redir->type) { + case NFROMTO: + case NFROM: + case NTO: + case NCLOBBER: + case NAPPEND: + expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); + redir->nfile.expfname = fn.list->text; + break; + case NFROMFD: + case NTOFD: + if (redir->ndup.vname) { + expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); + fixredir(redir, fn.list->text, 1); + } + break; + } + } +} + + + +/* + * Evaluate a pipeline. All the processes in the pipeline are children + * of the process creating the pipeline. (This differs from some versions + * of the shell, which make the last process in a pipeline the parent + * of all the rest.) + */ + +STATIC void +evalpipe(union node *n, int flags) +{ + struct job *jp; + struct nodelist *lp; + int pipelen; + int prevfd; + int pip[2]; + + TRACE(("evalpipe(0x%lx) called\n", (long)n)); + pipelen = 0; + for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) + pipelen++; + flags |= EV_EXIT; + INTOFF; + jp = makejob(n, pipelen); + prevfd = -1; + for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { + prehash(lp->n); + pip[1] = -1; + if (lp->next) { + if (pipe(pip) < 0) { + close(prevfd); + sh_error("Pipe call failed"); + } + } + if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { + INTON; + if (pip[1] >= 0) { + close(pip[0]); + } + if (prevfd > 0) { + dup2(prevfd, 0); + close(prevfd); + } + if (pip[1] > 1) { + dup2(pip[1], 1); + close(pip[1]); + } + evaltreenr(lp->n, flags); + /* never returns */ + } + if (prevfd >= 0) + close(prevfd); + prevfd = pip[0]; + close(pip[1]); + } + if (n->npipe.backgnd == 0) { + exitstatus = waitforjob(jp); + TRACE(("evalpipe: job done exit status %d\n", exitstatus)); + } + INTON; +} + + + +/* + * Execute a command inside back quotes. If it's a builtin command, we + * want to save its output in a block obtained from malloc. Otherwise + * we fork off a subprocess and get the output of the command via a pipe. + * Should be called with interrupts off. + */ + +void +evalbackcmd(union node *n, struct backcmd *result) +{ + int saveherefd; + + result->fd = -1; + result->buf = NULL; + result->nleft = 0; + result->jp = NULL; + if (n == NULL) { + goto out; + } + + saveherefd = herefd; + herefd = -1; + +#ifdef notyet + /* + * For now we disable executing builtins in the same + * context as the shell, because we are not keeping + * enough state to recover from changes that are + * supposed only to affect subshells. eg. echo "`cd /`" + */ + if (n->type == NCMD) { + struct ifsregion saveifs; + struct ifsregion *savelastp; + struct nodelist *saveargbackq; + + saveifs = ifsfirst; + savelastp = ifslastp; + saveargbackq = argbackq; + + exitstatus = oexitstatus; + evalcommand(n, EV_BACKCMD, result); + + ifsfirst = saveifs; + ifslastp = savelastp; + argbackq = saveargbackq; + } else +#endif + { + int pip[2]; + struct job *jp; + + if (pipe(pip) < 0) + sh_error("Pipe call failed"); + jp = makejob(n, 1); + if (forkshell(jp, n, FORK_NOJOB) == 0) { + FORCEINTON; + close(pip[0]); + if (pip[1] != 1) { + close(1); + copyfd(pip[1], 1); + close(pip[1]); + } + eflag = 0; + evaltreenr(n, EV_EXIT); + /* NOTREACHED */ + } + close(pip[1]); + result->fd = pip[0]; + result->jp = jp; + } + herefd = saveherefd; +out: + TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", + result->fd, result->buf, result->nleft, result->jp)); +} + +static char ** +parse_command_args(char **argv, const char **path) +{ + char *cp, c; + + for (;;) { + cp = *++argv; + if (!cp) + return 0; + if (*cp++ != '-') + break; + if (!(c = *cp++)) + break; + if (c == '-' && !*cp) { + argv++; + break; + } + do { + switch (c) { + case 'p': + *path = defpath; + break; + default: + /* run 'typecmd' for other options */ + return 0; + } + } while ((c = *cp++)); + } + return argv; +} + + + +/* + * Execute a simple command. + */ + +STATIC void +#ifdef notyet +evalcommand(union node *cmd, int flags, struct backcmd *backcmd) +#else +evalcommand(union node *cmd, int flags) +#endif +{ + struct stackmark smark; + union node *argp; + struct arglist arglist; + struct arglist varlist; + char **argv; + int argc; + struct strlist *sp; +#ifdef notyet + int pip[2]; +#endif + struct cmdentry cmdentry; + struct job *jp; + char *lastarg; + const char *path; + int spclbltin; + int execcmd; + int status; + char **nargv; + + /* First expand the arguments. */ + TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); + setstackmark(&smark); + back_exitstatus = 0; + + cmdentry.cmdtype = CMDBUILTIN; + cmdentry.u.cmd = &bltin; + varlist.lastp = &varlist.list; + *varlist.lastp = NULL; + arglist.lastp = &arglist.list; + *arglist.lastp = NULL; + + argc = 0; + for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) { + struct strlist **spp; + + spp = arglist.lastp; + expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); + for (sp = *spp; sp; sp = sp->next) + argc++; + } + + argv = nargv = stalloc(sizeof (char *) * (argc + 1)); + for (sp = arglist.list ; sp ; sp = sp->next) { + TRACE(("evalcommand arg: %s\n", sp->text)); + *nargv++ = sp->text; + } + *nargv = NULL; + + lastarg = NULL; + if (iflag && funcnest == 0 && argc > 0) + lastarg = nargv[-1]; + + preverrout.fd = 2; + expredir(cmd->ncmd.redirect); + status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2); + + path = vpath.text; + for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { + struct strlist **spp; + char *p; + + spp = varlist.lastp; + expandarg(argp, &varlist, EXP_VARTILDE); + + /* + * Modify the command lookup path, if a PATH= assignment + * is present + */ + p = (*spp)->text; + if (varequal(p, path)) + path = p; + } + + /* Print the command if xflag is set. */ + if (xflag) { + struct output *out; + int sep; + + out = &preverrout; + outstr(expandstr(ps4val()), out); + sep = 0; + sep = eprintlist(out, varlist.list, sep); + eprintlist(out, arglist.list, sep); + outcslow('\n', out); +#ifdef FLUSHERR + flushout(out); +#endif + } + + execcmd = 0; + spclbltin = -1; + + /* Now locate the command. */ + if (argc) { + const char *oldpath; + int cmd_flag = DO_ERR; + + path += 5; + oldpath = path; + for (;;) { + find_command(argv[0], &cmdentry, cmd_flag, path); + if (cmdentry.cmdtype == CMDUNKNOWN) { + status = 127; +#ifdef FLUSHERR + flushout(&errout); +#endif + goto bail; + } + + /* implement bltin and command here */ + if (cmdentry.cmdtype != CMDBUILTIN) + break; + if (spclbltin < 0) + spclbltin = + cmdentry.u.cmd->flags & + BUILTIN_SPECIAL + ; + if (cmdentry.u.cmd == EXECCMD) + execcmd++; + if (cmdentry.u.cmd != COMMANDCMD) + break; + + path = oldpath; + nargv = parse_command_args(argv, &path); + if (!nargv) + break; + argc -= nargv - argv; + argv = nargv; + cmd_flag |= DO_NOFUNC; + } + } + + if (status) { + /* We have a redirection error. */ + if (spclbltin > 0) + exraise(EXERROR); +bail: + exitstatus = status; + goto out; + } + + /* Execute the command. */ + switch (cmdentry.cmdtype) { + default: + /* Fork off a child process if necessary. */ + if (!(flags & EV_EXIT) || trap[0]) { + INTOFF; + jp = makejob(cmd, 1); + if (forkshell(jp, cmd, FORK_FG) != 0) { + exitstatus = waitforjob(jp); + INTON; + break; + } + FORCEINTON; + } + listsetvar(varlist.list, VEXPORT|VSTACK); + shellexec(argv, path, cmdentry.u.index); + /* NOTREACHED */ + + case CMDBUILTIN: + cmdenviron = varlist.list; + if (cmdenviron) { + struct strlist *list = cmdenviron; + int i = VNOSET; + if (spclbltin > 0 || argc == 0) { + i = 0; + if (execcmd && argc > 1) + i = VEXPORT; + } + listsetvar(list, i); + } + if (evalbltin(cmdentry.u.cmd, argc, argv)) { + int status; + int i, j; + + i = exception; + if (i == EXEXIT) + goto raise; + + status = 2; + j = 0; + if (i == EXINT) + j = SIGINT; + if (i == EXSIG) + j = pendingsigs; + if (j) + status = j + 128; + exitstatus = status; + + if (i == EXINT || spclbltin > 0) { +raise: + longjmp(handler->loc, 1); + } + FORCEINTON; + } + break; + + case CMDFUNCTION: + listsetvar(varlist.list, 0); + if (evalfun(cmdentry.u.func, argc, argv, flags)) + goto raise; + break; + } + +out: + popredir(execcmd); + if (lastarg) + /* dsl: I think this is intended to be used to support + * '_' in 'vi' command mode during line editing... + * However I implemented that within libedit itself. + */ + setvar("_", lastarg, 0); + popstackmark(&smark); +} + +STATIC int +evalbltin(const struct builtincmd *cmd, int argc, char **argv) { + char *volatile savecmdname; + struct jmploc *volatile savehandler; + struct jmploc jmploc; + int i; + + savecmdname = commandname; + if ((i = setjmp(jmploc.loc))) + goto cmddone; + savehandler = handler; + handler = &jmploc; + commandname = argv[0]; + argptr = argv + 1; + optptr = NULL; /* initialize nextopt */ + exitstatus = (*cmd->builtin)(argc, argv); + flushall(); +cmddone: + exitstatus |= outerr(out1); + freestdout(); + commandname = savecmdname; + exsig = 0; + handler = savehandler; + + return i; +} + +STATIC int +evalfun(struct funcnode *func, int argc, char **argv, int flags) +{ + volatile struct shparam saveparam; + struct localvar *volatile savelocalvars; + struct jmploc *volatile savehandler; + struct jmploc jmploc; + int e; + + saveparam = shellparam; + savelocalvars = localvars; + if ((e = setjmp(jmploc.loc))) { + goto funcdone; + } + INTOFF; + savehandler = handler; + handler = &jmploc; + localvars = NULL; + shellparam.malloc = 0; + func->count++; + funcnest++; + INTON; + shellparam.nparam = argc - 1; + shellparam.p = argv + 1; + shellparam.optind = 1; + shellparam.optoff = -1; + evaltree(&func->n, flags & EV_TESTED); +funcdone: + INTOFF; + funcnest--; + freefunc(func); + poplocalvars(); + localvars = savelocalvars; + freeparam(&shellparam); + shellparam = saveparam; + handler = savehandler; + INTON; + evalskip &= ~SKIPFUNC; + return e; +} + + +/* + * Search for a command. This is called before we fork so that the + * location of the command will be available in the parent as well as + * the child. The check for "goodname" is an overly conservative + * check that the name will not be subject to expansion. + */ + +STATIC void +prehash(union node *n) +{ + struct cmdentry entry; + + if (n->type == NCMD && n->ncmd.args) + if (goodname(n->ncmd.args->narg.text)) + find_command(n->ncmd.args->narg.text, &entry, 0, + pathval()); +} + + + +/* + * Builtin commands. Builtin commands whose functions are closely + * tied to evaluation are implemented here. + */ + +/* + * No command given. + */ + +STATIC int +bltincmd(int argc, char **argv) +{ + /* + * Preserve exitstatus of a previous possible redirection + * as POSIX mandates + */ + return back_exitstatus; +} + + +/* + * Handle break and continue commands. Break, continue, and return are + * all handled by setting the evalskip flag. The evaluation routines + * above all check this flag, and if it is set they start skipping + * commands rather than executing them. The variable skipcount is + * the number of loops to break/continue, or the number of function + * levels to return. (The latter is always 1.) It should probably + * be an error to break out of more loops than exist, but it isn't + * in the standard shell so we don't make it one here. + */ + +int +breakcmd(int argc, char **argv) +{ + int n = argc > 1 ? number(argv[1]) : 1; + + if (n <= 0) + sh_error(illnum, argv[1]); + if (n > loopnest) + n = loopnest; + if (n > 0) { + evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; + skipcount = n; + } + return 0; +} + + +/* + * The return command. + */ + +int +returncmd(int argc, char **argv) +{ + /* + * If called outside a function, do what ksh does; + * skip the rest of the file. + */ + evalskip = funcnest ? SKIPFUNC : SKIPFILE; + return argv[1] ? number(argv[1]) : exitstatus; +} + + +int +falsecmd(int argc, char **argv) +{ + return 1; +} + + +int +truecmd(int argc, char **argv) +{ + return 0; +} + + +int +execcmd(int argc, char **argv) +{ + if (argc > 1) { + iflag = 0; /* exit on error */ + mflag = 0; + optschanged(); + shellexec(argv + 1, pathval(), 0); + } + return 0; +} + + +STATIC int +eprintlist(struct output *out, struct strlist *sp, int sep) +{ + while (sp) { + const char *p; + + p = " %s" + (1 - sep); + sep |= 1; + outfmt(out, p, sp->text); + sp = sp->next; + } + + return sep; +} diff -puN /dev/null usr/dash/eval.h --- /dev/null +++ a/usr/dash/eval.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)eval.h 8.2 (Berkeley) 5/4/95 + */ + +extern char *commandname; /* currently executing command */ +extern int exitstatus; /* exit status of last command */ +extern int back_exitstatus; /* exit status of backquoted command */ +extern struct strlist *cmdenviron; /* environment for builtin command */ + + +struct backcmd { /* result of evalbackcmd */ + int fd; /* file descriptor to read from */ + char *buf; /* buffer */ + int nleft; /* number of chars in buffer */ + struct job *jp; /* job structure for command */ +}; + +int evalstring(char *, int); +union node; /* BLETCH for ansi C */ +void evaltree(union node *, int); +void evalbackcmd(union node *, struct backcmd *); + +extern int evalskip; + +/* reasons for skipping commands (see comment on breakcmd routine) */ +#define SKIPBREAK (1 << 0) +#define SKIPCONT (1 << 1) +#define SKIPFUNC (1 << 2) +#define SKIPFILE (1 << 3) +#define SKIPEVAL (1 << 4) diff -puN /dev/null usr/dash/exec.c --- /dev/null +++ a/usr/dash/exec.c @@ -0,0 +1,869 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +/* + * When commands are first encountered, they are entered in a hash table. + * This ensures that a full path search will not have to be done for them + * on each invocation. + * + * We should investigate converting to a linear search, even though that + * would make the command name "hash" a misnomer. + */ + +#include "shell.h" +#include "main.h" +#include "nodes.h" +#include "parser.h" +#include "redir.h" +#include "eval.h" +#include "exec.h" +#include "builtins.h" +#include "var.h" +#include "options.h" +#include "output.h" +#include "syntax.h" +#include "memalloc.h" +#include "error.h" +#include "init.h" +#include "mystring.h" +#include "show.h" +#include "jobs.h" +#include "alias.h" +#include "system.h" + + +#define CMDTABLESIZE 31 /* should be prime */ +#define ARB 1 /* actual size determined at run time */ + + + +struct tblentry { + struct tblentry *next; /* next entry in hash chain */ + union param param; /* definition of builtin function */ + short cmdtype; /* index identifying command */ + char rehash; /* if set, cd done since entry created */ + char cmdname[ARB]; /* name of command */ +}; + + +STATIC struct tblentry *cmdtable[CMDTABLESIZE]; +STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */ + + +STATIC void tryexec(char *, char **, char **); +STATIC void printentry(struct tblentry *); +STATIC void clearcmdentry(int); +STATIC struct tblentry *cmdlookup(const char *, int); +STATIC void delete_cmd_entry(void); +STATIC void addcmdentry(char *, struct cmdentry *); +STATIC int describe_command(struct output *, char *, int); + + +/* + * Exec a program. Never returns. If you change this routine, you may + * have to change the find_command routine as well. + */ + +void +shellexec(char **argv, const char *path, int idx) +{ + char *cmdname; + int e; + char **envp; + int exerrno; + + clearredir(1); + envp = environment(); + if (strchr(argv[0], '/') != NULL) { + tryexec(argv[0], argv, envp); + e = errno; + } else { + e = ENOENT; + while ((cmdname = padvance(&path, argv[0])) != NULL) { + if (--idx < 0 && pathopt == NULL) { + tryexec(cmdname, argv, envp); + if (errno != ENOENT && errno != ENOTDIR) + e = errno; + } + stunalloc(cmdname); + } + } + + /* Map to POSIX errors */ + switch (e) { + case EACCES: + exerrno = 126; + break; + case ENOENT: + exerrno = 127; + break; + default: + exerrno = 2; + break; + } + exitstatus = exerrno; + TRACE(("shellexec failed for %s, errno %d, suppressint %d\n", + argv[0], e, suppressint )); + exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC)); + /* NOTREACHED */ +} + + +STATIC void +tryexec(char *cmd, char **argv, char **envp) +{ + int repeated = 0; +#if !defined(BSD) && !defined(linux) + char *p; +#endif + +repeat: +#ifdef SYSV + do { + execve(cmd, argv, envp); + } while (errno == EINTR); +#else + execve(cmd, argv, envp); +#endif + if (repeated++) { + ckfree(argv); + } else if (errno == ENOEXEC) { + char **ap; + char **new; + + for (ap = argv; *ap; ap++) + ; + ap = new = ckmalloc((ap - argv + 2) * sizeof(char *)); + *ap++ = cmd = _PATH_BSHELL; + while ((*ap++ = *argv++)) + ; + argv = new; + goto repeat; + } +} + + + +/* + * Do a path search. The variable path (passed by reference) should be + * set to the start of the path before the first call; padvance will update + * this value as it proceeds. Successive calls to padvance will return + * the possible path expansions in sequence. If an option (indicated by + * a percent sign) appears in the path entry then the global variable + * pathopt will be set to point to it; otherwise pathopt will be set to + * NULL. + */ + +const char *pathopt; + +char * +padvance(const char **path, const char *name) +{ + const char *p; + char *q; + const char *start; + size_t len; + + if (*path == NULL) + return NULL; + start = *path; + for (p = start ; *p && *p != ':' && *p != '%' ; p++); + len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ + while (stackblocksize() < len) + growstackblock(); + q = stackblock(); + if (p != start) { + memcpy(q, start, p - start); + q += p - start; + *q++ = '/'; + } + strcpy(q, name); + pathopt = NULL; + if (*p == '%') { + pathopt = ++p; + while (*p && *p != ':') p++; + } + if (*p == ':') + *path = p + 1; + else + *path = NULL; + return stalloc(len); +} + + + +/*** Command hashing code ***/ + + +int +hashcmd(int argc, char **argv) +{ + struct tblentry **pp; + struct tblentry *cmdp; + int c; + struct cmdentry entry; + char *name; + + while ((c = nextopt("r")) != '\0') { + clearcmdentry(0); + return 0; + } + if (*argptr == NULL) { + for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { + for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { + if (cmdp->cmdtype == CMDNORMAL) + printentry(cmdp); + } + } + return 0; + } + c = 0; + while ((name = *argptr) != NULL) { + if ((cmdp = cmdlookup(name, 0)) != NULL + && (cmdp->cmdtype == CMDNORMAL + || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))) + delete_cmd_entry(); + find_command(name, &entry, DO_ERR, pathval()); + if (entry.cmdtype == CMDUNKNOWN) + c = 1; + argptr++; + } + return c; +} + + +STATIC void +printentry(struct tblentry *cmdp) +{ + int idx; + const char *path; + char *name; + + idx = cmdp->param.index; + path = pathval(); + do { + name = padvance(&path, cmdp->cmdname); + stunalloc(name); + } while (--idx >= 0); + out1str(name); + out1fmt(snlfmt, cmdp->rehash ? "*" : nullstr); +} + + + +/* + * Resolve a command name. If you change this routine, you may have to + * change the shellexec routine as well. + */ + +void +find_command(char *name, struct cmdentry *entry, int act, const char *path) +{ + struct tblentry *cmdp; + int idx; + int prev; + char *fullname; + struct stat64 statb; + int e; + int updatetbl; + struct builtincmd *bcmd; + + /* If name contains a slash, don't use PATH or hash table */ + if (strchr(name, '/') != NULL) { + entry->u.index = -1; + if (act & DO_ABS) { + while (stat64(name, &statb) < 0) { +#ifdef SYSV + if (errno == EINTR) + continue; +#endif + entry->cmdtype = CMDUNKNOWN; + return; + } + } + entry->cmdtype = CMDNORMAL; + return; + } + + updatetbl = (path == pathval()); + if (!updatetbl) { + act |= DO_ALTPATH; + if (strstr(path, "%builtin") != NULL) + act |= DO_ALTBLTIN; + } + + /* If name is in the table, check answer will be ok */ + if ((cmdp = cmdlookup(name, 0)) != NULL) { + int bit; + + switch (cmdp->cmdtype) { + default: +#if DEBUG + abort(); +#endif + case CMDNORMAL: + bit = DO_ALTPATH; + break; + case CMDFUNCTION: + bit = DO_NOFUNC; + break; + case CMDBUILTIN: + bit = DO_ALTBLTIN; + break; + } + if (act & bit) { + updatetbl = 0; + cmdp = NULL; + } else if (cmdp->rehash == 0) + /* if not invalidated by cd, we're done */ + goto success; + } + + /* If %builtin not in path, check for builtin next */ + bcmd = find_builtin(name); + if (bcmd && (bcmd->flags & BUILTIN_REGULAR || ( + act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0 + ))) + goto builtin_success; + + /* We have to search path. */ + prev = -1; /* where to start */ + if (cmdp && cmdp->rehash) { /* doing a rehash */ + if (cmdp->cmdtype == CMDBUILTIN) + prev = builtinloc; + else + prev = cmdp->param.index; + } + + e = ENOENT; + idx = -1; +loop: + while ((fullname = padvance(&path, name)) != NULL) { + stunalloc(fullname); + idx++; + if (pathopt) { + if (prefix(pathopt, "builtin")) { + if (bcmd) + goto builtin_success; + continue; + } else if (!(act & DO_NOFUNC) && + prefix(pathopt, "func")) { + /* handled below */ + } else { + /* ignore unimplemented options */ + continue; + } + } + /* if rehash, don't redo absolute path names */ + if (fullname[0] == '/' && idx <= prev) { + if (idx < prev) + continue; + TRACE(("searchexec \"%s\": no change\n", name)); + goto success; + } + while (stat64(fullname, &statb) < 0) { +#ifdef SYSV + if (errno == EINTR) + continue; +#endif + if (errno != ENOENT && errno != ENOTDIR) + e = errno; + goto loop; + } + e = EACCES; /* if we fail, this will be the error */ + if (!S_ISREG(statb.st_mode)) + continue; + if (pathopt) { /* this is a %func directory */ + stalloc(strlen(fullname) + 1); + readcmdfile(fullname); + if ((cmdp = cmdlookup(name, 0)) == NULL || + cmdp->cmdtype != CMDFUNCTION) + sh_error("%s not defined in %s", name, + fullname); + stunalloc(fullname); + goto success; + } +#ifdef notdef + /* XXX this code stops root executing stuff, and is buggy + if you need a group from the group list. */ + if (statb.st_uid == geteuid()) { + if ((statb.st_mode & 0100) == 0) + goto loop; + } else if (statb.st_gid == getegid()) { + if ((statb.st_mode & 010) == 0) + goto loop; + } else { + if ((statb.st_mode & 01) == 0) + goto loop; + } +#endif + TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); + if (!updatetbl) { + entry->cmdtype = CMDNORMAL; + entry->u.index = idx; + return; + } + INTOFF; + cmdp = cmdlookup(name, 1); + cmdp->cmdtype = CMDNORMAL; + cmdp->param.index = idx; + INTON; + goto success; + } + + /* We failed. If there was an entry for this command, delete it */ + if (cmdp && updatetbl) + delete_cmd_entry(); + if (act & DO_ERR) + sh_warnx("%s: %s", name, errmsg(e, E_EXEC)); + entry->cmdtype = CMDUNKNOWN; + return; + +builtin_success: + if (!updatetbl) { + entry->cmdtype = CMDBUILTIN; + entry->u.cmd = bcmd; + return; + } + INTOFF; + cmdp = cmdlookup(name, 1); + cmdp->cmdtype = CMDBUILTIN; + cmdp->param.cmd = bcmd; + INTON; +success: + cmdp->rehash = 0; + entry->cmdtype = cmdp->cmdtype; + entry->u = cmdp->param; +} + + + +/* + * Search the table of builtin commands. + */ + +struct builtincmd * +find_builtin(const char *name) +{ + struct builtincmd *bp; + + bp = bsearch( + &name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd), + pstrcmp + ); + return bp; +} + + + +/* + * Called when a cd is done. Marks all commands so the next time they + * are executed they will be rehashed. + */ + +void +hashcd(void) +{ + struct tblentry **pp; + struct tblentry *cmdp; + + for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { + for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { + if (cmdp->cmdtype == CMDNORMAL || ( + cmdp->cmdtype == CMDBUILTIN && + !(cmdp->param.cmd->flags & BUILTIN_REGULAR) && + builtinloc > 0 + )) + cmdp->rehash = 1; + } + } +} + + + +/* + * Fix command hash table when PATH changed. + * Called before PATH is changed. The argument is the new value of PATH; + * pathval() still returns the old value at this point. + * Called with interrupts off. + */ + +void +changepath(const char *newval) +{ + const char *old, *new; + int idx; + int firstchange; + int bltin; + + old = pathval(); + new = newval; + firstchange = 9999; /* assume no change */ + idx = 0; + bltin = -1; + for (;;) { + if (*old != *new) { + firstchange = idx; + if ((*old == '\0' && *new == ':') + || (*old == ':' && *new == '\0')) + firstchange++; + old = new; /* ignore subsequent differences */ + } + if (*new == '\0') + break; + if (*new == '%' && bltin < 0 && prefix(new + 1, "builtin")) + bltin = idx; + if (*new == ':') { + idx++; + } + new++, old++; + } + if (builtinloc < 0 && bltin >= 0) + builtinloc = bltin; /* zap builtins */ + if (builtinloc >= 0 && bltin < 0) + firstchange = 0; + clearcmdentry(firstchange); + builtinloc = bltin; +} + + +/* + * Clear out command entries. The argument specifies the first entry in + * PATH which has changed. + */ + +STATIC void +clearcmdentry(int firstchange) +{ + struct tblentry **tblp; + struct tblentry **pp; + struct tblentry *cmdp; + + INTOFF; + for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { + pp = tblp; + while ((cmdp = *pp) != NULL) { + if ((cmdp->cmdtype == CMDNORMAL && + cmdp->param.index >= firstchange) + || (cmdp->cmdtype == CMDBUILTIN && + builtinloc >= firstchange)) { + *pp = cmdp->next; + ckfree(cmdp); + } else { + pp = &cmdp->next; + } + } + } + INTON; +} + + + +/* + * Locate a command in the command hash table. If "add" is nonzero, + * add the command to the table if it is not already present. The + * variable "lastcmdentry" is set to point to the address of the link + * pointing to the entry, so that delete_cmd_entry can delete the + * entry. + * + * Interrupts must be off if called with add != 0. + */ + +struct tblentry **lastcmdentry; + + +STATIC struct tblentry * +cmdlookup(const char *name, int add) +{ + unsigned int hashval; + const char *p; + struct tblentry *cmdp; + struct tblentry **pp; + + p = name; + hashval = (unsigned char)*p << 4; + while (*p) + hashval += (unsigned char)*p++; + hashval &= 0x7FFF; + pp = &cmdtable[hashval % CMDTABLESIZE]; + for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { + if (equal(cmdp->cmdname, name)) + break; + pp = &cmdp->next; + } + if (add && cmdp == NULL) { + cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB + + strlen(name) + 1); + cmdp->next = NULL; + cmdp->cmdtype = CMDUNKNOWN; + strcpy(cmdp->cmdname, name); + } + lastcmdentry = pp; + return cmdp; +} + +/* + * Delete the command entry returned on the last lookup. + */ + +STATIC void +delete_cmd_entry(void) +{ + struct tblentry *cmdp; + + INTOFF; + cmdp = *lastcmdentry; + *lastcmdentry = cmdp->next; + if (cmdp->cmdtype == CMDFUNCTION) + freefunc(cmdp->param.func); + ckfree(cmdp); + INTON; +} + + + +#ifdef notdef +void +getcmdentry(char *name, struct cmdentry *entry) +{ + struct tblentry *cmdp = cmdlookup(name, 0); + + if (cmdp) { + entry->u = cmdp->param; + entry->cmdtype = cmdp->cmdtype; + } else { + entry->cmdtype = CMDUNKNOWN; + entry->u.index = 0; + } +} +#endif + + +/* + * Add a new command entry, replacing any existing command entry for + * the same name - except special builtins. + */ + +STATIC void +addcmdentry(char *name, struct cmdentry *entry) +{ + struct tblentry *cmdp; + + cmdp = cmdlookup(name, 1); + if (cmdp->cmdtype == CMDFUNCTION) { + freefunc(cmdp->param.func); + } + cmdp->cmdtype = entry->cmdtype; + cmdp->param = entry->u; + cmdp->rehash = 0; +} + + +/* + * Define a shell function. + */ + +void +defun(char *name, union node *func) +{ + struct cmdentry entry; + + INTOFF; + entry.cmdtype = CMDFUNCTION; + entry.u.func = copyfunc(func); + addcmdentry(name, &entry); + INTON; +} + + +/* + * Delete a function if it exists. + */ + +void +unsetfunc(const char *name) +{ + struct tblentry *cmdp; + + if ((cmdp = cmdlookup(name, 0)) != NULL && + cmdp->cmdtype == CMDFUNCTION) + delete_cmd_entry(); +} + +/* + * Locate and print what a word is... + */ + +int +typecmd(int argc, char **argv) +{ + int i; + int err = 0; + + for (i = 1; i < argc; i++) { + err |= describe_command(out1, argv[i], 1); + } + return err; +} + +STATIC int +describe_command(out, command, verbose) + struct output *out; + char *command; + int verbose; +{ + struct cmdentry entry; + struct tblentry *cmdp; + const struct alias *ap; + const char *path = pathval(); + + if (verbose) { + outstr(command, out); + } + + /* First look at the keywords */ + if (findkwd(command)) { + outstr(verbose ? " is a shell keyword" : command, out); + goto out; + } + + /* Then look at the aliases */ + if ((ap = lookupalias(command, 0)) != NULL) { + if (verbose) { + outfmt(out, " is an alias for %s", ap->val); + } else { + outstr("alias ", out); + printalias(ap); + return 0; + } + goto out; + } + + /* Then check if it is a tracked alias */ + if ((cmdp = cmdlookup(command, 0)) != NULL) { + entry.cmdtype = cmdp->cmdtype; + entry.u = cmdp->param; + } else { + /* Finally use brute force */ + find_command(command, &entry, DO_ABS, path); + } + + switch (entry.cmdtype) { + case CMDNORMAL: { + int j = entry.u.index; + char *p; + if (j == -1) { + p = command; + } else { + do { + p = padvance(&path, command); + stunalloc(p); + } while (--j >= 0); + } + if (verbose) { + outfmt( + out, " is%s %s", + cmdp ? " a tracked alias for" : nullstr, p + ); + } else { + outstr(p, out); + } + break; + } + + case CMDFUNCTION: + if (verbose) { + outstr(" is a shell function", out); + } else { + outstr(command, out); + } + break; + + case CMDBUILTIN: + if (verbose) { + outfmt( + out, " is a %sshell builtin", + entry.u.cmd->flags & BUILTIN_SPECIAL ? + "special " : nullstr + ); + } else { + outstr(command, out); + } + break; + + default: + if (verbose) { + outstr(": not found\n", out); + } + return 127; + } + +out: + outc('\n', out); + return 0; +} + +int +commandcmd(argc, argv) + int argc; + char **argv; +{ + int c; + enum { + VERIFY_BRIEF = 1, + VERIFY_VERBOSE = 2, + } verify = 0; + + while ((c = nextopt("pvV")) != '\0') + if (c == 'V') + verify |= VERIFY_VERBOSE; + else if (c == 'v') + verify |= VERIFY_BRIEF; +#ifdef DEBUG + else if (c != 'p') + abort(); +#endif + + if (verify) + return describe_command(out1, *argptr, verify - VERIFY_BRIEF); + + return 0; +} diff -puN /dev/null usr/dash/exec.h --- /dev/null +++ a/usr/dash/exec.h @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)exec.h 8.3 (Berkeley) 6/8/95 + */ + +/* values of cmdtype */ +#define CMDUNKNOWN -1 /* no entry in table for command */ +#define CMDNORMAL 0 /* command is an executable program */ +#define CMDFUNCTION 1 /* command is a shell function */ +#define CMDBUILTIN 2 /* command is a shell builtin */ + + +struct cmdentry { + int cmdtype; + union param { + int index; + const struct builtincmd *cmd; + struct funcnode *func; + } u; +}; + + +/* action to find_command() */ +#define DO_ERR 0x01 /* prints errors */ +#define DO_ABS 0x02 /* checks absolute paths */ +#define DO_NOFUNC 0x04 /* don't return shell functions, for command */ +#define DO_ALTPATH 0x08 /* using alternate path */ +#define DO_ALTBLTIN 0x20 /* %builtin in alt. path */ + +extern const char *pathopt; /* set by padvance */ + +void shellexec(char **, const char *, int) + __attribute__((__noreturn__)); +char *padvance(const char **, const char *); +int hashcmd(int, char **); +void find_command(char *, struct cmdentry *, int, const char *); +struct builtincmd *find_builtin(const char *); +void hashcd(void); +void changepath(const char *); +#ifdef notdef +void getcmdentry(char *, struct cmdentry *); +#endif +void defun(char *, union node *); +void unsetfunc(const char *); +int typecmd(int, char **); +int commandcmd(int, char **); diff -puN /dev/null usr/dash/expand.c --- /dev/null +++ a/usr/dash/expand.c @@ -0,0 +1,1744 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#ifdef HAVE_GETPWNAM +#include +#endif +#include +#include +#include +#include +#if defined(__GLIBC__) +#if !defined(FNMATCH_BROKEN) +#include +#if !defined(GLOB_BROKEN) +#include +#endif +#else +#include +#endif +#endif + +/* + * Routines to expand arguments to commands. We have to deal with + * backquotes, shell variables, and file metacharacters. + */ + +#include "shell.h" +#include "main.h" +#include "nodes.h" +#include "eval.h" +#include "expand.h" +#include "syntax.h" +#include "parser.h" +#include "jobs.h" +#include "options.h" +#include "var.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "mystring.h" +#include "show.h" +#include "system.h" + +/* + * _rmescape() flags + */ +#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */ +#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ +#define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */ +#define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ +#define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ + +/* Add CTLESC when necessary. */ +#define QUOTES_ESC (EXP_FULL | EXP_CASE) +/* Do not skip NUL characters. */ +#define QUOTES_KEEPNUL EXP_TILDE + +/* + * Structure specifying which parts of the string should be searched + * for IFS characters. + */ + +struct ifsregion { + struct ifsregion *next; /* next region in list */ + int begoff; /* offset of start of region */ + int endoff; /* offset of end of region */ + int nulonly; /* search for nul bytes only */ +}; + +/* output of current string */ +static char *expdest; +/* list of back quote expressions */ +static struct nodelist *argbackq; +/* first struct in list of ifs regions */ +static struct ifsregion ifsfirst; +/* last struct in list */ +static struct ifsregion *ifslastp; +/* holds expanded arg list */ +static struct arglist exparg; + +STATIC void argstr(char *, int); +STATIC char *exptilde(char *, char *, int); +STATIC void expbackq(union node *, int, int); +STATIC const char *subevalvar(char *, char *, int, int, int, int, int); +STATIC char *evalvar(char *, int); +STATIC size_t strtodest(const char *, const char *, int); +STATIC void memtodest(const char *, size_t, const char *, int); +STATIC ssize_t varvalue(char *, int, int); +STATIC void recordregion(int, int, int); +STATIC void removerecordregions(int); +STATIC void ifsbreakup(char *, struct arglist *); +STATIC void ifsfree(void); +STATIC void expandmeta(struct strlist *, int); +#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) +STATIC void addglob(const glob_t *); +#else +STATIC void expmeta(char *, char *); +#endif +STATIC void addfname(char *); +#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) +STATIC struct strlist *expsort(struct strlist *); +STATIC struct strlist *msort(struct strlist *, int); +#endif +STATIC int patmatch(char *, const char *); +#if !defined(__GLIBC__) || defined(FNMATCH_BROKEN) +STATIC int pmatch(const char *, const char *); +#else +#define pmatch(a, b) !fnmatch((a), (b), 0) +#endif +STATIC int cvtnum(long); +STATIC size_t esclen(const char *, const char *); +STATIC char *scanleft(char *, char *, char *, char *, int, int); +STATIC char *scanright(char *, char *, char *, char *, int, int); +STATIC void varunset(const char *, const char *, const char *, int) + __attribute__((__noreturn__)); + + +/* + * Prepare a pattern for a glob(3) call. + * + * Returns an stalloced string. + */ + +STATIC inline char * +preglob(const char *pattern, int quoted, int flag) { + flag |= RMESCAPE_GLOB; + if (quoted) { + flag |= RMESCAPE_QUOTED; + } + return _rmescapes((char *)pattern, flag); +} + + +STATIC size_t +esclen(const char *start, const char *p) { + size_t esc = 0; + + while (p > start && *--p == (char)CTLESC) { + esc++; + } + return esc; +} + + +static inline const char *getpwhome(const char *name) +{ +#ifdef HAVE_GETPWNAM + struct passwd *pw = getpwnam(name); + return pw ? pw->pw_dir : 0; +#else + return 0; +#endif +} + + +/* + * Expand shell variables and backquotes inside a here document. + */ + +void +expandhere(union node *arg, int fd) +{ + herefd = fd; + expandarg(arg, (struct arglist *)NULL, 0); + xwrite(fd, stackblock(), expdest - (char *)stackblock()); +} + + +/* + * Perform variable substitution and command substitution on an argument, + * placing the resulting list of arguments in arglist. If EXP_FULL is true, + * perform splitting and file name expansion. When arglist is NULL, perform + * here document expansion. + */ + +void +expandarg(union node *arg, struct arglist *arglist, int flag) +{ + struct strlist *sp; + char *p; + + argbackq = arg->narg.backquote; + STARTSTACKSTR(expdest); + ifsfirst.next = NULL; + ifslastp = NULL; + argstr(arg->narg.text, flag); + p = _STPUTC('\0', expdest); + expdest = p - 1; + if (arglist == NULL) { + return; /* here document expanded */ + } + p = grabstackstr(p); + exparg.lastp = &exparg.list; + /* + * TODO - EXP_REDIR + */ + if (flag & EXP_FULL) { + ifsbreakup(p, &exparg); + *exparg.lastp = NULL; + exparg.lastp = &exparg.list; + expandmeta(exparg.list, flag); + } else { + if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ + rmescapes(p); + sp = (struct strlist *)stalloc(sizeof (struct strlist)); + sp->text = p; + *exparg.lastp = sp; + exparg.lastp = &sp->next; + } + if (ifsfirst.next) + ifsfree(); + *exparg.lastp = NULL; + if (exparg.list) { + *arglist->lastp = exparg.list; + arglist->lastp = exparg.lastp; + } +} + + + +/* + * Perform variable and command substitution. If EXP_FULL is set, output CTLESC + * characters to allow for further processing. Otherwise treat + * $@ like $* since no splitting will be performed. + */ + +STATIC void +argstr(char *p, int flag) +{ + static const char spclchars[] = { + '=', + ':', + CTLQUOTEMARK, + CTLENDVAR, + CTLESC, + CTLVAR, + CTLBACKQ, + CTLBACKQ | CTLQUOTE, + CTLENDARI, + 0 + }; + const char *reject = spclchars; + int c; + int quotes = flag & QUOTES_ESC; + int breakall = flag & EXP_WORD; + int inquotes; + size_t length; + int startloc; + + if (!(flag & EXP_VARTILDE)) { + reject += 2; + } else if (flag & EXP_VARTILDE2) { + reject++; + } + inquotes = 0; + length = 0; + if (flag & EXP_TILDE) { + char *q; + + flag &= ~EXP_TILDE; +tilde: + q = p; + if (*q == (char)CTLESC && (flag & EXP_QWORD)) + q++; + if (*q == '~') + p = exptilde(p, q, flag); + } +start: + startloc = expdest - (char *)stackblock(); + for (;;) { + length += strcspn(p + length, reject); + c = (signed char)p[length]; + if (c && (!(c & 0x80) || c == CTLENDARI)) { + /* c == '=' || c == ':' || c == CTLENDARI */ + length++; + } + if (length > 0) { + int newloc; + expdest = stnputs(p, length, expdest); + newloc = expdest - (char *)stackblock(); + if (breakall && !inquotes && newloc > startloc) { + recordregion(startloc, newloc, 0); + } + startloc = newloc; + } + p += length + 1; + length = 0; + + switch (c) { + case '\0': + goto breakloop; + case '=': + if (flag & EXP_VARTILDE2) { + p--; + continue; + } + flag |= EXP_VARTILDE2; + reject++; + /* fall through */ + case ':': + /* + * sort of a hack - expand tildes in variable + * assignments (after the first '=' and after ':'s). + */ + if (*--p == '~') { + goto tilde; + } + continue; + } + + switch (c) { + case CTLENDVAR: /* ??? */ + goto breakloop; + case CTLQUOTEMARK: + /* "$@" syntax adherence hack */ + if ( + !inquotes && + !memcmp(p, dolatstr, DOLATSTRLEN) && + (p[4] == (char)CTLQUOTEMARK || ( + p[4] == (char)CTLENDVAR && + p[5] == (char)CTLQUOTEMARK + )) + ) { + p = evalvar(p + 1, flag) + 1; + goto start; + } + inquotes = !inquotes; +addquote: + if (quotes) { + p--; + length++; + startloc++; + } + break; + case CTLESC: + startloc++; + length++; + goto addquote; + case CTLVAR: + p = evalvar(p, flag); + goto start; + case CTLBACKQ: + c = 0; + case CTLBACKQ|CTLQUOTE: + expbackq(argbackq->n, c, quotes); + argbackq = argbackq->next; + goto start; + case CTLENDARI: + p--; + expari(quotes); + goto start; + } + } +breakloop: + ; +} + +STATIC char * +exptilde(char *startp, char *p, int flag) +{ + signed char c; + char *name; + const char *home; + int quotes = flag & QUOTES_ESC; + int startloc; + + name = p + 1; + + while ((c = *++p) != '\0') { + switch(c) { + case CTLESC: + return (startp); + case CTLQUOTEMARK: + return (startp); + case ':': + if (flag & EXP_VARTILDE) + goto done; + break; + case '/': + case CTLENDVAR: + goto done; + } + } +done: + *p = '\0'; + if (*name == '\0') { + home = lookupvar(homestr); + } else { + home = getpwhome(name); + } + if (!home || !*home) + goto lose; + *p = c; + startloc = expdest - (char *)stackblock(); + strtodest(home, SQSYNTAX, quotes); + recordregion(startloc, expdest - (char *)stackblock(), 0); + return (p); +lose: + *p = c; + return (startp); +} + + +STATIC void +removerecordregions(int endoff) +{ + if (ifslastp == NULL) + return; + + if (ifsfirst.endoff > endoff) { + while (ifsfirst.next != NULL) { + struct ifsregion *ifsp; + INTOFF; + ifsp = ifsfirst.next->next; + ckfree(ifsfirst.next); + ifsfirst.next = ifsp; + INTON; + } + if (ifsfirst.begoff > endoff) + ifslastp = NULL; + else { + ifslastp = &ifsfirst; + ifsfirst.endoff = endoff; + } + return; + } + + ifslastp = &ifsfirst; + while (ifslastp->next && ifslastp->next->begoff < endoff) + ifslastp=ifslastp->next; + while (ifslastp->next != NULL) { + struct ifsregion *ifsp; + INTOFF; + ifsp = ifslastp->next->next; + ckfree(ifslastp->next); + ifslastp->next = ifsp; + INTON; + } + if (ifslastp->endoff > endoff) + ifslastp->endoff = endoff; +} + + +/* + * Expand arithmetic expression. Backup to start of expression, + * evaluate, place result in (backed up) result, adjust string position. + */ +void +expari(int quotes) +{ + char *p, *start; + int begoff; + int flag; + int len; + + /* ifsfree(); */ + + /* + * This routine is slightly over-complicated for + * efficiency. Next we scan backwards looking for the + * start of arithmetic. + */ + start = stackblock(); + p = expdest - 1; + *p = '\0'; + p--; + do { + int esc; + + while (*p != (char)CTLARI) { + p--; +#ifdef DEBUG + if (p < start) { + sh_error("missing CTLARI (shouldn't happen)"); + } +#endif + } + + esc = esclen(start, p); + if (!(esc % 2)) { + break; + } + + p -= esc + 1; + } while (1); + + begoff = p - start; + + removerecordregions(begoff); + + flag = p[1]; + + expdest = p; + + if (quotes) + rmescapes(p + 2); + + len = cvtnum(arith(p + 2)); + + if (flag != '"') + recordregion(begoff, begoff + len, 0); +} + + +/* + * Expand stuff in backwards quotes. + */ + +STATIC void +expbackq(union node *cmd, int quoted, int quotes) +{ + struct backcmd in; + int i; + char buf[128]; + char *p; + char *dest; + int startloc; + char const *syntax = quoted? DQSYNTAX : BASESYNTAX; + struct stackmark smark; + + INTOFF; + setstackmark(&smark); + dest = expdest; + startloc = dest - (char *)stackblock(); + grabstackstr(dest); + evalbackcmd(cmd, (struct backcmd *) &in); + popstackmark(&smark); + + p = in.buf; + i = in.nleft; + if (i == 0) + goto read; + for (;;) { + memtodest(p, i, syntax, quotes); +read: + if (in.fd < 0) + break; + do { + i = read(in.fd, buf, sizeof buf); + } while (i < 0 && errno == EINTR); + TRACE(("expbackq: read returns %d\n", i)); + if (i <= 0) + break; + p = buf; + } + + if (in.buf) + ckfree(in.buf); + if (in.fd >= 0) { + close(in.fd); + back_exitstatus = waitforjob(in.jp); + } + INTON; + + /* Eat all trailing newlines */ + dest = expdest; + for (; dest > (char *)stackblock() && dest[-1] == '\n';) + STUNPUTC(dest); + expdest = dest; + + if (quoted == 0) + recordregion(startloc, dest - (char *)stackblock(), 0); + TRACE(("evalbackq: size=%d: \"%.*s\"\n", + (dest - (char *)stackblock()) - startloc, + (dest - (char *)stackblock()) - startloc, + stackblock() + startloc)); +} + + +STATIC char * +scanleft( + char *startp, char *rmesc, char *rmescend, char *str, int quotes, + int zero +) { + char *loc; + char *loc2; + char c; + + loc = startp; + loc2 = rmesc; + do { + int match; + const char *s = loc2; + c = *loc2; + if (zero) { + *loc2 = '\0'; + s = rmesc; + } + match = pmatch(str, s); + *loc2 = c; + if (match) + return loc; + if (quotes && *loc == (char)CTLESC) + loc++; + loc++; + loc2++; + } while (c); + return 0; +} + + +STATIC char * +scanright( + char *startp, char *rmesc, char *rmescend, char *str, int quotes, + int zero +) { + int esc = 0; + char *loc; + char *loc2; + + for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) { + int match; + char c = *loc2; + const char *s = loc2; + if (zero) { + *loc2 = '\0'; + s = rmesc; + } + match = pmatch(str, s); + *loc2 = c; + if (match) + return loc; + loc--; + if (quotes) { + if (--esc < 0) { + esc = esclen(startp, loc); + } + if (esc % 2) { + esc--; + loc--; + } + } + } + return 0; +} + +STATIC const char * +subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes) +{ + char *startp; + char *loc; + int saveherefd = herefd; + struct nodelist *saveargbackq = argbackq; + int amount; + char *rmesc, *rmescend; + int zero; + char *(*scan)(char *, char *, char *, char *, int , int); + + herefd = -1; + argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0); + STPUTC('\0', expdest); + herefd = saveherefd; + argbackq = saveargbackq; + startp = stackblock() + startloc; + + switch (subtype) { + case VSASSIGN: + setvar(str, startp, 0); + amount = startp - expdest; + STADJUST(amount, expdest); + return startp; + + case VSQUESTION: + varunset(p, str, startp, varflags); + /* NOTREACHED */ + } + + subtype -= VSTRIMRIGHT; +#ifdef DEBUG + if (subtype < 0 || subtype > 3) + abort(); +#endif + + rmesc = startp; + rmescend = stackblock() + strloc; + if (quotes) { + rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW); + if (rmesc != startp) { + rmescend = expdest; + startp = stackblock() + startloc; + } + } + rmescend--; + str = stackblock() + strloc; + preglob(str, varflags & VSQUOTE, 0); + + /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */ + zero = subtype >> 1; + /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */ + scan = (subtype & 1) ^ zero ? scanleft : scanright; + + loc = scan(startp, rmesc, rmescend, str, quotes, zero); + if (loc) { + if (zero) { + memmove(startp, loc, str - loc); + loc = startp + (str - loc) - 1; + } + *loc = '\0'; + amount = loc - expdest; + STADJUST(amount, expdest); + } + return loc; +} + + +/* + * Expand a variable, and return a pointer to the next character in the + * input string. + */ +STATIC char * +evalvar(char *p, int flag) +{ + int subtype; + int varflags; + char *var; + int patloc; + int c; + int startloc; + ssize_t varlen; + int easy; + int quotes; + int quoted; + + quotes = flag & QUOTES_ESC; + varflags = *p++; + subtype = varflags & VSTYPE; + quoted = varflags & VSQUOTE; + var = p; + easy = (!quoted || (*var == '@' && shellparam.nparam)); + startloc = expdest - (char *)stackblock(); + p = strchr(p, '=') + 1; + +again: + varlen = varvalue(var, varflags, flag); + if (varflags & VSNUL) + varlen--; + + if (subtype == VSPLUS) { + varlen = -1 - varlen; + goto vsplus; + } + + if (subtype == VSMINUS) { +vsplus: + if (varlen < 0) { + argstr( + p, flag | EXP_TILDE | + (quoted ? EXP_QWORD : EXP_WORD) + ); + goto end; + } + if (easy) + goto record; + goto end; + } + + if (subtype == VSASSIGN || subtype == VSQUESTION) { + if (varlen < 0) { + if (subevalvar(p, var, 0, subtype, startloc, + varflags, 0)) { + varflags &= ~VSNUL; + /* + * Remove any recorded regions beyond + * start of variable + */ + removerecordregions(startloc); + goto again; + } + goto end; + } + if (easy) + goto record; + goto end; + } + + if (varlen < 0 && uflag) + varunset(p, var, 0, 0); + + if (subtype == VSLENGTH) { + cvtnum(varlen > 0 ? varlen : 0); + goto record; + } + + if (subtype == VSNORMAL) { + if (!easy) + goto end; +record: + recordregion(startloc, expdest - (char *)stackblock(), quoted); + goto end; + } + +#ifdef DEBUG + switch (subtype) { + case VSTRIMLEFT: + case VSTRIMLEFTMAX: + case VSTRIMRIGHT: + case VSTRIMRIGHTMAX: + break; + default: + abort(); + } +#endif + + if (varlen >= 0) { + /* + * Terminate the string and start recording the pattern + * right after it + */ + STPUTC('\0', expdest); + patloc = expdest - (char *)stackblock(); + if (subevalvar(p, NULL, patloc, subtype, + startloc, varflags, quotes) == 0) { + int amount = expdest - ( + (char *)stackblock() + patloc - 1 + ); + STADJUST(-amount, expdest); + } + /* Remove any recorded regions beyond start of variable */ + removerecordregions(startloc); + goto record; + } + +end: + if (subtype != VSNORMAL) { /* skip to end of alternative */ + int nesting = 1; + for (;;) { + if ((c = (signed char)*p++) == CTLESC) + p++; + else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { + if (varlen >= 0) + argbackq = argbackq->next; + } else if (c == CTLVAR) { + if ((*p++ & VSTYPE) != VSNORMAL) + nesting++; + } else if (c == CTLENDVAR) { + if (--nesting == 0) + break; + } + } + } + return p; +} + + +/* + * Put a string on the stack. + */ + +STATIC void +memtodest(const char *p, size_t len, const char *syntax, int quotes) { + char *q; + + if (unlikely(!len)) + return; + + q = makestrspace(len * 2, expdest); + + do { + int c = (signed char)*p++; + if (c) { + if ((quotes & QUOTES_ESC) && + (syntax[c] == CCTL || syntax[c] == CBACK)) + USTPUTC(CTLESC, q); + } else if (!(quotes & QUOTES_KEEPNUL)) + continue; + USTPUTC(c, q); + } while (--len); + + expdest = q; +} + + +STATIC size_t +strtodest(p, syntax, quotes) + const char *p; + const char *syntax; + int quotes; +{ + size_t len = strlen(p); + memtodest(p, len, syntax, quotes); + return len; +} + + + +/* + * Add the value of a specialized variable to the stack string. + */ + +STATIC ssize_t +varvalue(char *name, int varflags, int flags) +{ + int num; + char *p; + int i; + int sep; + char sepc; + char **ap; + char const *syntax; + int quoted = varflags & VSQUOTE; + int subtype = varflags & VSTYPE; + int discard = subtype == VSPLUS || subtype == VSLENGTH; + int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL; + ssize_t len = 0; + + sep = quoted ? ((flags & EXP_FULL) << CHAR_BIT) : 0; + syntax = quoted ? DQSYNTAX : BASESYNTAX; + + switch (*name) { + case '$': + num = rootpid; + goto numvar; + case '?': + num = exitstatus; + goto numvar; + case '#': + num = shellparam.nparam; + goto numvar; + case '!': + num = backgndpid; + if (num == 0) + return -1; +numvar: + len = cvtnum(num); + break; + case '-': + p = makestrspace(NOPTS, expdest); + for (i = NOPTS - 1; i >= 0; i--) { + if (optlist[i]) { + USTPUTC(optletters[i], p); + len++; + } + } + expdest = p; + break; + case '@': + if (sep) + goto param; + /* fall through */ + case '*': + sep = ifsset() ? ifsval()[0] : ' '; +param: + if (!(ap = shellparam.p)) + return -1; + sepc = sep; + while ((p = *ap++)) { + len += strtodest(p, syntax, quotes); + + if (*ap && sep) { + len++; + memtodest(&sepc, 1, syntax, quotes); + } + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + num = atoi(name); + if (num < 0 || num > shellparam.nparam) + return -1; + p = num ? shellparam.p[num - 1] : arg0; + goto value; + default: + p = lookupvar(name); +value: + if (!p) + return -1; + + len = strtodest(p, syntax, quotes); + break; + } + + if (discard) + STADJUST(-len, expdest); + return len; +} + + + +/* + * Record the fact that we have to scan this region of the + * string for IFS characters. + */ + +STATIC void +recordregion(int start, int end, int nulonly) +{ + struct ifsregion *ifsp; + + if (ifslastp == NULL) { + ifsp = &ifsfirst; + } else { + INTOFF; + ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); + ifsp->next = NULL; + ifslastp->next = ifsp; + INTON; + } + ifslastp = ifsp; + ifslastp->begoff = start; + ifslastp->endoff = end; + ifslastp->nulonly = nulonly; +} + + + +/* + * Break the argument string into pieces based upon IFS and add the + * strings to the argument list. The regions of the string to be + * searched for IFS characters have been stored by recordregion. + */ +STATIC void +ifsbreakup(char *string, struct arglist *arglist) +{ + struct ifsregion *ifsp; + struct strlist *sp; + char *start; + char *p; + char *q; + const char *ifs, *realifs; + int ifsspc; + int nulonly; + + + start = string; + if (ifslastp != NULL) { + ifsspc = 0; + nulonly = 0; + realifs = ifsset() ? ifsval() : defifs; + ifsp = &ifsfirst; + do { + p = string + ifsp->begoff; + nulonly = ifsp->nulonly; + ifs = nulonly ? nullstr : realifs; + ifsspc = 0; + while (p < string + ifsp->endoff) { + q = p; + if (*p == (char)CTLESC) + p++; + if (strchr(ifs, *p)) { + if (!nulonly) + ifsspc = (strchr(defifs, *p) != NULL); + /* Ignore IFS whitespace at start */ + if (q == start && ifsspc) { + p++; + start = p; + continue; + } + *q = '\0'; + sp = (struct strlist *)stalloc(sizeof *sp); + sp->text = start; + *arglist->lastp = sp; + arglist->lastp = &sp->next; + p++; + if (!nulonly) { + for (;;) { + if (p >= string + ifsp->endoff) { + break; + } + q = p; + if (*p == (char)CTLESC) + p++; + if (strchr(ifs, *p) == NULL ) { + p = q; + break; + } else if (strchr(defifs, *p) == NULL) { + if (ifsspc) { + p++; + ifsspc = 0; + } else { + p = q; + break; + } + } else + p++; + } + } + start = p; + } else + p++; + } + } while ((ifsp = ifsp->next) != NULL); + if (nulonly) + goto add; + } + + if (!*start) + return; + +add: + sp = (struct strlist *)stalloc(sizeof *sp); + sp->text = start; + *arglist->lastp = sp; + arglist->lastp = &sp->next; +} + +STATIC void +ifsfree(void) +{ + struct ifsregion *p; + + INTOFF; + p = ifsfirst.next; + do { + struct ifsregion *ifsp; + ifsp = p->next; + ckfree(p); + p = ifsp; + } while (p); + ifslastp = NULL; + ifsfirst.next = NULL; + INTON; +} + + + +/* + * Expand shell metacharacters. At this point, the only control characters + * should be escapes. The results are stored in the list exparg. + */ + +#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) +STATIC void +expandmeta(str, flag) + struct strlist *str; + int flag; +{ + /* TODO - EXP_REDIR */ + + while (str) { + const char *p; + glob_t pglob; + int i; + + if (fflag) + goto nometa; + INTOFF; + p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP); + i = glob(p, GLOB_NOMAGIC, 0, &pglob); + if (p != str->text) + ckfree(p); + switch (i) { + case 0: + if (!(pglob.gl_flags & GLOB_MAGCHAR)) + goto nometa2; + addglob(&pglob); + globfree(&pglob); + INTON; + break; + case GLOB_NOMATCH: +nometa2: + globfree(&pglob); + INTON; +nometa: + *exparg.lastp = str; + rmescapes(str->text); + exparg.lastp = &str->next; + break; + default: /* GLOB_NOSPACE */ + sh_error("Out of space"); + } + str = str->next; + } +} + + +/* + * Add the result of glob(3) to the list. + */ + +STATIC void +addglob(pglob) + const glob_t *pglob; +{ + char **p = pglob->gl_pathv; + + do { + addfname(*p); + } while (*++p); +} + + +#else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ +STATIC char *expdir; + + +STATIC void +expandmeta(struct strlist *str, int flag) +{ + static const char metachars[] = { + '*', '?', '[', 0 + }; + /* TODO - EXP_REDIR */ + + while (str) { + struct strlist **savelastp; + struct strlist *sp; + char *p; + + if (fflag) + goto nometa; + if (!strpbrk(str->text, metachars)) + goto nometa; + savelastp = exparg.lastp; + + INTOFF; + p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP); + { + int i = strlen(str->text); + expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ + } + + expmeta(expdir, p); + ckfree(expdir); + if (p != str->text) + ckfree(p); + INTON; + if (exparg.lastp == savelastp) { + /* + * no matches + */ +nometa: + *exparg.lastp = str; + rmescapes(str->text); + exparg.lastp = &str->next; + } else { + *exparg.lastp = NULL; + *savelastp = sp = expsort(*savelastp); + while (sp->next != NULL) + sp = sp->next; + exparg.lastp = &sp->next; + } + str = str->next; + } +} + + +/* + * Do metacharacter (i.e. *, ?, [...]) expansion. + */ + +STATIC void +expmeta(char *enddir, char *name) +{ + char *p; + const char *cp; + char *start; + char *endname; + int metaflag; + struct stat64 statb; + DIR *dirp; + struct dirent *dp; + int atend; + int matchdot; + + metaflag = 0; + start = name; + for (p = name; *p; p++) { + if (*p == '*' || *p == '?') + metaflag = 1; + else if (*p == '[') { + char *q = p + 1; + if (*q == '!') + q++; + for (;;) { + if (*q == '\\') + q++; + if (*q == '/' || *q == '\0') + break; + if (*++q == ']') { + metaflag = 1; + break; + } + } + } else if (*p == '\\') + p++; + else if (*p == '/') { + if (metaflag) + goto out; + start = p + 1; + } + } +out: + if (metaflag == 0) { /* we've reached the end of the file name */ + if (enddir != expdir) + metaflag++; + p = name; + do { + if (*p == '\\') + p++; + *enddir++ = *p; + } while (*p++); + if (metaflag == 0 || lstat64(expdir, &statb) >= 0) + addfname(expdir); + return; + } + endname = p; + if (name < start) { + p = name; + do { + if (*p == '\\') + p++; + *enddir++ = *p++; + } while (p < start); + } + if (enddir == expdir) { + cp = "."; + } else if (enddir == expdir + 1 && *expdir == '/') { + cp = "/"; + } else { + cp = expdir; + enddir[-1] = '\0'; + } + if ((dirp = opendir(cp)) == NULL) + return; + if (enddir != expdir) + enddir[-1] = '/'; + if (*endname == 0) { + atend = 1; + } else { + atend = 0; + *endname++ = '\0'; + } + matchdot = 0; + p = start; + if (*p == '\\') + p++; + if (*p == '.') + matchdot++; + while (! int_pending() && (dp = readdir(dirp)) != NULL) { + if (dp->d_name[0] == '.' && ! matchdot) + continue; + if (pmatch(start, dp->d_name)) { + if (atend) { + scopy(dp->d_name, enddir); + addfname(expdir); + } else { + for (p = enddir, cp = dp->d_name; + (*p++ = *cp++) != '\0';) + continue; + p[-1] = '/'; + expmeta(p, endname); + } + } + } + closedir(dirp); + if (! atend) + endname[-1] = '/'; +} +#endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ + + +/* + * Add a file name to the list. + */ + +STATIC void +addfname(char *name) +{ + struct strlist *sp; + + sp = (struct strlist *)stalloc(sizeof *sp); + sp->text = sstrdup(name); + *exparg.lastp = sp; + exparg.lastp = &sp->next; +} + + +#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) +/* + * Sort the results of file name expansion. It calculates the number of + * strings to sort and then calls msort (short for merge sort) to do the + * work. + */ + +STATIC struct strlist * +expsort(struct strlist *str) +{ + int len; + struct strlist *sp; + + len = 0; + for (sp = str ; sp ; sp = sp->next) + len++; + return msort(str, len); +} + + +STATIC struct strlist * +msort(struct strlist *list, int len) +{ + struct strlist *p, *q = NULL; + struct strlist **lpp; + int half; + int n; + + if (len <= 1) + return list; + half = len >> 1; + p = list; + for (n = half ; --n >= 0 ; ) { + q = p; + p = p->next; + } + q->next = NULL; /* terminate first half of list */ + q = msort(list, half); /* sort first half of list */ + p = msort(p, len - half); /* sort second half */ + lpp = &list; + for (;;) { + if (strcmp(p->text, q->text) < 0) { + *lpp = p; + lpp = &p->next; + if ((p = *lpp) == NULL) { + *lpp = q; + break; + } + } else { + *lpp = q; + lpp = &q->next; + if ((q = *lpp) == NULL) { + *lpp = p; + break; + } + } + } + return list; +} +#endif + + +/* + * Returns true if the pattern matches the string. + */ + +STATIC inline int +patmatch(char *pattern, const char *string) +{ + return pmatch(preglob(pattern, 0, 0), string); +} + + +#if !defined(__GLIBC__) || defined(FNMATCH_BROKEN) +STATIC int ccmatch(const char *p, int chr, const char **r) +{ + static const struct class { + char name[10]; + int (*fn)(int); + } classes[] = { + { .name = ":alnum:]", .fn = isalnum }, + { .name = ":cntrl:]", .fn = iscntrl }, + { .name = ":lower:]", .fn = islower }, + { .name = ":space:]", .fn = isspace }, + { .name = ":alpha:]", .fn = isalpha }, + { .name = ":digit:]", .fn = isdigit }, + { .name = ":print:]", .fn = isprint }, + { .name = ":upper:]", .fn = isupper }, + { .name = ":blank:]", .fn = isblank }, + { .name = ":graph:]", .fn = isgraph }, + { .name = ":punct:]", .fn = ispunct }, + { .name = ":xdigit:]", .fn = isxdigit }, + }; + const struct class *class, *end; + + end = classes + sizeof(classes) / sizeof(classes[0]); + for (class = classes; class < end; class++) { + const char *q; + + q = prefix(p, class->name); + if (!q) + continue; + *r = q; + return class->fn(chr); + } + + *r = 0; + return 0; +} + +STATIC int +pmatch(const char *pattern, const char *string) +{ + const char *p, *q; + char c; + + p = pattern; + q = string; + for (;;) { + switch (c = *p++) { + case '\0': + goto breakloop; + case '\\': + if (*p) { + c = *p++; + } + goto dft; + case '?': + if (*q++ == '\0') + return 0; + break; + case '*': + c = *p; + while (c == '*') + c = *++p; + if (c != '\\' && c != '?' && c != '*' && c != '[') { + while (*q != c) { + if (*q == '\0') + return 0; + q++; + } + } + do { + if (pmatch(p, q)) + return 1; + } while (*q++ != '\0'); + return 0; + case '[': { + const char *startp; + int invert, found; + char chr; + + startp = p; + invert = 0; + if (*p == '!') { + invert++; + p++; + } + found = 0; + chr = *q++; + if (chr == '\0') + return 0; + c = *p++; + do { + if (!c) { + p = startp; + c = *p; + goto dft; + } + if (c == '[') { + const char *r; + + found |= ccmatch(p, chr, &r); + if (r) { + p = r; + continue; + } + } else if (c == '\\') + c = *p++; + if (*p == '-' && p[1] != ']') { + p++; + if (*p == '\\') + p++; + if (chr >= c && chr <= *p) + found = 1; + p++; + } else { + if (chr == c) + found = 1; + } + } while ((c = *p++) != ']'); + if (found == invert) + return 0; + break; + } +dft: default: + if (*q++ != c) + return 0; + break; + } + } +breakloop: + if (*q != '\0') + return 0; + return 1; +} +#endif + + + +/* + * Remove any CTLESC characters from a string. + */ + +char * +_rmescapes(char *str, int flag) +{ + char *p, *q, *r; + static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 }; + unsigned inquotes; + int notescaped; + int globbing; + + p = strpbrk(str, qchars); + if (!p) { + return str; + } + q = p; + r = str; + if (flag & RMESCAPE_ALLOC) { + size_t len = p - str; + size_t fulllen = len + strlen(p) + 1; + + if (flag & RMESCAPE_GROW) { + r = makestrspace(fulllen, expdest); + } else if (flag & RMESCAPE_HEAP) { + r = ckmalloc(fulllen); + } else { + r = stalloc(fulllen); + } + q = r; + if (len > 0) { + q = mempcpy(q, str, len); + } + } + inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED; + globbing = flag & RMESCAPE_GLOB; + notescaped = globbing; + while (*p) { + if (*p == (char)CTLQUOTEMARK) { + inquotes = ~inquotes; + p++; + notescaped = globbing; + continue; + } + if (*p == '\\') { + /* naked back slash */ + notescaped = 0; + goto copy; + } + if (*p == (char)CTLESC) { + p++; + if (notescaped && inquotes && *p != '/') { + *q++ = '\\'; + } + } + notescaped = globbing; +copy: + *q++ = *p++; + } + *q = '\0'; + if (flag & RMESCAPE_GROW) { + expdest = r; + STADJUST(q - r + 1, expdest); + } + return r; +} + + + +/* + * See if a pattern matches in a case statement. + */ + +int +casematch(union node *pattern, char *val) +{ + struct stackmark smark; + int result; + + setstackmark(&smark); + argbackq = pattern->narg.backquote; + STARTSTACKSTR(expdest); + ifslastp = NULL; + argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); + STACKSTRNUL(expdest); + result = patmatch(stackblock(), val); + popstackmark(&smark); + return result; +} + +/* + * Our own itoa(). + */ + +STATIC int +cvtnum(long num) +{ + int len; + + expdest = makestrspace(32, expdest); + len = fmtstr(expdest, 32, "%ld", num); + STADJUST(len, expdest); + return len; +} + +STATIC void +varunset(const char *end, const char *var, const char *umsg, int varflags) +{ + const char *msg; + const char *tail; + + tail = nullstr; + msg = "parameter not set"; + if (umsg) { + if (*end == (char)CTLENDVAR) { + if (varflags & VSNUL) + tail = " or null"; + } else + msg = umsg; + } + sh_error("%.*s: %s%s", end - var - 1, var, msg, tail); +} diff -puN /dev/null usr/dash/expand.h --- /dev/null +++ a/usr/dash/expand.h @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)expand.h 8.2 (Berkeley) 5/4/95 + */ + +#ifndef DASH_STRLIST_H +#define DASH_STRLIST_H + +struct strlist { + struct strlist *next; + char *text; +}; + + +struct arglist { + struct strlist *list; + struct strlist **lastp; +}; + +/* + * expandarg() flags + */ +#define EXP_FULL 0x1 /* perform word splitting & file globbing */ +#define EXP_TILDE 0x2 /* do normal tilde expansion */ +#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ +#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ +#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ +#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */ +#define EXP_VARTILDE2 0x40 /* expand tildes after colons only */ +#define EXP_WORD 0x80 /* expand word in parameter expansion */ +#define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */ + + +union node; +void expandhere(union node *, int); +void expandarg(union node *, struct arglist *, int); +void expari(int); +#define rmescapes(p) _rmescapes((p), 0) +char *_rmescapes(char *, int); +int casematch(union node *, char *); + +/* From arith.y */ +int arith(const char *); +int expcmd(int , char **); +#ifdef USE_LEX +void arith_lex_reset(void); +#else +#define arith_lex_reset() +#endif +int yylex(void); + +#endif /* DASH_STRLIST_H */ diff -puN /dev/null usr/dash/funcs/cmv --- /dev/null +++ a/usr/dash/funcs/cmv @@ -0,0 +1,47 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)cmv 8.2 (Berkeley) 5/4/95 + +# Conditional move--don't replace an existing file. + +cmv() { + if test $# != 2 + then echo "cmv: arg count" + return 2 + fi + if test -f "$2" -o -w "$2" + then echo "$2 exists" + return 2 + fi + /bin/mv "$1" "$2" +} diff -puN /dev/null usr/dash/funcs/dirs --- /dev/null +++ a/usr/dash/funcs/dirs @@ -0,0 +1,71 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)dirs 8.2 (Berkeley) 5/4/95 + +# pushd, popd, and dirs --- written by Chris Bertin +# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris +# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW + +pushd () { + SAVE=`pwd` + if [ "$1" = "" ] + then if [ "$DSTACK" = "" ] + then echo "pushd: directory stack empty." + return 1 + fi + set $DSTACK + cd $1 || return + shift 1 + DSTACK="$*" + else cd $1 > /dev/null || return + fi + DSTACK="$SAVE $DSTACK" + dirs +} + +popd () { + if [ "$DSTACK" = "" ] + then echo "popd: directory stack empty." + return 1 + fi + set $DSTACK + cd $1 + shift + DSTACK=$* + dirs +} + +dirs () { + echo "`pwd` $DSTACK" + return 0 +} diff -puN /dev/null usr/dash/funcs/kill --- /dev/null +++ a/usr/dash/funcs/kill @@ -0,0 +1,47 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)kill 8.2 (Berkeley) 5/4/95 + +# Convert job names to process ids and then run /bin/kill. + +kill() { + local args x + args= + for x in "$@" + do case $x in + %*) x=`jobid "$x"` ;; + esac + args="$args $x" + done + /bin/kill $args +} diff -puN /dev/null usr/dash/funcs/login --- /dev/null +++ a/usr/dash/funcs/login @@ -0,0 +1,36 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)login 8.2 (Berkeley) 5/4/95 + +# replaces the login builtin in the BSD shell +login () exec login "$@" diff -puN /dev/null usr/dash/funcs/newgrp --- /dev/null +++ a/usr/dash/funcs/newgrp @@ -0,0 +1,35 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)newgrp 8.2 (Berkeley) 5/4/95 + +newgrp() exec newgrp "$@" diff -puN /dev/null usr/dash/funcs/popd --- /dev/null +++ a/usr/dash/funcs/popd @@ -0,0 +1,71 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)popd 8.2 (Berkeley) 5/4/95 + +# pushd, popd, and dirs --- written by Chris Bertin +# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris +# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW + +pushd () { + SAVE=`pwd` + if [ "$1" = "" ] + then if [ "$DSTACK" = "" ] + then echo "pushd: directory stack empty." + return 1 + fi + set $DSTACK + cd $1 || return + shift 1 + DSTACK="$*" + else cd $1 > /dev/null || return + fi + DSTACK="$SAVE $DSTACK" + dirs +} + +popd () { + if [ "$DSTACK" = "" ] + then echo "popd: directory stack empty." + return 1 + fi + set $DSTACK + cd $1 + shift + DSTACK=$* + dirs +} + +dirs () { + echo "`pwd` $DSTACK" + return 0 +} diff -puN /dev/null usr/dash/funcs/pushd --- /dev/null +++ a/usr/dash/funcs/pushd @@ -0,0 +1,71 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)pushd 8.2 (Berkeley) 5/4/95 + +# pushd, popd, and dirs --- written by Chris Bertin +# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris +# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW + +pushd () { + SAVE=`pwd` + if [ "$1" = "" ] + then if [ "$DSTACK" = "" ] + then echo "pushd: directory stack empty." + return 1 + fi + set $DSTACK + cd $1 || return + shift 1 + DSTACK="$*" + else cd $1 > /dev/null || return + fi + DSTACK="$SAVE $DSTACK" + dirs +} + +popd () { + if [ "$DSTACK" = "" ] + then echo "popd: directory stack empty." + return 1 + fi + set $DSTACK + cd $1 + shift + DSTACK=$* + dirs +} + +dirs () { + echo "`pwd` $DSTACK" + return 0 +} diff -puN /dev/null usr/dash/funcs/suspend --- /dev/null +++ a/usr/dash/funcs/suspend @@ -0,0 +1,39 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)suspend 8.2 (Berkeley) 5/4/95 + +suspend() { + local - + set +j + kill -TSTP 0 +} diff -puN /dev/null usr/dash/gendeps.pl --- /dev/null +++ a/usr/dash/gendeps.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl +# +# Generate dependencies for *generated* header files. Generated +# header files have to use #include "foo.h" syntax. +# + +($src, $obj, @build_headers) = @ARGV; +%build_headers = map { $_ => 1 } @build_headers; + +open(GENDEPS, "> $obj/.gendeps\0") + or die "$0: Cannot create $obj/.gendeps: $!\n"; + +opendir(DIR, $src) or die "$0: Cannot opendir $src: $!\n"; +while ( defined($file = readdir(DIR)) ) { + if ( $file =~ /^(.*)\.c$/ ) { + $basename = $1; + @hdrs = (); + open(FILE, "< $src/$file\0") + or die "$0: Cannot open $src/$file: $!\n"; + while ( defined($line = ) ) { + if ( $line =~ /^\s*\#\s*include\s+\"(.*)\"/ ) { + $header = $1; + + if ( $build_headers{$header} ) { + push(@hdrs, "\$(obj)/$header"); + } + } + } + close(FILE); + + if (scalar(@hdrs)) { + print GENDEPS "\$(obj)/$basename.o: ", join(' ', @hdrs), "\n"; + } + } +} + +closedir(DIR); +close(GENDEPS); diff -puN /dev/null usr/dash/hetio.c --- /dev/null +++ a/usr/dash/hetio.c @@ -0,0 +1,397 @@ +/* + * Termios command line History and Editting for NetBSD sh (ash) + * Copyright (c) 1999 + * Main code: Adam Rogoyski + * Etc: Dave Cinege + * + * You may use this code as you wish, so long as the original author(s) + * are attributed in any redistributions of the source code. + * This code is 'as is' with no warranty. + * This code may safely be consumed by a BSD or GPL license. + * + * v 0.5 19990328 Initial release + * + * Future plans: Simple file and path name completion. (like BASH) + * + */ + +/* +Usage and Known bugs: + Terminal key codes are not extensive, and more will probably + need to be added. This version was created on Debian GNU/Linux 2.x. + Delete, Backspace, Home, End, and the arrow keys were tested + to work in an Xterm and console. Ctrl-A also works as Home. + Ctrl-E also works as End. Ctrl-D and Ctrl-U perform their respective + functions. The binary size increase is <3K. + + Editting will not display correctly for lines greater then the + terminal width. (more then one line.) However, history will. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "input.h" +#include "output.h" + +#include "hetio.h" + + +#define MAX_HISTORY 15 /* Maximum length of the linked list for the command line history */ + +#define ESC 27 +#define DEL 127 + +static struct history *his_front = NULL; /* First element in command line list */ +static struct history *his_end = NULL; /* Last element in command line list */ +static struct termios old_term, new_term; /* Current termio and the previous termio before starting ash */ + +static int history_counter = 0; /* Number of commands in history list */ +static int reset_term = 0; /* Set to true if the terminal needs to be reset upon exit */ +static int hetio_inter = 0; + +struct history +{ + char *s; + struct history *p; + struct history *n; +}; + + +void input_delete (int); +void input_home (int *); +void input_end (int *, int); +void input_backspace (int *, int *); + + + +void hetio_init(void) +{ + hetio_inter = 1; +} + + +void hetio_reset_term(void) +{ + if (reset_term) + tcsetattr(1, TCSANOW, &old_term); +} + + +void setIO(struct termios *new, struct termios *old) /* Set terminal IO to canonical mode, and save old term settings. */ +{ + tcgetattr(0, old); + memcpy(new, old, sizeof(*new)); + new->c_cc[VMIN] = 1; + new->c_cc[VTIME] = 0; + new->c_lflag &= ~ICANON; /* unbuffered input */ + new->c_lflag &= ~ECHO; + tcsetattr(0, TCSANOW, new); +} + +void input_home(int *cursor) /* Command line input routines */ +{ + while (*cursor > 0) { + out1c('\b'); + --*cursor; + } + flushout(out1); +} + + +void input_delete(int cursor) +{ + int j = 0; + + memmove(parsenextc + cursor, parsenextc + cursor + 1, + BUFSIZ - cursor - 1); + for (j = cursor; j < (BUFSIZ - 1); j++) { + if (!*(parsenextc + j)) + break; + else + out1c(*(parsenextc + j)); + } + + out1str(" \b"); + + while (j-- > cursor) + out1c('\b'); + flushout(out1); +} + + +void input_end(int *cursor, int len) +{ + while (*cursor < len) { + out1str("\033[C"); + ++*cursor; + } + flushout(out1); +} + + +void +input_backspace(int *cursor, int *len) +{ + int j = 0; + + if (*cursor > 0) { + out1str("\b \b"); + --*cursor; + memmove(parsenextc + *cursor, parsenextc + *cursor + 1, + BUFSIZ - *cursor + 1); + + for (j = *cursor; j < (BUFSIZ - 1); j++) { + if (!*(parsenextc + j)) + break; + else + out1c(*(parsenextc + j)); + } + + out1str(" \b"); + + while (j-- > *cursor) + out1c('\b'); + + --*len; + flushout(out1); + } +} + +int hetio_read_input(int fd) +{ + int nr = 0; + + /* Are we an interactive shell? */ + if (!hetio_inter || fd) { + return -255; + } else { + int len = 0; + int j = 0; + int cursor = 0; + int break_out = 0; + int ret = 0; + char c = 0; + struct history *hp = his_end; + + if (!reset_term) { + setIO(&new_term, &old_term); + reset_term = 1; + } else { + tcsetattr(0, TCSANOW, &new_term); + } + + memset(parsenextc, 0, BUFSIZ); + + while (1) { + if ((ret = read(fd, &c, 1)) < 1) + return ret; + + switch (c) { + case 1: /* Control-A Beginning of line */ + input_home(&cursor); + break; + case 5: /* Control-E EOL */ + input_end(&cursor, len); + break; + case 4: /* Control-D */ + if (!len) + exitshell(0); + break; + case 21: /* Control-U */ + /* Return to begining of line. */ + for (; cursor > 0; cursor--) + out1c('\b'); + /* Erase old command. */ + for (j = 0; j < len; j++) { + /* + * Clear buffer while we're at + * it. + */ + parsenextc[j] = 0; + out1c(' '); + } + /* return to begining of line */ + for (; len > 0; len--) + out1c('\b'); + flushout(out1); + break; + case '\b': /* Backspace */ + case DEL: + input_backspace(&cursor, &len); + break; + case '\n': /* Enter */ + *(parsenextc + len++ + 1) = c; + out1c(c); + flushout(out1); + break_out = 1; + break; + case ESC: /* escape sequence follows */ + if ((ret = read(fd, &c, 1)) < 1) + return ret; + + if (c == '[' ) { /* 91 */ + if ((ret = read(fd, &c, 1)) < 1) + return ret; + + switch (c) { + case 'A': + if (hp && hp->p) { /* Up */ + hp = hp->p; + goto hop; + } + break; + case 'B': + if (hp && hp->n && hp->n->s) { /* Down */ + hp = hp->n; + goto hop; + } + break; + +hop: /* hop */ + len = strlen(parsenextc); + + for (; cursor > 0; cursor--) /* return to begining of line */ + out1c('\b'); + + for (j = 0; j < len; j++) /* erase old command */ + out1c(' '); + + for (; j > 0; j--) /* return to begining of line */ + out1c('\b'); + + strcpy (parsenextc, hp->s); /* write new command */ + len = strlen (hp->s); + out1str(parsenextc); + flushout(out1); + cursor = len; + break; + case 'C': /* Right */ + if (cursor < len) { + out1str("\033[C"); + cursor++; + flushout(out1); + } + break; + case 'D': /* Left */ + if (cursor > 0) { + out1str("\033[D"); + cursor--; + flushout(out1); + } + break; + case '3': /* Delete */ + if (cursor != len) { + input_delete(cursor); + len--; + } + break; + case '1': /* Home (Ctrl-A) */ + input_home(&cursor); + break; + case '4': /* End (Ctrl-E) */ + input_end(&cursor, len); + break; + } + if (c == '1' || c == '3' || c == '4') + if ((ret = read(fd, &c, 1)) < 1) + return ret; /* read 126 (~) */ + } + + if (c == 'O') { /* 79 */ + if ((ret = read(fd, &c, 1)) < 1) + return ret; + switch (c) { + case 'H': /* Home (xterm) */ + input_home(&cursor); + break; + case 'F': /* End (xterm_ */ + input_end(&cursor, len); + break; + } + } + + c = 0; + break; + + default: /* If it's regular input, do the normal thing */ + if (!isprint(c)) /* Skip non-printable characters */ + break; + + if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ + break; + + len++; + + if (cursor == (len - 1)) { /* Append if at the end of the line */ + *(parsenextc + cursor) = c; + } else { /* Insert otherwise */ + memmove(parsenextc + cursor + 1, parsenextc + cursor, + len - cursor - 1); + + *(parsenextc + cursor) = c; + + for (j = cursor; j < len; j++) + out1c(*(parsenextc + j)); + for (; j > cursor; j--) + out1str("\033[D"); + } + + cursor++; + out1c(c); + flushout(out1); + break; + } + + if (break_out) /* Enter is the command terminator, no more input. */ + break; + } + + nr = len + 1; + tcsetattr(0, TCSANOW, &old_term); + + if (*(parsenextc)) { /* Handle command history log */ + struct history *h = his_end; + + if (!h) { /* No previous history */ + h = his_front = malloc(sizeof (struct history)); + h->n = malloc(sizeof (struct history)); + h->p = NULL; + h->s = strdup(parsenextc); + + h->n->p = h; + h->n->n = NULL; + h->n->s = NULL; + his_end = h->n; + history_counter++; + } else { /* Add a new history command */ + + h->n = malloc(sizeof (struct history)); + + h->n->p = h; + h->n->n = NULL; + h->n->s = NULL; + h->s = strdup(parsenextc); + his_end = h->n; + + if (history_counter >= MAX_HISTORY) { /* After max history, remove the last known command */ + struct history *p = his_front->n; + + p->p = NULL; + free(his_front->s); + free(his_front); + his_front = p; + } else { + history_counter++; + } + } + } + } + + return nr; +} diff -puN /dev/null usr/dash/hetio.h --- /dev/null +++ a/usr/dash/hetio.h @@ -0,0 +1,22 @@ +/* + * Termios command line History and Editting for NetBSD sh (ash) + * Copyright (c) 1999 + * Main code: Adam Rogoyski + * Etc: Dave Cinege + * + * You may use this code as you wish, so long as the original author(s) + * are attributed in any redistributions of the source code. + * This code is 'as is' with no warranty. + * This code may safely be consumed by a BSD or GPL license. + * + * v 0.5 19990328 Initial release + * + * Future plans: Simple file and path name completion. (like BASH) + * + */ + +void hetio_init(void); +int hetio_read_input(int fd); +void hetio_reset_term(void); + +extern int hetio_inter; diff -puN /dev/null usr/dash/histedit.c --- /dev/null +++ a/usr/dash/histedit.c @@ -0,0 +1,492 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +/* + * Editline and history functions (and glue). + */ +#include "shell.h" +#include "parser.h" +#include "var.h" +#include "options.h" +#include "main.h" +#include "output.h" +#include "mystring.h" +#include "error.h" +#ifndef SMALL +#include "myhistedit.h" +#include "eval.h" +#include "memalloc.h" + +#define MAXHISTLOOPS 4 /* max recursions through fc */ +#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */ + +History *hist; /* history cookie */ +EditLine *el; /* editline cookie */ +int displayhist; +static FILE *el_in, *el_out; + +STATIC const char *fc_replace(const char *, char *, char *); + +#ifdef DEBUG +extern FILE *tracefile; +#endif + +/* + * Set history and editing status. Called whenever the status may + * have changed (figures out what to do). + */ +void +histedit(void) +{ + FILE *el_err; + +#define editing (Eflag || Vflag) + + if (iflag) { + if (!hist) { + /* + * turn history on + */ + INTOFF; + hist = history_init(); + INTON; + + if (hist != NULL) + sethistsize(histsizeval()); + else + out2str("sh: can't initialize history\n"); + } + if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ + /* + * turn editing on + */ + INTOFF; + if (el_in == NULL) + el_in = fdopen(0, "r"); + if (el_out == NULL) + el_out = fdopen(2, "w"); + if (el_in == NULL || el_out == NULL) + goto bad; + el_err = el_out; +#if DEBUG + if (tracefile) + el_err = tracefile; +#endif + el = el_init(arg0, el_in, el_out, el_err); + if (el != NULL) { + if (hist) + el_set(el, EL_HIST, history, hist); + el_set(el, EL_PROMPT, getprompt); + } else { +bad: + out2str("sh: can't initialize editing\n"); + } + INTON; + } else if (!editing && el) { + INTOFF; + el_end(el); + el = NULL; + INTON; + } + if (el) { + if (Vflag) + el_set(el, EL_EDITOR, "vi"); + else if (Eflag) + el_set(el, EL_EDITOR, "emacs"); + el_source(el, NULL); + } + } else { + INTOFF; + if (el) { /* no editing if not interactive */ + el_end(el); + el = NULL; + } + if (hist) { + history_end(hist); + hist = NULL; + } + INTON; + } +} + + +void +sethistsize(const char *hs) +{ + int histsize; + HistEvent he; + + if (hist != NULL) { + if (hs == NULL || *hs == '\0' || + (histsize = atoi(hs)) < 0) + histsize = 100; + history(hist, &he, H_SETSIZE, histsize); + } +} + +void +setterm(const char *term) +{ + if (el != NULL && term != NULL) + if (el_set(el, EL_TERMINAL, term) != 0) { + outfmt(out2, "sh: Can't set terminal type %s\n", term); + outfmt(out2, "sh: Using dumb terminal settings.\n"); + } +} + +/* + * This command is provided since POSIX decided to standardize + * the Korn shell fc command. Oh well... + */ +int +histcmd(int argc, char **argv) +{ + int ch; + const char *editor = NULL; + HistEvent he; + int lflg = 0, nflg = 0, rflg = 0, sflg = 0; + int i, retval; + const char *firststr, *laststr; + int first, last, direction; + char *pat = NULL, *repl; /* ksh "fc old=new" crap */ + static int active = 0; + struct jmploc jmploc; + struct jmploc *volatile savehandler; + char editfile[MAXPATHLEN + 1]; + FILE *efp; +#ifdef __GNUC__ + /* Avoid longjmp clobbering */ + (void) &editor; + (void) &lflg; + (void) &nflg; + (void) &rflg; + (void) &sflg; + (void) &firststr; + (void) &laststr; + (void) &pat; + (void) &repl; + (void) &efp; + (void) &argc; + (void) &argv; +#endif + + if (hist == NULL) + sh_error("history not active"); + + if (argc == 1) + sh_error("missing history argument"); + +#ifdef __GLIBC__ + optind = 0; +#else + optreset = 1; optind = 1; /* initialize getopt */ +#endif + while (not_fcnumber(argv[optind]) && + (ch = getopt(argc, argv, ":e:lnrs")) != -1) + switch ((char)ch) { + case 'e': + editor = optionarg; + break; + case 'l': + lflg = 1; + break; + case 'n': + nflg = 1; + break; + case 'r': + rflg = 1; + break; + case 's': + sflg = 1; + break; + case ':': + sh_error("option -%c expects argument", optopt); + /* NOTREACHED */ + case '?': + default: + sh_error("unknown option: -%c", optopt); + /* NOTREACHED */ + } + argc -= optind, argv += optind; + + /* + * If executing... + */ + if (lflg == 0 || editor || sflg) { + lflg = 0; /* ignore */ + editfile[0] = '\0'; + /* + * Catch interrupts to reset active counter and + * cleanup temp files. + */ + if (setjmp(jmploc.loc)) { + active = 0; + if (*editfile) + unlink(editfile); + handler = savehandler; + longjmp(handler->loc, 1); + } + savehandler = handler; + handler = &jmploc; + if (++active > MAXHISTLOOPS) { + active = 0; + displayhist = 0; + sh_error("called recursively too many times"); + } + /* + * Set editor. + */ + if (sflg == 0) { + if (editor == NULL && + (editor = bltinlookup("FCEDIT")) == NULL && + (editor = bltinlookup("EDITOR")) == NULL) + editor = DEFEDITOR; + if (editor[0] == '-' && editor[1] == '\0') { + sflg = 1; /* no edit */ + editor = NULL; + } + } + } + + /* + * If executing, parse [old=new] now + */ + if (lflg == 0 && argc > 0 && + ((repl = strchr(argv[0], '=')) != NULL)) { + pat = argv[0]; + *repl++ = '\0'; + argc--, argv++; + } + /* + * determine [first] and [last] + */ + switch (argc) { + case 0: + firststr = lflg ? "-16" : "-1"; + laststr = "-1"; + break; + case 1: + firststr = argv[0]; + laststr = lflg ? "-1" : argv[0]; + break; + case 2: + firststr = argv[0]; + laststr = argv[1]; + break; + default: + sh_error("too many args"); + /* NOTREACHED */ + } + /* + * Turn into event numbers. + */ + first = str_to_event(firststr, 0); + last = str_to_event(laststr, 1); + + if (rflg) { + i = last; + last = first; + first = i; + } + /* + * XXX - this should not depend on the event numbers + * always increasing. Add sequence numbers or offset + * to the history element in next (diskbased) release. + */ + direction = first < last ? H_PREV : H_NEXT; + + /* + * If editing, grab a temp file. + */ + if (editor) { + int fd; + INTOFF; /* easier */ + sprintf(editfile, "%s_shXXXXXX", _PATH_TMP); + if ((fd = mkstemp(editfile)) < 0) + sh_error("can't create temporary file %s", editfile); + if ((efp = fdopen(fd, "w")) == NULL) { + close(fd); + sh_error("can't allocate stdio buffer for temp"); + } + } + + /* + * Loop through selected history events. If listing or executing, + * do it now. Otherwise, put into temp file and call the editor + * after. + * + * The history interface needs rethinking, as the following + * convolutions will demonstrate. + */ + history(hist, &he, H_FIRST); + retval = history(hist, &he, H_NEXT_EVENT, first); + for (;retval != -1; retval = history(hist, &he, direction)) { + if (lflg) { + if (!nflg) + out1fmt("%5d ", he.num); + out1str(he.str); + } else { + const char *s = pat ? + fc_replace(he.str, pat, repl) : he.str; + + if (sflg) { + if (displayhist) { + out2str(s); + } + + evalstring(strcpy(stalloc(strlen(s) + 1), s), + ~0); + if (displayhist && hist) { + /* + * XXX what about recursive and + * relative histnums. + */ + history(hist, &he, H_ENTER, s); + } + } else + fputs(s, efp); + } + /* + * At end? (if we were to lose last, we'd sure be + * messed up). + */ + if (he.num == last) + break; + } + if (editor) { + char *editcmd; + + fclose(efp); + editcmd = stalloc(strlen(editor) + strlen(editfile) + 2); + sprintf(editcmd, "%s %s", editor, editfile); + /* XXX - should use no JC command */ + evalstring(editcmd, ~0); + INTON; + readcmdfile(editfile); /* XXX - should read back - quick tst */ + unlink(editfile); + } + + if (lflg == 0 && active > 0) + --active; + if (displayhist) + displayhist = 0; + return 0; +} + +STATIC const char * +fc_replace(const char *s, char *p, char *r) +{ + char *dest; + int plen = strlen(p); + + STARTSTACKSTR(dest); + while (*s) { + if (*s == *p && strncmp(s, p, plen) == 0) { + while (*r) + STPUTC(*r++, dest); + s += plen; + *p = '\0'; /* so no more matches */ + } else + STPUTC(*s++, dest); + } + STACKSTRNUL(dest); + dest = grabstackstr(dest); + + return (dest); +} + +int +not_fcnumber(char *s) +{ + if (s == NULL) + return 0; + if (*s == '-') + s++; + return (!is_number(s)); +} + +int +str_to_event(const char *str, int last) +{ + HistEvent he; + const char *s = str; + int relative = 0; + int i, retval; + + retval = history(hist, &he, H_FIRST); + switch (*s) { + case '-': + relative = 1; + /*FALLTHROUGH*/ + case '+': + s++; + } + if (is_number(s)) { + i = atoi(s); + if (relative) { + while (retval != -1 && i--) { + retval = history(hist, &he, H_NEXT); + } + if (retval == -1) + retval = history(hist, &he, H_LAST); + } else { + retval = history(hist, &he, H_NEXT_EVENT, i); + if (retval == -1) { + /* + * the notion of first and last is + * backwards to that of the history package + */ + retval = history(hist, &he, + last ? H_FIRST : H_LAST); + } + } + if (retval == -1) + sh_error("history number %s not found (internal error)", + str); + } else { + /* + * pattern + */ + retval = history(hist, &he, H_PREV_STR, str); + if (retval == -1) + sh_error("history pattern not found: %s", str); + } + return (he.num); +} +#endif diff -puN /dev/null usr/dash/init.h --- /dev/null +++ a/usr/dash/init.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)init.h 8.2 (Berkeley) 5/4/95 + */ + +void init(void); +void reset(void); +void initshellproc(void); diff -puN /dev/null usr/dash/input.c --- /dev/null +++ a/usr/dash/input.c @@ -0,0 +1,563 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include /* defines BUFSIZ */ +#include +#include +#include +#include + +/* + * This file implements the input routines used by the parser. + */ + +#include "shell.h" +#include "redir.h" +#include "syntax.h" +#include "input.h" +#include "output.h" +#include "options.h" +#include "memalloc.h" +#include "error.h" +#include "alias.h" +#include "parser.h" +#include "main.h" +#ifndef SMALL +#include "myhistedit.h" +#endif + +#ifdef HETIO +#include "hetio.h" +#endif + +#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ +#define IBUFSIZ (BUFSIZ + 1) + +MKINIT +struct strpush { + struct strpush *prev; /* preceding string on stack */ + char *prevstring; + int prevnleft; + struct alias *ap; /* if push was associated with an alias */ + char *string; /* remember the string since it may change */ +}; + +/* + * The parsefile structure pointed to by the global variable parsefile + * contains information about the current file being read. + */ + +MKINIT +struct parsefile { + struct parsefile *prev; /* preceding file on stack */ + int linno; /* current line */ + int fd; /* file descriptor (or -1 if string) */ + int nleft; /* number of chars left in this line */ + int lleft; /* number of chars left in this buffer */ + char *nextc; /* next char in buffer */ + char *buf; /* input buffer */ + struct strpush *strpush; /* for pushing strings at this level */ + struct strpush basestrpush; /* so pushing one is fast */ +}; + + +int plinno = 1; /* input line number */ +int parsenleft; /* copy of parsefile->nleft */ +MKINIT int parselleft; /* copy of parsefile->lleft */ +char *parsenextc; /* copy of parsefile->nextc */ +MKINIT struct parsefile basepf; /* top level input file */ +MKINIT char basebuf[IBUFSIZ]; /* buffer for top level input file */ +struct parsefile *parsefile = &basepf; /* current input file */ +int whichprompt; /* 1 == PS1, 2 == PS2 */ + +#ifndef SMALL +EditLine *el; /* cookie for editline package */ +#endif + +STATIC void pushfile(void); +static int preadfd(void); + +#ifdef mkinit +INCLUDE +INCLUDE "input.h" +INCLUDE "error.h" + +INIT { + basepf.nextc = basepf.buf = basebuf; +} + +RESET { + parselleft = parsenleft = 0; /* clear input buffer */ + popallfiles(); +} +#endif + + +/* + * Read a line from the script. + */ + +char * +pfgets(char *line, int len) +{ + char *p = line; + int nleft = len; + int c; + + while (--nleft > 0) { + c = pgetc2(); + if (c == PEOF) { + if (p == line) + return NULL; + break; + } + *p++ = c; + if (c == '\n') + break; + } + *p = '\0'; + return line; +} + + +/* + * Read a character from the script, returning PEOF on end of file. + * Nul characters in the input are silently discarded. + */ + +int +pgetc(void) +{ + return pgetc_macro(); +} + + +/* + * Same as pgetc(), but ignores PEOA. + */ + +int +pgetc2() +{ + int c; + do { + c = pgetc_macro(); + } while (c == PEOA); + return c; +} + + +static int +preadfd(void) +{ + int nr; + char *buf = parsefile->buf; + parsenextc = buf; + +retry: +#ifndef SMALL + if (parsefile->fd == 0 && el) { + static const char *rl_cp; + static int el_len; + + if (rl_cp == NULL) + rl_cp = el_gets(el, &el_len); + if (rl_cp == NULL) + nr = 0; + else { + nr = el_len; + if (nr > IBUFSIZ - 1) + nr = IBUFSIZ - 1; + memcpy(buf, rl_cp, nr); + if (nr != el_len) { + el_len -= nr; + rl_cp += nr; + } else + rl_cp = 0; + } + + } else +#endif + +#ifdef HETIO + nr = hetio_read_input(parsefile->fd); + if (nr == -255) +#endif + nr = read(parsefile->fd, buf, IBUFSIZ - 1); + + + if (nr < 0) { + if (errno == EINTR) + goto retry; + if (parsefile->fd == 0 && errno == EWOULDBLOCK) { + int flags = fcntl(0, F_GETFL, 0); + if (flags >= 0 && flags & O_NONBLOCK) { + flags &=~ O_NONBLOCK; + if (fcntl(0, F_SETFL, flags) >= 0) { + out2str("sh: turning off NDELAY mode\n"); + goto retry; + } + } + } + } + return nr; +} + +/* + * Refill the input buffer and return the next input character: + * + * 1) If a string was pushed back on the input, pop it; + * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading + * from a string so we can't refill the buffer, return EOF. + * 3) If the is more stuff in this buffer, use it else call read to fill it. + * 4) Process input up to the next newline, deleting nul characters. + */ + +int +preadbuffer(void) +{ + char *q; + int more; +#ifndef SMALL + int something; +#endif + char savec; + + while (unlikely(parsefile->strpush)) { + if ( + parsenleft == -1 && parsefile->strpush->ap && + parsenextc[-1] != ' ' && parsenextc[-1] != '\t' + ) { + return PEOA; + } + popstring(); + if (--parsenleft >= 0) + return (signed char)*parsenextc++; + } + if (unlikely(parsenleft == EOF_NLEFT || parsefile->buf == NULL)) + return PEOF; + flushout(&output); +#ifdef FLUSHERR + flushout(&errout); +#endif + + more = parselleft; + if (more <= 0) { +again: + if ((more = preadfd()) <= 0) { + parselleft = parsenleft = EOF_NLEFT; + return PEOF; + } + } + + q = parsenextc; + + /* delete nul characters */ +#ifndef SMALL + something = 0; +#endif + for (;;) { + int c; + + more--; + c = *q; + + if (!c) + memmove(q, q + 1, more); + else { + q++; + + if (c == '\n') { + parsenleft = q - parsenextc - 1; + break; + } + +#ifndef SMALL + switch (c) { + default: + something = 1; + /* fall through */ + case '\t': + case ' ': + break; + } +#endif + } + + if (more <= 0) { + parsenleft = q - parsenextc - 1; + if (parsenleft < 0) + goto again; + break; + } + } + parselleft = more; + + savec = *q; + *q = '\0'; + +#ifndef SMALL + if (parsefile->fd == 0 && hist && something) { + HistEvent he; + INTOFF; + history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND, + parsenextc); + INTON; + } +#endif + + if (vflag) { + out2str(parsenextc); +#ifdef FLUSHERR + flushout(out2); +#endif + } + + *q = savec; + + return (signed char)*parsenextc++; +} + +/* + * Undo the last call to pgetc. Only one character may be pushed back. + * PEOF may be pushed back. + */ + +void +pungetc(void) +{ + parsenleft++; + parsenextc--; +} + +/* + * Push a string back onto the input at this current parsefile level. + * We handle aliases this way. + */ +void +pushstring(char *s, void *ap) +{ + struct strpush *sp; + size_t len; + + len = strlen(s); + INTOFF; +/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ + if (parsefile->strpush) { + sp = ckmalloc(sizeof (struct strpush)); + sp->prev = parsefile->strpush; + parsefile->strpush = sp; + } else + sp = parsefile->strpush = &(parsefile->basestrpush); + sp->prevstring = parsenextc; + sp->prevnleft = parsenleft; + sp->ap = (struct alias *)ap; + if (ap) { + ((struct alias *)ap)->flag |= ALIASINUSE; + sp->string = s; + } + parsenextc = s; + parsenleft = len; + INTON; +} + +void +popstring(void) +{ + struct strpush *sp = parsefile->strpush; + + INTOFF; + if (sp->ap) { + if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') { + checkkwd |= CHKALIAS; + } + if (sp->string != sp->ap->val) { + ckfree(sp->string); + } + sp->ap->flag &= ~ALIASINUSE; + if (sp->ap->flag & ALIASDEAD) { + unalias(sp->ap->name); + } + } + parsenextc = sp->prevstring; + parsenleft = sp->prevnleft; +/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ + parsefile->strpush = sp->prev; + if (sp != &(parsefile->basestrpush)) + ckfree(sp); + INTON; +} + +/* + * Set the input to take input from a file. If push is set, push the + * old input onto the stack first. + */ + +int +setinputfile(const char *fname, int flags) +{ + int fd; + int fd2; + + INTOFF; + if ((fd = open(fname, O_RDONLY)) < 0) { + if (flags & INPUT_NOFILE_OK) + goto out; + sh_error("Can't open %s", fname); + } + if (fd < 10) { + fd2 = copyfd(fd, 10); + close(fd); + if (fd2 < 0) + sh_error("Out of file descriptors"); + fd = fd2; + } + setinputfd(fd, flags & INPUT_PUSH_FILE); +out: + INTON; + return fd; +} + + +/* + * Like setinputfile, but takes an open file descriptor. Call this with + * interrupts off. + */ + +void +setinputfd(int fd, int push) +{ + (void) fcntl(fd, F_SETFD, FD_CLOEXEC); + if (push) { + pushfile(); + parsefile->buf = 0; + } + parsefile->fd = fd; + if (parsefile->buf == NULL) + parsefile->buf = ckmalloc(IBUFSIZ); + parselleft = parsenleft = 0; + plinno = 1; +} + + +/* + * Like setinputfile, but takes input from a string. + */ + +void +setinputstring(char *string) +{ + INTOFF; + pushfile(); + parsenextc = string; + parsenleft = strlen(string); + parsefile->buf = NULL; + plinno = 1; + INTON; +} + + + +/* + * To handle the "." command, a stack of input files is used. Pushfile + * adds a new entry to the stack and popfile restores the previous level. + */ + +STATIC void +pushfile(void) +{ + struct parsefile *pf; + + parsefile->nleft = parsenleft; + parsefile->lleft = parselleft; + parsefile->nextc = parsenextc; + parsefile->linno = plinno; + pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); + pf->prev = parsefile; + pf->fd = -1; + pf->strpush = NULL; + pf->basestrpush.prev = NULL; + parsefile = pf; +} + + +void +popfile(void) +{ + struct parsefile *pf = parsefile; + + INTOFF; + if (pf->fd >= 0) + close(pf->fd); + if (pf->buf) + ckfree(pf->buf); + while (pf->strpush) + popstring(); + parsefile = pf->prev; + ckfree(pf); + parsenleft = parsefile->nleft; + parselleft = parsefile->lleft; + parsenextc = parsefile->nextc; + plinno = parsefile->linno; + INTON; +} + + +/* + * Return to top level. + */ + +void +popallfiles(void) +{ + while (parsefile != &basepf) + popfile(); +} + + + +/* + * Close the file(s) that the shell is reading commands from. Called + * after a fork is done. + */ + +void +closescript(void) +{ + popallfiles(); + if (parsefile->fd > 0) { + close(parsefile->fd); + parsefile->fd = 0; + } +} diff -puN /dev/null usr/dash/input.h --- /dev/null +++ a/usr/dash/input.h @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)input.h 8.2 (Berkeley) 5/4/95 + */ + +/* PEOF (the end of file marker) is defined in syntax.h */ + +enum { + INPUT_PUSH_FILE = 1, + INPUT_NOFILE_OK = 2, +}; + +/* + * The input line number. Input.c just defines this variable, and saves + * and restores it when files are pushed and popped. The user of this + * package must set its value. + */ +extern int plinno; +extern int parsenleft; /* number of characters left in input buffer */ +extern char *parsenextc; /* next character in input buffer */ + +char *pfgets(char *, int); +int pgetc(void); +int pgetc2(void); +int preadbuffer(void); +void pungetc(void); +void pushstring(char *, void *); +void popstring(void); +int setinputfile(const char *, int); +void setinputfd(int, int); +void setinputstring(char *); +void popfile(void); +void popallfiles(void); +void closescript(void); + +#define pgetc_macro() \ + (--parsenleft >= 0 ? (signed char)*parsenextc++ : preadbuffer()) diff -puN /dev/null usr/dash/jobs.c --- /dev/null +++ a/usr/dash/jobs.c @@ -0,0 +1,1499 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef BSD +#include +#include +#include +#endif +#include + +#include "shell.h" +#if JOBS +#include +#undef CEOF /* syntax.h redefines this */ +#endif +#include "redir.h" +#include "show.h" +#include "main.h" +#include "parser.h" +#include "nodes.h" +#include "jobs.h" +#include "options.h" +#include "trap.h" +#include "syntax.h" +#include "input.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "mystring.h" +#include "system.h" + +/* mode flags for set_curjob */ +#define CUR_DELETE 2 +#define CUR_RUNNING 1 +#define CUR_STOPPED 0 + +/* mode flags for dowait */ +#define DOWAIT_NORMAL 0 +#define DOWAIT_BLOCK 1 + +/* array of jobs */ +static struct job *jobtab; +/* size of array */ +static unsigned njobs; +/* pid of last background process */ +pid_t backgndpid; + +#if JOBS +/* pgrp of shell on invocation */ +static int initialpgrp; +/* control terminal */ +static int ttyfd = -1; +#endif + +/* current job */ +static struct job *curjob; +/* number of presumed living untracked jobs */ +static int jobless; + +STATIC void set_curjob(struct job *, unsigned); +STATIC int jobno(const struct job *); +STATIC int sprint_status(char *, int, int); +STATIC void freejob(struct job *); +STATIC struct job *getjob(const char *, int); +STATIC struct job *growjobtab(void); +STATIC void forkchild(struct job *, union node *, int); +STATIC void forkparent(struct job *, union node *, int, pid_t); +STATIC int dowait(int, struct job *); +#ifdef SYSV +STATIC int onsigchild(void); +#endif +STATIC int waitproc(int, int *); +STATIC char *commandtext(union node *); +STATIC void cmdtxt(union node *); +STATIC void cmdlist(union node *, int); +STATIC void cmdputs(const char *); +STATIC void showpipe(struct job *, struct output *); +STATIC int getstatus(struct job *); + +#if JOBS +static int restartjob(struct job *, int); +static void xtcsetpgrp(int, pid_t); +#endif + +STATIC void +set_curjob(struct job *jp, unsigned mode) +{ + struct job *jp1; + struct job **jpp, **curp; + + /* first remove from list */ + jpp = curp = &curjob; + do { + jp1 = *jpp; + if (jp1 == jp) + break; + jpp = &jp1->prev_job; + } while (1); + *jpp = jp1->prev_job; + + /* Then re-insert in correct position */ + jpp = curp; + switch (mode) { + default: +#ifdef DEBUG + abort(); +#endif + case CUR_DELETE: + /* job being deleted */ + break; + case CUR_RUNNING: + /* newly created job or backgrounded job, + put after all stopped jobs. */ + do { + jp1 = *jpp; + if (!JOBS || !jp1 || jp1->state != JOBSTOPPED) + break; + jpp = &jp1->prev_job; + } while (1); + /* FALLTHROUGH */ +#if JOBS + case CUR_STOPPED: +#endif + /* newly stopped job - becomes curjob */ + jp->prev_job = *jpp; + *jpp = jp; + break; + } +} + +#if JOBS +/* + * Turn job control on and off. + * + * Note: This code assumes that the third arg to ioctl is a character + * pointer, which is true on Berkeley systems but not System V. Since + * System V doesn't have job control yet, this isn't a problem now. + * + * Called with interrupts off. + */ + +int jobctl; + +void +setjobctl(int on) +{ + int fd; + int pgrp; + + if (on == jobctl || rootshell == 0) + return; + if (on) { + int ofd; + ofd = fd = open(_PATH_TTY, O_RDWR); + if (fd < 0) { + fd += 3; + while (!isatty(fd) && --fd >= 0) + ; + } + fd = fcntl(fd, F_DUPFD, 10); + close(ofd); + if (fd < 0) + goto out; + fcntl(fd, F_SETFD, FD_CLOEXEC); + do { /* while we are in the background */ + if ((pgrp = tcgetpgrp(fd)) < 0) { +out: + sh_warnx("can't access tty; job control turned off"); + mflag = on = 0; + goto close; + } + if (pgrp == getpgrp()) + break; + killpg(0, SIGTTIN); + } while (1); + initialpgrp = pgrp; + + setsignal(SIGTSTP); + setsignal(SIGTTOU); + setsignal(SIGTTIN); + pgrp = rootpid; + setpgid(0, pgrp); + xtcsetpgrp(fd, pgrp); + } else { + /* turning job control off */ + fd = ttyfd; + pgrp = initialpgrp; + xtcsetpgrp(fd, pgrp); + setpgid(0, pgrp); + setsignal(SIGTSTP); + setsignal(SIGTTOU); + setsignal(SIGTTIN); +close: + close(fd); + fd = -1; + } + ttyfd = fd; + jobctl = on; +} +#endif + + +int +killcmd(argc, argv) + int argc; + char **argv; +{ + int signo = -1; + int list = 0; + int i; + pid_t pid; + struct job *jp; + + if (argc <= 1) { +usage: + sh_error( +"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n" +"kill -l [exitstatus]" + ); + } + + if (**++argv == '-') { + signo = decode_signal(*argv + 1, 1); + if (signo < 0) { + int c; + + while ((c = nextopt("ls:")) != '\0') + switch (c) { + default: +#ifdef DEBUG + abort(); +#endif + case 'l': + list = 1; + break; + case 's': + signo = decode_signal(optionarg, 1); + if (signo < 0) { + sh_error( + "invalid signal number or name: %s", + optionarg + ); + } + break; + } + argv = argptr; + } else + argv++; + } + + if (!list && signo < 0) + signo = SIGTERM; + + if ((signo < 0 || !*argv) ^ list) { + goto usage; + } + + if (list) { + struct output *out; + + out = out1; + if (!*argv) { + outstr("0\n", out); + for (i = 1; i < NSIG; i++) { + outfmt(out, snlfmt, signal_name(i)); + } + return 0; + } + signo = number(*argv); + if (signo > 128) + signo -= 128; + if (0 < signo && signo < NSIG) + outfmt(out, snlfmt, signal_name(signo)); + else + sh_error("invalid signal number or exit status: %s", + *argv); + return 0; + } + + i = 0; + do { + if (**argv == '%') { + jp = getjob(*argv, 0); + pid = -jp->ps[0].pid; + } else + pid = **argv == '-' ? + -number(*argv + 1) : number(*argv); + if (kill(pid, signo) != 0) { + sh_warnx("%s\n", strerror(errno)); + i = 1; + } + } while (*++argv); + + return i; +} + +STATIC int +jobno(const struct job *jp) +{ + return jp - jobtab + 1; +} + +#if JOBS +int +fgcmd(int argc, char **argv) +{ + struct job *jp; + struct output *out; + int mode; + int retval; + + mode = (**argv == 'f') ? FORK_FG : FORK_BG; + nextopt(nullstr); + argv = argptr; + out = out1; + do { + jp = getjob(*argv, 1); + if (mode == FORK_BG) { + set_curjob(jp, CUR_RUNNING); + outfmt(out, "[%d] ", jobno(jp)); + } + outstr(jp->ps->cmd, out); + showpipe(jp, out); + retval = restartjob(jp, mode); + } while (*argv && *++argv); + return retval; +} + +int bgcmd(int, char **) __attribute__((__alias__("fgcmd"))); + + +STATIC int +restartjob(struct job *jp, int mode) +{ + struct procstat *ps; + int i; + int status; + pid_t pgid; + + INTOFF; + if (jp->state == JOBDONE) + goto out; + jp->state = JOBRUNNING; + pgid = jp->ps->pid; + if (mode == FORK_FG) + xtcsetpgrp(ttyfd, pgid); + killpg(pgid, SIGCONT); + ps = jp->ps; + i = jp->nprocs; + do { + if (WIFSTOPPED(ps->status)) { + ps->status = -1; + } + } while (ps++, --i); +out: + status = (mode == FORK_FG) ? waitforjob(jp) : 0; + INTON; + return status; +} +#endif + +STATIC int +sprint_status(char *s, int status, int sigonly) +{ + int col; + int st; + + col = 0; + st = WEXITSTATUS(status); + if (!WIFEXITED(status)) { +#if JOBS + st = WSTOPSIG(status); + if (!WIFSTOPPED(status)) +#endif + st = WTERMSIG(status); + if (sigonly) { + if (st == SIGINT || st == SIGPIPE) + goto out; +#if JOBS + if (WIFSTOPPED(status)) + goto out; +#endif + } + col = fmtstr(s, 32, strsignal(st)); + if (WCOREDUMP(status)) { + col += fmtstr(s + col, 16, " (core dumped)"); + } + } else if (!sigonly) { + if (st) + col = fmtstr(s, 16, "Done(%d)", st); + else + col = fmtstr(s, 16, "Done"); + } + +out: + return col; +} + +static void +showjob(struct output *out, struct job *jp, int mode) +{ + struct procstat *ps; + struct procstat *psend; + int col; + int indent; + char s[80]; + + ps = jp->ps; + + if (mode & SHOW_PGID) { + /* just output process (group) id of pipeline */ + outfmt(out, "%d\n", ps->pid); + return; + } + + col = fmtstr(s, 16, "[%d] ", jobno(jp)); + indent = col; + + if (jp == curjob) + s[col - 2] = '+'; + else if (curjob && jp == curjob->prev_job) + s[col - 2] = '-'; + + if (mode & SHOW_PID) + col += fmtstr(s + col, 16, "%d ", ps->pid); + + psend = ps + jp->nprocs; + + if (jp->state == JOBRUNNING) { + scopy("Running", s + col); + col += strlen("Running"); + } else { + int status = psend[-1].status; +#if JOBS + if (jp->state == JOBSTOPPED) + status = jp->stopstatus; +#endif + col += sprint_status(s + col, status, 0); + } + + goto start; + + do { + /* for each process */ + col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3; + +start: + outfmt( + out, "%s%*c%s", + s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd + ); + if (!(mode & SHOW_PID)) { + showpipe(jp, out); + break; + } + if (++ps == psend) { + outcslow('\n', out); + break; + } + } while (1); + + jp->changed = 0; + + if (jp->state == JOBDONE) { + TRACE(("showjob: freeing job %d\n", jobno(jp))); + freejob(jp); + } +} + + +int +jobscmd(int argc, char **argv) +{ + int mode, m; + struct output *out; + + mode = 0; + while ((m = nextopt("lp"))) + if (m == 'l') + mode = SHOW_PID; + else + mode = SHOW_PGID; + + out = out1; + argv = argptr; + if (*argv) + do + showjob(out, getjob(*argv,0), mode); + while (*++argv); + else + showjobs(out, mode); + + return 0; +} + + +/* + * Print a list of jobs. If "change" is nonzero, only print jobs whose + * statuses have changed since the last call to showjobs. + */ + +void +showjobs(struct output *out, int mode) +{ + struct job *jp; + + TRACE(("showjobs(%x) called\n", mode)); + + /* If not even one one job changed, there is nothing to do */ + while (dowait(DOWAIT_NORMAL, NULL) > 0) + continue; + + for (jp = curjob; jp; jp = jp->prev_job) { + if (!(mode & SHOW_CHANGED) || jp->changed) + showjob(out, jp, mode); + } +} + +/* + * Mark a job structure as unused. + */ + +STATIC void +freejob(struct job *jp) +{ + struct procstat *ps; + int i; + + INTOFF; + for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) { + if (ps->cmd != nullstr) + ckfree(ps->cmd); + } + if (jp->ps != &jp->ps0) + ckfree(jp->ps); + jp->used = 0; + set_curjob(jp, CUR_DELETE); + INTON; +} + + + +int +waitcmd(int argc, char **argv) +{ + struct job *job; + int retval; + struct job *jp; + + EXSIGON(); + + nextopt(nullstr); + retval = 0; + + argv = argptr; + if (!*argv) { + /* wait for all jobs */ + for (;;) { + jp = curjob; + while (1) { + if (!jp) { + /* no running procs */ + goto out; + } + if (jp->state == JOBRUNNING) + break; + jp->waited = 1; + jp = jp->prev_job; + } + dowait(DOWAIT_BLOCK, 0); + } + } + + retval = 127; + do { + if (**argv != '%') { + pid_t pid = number(*argv); + job = curjob; + goto start; + do { + if (job->ps[job->nprocs - 1].pid == pid) + break; + job = job->prev_job; +start: + if (!job) + goto repeat; + } while (1); + } else + job = getjob(*argv, 0); + /* loop until process terminated or stopped */ + while (job->state == JOBRUNNING) + dowait(DOWAIT_BLOCK, 0); + job->waited = 1; + retval = getstatus(job); +repeat: + ; + } while (*++argv); + +out: + return retval; +} + + + +/* + * Convert a job name to a job structure. + */ + +STATIC struct job * +getjob(const char *name, int getctl) +{ + struct job *jp; + struct job *found; + const char *err_msg = "No such job: %s"; + unsigned num; + int c; + const char *p; + char *(*match)(const char *, const char *); + + jp = curjob; + p = name; + if (!p) + goto currentjob; + + if (*p != '%') + goto err; + + c = *++p; + if (!c) + goto currentjob; + + if (!p[1]) { + if (c == '+' || c == '%') { +currentjob: + err_msg = "No current job"; + goto check; + } else if (c == '-') { + if (jp) + jp = jp->prev_job; + err_msg = "No previous job"; +check: + if (!jp) + goto err; + goto gotit; + } + } + + if (is_number(p)) { + num = atoi(p); + if (num < njobs) { + jp = jobtab + num - 1; + if (jp->used) + goto gotit; + goto err; + } + } + + match = prefix; + if (*p == '?') { + match = strstr; + p++; + } + + found = 0; + while (1) { + if (!jp) + goto err; + if (match(jp->ps[0].cmd, p)) { + if (found) + goto err; + found = jp; + err_msg = "%s: ambiguous"; + } + jp = jp->prev_job; + } + +gotit: +#if JOBS + err_msg = "job %s not created under job control"; + if (getctl && jp->jobctl == 0) + goto err; +#endif + return jp; +err: + sh_error(err_msg, name); +} + + + +/* + * Return a new job structure. + * Called with interrupts off. + */ + +struct job * +makejob(union node *node, int nprocs) +{ + int i; + struct job *jp; + + for (i = njobs, jp = jobtab ; ; jp++) { + if (--i < 0) { + jp = growjobtab(); + break; + } + if (jp->used == 0) + break; + if (jp->state != JOBDONE || !jp->waited) + continue; + if (jobctl) + continue; + freejob(jp); + break; + } + memset(jp, 0, sizeof(*jp)); +#if JOBS + if (jobctl) + jp->jobctl = 1; +#endif + jp->prev_job = curjob; + curjob = jp; + jp->used = 1; + jp->ps = &jp->ps0; + if (nprocs > 1) { + jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); + } + TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, + jobno(jp))); + return jp; +} + +STATIC struct job * +growjobtab(void) +{ + size_t len; + ptrdiff_t offset; + struct job *jp, *jq; + + len = njobs * sizeof(*jp); + jq = jobtab; + jp = ckrealloc(jq, len + 4 * sizeof(*jp)); + + offset = (char *)jp - (char *)jq; + if (offset) { + /* Relocate pointers */ + size_t l = len; + + jq = (struct job *)((char *)jq + l); + while (l) { + l -= sizeof(*jp); + jq--; +#define joff(p) ((struct job *)((char *)(p) + l)) +#define jmove(p) (p) = (void *)((char *)(p) + offset) + if (likely(joff(jp)->ps == &jq->ps0)) + jmove(joff(jp)->ps); + if (joff(jp)->prev_job) + jmove(joff(jp)->prev_job); + } + if (curjob) + jmove(curjob); +#undef joff +#undef jmove + } + + njobs += 4; + jobtab = jp; + jp = (struct job *)((char *)jp + len); + jq = jp + 3; + do { + jq->used = 0; + } while (--jq >= jp); + return jp; +} + + +/* + * Fork off a subshell. If we are doing job control, give the subshell its + * own process group. Jp is a job structure that the job is to be added to. + * N is the command that will be evaluated by the child. Both jp and n may + * be NULL. The mode parameter can be one of the following: + * FORK_FG - Fork off a foreground process. + * FORK_BG - Fork off a background process. + * FORK_NOJOB - Like FORK_FG, but don't give the process its own + * process group even if job control is on. + * + * When job control is turned off, background processes have their standard + * input redirected to /dev/null (except for the second and later processes + * in a pipeline). + * + * Called with interrupts off. + */ + +STATIC inline void +forkchild(struct job *jp, union node *n, int mode) +{ + int oldlvl; + + TRACE(("Child shell %d\n", getpid())); + oldlvl = shlvl; + shlvl++; + + closescript(); + clear_traps(); +#if JOBS + /* do job control only in root shell */ + jobctl = 0; + if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) { + pid_t pgrp; + + if (jp->nprocs == 0) + pgrp = getpid(); + else + pgrp = jp->ps[0].pid; + /* This can fail because we are doing it in the parent also */ + (void)setpgid(0, pgrp); + if (mode == FORK_FG) + xtcsetpgrp(ttyfd, pgrp); + setsignal(SIGTSTP); + setsignal(SIGTTOU); + } else +#endif + if (mode == FORK_BG) { + ignoresig(SIGINT); + ignoresig(SIGQUIT); + if (jp->nprocs == 0) { + close(0); + if (open(_PATH_DEVNULL, O_RDONLY) != 0) + sh_error("Can't open %s", _PATH_DEVNULL); + } + } + if (!oldlvl && iflag) { + setsignal(SIGINT); + setsignal(SIGQUIT); + setsignal(SIGTERM); + } + for (jp = curjob; jp; jp = jp->prev_job) + freejob(jp); + jobless = 0; +} + +STATIC inline void +forkparent(struct job *jp, union node *n, int mode, pid_t pid) +{ + TRACE(("In parent shell: child = %d\n", pid)); + if (!jp) { + while (jobless && dowait(DOWAIT_NORMAL, 0) > 0); + jobless++; + return; + } +#if JOBS + if (mode != FORK_NOJOB && jp->jobctl) { + int pgrp; + + if (jp->nprocs == 0) + pgrp = pid; + else + pgrp = jp->ps[0].pid; + /* This can fail because we are doing it in the child also */ + (void)setpgid(pid, pgrp); + } +#endif + if (mode == FORK_BG) { + backgndpid = pid; /* set $! */ + set_curjob(jp, CUR_RUNNING); + } + if (jp) { + struct procstat *ps = &jp->ps[jp->nprocs++]; + ps->pid = pid; + ps->status = -1; + ps->cmd = nullstr; + if (jobctl && n) + ps->cmd = commandtext(n); + } +} + +int +forkshell(struct job *jp, union node *n, int mode) +{ + int pid; + + TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); + pid = fork(); + if (pid < 0) { + TRACE(("Fork failed, errno=%d", errno)); + if (jp) + freejob(jp); + sh_error("Cannot fork"); + } + if (pid == 0) + forkchild(jp, n, mode); + else + forkparent(jp, n, mode, pid); + return pid; +} + +/* + * Wait for job to finish. + * + * Under job control we have the problem that while a child process is + * running interrupts generated by the user are sent to the child but not + * to the shell. This means that an infinite loop started by an inter- + * active user may be hard to kill. With job control turned off, an + * interactive user may place an interactive program inside a loop. If + * the interactive program catches interrupts, the user doesn't want + * these interrupts to also abort the loop. The approach we take here + * is to have the shell ignore interrupt signals while waiting for a + * forground process to terminate, and then send itself an interrupt + * signal if the child process was terminated by an interrupt signal. + * Unfortunately, some programs want to do a bit of cleanup and then + * exit on interrupt; unless these processes terminate themselves by + * sending a signal to themselves (instead of calling exit) they will + * confuse this approach. + * + * Called with interrupts off. + */ + +int +waitforjob(struct job *jp) +{ + int st; + + TRACE(("waitforjob(%%%d) called\n", jobno(jp))); + while (jp->state == JOBRUNNING) { + dowait(DOWAIT_BLOCK, jp); + } + st = getstatus(jp); +#if JOBS + if (jp->jobctl) { + xtcsetpgrp(ttyfd, rootpid); + /* + * This is truly gross. + * If we're doing job control, then we did a TIOCSPGRP which + * caused us (the shell) to no longer be in the controlling + * session -- so we wouldn't have seen any ^C/SIGINT. So, we + * intuit from the subprocess exit status whether a SIGINT + * occurred, and if so interrupt ourselves. Yuck. - mycroft + */ + if (jp->sigint) + raise(SIGINT); + } +#endif + if (! JOBS || jp->state == JOBDONE) + freejob(jp); + return st; +} + + + +/* + * Wait for a process to terminate. + */ + +STATIC int +dowait(int block, struct job *job) +{ + int pid; + int status; + struct job *jp; + struct job *thisjob; + int state; + + TRACE(("dowait(%d) called\n", block)); + pid = waitproc(block, &status); + TRACE(("wait returns pid %d, status=%d\n", pid, status)); + if (pid <= 0) + return pid; + INTOFF; + thisjob = NULL; + for (jp = curjob; jp; jp = jp->prev_job) { + struct procstat *sp; + struct procstat *spend; + if (jp->state == JOBDONE) + continue; + state = JOBDONE; + spend = jp->ps + jp->nprocs; + sp = jp->ps; + do { + if (sp->pid == pid) { + TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status)); + sp->status = status; + thisjob = jp; + } + if (sp->status == -1) + state = JOBRUNNING; +#if JOBS + if (state == JOBRUNNING) + continue; + if (WIFSTOPPED(sp->status)) { + jp->stopstatus = sp->status; + state = JOBSTOPPED; + } +#endif + } while (++sp < spend); + if (thisjob) + goto gotjob; + } + if (!JOBS || !WIFSTOPPED(status)) + jobless--; + goto out; + +gotjob: + if (state != JOBRUNNING) { + thisjob->changed = 1; + + if (thisjob->state != state) { + TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state)); + thisjob->state = state; +#if JOBS + if (state == JOBSTOPPED) { + set_curjob(thisjob, CUR_STOPPED); + } +#endif + } + } + +out: + INTON; + + if (thisjob && thisjob == job) { + char s[48 + 1]; + int len; + + len = sprint_status(s, status, 1); + if (len) { + s[len] = '\n'; + s[len + 1] = 0; + outstr(s, out2); + } + } + return pid; +} + + + +/* + * Do a wait system call. If job control is compiled in, we accept + * stopped processes. If block is zero, we return a value of zero + * rather than blocking. + * + * System V doesn't have a non-blocking wait system call. It does + * have a SIGCLD signal that is sent to a process when one of it's + * children dies. The obvious way to use SIGCLD would be to install + * a handler for SIGCLD which simply bumped a counter when a SIGCLD + * was received, and have waitproc bump another counter when it got + * the status of a process. Waitproc would then know that a wait + * system call would not block if the two counters were different. + * This approach doesn't work because if a process has children that + * have not been waited for, System V will send it a SIGCLD when it + * installs a signal handler for SIGCLD. What this means is that when + * a child exits, the shell will be sent SIGCLD signals continuously + * until is runs out of stack space, unless it does a wait call before + * restoring the signal handler. The code below takes advantage of + * this (mis)feature by installing a signal handler for SIGCLD and + * then checking to see whether it was called. If there are any + * children to be waited for, it will be. + * + * If neither SYSV nor BSD is defined, we don't implement nonblocking + * waits at all. In this case, the user will not be informed when + * a background process until the next time she runs a real program + * (as opposed to running a builtin command or just typing return), + * and the jobs command may give out of date information. + */ + +#ifdef SYSV +STATIC int gotsigchild; + +STATIC int onsigchild() { + gotsigchild = 1; +} +#endif + + +STATIC int +waitproc(int block, int *status) +{ +#ifdef BSD + int flags = 0; + +#if JOBS + if (jobctl) + flags |= WUNTRACED; +#endif + if (block == 0) + flags |= WNOHANG; + return wait3(status, flags, (struct rusage *)NULL); +#else +#ifdef SYSV + int (*save)(); + + if (block == 0) { + gotsigchild = 0; + save = signal(SIGCLD, onsigchild); + signal(SIGCLD, save); + if (gotsigchild == 0) + return 0; + } + return wait(status); +#else + if (block == 0) + return 0; + return wait(status); +#endif +#endif +} + +/* + * return 1 if there are stopped jobs, otherwise 0 + */ +int job_warning; +int +stoppedjobs(void) +{ + struct job *jp; + int retval; + + retval = 0; + if (job_warning) + goto out; + jp = curjob; + if (jp && jp->state == JOBSTOPPED) { + out2str("You have stopped jobs.\n"); + job_warning = 2; + retval++; + } + +out: + return retval; +} + +/* + * Return a string identifying a command (to be printed by the + * jobs command). + */ + +STATIC char *cmdnextc; + +STATIC char * +commandtext(union node *n) +{ + char *name; + + STARTSTACKSTR(cmdnextc); + cmdtxt(n); + name = stackblock(); + TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n", + name, cmdnextc, ps->cmd)); + return savestr(name); +} + + +STATIC void +cmdtxt(union node *n) +{ + union node *np; + struct nodelist *lp; + const char *p; + char s[2]; + + if (!n) + return; + switch (n->type) { + default: +#if DEBUG + abort(); +#endif + case NPIPE: + lp = n->npipe.cmdlist; + for (;;) { + cmdtxt(lp->n); + lp = lp->next; + if (!lp) + break; + cmdputs(" | "); + } + break; + case NSEMI: + p = "; "; + goto binop; + case NAND: + p = " && "; + goto binop; + case NOR: + p = " || "; +binop: + cmdtxt(n->nbinary.ch1); + cmdputs(p); + n = n->nbinary.ch2; + goto donode; + case NREDIR: + case NBACKGND: + n = n->nredir.n; + goto donode; + case NNOT: + cmdputs("!"); + n = n->nnot.com; +donode: + cmdtxt(n); + break; + case NIF: + cmdputs("if "); + cmdtxt(n->nif.test); + cmdputs("; then "); + n = n->nif.ifpart; + if (n->nif.elsepart) { + cmdtxt(n); + cmdputs("; else "); + n = n->nif.elsepart; + } + p = "; fi"; + goto dotail; + case NSUBSHELL: + cmdputs("("); + n = n->nredir.n; + p = ")"; + goto dotail; + case NWHILE: + p = "while "; + goto until; + case NUNTIL: + p = "until "; +until: + cmdputs(p); + cmdtxt(n->nbinary.ch1); + n = n->nbinary.ch2; + p = "; done"; +dodo: + cmdputs("; do "); +dotail: + cmdtxt(n); + goto dotail2; + case NFOR: + cmdputs("for "); + cmdputs(n->nfor.var); + cmdputs(" in "); + cmdlist(n->nfor.args, 1); + n = n->nfor.body; + p = "; done"; + goto dodo; + case NDEFUN: + cmdputs(n->narg.text); + p = "() { ... }"; + goto dotail2; + case NCMD: + cmdlist(n->ncmd.args, 1); + cmdlist(n->ncmd.redirect, 0); + break; + case NARG: + p = n->narg.text; +dotail2: + cmdputs(p); + break; + case NHERE: + case NXHERE: + p = "<<..."; + goto dotail2; + case NCASE: + cmdputs("case "); + cmdputs(n->ncase.expr->narg.text); + cmdputs(" in "); + for (np = n->ncase.cases; np; np = np->nclist.next) { + cmdtxt(np->nclist.pattern); + cmdputs(") "); + cmdtxt(np->nclist.body); + cmdputs(";; "); + } + p = "esac"; + goto dotail2; + case NTO: + p = ">"; + goto redir; + case NCLOBBER: + p = ">|"; + goto redir; + case NAPPEND: + p = ">>"; + goto redir; + case NTOFD: + p = ">&"; + goto redir; + case NFROM: + p = "<"; + goto redir; + case NFROMFD: + p = "<&"; + goto redir; + case NFROMTO: + p = "<>"; +redir: + s[0] = n->nfile.fd + '0'; + s[1] = '\0'; + cmdputs(s); + cmdputs(p); + if (n->type == NTOFD || n->type == NFROMFD) { + s[0] = n->ndup.dupfd + '0'; + p = s; + goto dotail2; + } else { + n = n->nfile.fname; + goto donode; + } + } +} + +STATIC void +cmdlist(union node *np, int sep) +{ + for (; np; np = np->narg.next) { + if (!sep) + cmdputs(spcstr); + cmdtxt(np); + if (sep && np->narg.next) + cmdputs(spcstr); + } +} + + +STATIC void +cmdputs(const char *s) +{ + const char *p, *str; + char cc[2] = " "; + char *nextc; + signed char c; + int subtype = 0; + int quoted = 0; + static const char vstype[VSTYPE + 1][4] = { + "", "}", "-", "+", "?", "=", + "%", "%%", "#", "##", + }; + + nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc); + p = s; + while ((c = *p++) != 0) { + str = 0; + switch (c) { + case CTLESC: + c = *p++; + break; + case CTLVAR: + subtype = *p++; + if ((subtype & VSTYPE) == VSLENGTH) + str = "${#"; + else + str = "${"; + if (!(subtype & VSQUOTE) != !(quoted & 1)) { + quoted ^= 1; + c = '"'; + } else + goto dostr; + break; + case CTLENDVAR: + str = "\"}" + !(quoted & 1); + quoted >>= 1; + subtype = 0; + goto dostr; + case CTLBACKQ: + str = "$(...)"; + goto dostr; + case CTLBACKQ+CTLQUOTE: + str = "\"$(...)\""; + goto dostr; + case CTLARI: + str = "$(("; + goto dostr; + case CTLENDARI: + str = "))"; + goto dostr; + case CTLQUOTEMARK: + quoted ^= 1; + c = '"'; + break; + case '=': + if (subtype == 0) + break; + if ((subtype & VSTYPE) != VSNORMAL) + quoted <<= 1; + str = vstype[subtype & VSTYPE]; + if (subtype & VSNUL) + c = ':'; + else + goto checkstr; + break; + case '\'': + case '\\': + case '"': + case '$': + /* These can only happen inside quotes */ + cc[0] = c; + str = cc; + c = '\\'; + break; + default: + break; + } + USTPUTC(c, nextc); +checkstr: + if (!str) + continue; +dostr: + while ((c = *str++)) { + USTPUTC(c, nextc); + } + } + if (quoted & 1) { + USTPUTC('"', nextc); + } + *nextc = 0; + cmdnextc = nextc; +} + + +STATIC void +showpipe(struct job *jp, struct output *out) +{ + struct procstat *sp; + struct procstat *spend; + + spend = jp->ps + jp->nprocs; + for (sp = jp->ps + 1; sp < spend; sp++) + outfmt(out, " | %s", sp->cmd); + outcslow('\n', out); + flushall(); +} + + +#if JOBS +STATIC void +xtcsetpgrp(int fd, pid_t pgrp) +{ + if (tcsetpgrp(fd, pgrp)) + sh_error("Cannot set tty process group (%s)", strerror(errno)); +} +#endif + + +STATIC int +getstatus(struct job *job) { + int status; + int retval; + + status = job->ps[job->nprocs - 1].status; + retval = WEXITSTATUS(status); + if (!WIFEXITED(status)) { +#if JOBS + retval = WSTOPSIG(status); + if (!WIFSTOPPED(status)) +#endif + { + /* XXX: limits number of signals */ + retval = WTERMSIG(status); +#if JOBS + if (retval == SIGINT) + job->sigint = 1; +#endif + } + retval += 128; + } + TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n", + jobno(job), job->nprocs, status, retval)); + return retval; +} diff -puN /dev/null usr/dash/jobs.h --- /dev/null +++ a/usr/dash/jobs.h @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)jobs.h 8.2 (Berkeley) 5/4/95 + */ + +#include +#include + +/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */ +#define FORK_FG 0 +#define FORK_BG 1 +#define FORK_NOJOB 2 + +/* mode flags for showjob(s) */ +#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */ +#define SHOW_PID 0x04 /* include process pid */ +#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */ + + +/* + * A job structure contains information about a job. A job is either a + * single process or a set of processes contained in a pipeline. In the + * latter case, pidlist will be non-NULL, and will point to a -1 terminated + * array of pids. + */ + +struct procstat { + pid_t pid; /* process id */ + int status; /* last process status from wait() */ + char *cmd; /* text of command being run */ +}; + +struct job { + struct procstat ps0; /* status of process */ + struct procstat *ps; /* status or processes when more than one */ +#if JOBS + int stopstatus; /* status of a stopped job */ +#endif + uint32_t + nprocs: 16, /* number of processes */ + state: 8, +#define JOBRUNNING 0 /* at least one proc running */ +#define JOBSTOPPED 1 /* all procs are stopped */ +#define JOBDONE 2 /* all procs are completed */ +#if JOBS + sigint: 1, /* job was killed by SIGINT */ + jobctl: 1, /* job running under job control */ +#endif + waited: 1, /* true if this entry has been waited for */ + used: 1, /* true if this entry is in used */ + changed: 1; /* true if status has changed */ + struct job *prev_job; /* previous job */ +}; + +extern pid_t backgndpid; /* pid of last background process */ +extern int job_warning; /* user was warned about stopped jobs */ +#if JOBS +extern int jobctl; /* true if doing job control */ +#else +#define jobctl 0 +#endif + +void setjobctl(int); +int killcmd(int, char **); +int fgcmd(int, char **); +int bgcmd(int, char **); +int jobscmd(int, char **); +struct output; +void showjobs(struct output *, int); +int waitcmd(int, char **); +struct job *makejob(union node *, int); +int forkshell(struct job *, union node *, int); +int waitforjob(struct job *); +int stoppedjobs(void); + +#if ! JOBS +#define setjobctl(on) /* do nothing */ +#endif diff -puN /dev/null usr/dash/Kbuild --- /dev/null +++ a/usr/dash/Kbuild @@ -0,0 +1,146 @@ +# +# Kbuild file for dash +# + +COMMON_CFLAGS := +COMMON_CPPFLAGS := \ + -DBSD=1 -DSMALL -DSHELL \ + -DGLOB_BROKEN -DFNMATCH_BROKEN -DIFS_BROKEN \ + -DJOBS=0 + +CFLAGS := $(COMMON_CFLAGS) +CPPFLAGS := $(COMMON_CPPFLAGS) +CFLAGS_FOR_BUILD := $(COMMON_CFLAGS) +CPPFLAGS_FOR_BUILD := $(COMMON_CPPFLAGS) + +DEFS := -DHAVE_CONFIG_H +DEFAULT_INCLUDES := \ + -I$(srctree)/$(src) -I$(objtree)/$(obj) \ + -include $(srctree)/$(src)/config.h + +EXTRA_KLIBCCFLAGS := $(DEFS) $(DEFAULT_INCLUDES) $(CPPFLAGS) $(CFLAGS) +HOST_EXTRACFLAGS := $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) + +SRCS := alias.c arith_yylex.c cd.c error.c eval.c exec.c expand.c \ + histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \ + mystring.c options.c parser.c redir.c show.c trap.c output.c \ + bltin/printf.c system.c bltin/test.c var.c + +OBJ1 := builtins.o init.o nodes.o syntax.o +OBJ2 := alias.o arith.o arith_yylex.o cd.o \ + error.o eval.o exec.o expand.o \ + histedit.o input.o jobs.o \ + mail.o main.o memalloc.o \ + miscbltin.o mystring.o options.o \ + parser.o redir.o show.o trap.o \ + output.o bltin/printf.o system.o \ + bltin/test.o var.o + +OBJS := $(OBJ1) $(OBJ2) + +HELPERS := mkinit mksyntax mknodes mksignames +BUILT_SOURCES := arith.h builtins.h nodes.h syntax.h token.h +CLEANFILES := \ + $(BUILT_SOURCES) $(patsubst %.o,%.c,$(OBJ1)) \ + arith.c $(HELPERS) builtins.def + +static-y := sh + +sh-y := $(OBJS) + +# The shared binary +shared-y := sh.shared +sh.shared-y := $(sh-y) + +hostprogs-y := $(HELPERS) + +# For cleaning +targets := sh sh.g sh.shared sh.shared.g $(CLEANFILES) + +$(addprefix $(obj)/, $(OBJS)): $(addprefix $(obj)/, $(BUILT_SOURCES)) + +# Generate token.h +quiet_cmd_mktokens = GEN $@ + cmd_mktokens = sh $< > $@ +$(obj)/token.h: $(src)/mktokens + $(call cmd,mktokens) + +# Generate builtins.def +targets += builtins.def +quiet_cmd_mkbuiltins_def = GEN $@ + cmd_mkbuiltins_def = $(HOSTCC) $(hostc_flags) -x c -E -o $@ $< +$(obj)/builtins.def: $(src)/builtins.def.in $(src)/config.h + $(call cmd,mkbuiltins_def) + +# Generate builtins{.c + .h} +quiet_cmd_mkbuiltins = GEN $@ + cmd_mkbuiltins = mkdir -p $(obj)/bltin && cd $(obj) && \ + sh $(srctree)/$(src)/mkbuiltins builtins.def +$(obj)/builtins.c: $(src)/mkbuiltins $(obj)/builtins.def + $(call cmd,mkbuiltins) + +# side effect.. +$(obj)/builtins.h: $(obj)/builtins.c + $(Q): + +# Generate init.c +quiet_cmd_mkinit = GEN $@ + cmd_mkinit = cd $(obj) && ./mkinit $(addprefix $(srctree)/$(src)/, $(SRCS)) +$(obj)/init.c: $(obj)/mkinit $(addprefix $(src)/, $(SRCS)) + $(call cmd,mkinit) + +# Generate nodes{.c + .h} +quiet_cmd_mknodes = GEN $@ + cmd_mknodes = cd $(obj) && ./mknodes $(srctree)/$(src)/nodetypes \ + $(srctree)/$(src)/nodes.c.pat +$(obj)/nodes.c: $(obj)/mknodes $(src)/nodetypes $(src)/nodes.c.pat + $(call cmd,mknodes) + +quiet_cmd_mknodes_h = DUMMY $@ + cmd_mknodes_h = : +$(obj)/nodes.h: $(obj)/nodes.c + $(call cmd,mknodes_h) + +quiet_cmd_mksyntax = GEN $@ + cmd_mksyntax = cd $(obj) && ./mksyntax +$(obj)/syntax.c: $(obj)/mksyntax + $(call cmd,mksyntax) + +# side effect.. +$(obj)/syntax.h: $(obj)/syntax.c + $(Q): + +BISON := bison + +quiet_cmd_bison = BISON $@ + cmd_bison = $(BISON) -d -o $@ $< + +$(obj)/%.c %(obj)/%.h: $(src)/%.y + $(call cmd,bison) + +$(obj)/arith.c $(obj)/arith.h: $(src)/arith.y + +# Targets to install +install-y := sh.shared + +# Dependencies on generated files. This really should be automated. +$(obj)/arith_yylex.o: $(obj)/arith.h +$(obj)/builtins.o: $(obj)/builtins.h +$(obj)/cd.o: $(obj)/nodes.h +$(obj)/eval.o: $(obj)/nodes.h $(obj)/syntax.h $(obj)/builtins.h +$(obj)/exec.o: $(obj)/nodes.h $(obj)/builtins.h $(obj)/syntax.h +$(obj)/expand.o: $(obj)/nodes.h $(obj)/syntax.h +$(obj)/input.o: $(obj)/syntax.h +$(obj)/jobs.o: $(obj)/nodes.h $(obj)/syntax.h +$(obj)/mail.o: $(obj)/nodes.h +$(obj)/main.o: $(obj)/nodes.h +$(obj)/mystring.o: $(obj)/syntax.h +$(obj)/nodes.o: $(obj)/nodes.h +$(obj)/options.o: $(obj)/nodes.h +$(obj)/output.o: $(obj)/syntax.h +$(obj)/parser.o: $(obj)/nodes.h $(obj)/syntax.h $(obj)/builtins.h $(obj)/token.h +$(obj)/redir.o: $(obj)/nodes.h +$(obj)/show.o: $(obj)/nodes.h +$(obj)/syntax.o: $(obj)/syntax.h +$(obj)/trap.o: $(obj)/nodes.h $(obj)/syntax.h +$(obj)/var.o: $(obj)/nodes.h $(obj)/syntax.h diff -puN /dev/null usr/dash/machdep.h --- /dev/null +++ a/usr/dash/machdep.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)machdep.h 8.2 (Berkeley) 5/4/95 + */ + +#include "config.h" + +/* + * Most machines require the value returned from malloc to be aligned + * in some way. The following macro will get this right on many machines. + */ +#ifdef HAVE_STRTOD +# define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1) +#else +# define SHELL_SIZE (sizeof(union {int i; char *cp;}) - 1) +#endif + +/* + * It appears that grabstackstr() will barf with such alignments + * because stalloc() will return a string allocated in a new stackblock. + */ +#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE) diff -puN /dev/null usr/dash/mail.c --- /dev/null +++ a/usr/dash/mail.c @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Routines to check for mail. (Perhaps make part of main.c?) + */ +#include +#include +#include + +#include "shell.h" +#include "nodes.h" +#include "exec.h" /* defines padvance() */ +#include "var.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "mail.h" +#include "mystring.h" + + +#define MAXMBOXES 10 + +/* times of mailboxes */ +static time_t mailtime[MAXMBOXES]; +/* Set if MAIL or MAILPATH is changed. */ +static int changed; + + + +/* + * Print appropriate message(s) if mail has arrived. If changed is set, + * then the value of MAIL has changed, so we just update the values. + */ + +void +chkmail(void) +{ + const char *mpath; + char *p; + char *q; + time_t *mtp; + struct stackmark smark; + struct stat64 statb; + + setstackmark(&smark); + mpath = mpathset() ? mpathval() : mailval(); + for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) { + p = padvance(&mpath, nullstr); + if (p == NULL) + break; + if (*p == '\0') + continue; + for (q = p ; *q ; q++); +#ifdef DEBUG + if (q[-1] != '/') + abort(); +#endif + q[-1] = '\0'; /* delete trailing '/' */ + if (stat64(p, &statb) < 0) { + *mtp = 0; + continue; + } + if (!changed && statb.st_mtime != *mtp) { + outfmt( + &errout, snlfmt, + pathopt ? pathopt : "you have mail" + ); + } + *mtp = statb.st_mtime; + } + changed = 0; + popstackmark(&smark); +} + + +void +changemail(const char *val) +{ + changed++; +} diff -puN /dev/null usr/dash/mail.h --- /dev/null +++ a/usr/dash/mail.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mail.h 8.2 (Berkeley) 5/4/95 + */ + +void chkmail(void); +void changemail(const char *); diff -puN /dev/null usr/dash/main.c --- /dev/null +++ a/usr/dash/main.c @@ -0,0 +1,349 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + + +#include "shell.h" +#include "main.h" +#include "mail.h" +#include "options.h" +#include "output.h" +#include "parser.h" +#include "nodes.h" +#include "expand.h" +#include "eval.h" +#include "jobs.h" +#include "input.h" +#include "trap.h" +#include "var.h" +#include "show.h" +#include "memalloc.h" +#include "error.h" +#include "init.h" +#include "mystring.h" +#include "exec.h" +#include "cd.h" + +#ifdef HETIO +#include "hetio.h" +#endif + +#define PROFILE 0 + +int rootpid; +int shlvl; +#ifdef __GLIBC__ +int *dash_errno; +#endif +#if PROFILE +short profile_buf[16384]; +extern int etext(); +#endif + +STATIC void read_profile(const char *); +STATIC char *find_dot_file(char *); +static int cmdloop(int); +int main(int, char **); + +/* + * Main routine. We initialize things, parse the arguments, execute + * profiles if we're a login shell, and then call cmdloop to execute + * commands. The setjmp call sets up the location to jump to when an + * exception occurs. When an exception occurs the variable "state" + * is used to figure out how far we had gotten. + */ + +int +main(int argc, char **argv) +{ + char *shinit; + volatile int state; + struct jmploc jmploc; + struct stackmark smark; + +#ifdef __GLIBC__ + dash_errno = __errno_location(); +#endif + +#if PROFILE + monitor(4, etext, profile_buf, sizeof profile_buf, 50); +#endif + state = 0; + if (unlikely(setjmp(jmploc.loc))) { + int e; + int s; + + reset(); + + e = exception; + if (e == EXERROR) + exitstatus = 2; + + s = state; + if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) + exitshell(); + + if (e == EXINT +#if ATTY + && (! attyset() || equal(termval(), "emacs")) +#endif + ) { + out2c('\n'); +#ifdef FLUSHERR + flushout(out2); +#endif + } + popstackmark(&smark); + FORCEINTON; /* enable interrupts */ + if (s == 1) + goto state1; + else if (s == 2) + goto state2; + else if (s == 3) + goto state3; + else + goto state4; + } + handler = &jmploc; +#ifdef DEBUG + opentrace(); + trputs("Shell args: "); trargs(argv); +#endif + rootpid = getpid(); + init(); + setstackmark(&smark); + procargs(argc, argv); + if (argv[0] && argv[0][0] == '-') { + state = 1; + read_profile("/etc/profile"); +state1: + state = 2; + read_profile(".profile"); + } +state2: + state = 3; + if ( +#ifndef linux + getuid() == geteuid() && getgid() == getegid() && +#endif + iflag + ) { + if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { + read_profile(shinit); + } + } +state3: + state = 4; + if (minusc) + evalstring(minusc, 0); + + if (sflag || minusc == NULL) { +state4: /* XXX ??? - why isn't this before the "if" statement */ + cmdloop(1); + } +#if PROFILE + monitor(0); +#endif +#if GPROF + { + extern void _mcleanup(void); + _mcleanup(); + } +#endif + exitshell(); + /* NOTREACHED */ +} + + +/* + * Read and execute commands. "Top" is nonzero for the top level command + * loop; it turns on prompting if the shell is interactive. + */ + +static int +cmdloop(int top) +{ + union node *n; + struct stackmark smark; + int inter; + int numeof = 0; + + TRACE(("cmdloop(%d) called\n", top)); +#ifdef HETIO + if(iflag && top) + hetio_init(); +#endif + for (;;) { + int skip; + + setstackmark(&smark); + if (jobctl) + showjobs(out2, SHOW_CHANGED); + inter = 0; + if (iflag && top) { + inter++; + chkmail(); + } + n = parsecmd(inter); + /* showtree(n); DEBUG */ + if (n == NEOF) { + if (!top || numeof >= 50) + break; + if (!stoppedjobs()) { + if (!Iflag) + break; + out2str("\nUse \"exit\" to leave shell.\n"); + } + numeof++; + } else if (nflag == 0) { + job_warning = (job_warning == 2) ? 1 : 0; + numeof = 0; + evaltree(n, 0); + } + popstackmark(&smark); + + skip = evalskip; + if (skip) { + evalskip = 0; + return skip & SKIPEVAL; + } + } + + return 0; +} + + + +/* + * Read /etc/profile or .profile. Return on error. + */ + +STATIC void +read_profile(const char *name) +{ + int skip; + + if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0) + return; + + skip = cmdloop(0); + popfile(); + + if (skip) + exitshell(); +} + + + +/* + * Read a file containing shell functions. + */ + +void +readcmdfile(char *name) +{ + setinputfile(name, INPUT_PUSH_FILE); + cmdloop(0); + popfile(); +} + + + +/* + * Take commands from a file. To be compatible we should do a path + * search for the file, which is necessary to find sub-commands. + */ + + +STATIC char * +find_dot_file(char *basename) +{ + char *fullname; + const char *path = pathval(); + struct stat statb; + + /* don't try this for absolute or relative paths */ + if (strchr(basename, '/')) + return basename; + + while ((fullname = padvance(&path, basename)) != NULL) { + if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { + /* + * Don't bother freeing here, since it will + * be freed by the caller. + */ + return fullname; + } + stunalloc(fullname); + } + + /* not found in the PATH */ + sh_error("%s: not found", basename); + /* NOTREACHED */ +} + +int +dotcmd(int argc, char **argv) +{ + int status = 0; + + if (argc >= 2) { /* That's what SVR2 does */ + char *fullname; + + fullname = find_dot_file(argv[1]); + setinputfile(fullname, INPUT_PUSH_FILE); + commandname = fullname; + cmdloop(0); + popfile(); + status = exitstatus; + } + return status; +} + + +int +exitcmd(int argc, char **argv) +{ + if (stoppedjobs()) + return 0; + if (argc > 1) + exitstatus = number(argv[1]); + exraise(EXEXIT); + /* NOTREACHED */ +} diff -puN /dev/null usr/dash/main.h --- /dev/null +++ a/usr/dash/main.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)main.h 8.2 (Berkeley) 5/4/95 + */ + +#include + +/* pid of main shell */ +extern int rootpid; +/* shell level: 0 for the main shell, 1 for its children, and so on */ +extern int shlvl; +#define rootshell (!shlvl) + +#ifdef __GLIBC__ +/* glibc sucks */ +extern int *dash_errno; +#undef errno +#define errno (*dash_errno) +#endif + +void readcmdfile(char *); +int dotcmd(int, char **); +int exitcmd(int, char **); diff -puN /dev/null usr/dash/memalloc.c --- /dev/null +++ a/usr/dash/memalloc.c @@ -0,0 +1,329 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "shell.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "machdep.h" +#include "mystring.h" +#include "system.h" + +/* + * Like malloc, but returns an error when out of space. + */ + +pointer +ckmalloc(size_t nbytes) +{ + pointer p; + + p = malloc(nbytes); + if (p == NULL) + sh_error("Out of space"); + return p; +} + + +/* + * Same for realloc. + */ + +pointer +ckrealloc(pointer p, size_t nbytes) +{ + p = realloc(p, nbytes); + if (p == NULL) + sh_error("Out of space"); + return p; +} + + +/* + * Make a copy of a string in safe storage. + */ + +char * +savestr(const char *s) +{ + char *p = strdup(s); + if (!p) + sh_error("Out of space"); + return p; +} + + +/* + * Parse trees for commands are allocated in lifo order, so we use a stack + * to make this more efficient, and also to avoid all sorts of exception + * handling code to handle interrupts in the middle of a parse. + * + * The size 504 was chosen because the Ultrix malloc handles that size + * well. + */ + +/* minimum size of a block */ +#define MINSIZE SHELL_ALIGN(504) + +struct stack_block { + struct stack_block *prev; + char space[MINSIZE]; +}; + +struct stack_block stackbase; +struct stack_block *stackp = &stackbase; +struct stackmark *markp; +char *stacknxt = stackbase.space; +size_t stacknleft = MINSIZE; +char *sstrend = stackbase.space + MINSIZE; +int herefd = -1; + +pointer +stalloc(size_t nbytes) +{ + char *p; + size_t aligned; + + aligned = SHELL_ALIGN(nbytes); + if (aligned > stacknleft) { + size_t len; + size_t blocksize; + struct stack_block *sp; + + blocksize = aligned; + if (blocksize < MINSIZE) + blocksize = MINSIZE; + len = sizeof(struct stack_block) - MINSIZE + blocksize; + if (len < blocksize) + sh_error("Out of space"); + INTOFF; + sp = ckmalloc(len); + sp->prev = stackp; + stacknxt = sp->space; + stacknleft = blocksize; + sstrend = stacknxt + blocksize; + stackp = sp; + INTON; + } + p = stacknxt; + stacknxt += aligned; + stacknleft -= aligned; + return p; +} + + +void +stunalloc(pointer p) +{ +#ifdef DEBUG + if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) { + write(2, "stunalloc\n", 10); + abort(); + } +#endif + stacknleft += stacknxt - (char *)p; + stacknxt = p; +} + + + +void +setstackmark(struct stackmark *mark) +{ + mark->stackp = stackp; + mark->stacknxt = stacknxt; + mark->stacknleft = stacknleft; + mark->marknext = markp; + markp = mark; +} + + +void +popstackmark(struct stackmark *mark) +{ + struct stack_block *sp; + + INTOFF; + markp = mark->marknext; + while (stackp != mark->stackp) { + sp = stackp; + stackp = sp->prev; + ckfree(sp); + } + stacknxt = mark->stacknxt; + stacknleft = mark->stacknleft; + sstrend = mark->stacknxt + mark->stacknleft; + INTON; +} + + +/* + * When the parser reads in a string, it wants to stick the string on the + * stack and only adjust the stack pointer when it knows how big the + * string is. Stackblock (defined in stack.h) returns a pointer to a block + * of space on top of the stack and stackblocklen returns the length of + * this block. Growstackblock will grow this space by at least one byte, + * possibly moving it (like realloc). Grabstackblock actually allocates the + * part of the block that has been used. + */ + +void +growstackblock(void) +{ + size_t newlen; + + newlen = stacknleft * 2; + if (newlen < stacknleft) + sh_error("Out of space"); + if (newlen < 128) + newlen += 128; + + if (stacknxt == stackp->space && stackp != &stackbase) { + struct stack_block *oldstackp; + struct stackmark *xmark; + struct stack_block *sp; + struct stack_block *prevstackp; + size_t grosslen; + + INTOFF; + oldstackp = stackp; + sp = stackp; + prevstackp = sp->prev; + grosslen = newlen + sizeof(struct stack_block) - MINSIZE; + sp = ckrealloc((pointer)sp, grosslen); + sp->prev = prevstackp; + stackp = sp; + stacknxt = sp->space; + stacknleft = newlen; + sstrend = sp->space + newlen; + + /* + * Stack marks pointing to the start of the old block + * must be relocated to point to the new block + */ + xmark = markp; + while (xmark != NULL && xmark->stackp == oldstackp) { + xmark->stackp = stackp; + xmark->stacknxt = stacknxt; + xmark->stacknleft = stacknleft; + xmark = xmark->marknext; + } + INTON; + } else { + char *oldspace = stacknxt; + int oldlen = stacknleft; + char *p = stalloc(newlen); + + /* free the space we just allocated */ + stacknxt = memcpy(p, oldspace, oldlen); + stacknleft += newlen; + } +} + +void +grabstackblock(size_t len) +{ + len = SHELL_ALIGN(len); + stacknxt += len; + stacknleft -= len; +} + +/* + * The following routines are somewhat easier to use than the above. + * The user declares a variable of type STACKSTR, which may be declared + * to be a register. The macro STARTSTACKSTR initializes things. Then + * the user uses the macro STPUTC to add characters to the string. In + * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is + * grown as necessary. When the user is done, she can just leave the + * string there and refer to it using stackblock(). Or she can allocate + * the space for it using grabstackstr(). If it is necessary to allow + * someone else to use the stack temporarily and then continue to grow + * the string, the user should use grabstack to allocate the space, and + * then call ungrabstr(p) to return to the previous mode of operation. + * + * USTPUTC is like STPUTC except that it doesn't check for overflow. + * CHECKSTACKSPACE can be called before USTPUTC to ensure that there + * is space for at least one character. + */ + +void * +growstackstr(void) +{ + size_t len = stackblocksize(); + if (herefd >= 0 && len >= 1024) { + xwrite(herefd, stackblock(), len); + return stackblock(); + } + growstackblock(); + return stackblock() + len; +} + +/* + * Called from CHECKSTRSPACE. + */ + +char * +makestrspace(size_t newlen, char *p) +{ + size_t len = p - stacknxt; + size_t size = stackblocksize(); + + for (;;) { + size_t nleft; + + size = stackblocksize(); + nleft = size - len; + if (nleft >= newlen) + break; + growstackblock(); + } + return stackblock() + len; +} + +char * +stnputs(const char *s, size_t n, char *p) +{ + p = makestrspace(n, p); + p = mempcpy(p, s, n); + return p; +} + +char * +stputs(const char *s, char *p) +{ + return stnputs(s, strlen(s), p); +} diff -puN /dev/null usr/dash/memalloc.h --- /dev/null +++ a/usr/dash/memalloc.h @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)memalloc.h 8.2 (Berkeley) 5/4/95 + */ + +#include + +struct stackmark { + struct stack_block *stackp; + char *stacknxt; + size_t stacknleft; + struct stackmark *marknext; +}; + + +extern char *stacknxt; +extern size_t stacknleft; +extern char *sstrend; +extern int herefd; + +pointer ckmalloc(size_t); +pointer ckrealloc(pointer, size_t); +char *savestr(const char *); +pointer stalloc(size_t); +void stunalloc(pointer); +void setstackmark(struct stackmark *); +void popstackmark(struct stackmark *); +void growstackblock(void); +void grabstackblock(size_t); +void *growstackstr(void); +char *makestrspace(size_t, char *); +char *stnputs(const char *, size_t, char *); +char *stputs(const char *, char *); + + +static inline char *_STPUTC(char c, char *p) { + if (p == sstrend) + p = growstackstr(); + *p++ = c; + return p; +} + +#define stackblock() ((void *)stacknxt) +#define stackblocksize() stacknleft +#define STARTSTACKSTR(p) ((p) = stackblock()) +#define STPUTC(c, p) ((p) = _STPUTC((c), (p))) +#define CHECKSTRSPACE(n, p) \ + ({ \ + char *q = (p); \ + size_t l = (n); \ + size_t m = sstrend - q; \ + if (l > m) \ + (p) = makestrspace(l, q); \ + 0; \ + }) +#define USTPUTC(c, p) (*p++ = (c)) +#define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0')) +#define STUNPUTC(p) (--p) +#define STTOPC(p) p[-1] +#define STADJUST(amount, p) (p += (amount)) + +#define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock()) +#define ungrabstackstr(s, p) stunalloc((s)) +#define stackstrend() ((void *)sstrend) + +#define ckfree(p) free((pointer)(p)) diff -puN /dev/null usr/dash/miscbltin.c --- /dev/null +++ a/usr/dash/miscbltin.c @@ -0,0 +1,457 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Miscelaneous builtins. + */ + +#include /* quad_t */ +#include /* BSD4_4 */ +#include +#include +#include +#include +#include +#include +#include + +#include "shell.h" +#include "options.h" +#include "var.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "miscbltin.h" +#include "mystring.h" +#include "main.h" + +#undef rflag + + + +/* + * The read builtin. The -e option causes backslashes to escape the + * following character. + * + * This uses unbuffered input, which may be avoidable in some cases. + */ + +int +readcmd(int argc, char **argv) +{ + char **ap; + int backslash; + char c; + int rflag; + char *prompt; + const char *ifs; + char *p; + int startword; + int status; + int i; + + rflag = 0; + prompt = NULL; + while ((i = nextopt("p:r")) != '\0') { + if (i == 'p') + prompt = optionarg; + else + rflag = 1; + } + if (prompt && isatty(0)) { + out2str(prompt); +#ifdef FLUSHERR + flushall(); +#endif + } + if (*(ap = argptr) == NULL) + sh_error("arg count"); + if ((ifs = bltinlookup("IFS")) == NULL) + ifs = defifs; + status = 0; + startword = 1; + backslash = 0; + STARTSTACKSTR(p); + for (;;) { + if (read(0, &c, 1) != 1) { + status = 1; + break; + } + if (c == '\0') + continue; + if (backslash) { + backslash = 0; + if (c != '\n') + goto put; + continue; + } + if (!rflag && c == '\\') { + backslash++; + continue; + } + if (c == '\n') + break; + if (startword && *ifs == ' ' && strchr(ifs, c)) { + continue; + } + startword = 0; + if (ap[1] != NULL && strchr(ifs, c) != NULL) { + STACKSTRNUL(p); + setvar(*ap, stackblock(), 0); + ap++; + startword = 1; + STARTSTACKSTR(p); + } else { +put: + STPUTC(c, p); + } + } + STACKSTRNUL(p); + /* Remove trailing blanks */ + while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL) + *p = '\0'; + setvar(*ap, stackblock(), 0); + while (*++ap != NULL) + setvar(*ap, nullstr, 0); + return status; +} + + + +/* + * umask builtin + * + * This code was ripped from pdksh 5.2.14 and hacked for use with + * dash by Herbert Xu. + * + * Public domain. + */ + +int +umaskcmd(int argc, char **argv) +{ + char *ap; + int mask; + int i; + int symbolic_mode = 0; + + while ((i = nextopt("S")) != '\0') { + symbolic_mode = 1; + } + + INTOFF; + mask = umask(0); + umask(mask); + INTON; + + if ((ap = *argptr) == NULL) { + if (symbolic_mode) { + char buf[18]; + int j; + + mask = ~mask; + ap = buf; + for (i = 0; i < 3; i++) { + *ap++ = "ugo"[i]; + *ap++ = '='; + for (j = 0; j < 3; j++) + if (mask & (1 << (8 - (3*i + j)))) + *ap++ = "rwx"[j]; + *ap++ = ','; + } + ap[-1] = '\0'; + out1fmt("%s\n", buf); + } else { + out1fmt("%.4o\n", mask); + } + } else { + int new_mask; + + if (isdigit(*ap)) { + new_mask = 0; + do { + if (*ap >= '8' || *ap < '0') + sh_error(illnum, *argptr); + new_mask = (new_mask << 3) + (*ap - '0'); + } while (*++ap != '\0'); + } else { + int positions, new_val; + char op; + + mask = ~mask; + new_mask = mask; + positions = 0; + while (*ap) { + while (*ap && strchr("augo", *ap)) + switch (*ap++) { + case 'a': positions |= 0111; break; + case 'u': positions |= 0100; break; + case 'g': positions |= 0010; break; + case 'o': positions |= 0001; break; + } + if (!positions) + positions = 0111; /* default is a */ + if (!strchr("=+-", op = *ap)) + break; + ap++; + new_val = 0; + while (*ap && strchr("rwxugoXs", *ap)) + switch (*ap++) { + case 'r': new_val |= 04; break; + case 'w': new_val |= 02; break; + case 'x': new_val |= 01; break; + case 'u': new_val |= mask >> 6; + break; + case 'g': new_val |= mask >> 3; + break; + case 'o': new_val |= mask >> 0; + break; + case 'X': if (mask & 0111) + new_val |= 01; + break; + case 's': /* ignored */ + break; + } + new_val = (new_val & 07) * positions; + switch (op) { + case '-': + new_mask &= ~new_val; + break; + case '=': + new_mask = new_val + | (new_mask & ~(positions * 07)); + break; + case '+': + new_mask |= new_val; + } + if (*ap == ',') { + positions = 0; + ap++; + } else if (!strchr("=+-", *ap)) + break; + } + if (*ap) { + sh_error("Illegal mode: %s", *argptr); + return 1; + } + new_mask = ~new_mask; + } + umask(new_mask); + } + return 0; +} + +#ifdef HAVE_GETRLIMIT +/* + * ulimit builtin + * + * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and + * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with + * ash by J.T. Conklin. + * + * Public domain. + */ + +struct limits { + const char *name; + int cmd; + int factor; /* multiply by to get rlim_{cur,max} values */ + char option; +}; + +static const struct limits limits[] = { +#ifdef RLIMIT_CPU + { "time(seconds)", RLIMIT_CPU, 1, 't' }, +#endif +#ifdef RLIMIT_FSIZE + { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, +#endif +#ifdef RLIMIT_DATA + { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, +#endif +#ifdef RLIMIT_STACK + { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, +#endif +#ifdef RLIMIT_CORE + { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, +#endif +#ifdef RLIMIT_RSS + { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, +#endif +#ifdef RLIMIT_MEMLOCK + { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, +#endif +#ifdef RLIMIT_NPROC + { "process", RLIMIT_NPROC, 1, 'p' }, +#endif +#ifdef RLIMIT_NOFILE + { "nofiles", RLIMIT_NOFILE, 1, 'n' }, +#endif +#ifdef RLIMIT_AS + { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' }, +#endif +#ifdef RLIMIT_LOCKS + { "locks", RLIMIT_LOCKS, 1, 'w' }, +#endif + { (char *) 0, 0, 0, '\0' } +}; + +enum limtype { SOFT = 0x1, HARD = 0x2 }; + +static void printlim(enum limtype how, const struct rlimit *limit, + const struct limits *l) +{ + rlim_t val; + + val = limit->rlim_max; + if (how & SOFT) + val = limit->rlim_cur; + + if (val == RLIM_INFINITY) + out1fmt("unlimited\n"); + else { + val /= l->factor; + out1fmt("%jd\n", (intmax_t) val); + } +} + +int +ulimitcmd(int argc, char **argv) +{ + int c; + rlim_t val = 0; + enum limtype how = SOFT | HARD; + const struct limits *l; + int set, all = 0; + int optc, what; + struct rlimit limit; + + what = 'f'; + while ((optc = nextopt("HSa" +#ifdef RLIMIT_CPU + "t" +#endif +#ifdef RLIMIT_FSIZE + "f" +#endif +#ifdef RLIMIT_DATA + "d" +#endif +#ifdef RLIMIT_STACK + "s" +#endif +#ifdef RLIMIT_CORE + "c" +#endif +#ifdef RLIMIT_RSS + "m" +#endif +#ifdef RLIMIT_MEMLOCK + "l" +#endif +#ifdef RLIMIT_NPROC + "p" +#endif +#ifdef RLIMIT_NOFILE + "n" +#endif +#ifdef RLIMIT_AS + "v" +#endif +#ifdef RLIMIT_LOCKS + "w" +#endif + )) != '\0') + switch (optc) { + case 'H': + how = HARD; + break; + case 'S': + how = SOFT; + break; + case 'a': + all = 1; + break; + default: + what = optc; + } + + for (l = limits; l->option != what; l++) + ; + + set = *argptr ? 1 : 0; + if (set) { + char *p = *argptr; + + if (all || argptr[1]) + sh_error("too many arguments"); + if (strcmp(p, "unlimited") == 0) + val = RLIM_INFINITY; + else { + val = (rlim_t) 0; + + while ((c = *p++) >= '0' && c <= '9') + { + val = (val * 10) + (long)(c - '0'); + if (val < (rlim_t) 0) + break; + } + if (c) + sh_error("bad number"); + val *= l->factor; + } + } + if (all) { + for (l = limits; l->name; l++) { + getrlimit(l->cmd, &limit); + out1fmt("%-20s ", l->name); + printlim(how, &limit, l); + } + return 0; + } + + getrlimit(l->cmd, &limit); + if (set) { + if (how & HARD) + limit.rlim_max = val; + if (how & SOFT) + limit.rlim_cur = val; + if (setrlimit(l->cmd, &limit) < 0) + sh_error("error setting limit (%s)", strerror(errno)); + } else { + printlim(how, &limit, l); + } + return 0; +} +#endif diff -puN /dev/null usr/dash/miscbltin.h --- /dev/null +++ a/usr/dash/miscbltin.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1997 Christos Zoulas. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +int readcmd(int, char **); +int umaskcmd(int, char **); +int ulimitcmd(int, char **); diff -puN /dev/null usr/dash/mkbuiltins --- /dev/null +++ a/usr/dash/mkbuiltins @@ -0,0 +1,101 @@ +#!/bin/sh - +# $NetBSD: mkbuiltins,v 1.17 2002/11/24 22:35:41 christos Exp $ +# +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95 + +tempfile=tempfile +if ! type tempfile > /dev/null 2>&1; then + tempfile="mktemp ${TMPDIR:-/tmp}/builtin.XXXXXX" +fi + +trap 'rm -f $temp $temp2' EXIT +temp=$($tempfile) +temp2=$($tempfile) + +builtins=$1 + +exec > builtins.c +cat <<\! +/* + * This file was generated by the mkbuiltins program. + */ + +#include "shell.h" +#include "builtins.h" + +! +< $builtins sed '/^#/d; /^$/d' > $temp +awk '{ printf "int %s(int, char **);\n", $1}' $temp +echo ' +const struct builtincmd builtincmd[] = {' +awk '{ for (i = 2 ; i <= NF ; i++) { + line = $i "\t" $1 + if ($i ~ /^-/) + line = $(++i) "\t" line + print line + }}' $temp | sort -k 1,1 | tee $temp2 | awk '{ + opt = "" + if (NF > 2) { + opt = substr($2, 2) + $2 = $3 + } + printf "\t{ \"%s\", %s, %d },\n", $1, $2, + (opt ~ /s/) + (opt ~ /[su]/) * 2 + (opt ~ /a/) * 4 + }' +echo '};' + +exec > builtins.h +cat <<\! +/* + * This file was generated by the mkbuiltins program. + */ + +! +sed 's/ -[a-z]*//' $temp2 | nl -v 0 | sort -u -k 3,3 | +tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | + awk '{ printf "#define %s (builtincmd + %d)\n", $3, $1}' +printf '\n#define NUMBUILTINS %d\n' $(wc -l < $temp2) +echo ' +#define BUILTIN_SPECIAL 0x1 +#define BUILTIN_REGULAR 0x2 +#define BUILTIN_ASSIGN 0x4 + +struct builtincmd { + const char *name; + int (*builtin)(int, char **); + unsigned flags; +}; + +extern const struct builtincmd builtincmd[];' diff -puN /dev/null usr/dash/mkinit.c --- /dev/null +++ a/usr/dash/mkinit.c @@ -0,0 +1,476 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This program scans all the source files for code to handle various + * special events and combines this code into one file. This (allegedly) + * improves the structure of the program since there is no need for + * anyone outside of a module to know that that module performs special + * operations on particular events. + * + * Usage: mkinit sourcefile... + */ + + +#include +#include +#include +#include +#include +#include + + +/* + * OUTFILE is the name of the output file. Output is initially written + * to the file OUTTEMP, which is then moved to OUTFILE. + */ + +#define OUTFILE "init.c" +#define OUTTEMP "init.c.new" + + +/* + * A text structure is basicly just a string that grows as more characters + * are added onto the end of it. It is implemented as a linked list of + * blocks of characters. The routines addstr and addchar append a string + * or a single character, respectively, to a text structure. Writetext + * writes the contents of a text structure to a file. + */ + +#define BLOCKSIZE 512 + +struct text { + char *nextc; + int nleft; + struct block *start; + struct block *last; +}; + +struct block { + struct block *next; + char text[BLOCKSIZE]; +}; + + +/* + * There is one event structure for each event that mkinit handles. + */ + +struct event { + char *name; /* name of event (e.g. INIT) */ + char *routine; /* name of routine called on event */ + char *comment; /* comment describing routine */ + struct text code; /* code for handling event */ +}; + + +char writer[] = "\ +/*\n\ + * This file was generated by the mkinit program.\n\ + */\n\ +\n"; + +char init[] = "\ +/*\n\ + * Initialization code.\n\ + */\n"; + +char reset[] = "\ +/*\n\ + * This routine is called when an error or an interrupt occurs in an\n\ + * interactive shell and control is returned to the main command loop.\n\ + */\n"; + + +struct event event[] = { + {"INIT", "init", init}, + {"RESET", "reset", reset}, + {NULL, NULL} +}; + + +char *curfile; /* current file */ +int linno; /* current line */ +char *header_files[200]; /* list of header files */ +struct text defines; /* #define statements */ +struct text decls; /* declarations */ +int amiddecls; /* for formatting */ + + +void readfile(char *); +int match(char *, char *); +int gooddefine(char *); +void doevent(struct event *, FILE *, char *); +void doinclude(char *); +void dodecl(char *, FILE *); +void output(void); +void addstr(char *, struct text *); +void addchar(int, struct text *); +void writetext(struct text *, FILE *); +FILE *ckfopen(char *, char *); +void *ckmalloc(int); +char *savestr(char *); +static void error(char *); +int main(int, char **); + +#define equal(s1, s2) (strcmp(s1, s2) == 0) + +int +main(int argc, char **argv) +{ + char **ap; + + header_files[0] = "\"shell.h\""; + header_files[1] = "\"mystring.h\""; + header_files[2] = "\"init.h\""; + for (ap = argv + 1 ; *ap ; ap++) + readfile(*ap); + output(); + rename(OUTTEMP, OUTFILE); + exit(0); + /* NOTREACHED */ +} + + +/* + * Parse an input file. + */ + +void +readfile(char *fname) +{ + FILE *fp; + char line[1024]; + struct event *ep; + + fp = ckfopen(fname, "r"); + curfile = fname; + linno = 0; + amiddecls = 0; + while (fgets(line, sizeof line, fp) != NULL) { + linno++; + for (ep = event ; ep->name ; ep++) { + if (line[0] == ep->name[0] && match(ep->name, line)) { + doevent(ep, fp, fname); + break; + } + } + if (line[0] == 'I' && match("INCLUDE", line)) + doinclude(line); + if (line[0] == 'M' && match("MKINIT", line)) + dodecl(line, fp); + if (line[0] == '#' && gooddefine(line)) { + char *cp; + char line2[1024]; + static const char undef[] = "#undef "; + + strcpy(line2, line); + memcpy(line2, undef, sizeof(undef) - 1); + cp = line2 + sizeof(undef) - 1; + while(*cp && (*cp == ' ' || *cp == '\t')) + cp++; + while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n') + cp++; + *cp++ = '\n'; *cp = '\0'; + addstr(line2, &defines); + addstr(line, &defines); + } + } + fclose(fp); +} + + +int +match(char *name, char *line) +{ + char *p, *q; + + p = name, q = line; + while (*p) { + if (*p++ != *q++) + return 0; + } + if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n') + return 0; + return 1; +} + + +int +gooddefine(char *line) +{ + char *p; + + if (! match("#define", line)) + return 0; /* not a define */ + p = line + 7; + while (*p == ' ' || *p == '\t') + p++; + while (*p != ' ' && *p != '\t') { + if (*p == '(') + return 0; /* macro definition */ + p++; + } + while (*p != '\n' && *p != '\0') + p++; + if (p[-1] == '\\') + return 0; /* multi-line definition */ + return 1; +} + + +void +doevent(struct event *ep, FILE *fp, char *fname) +{ + char line[1024]; + int indent; + char *p; + + sprintf(line, "\n /* from %s: */\n", fname); + addstr(line, &ep->code); + addstr(" {\n", &ep->code); + for (;;) { + linno++; + if (fgets(line, sizeof line, fp) == NULL) + error("Unexpected EOF"); + if (equal(line, "}\n")) + break; + indent = 6; + for (p = line ; *p == '\t' ; p++) + indent += 8; + for ( ; *p == ' ' ; p++) + indent++; + if (*p == '\n' || *p == '#') + indent = 0; + while (indent >= 8) { + addchar('\t', &ep->code); + indent -= 8; + } + while (indent > 0) { + addchar(' ', &ep->code); + indent--; + } + addstr(p, &ep->code); + } + addstr(" }\n", &ep->code); +} + + +void +doinclude(char *line) +{ + char *p; + char *name; + char **pp; + + for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++); + if (*p == '\0') + error("Expecting '\"' or '<'"); + name = p; + while (*p != ' ' && *p != '\t' && *p != '\n') + p++; + if (p[-1] != '"' && p[-1] != '>') + error("Missing terminator"); + *p = '\0'; + + /* name now contains the name of the include file */ + for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++); + if (*pp == NULL) + *pp = savestr(name); +} + + +void +dodecl(char *line1, FILE *fp) +{ + char line[1024]; + char *p, *q; + + if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */ + addchar('\n', &decls); + do { + linno++; + if (fgets(line, sizeof line, fp) == NULL) + error("Unterminated structure declaration"); + addstr(line, &decls); + } while (line[0] != '}'); + amiddecls = 0; + } else { + if (! amiddecls) + addchar('\n', &decls); + q = NULL; + for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++) + continue; + if (*p == '=') { /* eliminate initialization */ + for (q = p ; *q && *q != ';' ; q++); + if (*q == '\0') + q = NULL; + else { + while (p[-1] == ' ') + p--; + *p = '\0'; + } + } + addstr("extern", &decls); + addstr(line1 + 6, &decls); + if (q != NULL) + addstr(q, &decls); + amiddecls = 1; + } +} + + + +/* + * Write the output to the file OUTTEMP. + */ + +void +output(void) +{ + FILE *fp; + char **pp; + struct event *ep; + + fp = ckfopen(OUTTEMP, "w"); + fputs(writer, fp); + for (pp = header_files ; *pp ; pp++) + fprintf(fp, "#include %s\n", *pp); + fputs("\n\n\n", fp); + writetext(&defines, fp); + fputs("\n\n", fp); + writetext(&decls, fp); + for (ep = event ; ep->name ; ep++) { + fputs("\n\n\n", fp); + fputs(ep->comment, fp); + fprintf(fp, "\nvoid\n%s() {\n", ep->routine); + writetext(&ep->code, fp); + fprintf(fp, "}\n"); + } + fclose(fp); +} + + +/* + * A text structure is simply a block of text that is kept in memory. + * Addstr appends a string to the text struct, and addchar appends a single + * character. + */ + +void +addstr(char *s, struct text *text) +{ + while (*s) { + if (--text->nleft < 0) + addchar(*s++, text); + else + *text->nextc++ = *s++; + } +} + + +void +addchar(int c, struct text *text) +{ + struct block *bp; + + if (--text->nleft < 0) { + bp = ckmalloc(sizeof *bp); + if (text->start == NULL) + text->start = bp; + else + text->last->next = bp; + text->last = bp; + text->nextc = bp->text; + text->nleft = BLOCKSIZE - 1; + } + *text->nextc++ = c; +} + +/* + * Write the contents of a text structure to a file. + */ +void +writetext(struct text *text, FILE *fp) +{ + struct block *bp; + + if (text->start != NULL) { + for (bp = text->start ; bp != text->last ; bp = bp->next) + fwrite(bp->text, sizeof (char), BLOCKSIZE, fp); + fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp); + } +} + +FILE * +ckfopen(char *file, char *mode) +{ + FILE *fp; + + if ((fp = fopen(file, mode)) == NULL) { + fprintf(stderr, "Can't open %s\n", file); + exit(2); + } + return fp; +} + +void * +ckmalloc(int nbytes) +{ + char *p; + + if ((p = malloc(nbytes)) == NULL) + error("Out of space"); + return p; +} + +char * +savestr(char *s) +{ + char *p; + + p = ckmalloc(strlen(s) + 1); + strcpy(p, s); + return p; +} + +static void +error(char *msg) +{ + if (curfile != NULL) + fprintf(stderr, "%s:%d: ", curfile, linno); + fprintf(stderr, "%s\n", msg); + exit(2); + /* NOTREACHED */ +} diff -puN /dev/null usr/dash/mknodes.c --- /dev/null +++ a/usr/dash/mknodes.c @@ -0,0 +1,448 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This program reads the nodetypes file and nodes.c.pat file. It generates + * the files nodes.h and nodes.c. + */ + +#include +#include +#include +#include + +#define MAXTYPES 50 /* max number of node types */ +#define MAXFIELDS 20 /* max fields in a structure */ +#define BUFLEN 100 /* size of character buffers */ + +/* field types */ +#define T_NODE 1 /* union node *field */ +#define T_NODELIST 2 /* struct nodelist *field */ +#define T_STRING 3 +#define T_INT 4 /* int field */ +#define T_OTHER 5 /* other */ +#define T_TEMP 6 /* don't copy this field */ + + +struct field { /* a structure field */ + char *name; /* name of field */ + int type; /* type of field */ + char *decl; /* declaration of field */ +}; + + +struct str { /* struct representing a node structure */ + char *tag; /* structure tag */ + int nfields; /* number of fields in the structure */ + struct field field[MAXFIELDS]; /* the fields of the structure */ + int done; /* set if fully parsed */ +}; + + +static int ntypes; /* number of node types */ +static char *nodename[MAXTYPES]; /* names of the nodes */ +static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */ +static int nstr; /* number of structures */ +static struct str str[MAXTYPES]; /* the structures */ +static struct str *curstr; /* current structure */ +static FILE *infp; +static char line[1024]; +static int linno; +static char *linep; + +static void parsenode(void); +static void parsefield(void); +static void output(char *); +static void outsizes(FILE *); +static void outfunc(FILE *, int); +static void indent(int, FILE *); +static int nextfield(char *); +static void skipbl(void); +static int readline(void); +static void error(const char *, ...); +static char *savestr(const char *); +int main(int, char **); + + +int +main(int argc, char **argv) +{ + + /* + * some versions of linux complain: initializer element is not + * constant if this is done at compile time. + */ + infp = stdin; + + if (argc != 3) + error("usage: mknodes file"); + if ((infp = fopen(argv[1], "r")) == NULL) + error("Can't open %s", argv[1]); + while (readline()) { + if (line[0] == ' ' || line[0] == '\t') + parsefield(); + else if (line[0] != '\0') + parsenode(); + } + output(argv[2]); + exit(0); + /* NOTREACHED */ +} + + + +static void +parsenode(void) +{ + char name[BUFLEN]; + char tag[BUFLEN]; + struct str *sp; + + if (curstr && curstr->nfields > 0) + curstr->done = 1; + nextfield(name); + if (! nextfield(tag)) + error("Tag expected"); + if (*linep != '\0') + error("Garbage at end of line"); + nodename[ntypes] = savestr(name); + for (sp = str ; sp < str + nstr ; sp++) { + if (strcmp(sp->tag, tag) == 0) + break; + } + if (sp >= str + nstr) { + sp->tag = savestr(tag); + sp->nfields = 0; + curstr = sp; + nstr++; + } + nodestr[ntypes] = sp; + ntypes++; +} + + +static void +parsefield(void) +{ + char name[BUFLEN]; + char type[BUFLEN]; + char decl[2 * BUFLEN]; + struct field *fp; + + if (curstr == NULL || curstr->done) + error("No current structure to add field to"); + if (! nextfield(name)) + error("No field name"); + if (! nextfield(type)) + error("No field type"); + fp = &curstr->field[curstr->nfields]; + fp->name = savestr(name); + if (strcmp(type, "nodeptr") == 0) { + fp->type = T_NODE; + sprintf(decl, "union node *%s", name); + } else if (strcmp(type, "nodelist") == 0) { + fp->type = T_NODELIST; + sprintf(decl, "struct nodelist *%s", name); + } else if (strcmp(type, "string") == 0) { + fp->type = T_STRING; + sprintf(decl, "char *%s", name); + } else if (strcmp(type, "int") == 0) { + fp->type = T_INT; + sprintf(decl, "int %s", name); + } else if (strcmp(type, "other") == 0) { + fp->type = T_OTHER; + } else if (strcmp(type, "temp") == 0) { + fp->type = T_TEMP; + } else { + error("Unknown type %s", type); + } + if (fp->type == T_OTHER || fp->type == T_TEMP) { + skipbl(); + fp->decl = savestr(linep); + } else { + if (*linep) + error("Garbage at end of line"); + fp->decl = savestr(decl); + } + curstr->nfields++; +} + + +char writer[] = "\ +/*\n\ + * This file was generated by the mknodes program.\n\ + */\n\ +\n"; + +static void +output(char *file) +{ + FILE *hfile; + FILE *cfile; + FILE *patfile; + int i; + struct str *sp; + struct field *fp; + char *p; + + if ((patfile = fopen(file, "r")) == NULL) + error("Can't open %s", file); + if ((hfile = fopen("nodes.h", "w")) == NULL) + error("Can't create nodes.h"); + if ((cfile = fopen("nodes.c", "w")) == NULL) + error("Can't create nodes.c"); + fputs(writer, hfile); + for (i = 0 ; i < ntypes ; i++) + fprintf(hfile, "#define %s %d\n", nodename[i], i); + fputs("\n\n\n", hfile); + for (sp = str ; sp < &str[nstr] ; sp++) { + fprintf(hfile, "struct %s {\n", sp->tag); + for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) { + fprintf(hfile, " %s;\n", fp->decl); + } + fputs("};\n\n\n", hfile); + } + fputs("union node {\n", hfile); + fprintf(hfile, " int type;\n"); + for (sp = str ; sp < &str[nstr] ; sp++) { + fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag); + } + fputs("};\n\n\n", hfile); + fputs("struct nodelist {\n", hfile); + fputs("\tstruct nodelist *next;\n", hfile); + fputs("\tunion node *n;\n", hfile); + fputs("};\n\n\n", hfile); + fputs("struct funcnode {\n", hfile); + fputs("\tint count;\n", hfile); + fputs("\tunion node n;\n", hfile); + fputs("};\n\n\n", hfile); + fputs("struct funcnode *copyfunc(union node *);\n", hfile); + fputs("void freefunc(struct funcnode *);\n", hfile); + + fputs(writer, cfile); + while (fgets(line, sizeof line, patfile) != NULL) { + for (p = line ; *p == ' ' || *p == '\t' ; p++); + if (strcmp(p, "%SIZES\n") == 0) + outsizes(cfile); + else if (strcmp(p, "%CALCSIZE\n") == 0) + outfunc(cfile, 1); + else if (strcmp(p, "%COPY\n") == 0) + outfunc(cfile, 0); + else + fputs(line, cfile); + } +} + + + +static void +outsizes(FILE *cfile) +{ + int i; + + fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes); + for (i = 0 ; i < ntypes ; i++) { + fprintf(cfile, " SHELL_ALIGN(sizeof (struct %s)),\n", + nodestr[i]->tag); + } + fprintf(cfile, "};\n"); +} + + +static void +outfunc(FILE *cfile, int calcsize) +{ + struct str *sp; + struct field *fp; + int i; + + fputs(" if (n == NULL)\n", cfile); + if (calcsize) + fputs(" return;\n", cfile); + else + fputs(" return NULL;\n", cfile); + if (calcsize) + fputs(" funcblocksize += nodesize[n->type];\n", cfile); + else { + fputs(" new = funcblock;\n", cfile); + fputs(" funcblock = (char *) funcblock + nodesize[n->type];\n", cfile); + } + fputs(" switch (n->type) {\n", cfile); + for (sp = str ; sp < &str[nstr] ; sp++) { + for (i = 0 ; i < ntypes ; i++) { + if (nodestr[i] == sp) + fprintf(cfile, " case %s:\n", nodename[i]); + } + for (i = sp->nfields ; --i >= 1 ; ) { + fp = &sp->field[i]; + switch (fp->type) { + case T_NODE: + if (calcsize) { + indent(12, cfile); + fprintf(cfile, "calcsize(n->%s.%s);\n", + sp->tag, fp->name); + } else { + indent(12, cfile); + fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n", + sp->tag, fp->name, sp->tag, fp->name); + } + break; + case T_NODELIST: + if (calcsize) { + indent(12, cfile); + fprintf(cfile, "sizenodelist(n->%s.%s);\n", + sp->tag, fp->name); + } else { + indent(12, cfile); + fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n", + sp->tag, fp->name, sp->tag, fp->name); + } + break; + case T_STRING: + if (calcsize) { + indent(12, cfile); + fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n", + sp->tag, fp->name); + } else { + indent(12, cfile); + fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n", + sp->tag, fp->name, sp->tag, fp->name); + } + break; + case T_INT: + case T_OTHER: + if (! calcsize) { + indent(12, cfile); + fprintf(cfile, "new->%s.%s = n->%s.%s;\n", + sp->tag, fp->name, sp->tag, fp->name); + } + break; + } + } + indent(12, cfile); + fputs("break;\n", cfile); + } + fputs(" };\n", cfile); + if (! calcsize) + fputs(" new->type = n->type;\n", cfile); +} + + +static void +indent(int amount, FILE *fp) +{ + while (amount >= 8) { + putc('\t', fp); + amount -= 8; + } + while (--amount >= 0) { + putc(' ', fp); + } +} + + +static int +nextfield(char *buf) +{ + char *p, *q; + + p = linep; + while (*p == ' ' || *p == '\t') + p++; + q = buf; + while (*p != ' ' && *p != '\t' && *p != '\0') + *q++ = *p++; + *q = '\0'; + linep = p; + return (q > buf); +} + + +static void +skipbl(void) +{ + while (*linep == ' ' || *linep == '\t') + linep++; +} + + +static int +readline(void) +{ + char *p; + + if (fgets(line, 1024, infp) == NULL) + return 0; + for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++); + while (p > line && (p[-1] == ' ' || p[-1] == '\t')) + p--; + *p = '\0'; + linep = line; + linno++; + if (p - line > BUFLEN) + error("Line too long"); + return 1; +} + + + +static void +error(const char *msg, ...) +{ + va_list va; + + va_start(va, msg); + + (void) fprintf(stderr, "line %d: ", linno); + (void) vfprintf(stderr, msg, va); + (void) fputc('\n', stderr); + + va_end(va); + + exit(2); + /* NOTREACHED */ +} + + + +static char * +savestr(const char *s) +{ + char *p; + + if ((p = malloc(strlen(s) + 1)) == NULL) + error("Out of space"); + (void) strcpy(p, s); + return p; +} diff -puN /dev/null usr/dash/mksyntax.c --- /dev/null +++ a/usr/dash/mksyntax.c @@ -0,0 +1,315 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This program creates syntax.h and syntax.c. + */ + +#include +#include +#include +#include +#include "parser.h" + + +struct synclass { + char *name; + char *comment; +}; + +/* Syntax classes */ +struct synclass synclass[] = { + { "CWORD", "character is nothing special" }, + { "CNL", "newline character" }, + { "CBACK", "a backslash character" }, + { "CSQUOTE", "single quote" }, + { "CDQUOTE", "double quote" }, + { "CENDQUOTE", "a terminating quote" }, + { "CBQUOTE", "backwards single quote" }, + { "CVAR", "a dollar sign" }, + { "CENDVAR", "a '}' character" }, + { "CLP", "a left paren in arithmetic" }, + { "CRP", "a right paren in arithmetic" }, + { "CEOF", "end of file" }, + { "CCTL", "like CWORD, except it must be escaped" }, + { "CSPCL", "these terminate a word" }, + { "CIGN", "character should be ignored" }, + { NULL, NULL } +}; + + +/* + * Syntax classes for is_ functions. Warning: if you add new classes + * you may have to change the definition of the is_in_name macro. + */ +struct synclass is_entry[] = { + { "ISDIGIT", "a digit" }, + { "ISUPPER", "an upper case letter" }, + { "ISLOWER", "a lower case letter" }, + { "ISUNDER", "an underscore" }, + { "ISSPECL", "the name of a special parameter" }, + { NULL, NULL } +}; + +static char writer[] = "\ +/*\n\ + * This file was generated by the mksyntax program.\n\ + */\n\ +\n"; + + +static FILE *cfile; +static FILE *hfile; +static char *syntax[513]; + +static void filltable(char *); +static void init(void); +static void add(char *, char *); +static void print(char *); +static void output_type_macros(void); +int main(int, char **); + +int +main(int argc, char **argv) +{ + int i; + char buf[80]; + int pos; + + /* Create output files */ + if ((cfile = fopen("syntax.c", "w")) == NULL) { + perror("syntax.c"); + exit(2); + } + if ((hfile = fopen("syntax.h", "w")) == NULL) { + perror("syntax.h"); + exit(2); + } + fputs(writer, hfile); + fputs(writer, cfile); + + fputs("#include \n", hfile); + fputs("\n", hfile); + fputs("#ifdef CEOF\n", hfile); + fputs("#undef CEOF\n", hfile); + fputs("#endif\n", hfile); + fputs("\n", hfile); + + /* Generate the #define statements in the header file */ + fputs("/* Syntax classes */\n", hfile); + for (i = 0 ; synclass[i].name ; i++) { + sprintf(buf, "#define %s %d", synclass[i].name, i); + fputs(buf, hfile); + for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) + putc('\t', hfile); + fprintf(hfile, "/* %s */\n", synclass[i].comment); + } + putc('\n', hfile); + fputs("/* Syntax classes for is_ functions */\n", hfile); + for (i = 0 ; is_entry[i].name ; i++) { + sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i); + fputs(buf, hfile); + for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07) + putc('\t', hfile); + fprintf(hfile, "/* %s */\n", is_entry[i].comment); + } + putc('\n', hfile); + fprintf(hfile, "#define SYNBASE %d\n", 130); + fprintf(hfile, "#define PEOF %d\n\n", -130); + fprintf(hfile, "#define PEOA %d\n\n", -129); + putc('\n', hfile); + fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); + fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); + fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile); + fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile); + putc('\n', hfile); + output_type_macros(); /* is_digit, etc. */ + putc('\n', hfile); + + /* Generate the syntax tables. */ + fputs("#include \"shell.h\"\n", cfile); + fputs("#include \"syntax.h\"\n\n", cfile); + init(); + fputs("/* syntax table used when not in quotes */\n", cfile); + add("\n", "CNL"); + add("\\", "CBACK"); + add("'", "CSQUOTE"); + add("\"", "CDQUOTE"); + add("`", "CBQUOTE"); + add("$", "CVAR"); + add("}", "CENDVAR"); + add("<>();&| \t", "CSPCL"); + syntax[1] = "CSPCL"; + print("basesyntax"); + init(); + fputs("\n/* syntax table used when in double quotes */\n", cfile); + add("\n", "CNL"); + add("\\", "CBACK"); + add("\"", "CENDQUOTE"); + add("`", "CBQUOTE"); + add("$", "CVAR"); + add("}", "CENDVAR"); + /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ + add("!*?[=~:/-]", "CCTL"); + print("dqsyntax"); + init(); + fputs("\n/* syntax table used when in single quotes */\n", cfile); + add("\n", "CNL"); + add("'", "CENDQUOTE"); + /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ + add("!*?[=~:/-]\\", "CCTL"); + print("sqsyntax"); + init(); + fputs("\n/* syntax table used when in arithmetic */\n", cfile); + add("\n", "CNL"); + add("\\", "CBACK"); + add("`", "CBQUOTE"); + add("$", "CVAR"); + add("}", "CENDVAR"); + add("(", "CLP"); + add(")", "CRP"); + print("arisyntax"); + filltable("0"); + fputs("\n/* character classification table */\n", cfile); + add("0123456789", "ISDIGIT"); + add("abcdefghijklmnopqrstucvwxyz", "ISLOWER"); + add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER"); + add("_", "ISUNDER"); + add("#?$!-*@", "ISSPECL"); + print("is_type"); + exit(0); + /* NOTREACHED */ +} + + + +/* + * Clear the syntax table. + */ + +static void +filltable(char *dftval) +{ + int i; + + for (i = 0 ; i < 257; i++) + syntax[i] = dftval; +} + + +/* + * Initialize the syntax table with default values. + */ + +static void +init(void) +{ + int ctl; + + filltable("CWORD"); + syntax[0] = "CEOF"; + syntax[1] = "CIGN"; + for (ctl = CTL_FIRST; ctl <= CTL_LAST; ctl++ ) + syntax[130 + ctl] = "CCTL"; +} + + +/* + * Add entries to the syntax table. + */ + +static void +add(char *p, char *type) +{ + while (*p) + syntax[(signed char)*p++ + 130] = type; +} + + + +/* + * Output the syntax table. + */ + +static void +print(char *name) +{ + int i; + int col; + + fprintf(hfile, "extern const char %s[];\n", name); + fprintf(cfile, "const char %s[%d] = {\n", name, 257); + col = 0; + for (i = 0 ; i < 257; i++) { + if (i == 0) { + fputs(" ", cfile); + } else if ((i & 03) == 0) { + fputs(",\n ", cfile); + col = 0; + } else { + putc(',', cfile); + while (++col < 9 * (i & 03)) + putc(' ', cfile); + } + fputs(syntax[i], cfile); + col += strlen(syntax[i]); + } + fputs("\n};\n", cfile); +} + + + +/* + * Output character classification macros (e.g. is_digit). If digits are + * contiguous, we can test for them quickly. + */ + +static char *macro[] = { + "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)\n", + "#define is_alpha(c)\tisalpha((unsigned char)(c))\n", + "#define is_name(c)\t((c) == '_' || isalpha((unsigned char)(c)))\n", + "#define is_in_name(c)\t((c) == '_' || isalnum((unsigned char)(c)))\n", + "#define is_special(c)\t((is_type+SYNBASE)[(signed char)(c)] & (ISSPECL|ISDIGIT))\n", + NULL +}; + +static void +output_type_macros(void) +{ + char **pp; + + for (pp = macro ; *pp ; pp++) + fputs(*pp, hfile); + fputs("#define digit_val(c)\t((c) - '0')\n", hfile); +} diff -puN /dev/null usr/dash/mktokens --- /dev/null +++ a/usr/dash/mktokens @@ -0,0 +1,92 @@ +#!/bin/sh - +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)mktokens 8.1 (Berkeley) 5/31/93 + +# The following is a list of tokens. The second column is nonzero if the +# token marks the end of a list. The third column is the name to print in +# error messages. + +cat > /tmp/ka$$ <<\! +TEOF 1 end of file +TNL 0 newline +TSEMI 0 ";" +TBACKGND 0 "&" +TAND 0 "&&" +TOR 0 "||" +TPIPE 0 "|" +TLP 0 "(" +TRP 1 ")" +TENDCASE 1 ";;" +TENDBQUOTE 1 "`" +TREDIR 0 redirection +TWORD 0 word +TNOT 0 "!" +TCASE 0 "case" +TDO 1 "do" +TDONE 1 "done" +TELIF 1 "elif" +TELSE 1 "else" +TESAC 1 "esac" +TFI 1 "fi" +TFOR 0 "for" +TIF 0 "if" +TIN 0 "in" +TTHEN 1 "then" +TUNTIL 0 "until" +TWHILE 0 "while" +TBEGIN 0 "{" +TEND 1 "}" +! +nl=`wc -l /tmp/ka$$` + +awk '{print "#define " $1 " " NR-1}' /tmp/ka$$ +echo ' +/* Array indicating which tokens mark the end of a list */ +const char tokendlist[] = {' +awk '{print "\t" $2 ","}' /tmp/ka$$ +echo '}; + +const char *const tokname[] = {' +sed -e 's/"/\\"/g' \ + -e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \ + /tmp/ka$$ +echo '}; +' +sed 's/"//g' /tmp/ka$$ | awk ' +/TNOT/{print "#define KWDOFFSET " NR-1; print ""; + print "STATIC const char *const parsekwd[] = {"} +/TNOT/,/neverfound/{if (last) print " \"" last "\","; last = $3} +END{print " \"" last "\"\n};"}' + +rm /tmp/ka$$ diff -puN /dev/null usr/dash/myhistedit.h --- /dev/null +++ a/usr/dash/myhistedit.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)myhistedit.h 8.2 (Berkeley) 5/4/95 + */ + +#include + +extern History *hist; +extern EditLine *el; +extern int displayhist; + +void histedit(void); +void sethistsize(const char *); +void setterm(const char *); +int histcmd(int, char **); +int not_fcnumber(char *); +int str_to_event(const char *, int); diff -puN /dev/null usr/dash/mystring.c --- /dev/null +++ a/usr/dash/mystring.c @@ -0,0 +1,209 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * String functions. + * + * equal(s1, s2) Return true if strings are equal. + * scopy(from, to) Copy a string. + * scopyn(from, to, n) Like scopy, but checks for overflow. + * number(s) Convert a string of digits to an integer. + * is_number(s) Return true if s is a string of digits. + */ + +#include +#include "shell.h" +#include "syntax.h" +#include "error.h" +#include "mystring.h" +#include "memalloc.h" +#include "parser.h" +#include "system.h" + + +char nullstr[1]; /* zero length string */ +const char spcstr[] = " "; +const char snlfmt[] = "%s\n"; +const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' }; +const char illnum[] = "Illegal number: %s"; +const char homestr[] = "HOME"; + +/* + * equal - #defined in mystring.h + */ + +/* + * scopy - #defined in mystring.h + */ + + +#if 0 +/* + * scopyn - copy a string from "from" to "to", truncating the string + * if necessary. "To" is always nul terminated, even if + * truncation is performed. "Size" is the size of "to". + */ + +void +scopyn(const char *from, char *to, int size) +{ + + while (--size > 0) { + if ((*to++ = *from++) == '\0') + return; + } + *to = '\0'; +} +#endif + + +/* + * prefix -- see if pfx is a prefix of string. + */ + +char * +prefix(const char *string, const char *pfx) +{ + while (*pfx) { + if (*pfx++ != *string++) + return 0; + } + return (char *) string; +} + + +/* + * Convert a string of digits to an integer, printing an error message on + * failure. + */ + +int +number(const char *s) +{ + + if (! is_number(s)) + sh_error(illnum, s); + return atoi(s); +} + + + +/* + * Check for a valid number. This should be elsewhere. + */ + +int +is_number(const char *p) +{ + do { + if (! is_digit(*p)) + return 0; + } while (*++p != '\0'); + return 1; +} + + +/* + * Produce a possibly single quoted string suitable as input to the shell. + * The return string is allocated on the stack. + */ + +char * +single_quote(const char *s) { + char *p; + + STARTSTACKSTR(p); + + do { + char *q; + size_t len; + + len = strchrnul(s, '\'') - s; + + q = p = makestrspace(len + 3, p); + + *q++ = '\''; + q = mempcpy(q, s, len); + *q++ = '\''; + s += len; + + STADJUST(q - p, p); + + len = strspn(s, "'"); + if (!len) + break; + + q = p = makestrspace(len + 3, p); + + *q++ = '"'; + q = mempcpy(q, s, len); + *q++ = '"'; + s += len; + + STADJUST(q - p, p); + } while (*s); + + USTPUTC(0, p); + + return stackblock(); +} + +/* + * Like strdup but works with the ash stack. + */ + +char * +sstrdup(const char *p) +{ + size_t len = strlen(p) + 1; + return memcpy(stalloc(len), p, len); +} + +/* + * Wrapper around strcmp for qsort/bsearch/... + */ +int +pstrcmp(const void *a, const void *b) +{ + return strcmp(*(const char *const *) a, *(const char *const *) b); +} + +/* + * Find a string is in a sorted array. + */ +const char *const * +findstring(const char *s, const char *const *array, size_t nmemb) +{ + return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp); +} diff -puN /dev/null usr/dash/mystring.h --- /dev/null +++ a/usr/dash/mystring.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mystring.h 8.2 (Berkeley) 5/4/95 + */ + +#include + +extern const char snlfmt[]; +extern const char spcstr[]; +extern const char dolatstr[]; +#define DOLATSTRLEN 4 +extern const char illnum[]; +extern const char homestr[]; + +#if 0 +void scopyn(const char *, char *, int); +#endif +char *prefix(const char *, const char *); +int number(const char *); +int is_number(const char *); +char *single_quote(const char *); +char *sstrdup(const char *); +int pstrcmp(const void *, const void *); +const char *const *findstring(const char *, const char *const *, size_t); + +#define equal(s1, s2) (strcmp(s1, s2) == 0) +#define scopy(s1, s2) ((void)strcpy(s2, s1)) diff -puN /dev/null usr/dash/nodes.c.pat --- /dev/null +++ a/usr/dash/nodes.c.pat @@ -0,0 +1,166 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 + */ + +#include +/* + * Routine for dealing with parsed shell commands. + */ + +#include "shell.h" +#include "nodes.h" +#include "memalloc.h" +#include "machdep.h" +#include "mystring.h" +#include "system.h" + + +int funcblocksize; /* size of structures in function */ +int funcstringsize; /* size of strings in node */ +pointer funcblock; /* block to allocate function from */ +char *funcstring; /* block to allocate strings from */ + +%SIZES + + +STATIC void calcsize(union node *); +STATIC void sizenodelist(struct nodelist *); +STATIC union node *copynode(union node *); +STATIC struct nodelist *copynodelist(struct nodelist *); +STATIC char *nodesavestr(char *); + + + +/* + * Make a copy of a parse tree. + */ + +struct funcnode * +copyfunc(union node *n) +{ + struct funcnode *f; + size_t blocksize; + + funcblocksize = offsetof(struct funcnode, n); + funcstringsize = 0; + calcsize(n); + blocksize = funcblocksize; + f = ckmalloc(blocksize + funcstringsize); + funcblock = (char *) f + offsetof(struct funcnode, n); + funcstring = (char *) f + blocksize; + copynode(n); + f->count = 0; + return f; +} + + + +STATIC void +calcsize(n) + union node *n; +{ + %CALCSIZE +} + + + +STATIC void +sizenodelist(lp) + struct nodelist *lp; +{ + while (lp) { + funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); + calcsize(lp->n); + lp = lp->next; + } +} + + + +STATIC union node * +copynode(n) + union node *n; +{ + union node *new; + + %COPY + return new; +} + + +STATIC struct nodelist * +copynodelist(lp) + struct nodelist *lp; +{ + struct nodelist *start; + struct nodelist **lpp; + + lpp = &start; + while (lp) { + *lpp = funcblock; + funcblock = (char *) funcblock + + SHELL_ALIGN(sizeof(struct nodelist)); + (*lpp)->n = copynode(lp->n); + lp = lp->next; + lpp = &(*lpp)->next; + } + *lpp = NULL; + return start; +} + + + +STATIC char * +nodesavestr(s) + char *s; +{ + char *rtn = funcstring; + + funcstring = stpcpy(funcstring, s) + 1; + return rtn; +} + + + +/* + * Free a parse tree. + */ + +void +freefunc(struct funcnode *f) +{ + if (f && --f->count < 0) + ckfree(f); +} diff -puN /dev/null usr/dash/nodetypes --- /dev/null +++ a/usr/dash/nodetypes @@ -0,0 +1,144 @@ +# Copyright (c) 1991, 1993 +# The Regents of the University of California. All rights reserved. +# Copyright (c) 1997-2005 +# Herbert Xu . All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Kenneth Almquist. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)nodetypes 8.2 (Berkeley) 5/4/95 + +# This file describes the nodes used in parse trees. Unindented lines +# contain a node type followed by a structure tag. Subsequent indented +# lines specify the fields of the structure. Several node types can share +# the same structure, in which case the fields of the structure should be +# specified only once. +# +# A field of a structure is described by the name of the field followed +# by a type. The currently implemented types are: +# nodeptr - a pointer to a node +# nodelist - a pointer to a list of nodes +# string - a pointer to a nul terminated string +# int - an integer +# other - any type that can be copied by assignment +# temp - a field that doesn't have to be copied when the node is copied +# The last two types should be followed by the text of a C declaration for +# the field. + +NCMD ncmd # a simple command + type int + assign nodeptr # variable assignments + args nodeptr # the arguments + redirect nodeptr # list of file redirections + +NPIPE npipe # a pipeline + type int + backgnd int # set to run pipeline in background + cmdlist nodelist # the commands in the pipeline + +NREDIR nredir # redirection (of a complex command) + type int + n nodeptr # the command + redirect nodeptr # list of file redirections + +NBACKGND nredir # run command in background +NSUBSHELL nredir # run command in a subshell + +NAND nbinary # the && operator +NOR nbinary # the || operator + +NSEMI nbinary # two commands separated by a semicolon + type int + ch1 nodeptr # the first child + ch2 nodeptr # the second child + +NIF nif # the if statement. Elif clauses are handled + type int # using multiple if nodes. + test nodeptr # if test + ifpart nodeptr # then ifpart + elsepart nodeptr # else elsepart + +NWHILE nbinary # the while statement. First child is the test +NUNTIL nbinary # the until statement + +NFOR nfor # the for statement + type int + args nodeptr # for var in args + body nodeptr # do body; done + var string # the for variable + +NCASE ncase # a case statement + type int + expr nodeptr # the word to switch on + cases nodeptr # the list of cases (NCLIST nodes) + +NCLIST nclist # a case + type int + next nodeptr # the next case in list + pattern nodeptr # list of patterns for this case + body nodeptr # code to execute for this case + + +NDEFUN narg # define a function. The "next" field contains + # the body of the function. + +NARG narg # represents a word + type int + next nodeptr # next word in list + text string # the text of the word + backquote nodelist # list of commands in back quotes + +NTO nfile # fd> fname +NCLOBBER nfile # fd>| fname +NFROM nfile # fd< fname +NFROMTO nfile # fd<> fname +NAPPEND nfile # fd>> fname + type int + next nodeptr # next redirection in list + fd int # file descriptor being redirected + fname nodeptr # file name, in a NARG node + expfname temp char *expfname # actual file name + +NTOFD ndup # fd<&dupfd +NFROMFD ndup # fd>&dupfd + type int + next nodeptr # next redirection in list + fd int # file descriptor being redirected + dupfd int # file descriptor to duplicate + vname nodeptr # file name if fd>&$var + + +NHERE nhere # fd<<\! +NXHERE nhere # fd<. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include "shell.h" +#define DEFINE_OPTIONS +#include "options.h" +#undef DEFINE_OPTIONS +#include "nodes.h" /* for other header files */ +#include "eval.h" +#include "jobs.h" +#include "input.h" +#include "output.h" +#include "trap.h" +#include "var.h" +#include "memalloc.h" +#include "error.h" +#include "mystring.h" +#ifndef SMALL +#include "myhistedit.h" +#endif +#include "show.h" + +char *arg0; /* value of $0 */ +struct shparam shellparam; /* current positional parameters */ +char **argptr; /* argument list for builtin commands */ +char *optionarg; /* set by nextopt (like getopt) */ +char *optptr; /* used by nextopt */ + +char *minusc; /* argument to -c option */ + +static const char *const optnames[NOPTS] = { + "errexit", + "noglob", + "ignoreeof", + "interactive", + "monitor", + "noexec", + "stdin", + "xtrace", + "verbose", + "vi", + "emacs", + "noclobber", + "allexport", + "notify", + "nounset", + "nolog", + "debug", +}; + +const char optletters[NOPTS] = { + 'e', + 'f', + 'I', + 'i', + 'm', + 'n', + 's', + 'x', + 'v', + 'V', + 'E', + 'C', + 'a', + 'b', + 'u', + 0, + 0, +}; + +char optlist[NOPTS]; + + +STATIC void options(int); +STATIC void minus_o(char *, int); +STATIC void setoption(int, int); +STATIC int getopts(char *, char *, char **, int *, int *); + + +/* + * Process the shell command line arguments. + */ + +void +procargs(int argc, char **argv) +{ + int i; + const char *xminusc; + char **xargv; + + xargv = argv; + arg0 = xargv[0]; + if (argc > 0) + xargv++; + for (i = 0; i < NOPTS; i++) + optlist[i] = 2; + argptr = xargv; + options(1); + xargv = argptr; + xminusc = minusc; + if (*xargv == NULL) { + if (xminusc) + sh_error("-c requires an argument"); + sflag = 1; + } + if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1)) + iflag = 1; + if (mflag == 2) + mflag = iflag; + for (i = 0; i < NOPTS; i++) + if (optlist[i] == 2) + optlist[i] = 0; +#if DEBUG == 2 + debug = 1; +#endif + /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ + if (xminusc) { + minusc = *xargv++; + if (*xargv) + goto setarg0; + } else if (!sflag) { + setinputfile(*xargv, 0); +setarg0: + arg0 = *xargv++; + commandname = arg0; + } + + shellparam.p = xargv; + shellparam.optind = 1; + shellparam.optoff = -1; + /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ + while (*xargv) { + shellparam.nparam++; + xargv++; + } + optschanged(); +} + + +void +optschanged(void) +{ +#ifdef DEBUG + opentrace(); +#endif + setinteractive(iflag); +#ifndef SMALL + histedit(); +#endif + setjobctl(mflag); +} + +/* + * Process shell options. The global variable argptr contains a pointer + * to the argument list; we advance it past the options. + */ + +STATIC void +options(int cmdline) +{ + char *p; + int val; + int c; + + if (cmdline) + minusc = NULL; + while ((p = *argptr) != NULL) { + argptr++; + if ((c = *p++) == '-') { + val = 1; + if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) { + if (!cmdline) { + /* "-" means turn off -x and -v */ + if (p[0] == '\0') + xflag = vflag = 0; + /* "--" means reset params */ + else if (*argptr == NULL) + setparam(argptr); + } + break; /* "-" or "--" terminates options */ + } + } else if (c == '+') { + val = 0; + } else { + argptr--; + break; + } + while ((c = *p++) != '\0') { + if (c == 'c' && cmdline) { + minusc = p; /* command is after shell args*/ + } else if (c == 'o') { + minus_o(*argptr, val); + if (*argptr) + argptr++; + } else { + setoption(c, val); + } + } + } +} + +STATIC void +minus_o(char *name, int val) +{ + int i; + + if (name == NULL) { + out1str("Current option settings\n"); + for (i = 0; i < NOPTS; i++) + out1fmt("%-16s%s\n", optnames[i], + optlist[i] ? "on" : "off"); + } else { + for (i = 0; i < NOPTS; i++) + if (equal(name, optnames[i])) { + optlist[i] = val; + return; + } + sh_error("Illegal option -o %s", name); + } +} + + +STATIC void +setoption(int flag, int val) +{ + int i; + + for (i = 0; i < NOPTS; i++) + if (optletters[i] == flag) { + optlist[i] = val; + if (val) { + /* #%$ hack for ksh semantics */ + if (flag == 'V') + Eflag = 0; + else if (flag == 'E') + Vflag = 0; + } + return; + } + sh_error("Illegal option -%c", flag); + /* NOTREACHED */ +} + + + +/* + * Set the shell parameters. + */ + +void +setparam(char **argv) +{ + char **newparam; + char **ap; + int nparam; + + for (nparam = 0 ; argv[nparam] ; nparam++); + ap = newparam = ckmalloc((nparam + 1) * sizeof *ap); + while (*argv) { + *ap++ = savestr(*argv++); + } + *ap = NULL; + freeparam(&shellparam); + shellparam.malloc = 1; + shellparam.nparam = nparam; + shellparam.p = newparam; + shellparam.optind = 1; + shellparam.optoff = -1; +} + + +/* + * Free the list of positional parameters. + */ + +void +freeparam(volatile struct shparam *param) +{ + char **ap; + + if (param->malloc) { + for (ap = param->p ; *ap ; ap++) + ckfree(*ap); + ckfree(param->p); + } +} + + + +/* + * The shift builtin command. + */ + +int +shiftcmd(int argc, char **argv) +{ + int n; + char **ap1, **ap2; + + n = 1; + if (argc > 1) + n = number(argv[1]); + if (n > shellparam.nparam) + sh_error("can't shift that many"); + INTOFF; + shellparam.nparam -= n; + for (ap1 = shellparam.p ; --n >= 0 ; ap1++) { + if (shellparam.malloc) + ckfree(*ap1); + } + ap2 = shellparam.p; + while ((*ap2++ = *ap1++) != NULL); + shellparam.optind = 1; + shellparam.optoff = -1; + INTON; + return 0; +} + + + +/* + * The set command builtin. + */ + +int +setcmd(int argc, char **argv) +{ + if (argc == 1) + return showvars(nullstr, 0, VUNSET); + INTOFF; + options(0); + optschanged(); + if (*argptr != NULL) { + setparam(argptr); + } + INTON; + return 0; +} + + +void +getoptsreset(value) + const char *value; +{ + shellparam.optind = number(value); + shellparam.optoff = -1; +} + +/* + * The getopts builtin. Shellparam.optnext points to the next argument + * to be processed. Shellparam.optptr points to the next character to + * be processed in the current argument. If shellparam.optnext is NULL, + * then it's the first time getopts has been called. + */ + +int +getoptscmd(int argc, char **argv) +{ + char **optbase; + + if (argc < 3) + sh_error("Usage: getopts optstring var [arg]"); + else if (argc == 3) { + optbase = shellparam.p; + if (shellparam.optind > shellparam.nparam + 1) { + shellparam.optind = 1; + shellparam.optoff = -1; + } + } + else { + optbase = &argv[3]; + if (shellparam.optind > argc - 2) { + shellparam.optind = 1; + shellparam.optoff = -1; + } + } + + return getopts(argv[1], argv[2], optbase, &shellparam.optind, + &shellparam.optoff); +} + +STATIC int +getopts(char *optstr, char *optvar, char **optfirst, int *optind, int *optoff) +{ + char *p, *q; + char c = '?'; + int done = 0; + int err = 0; + char s[12]; + char **optnext; + + if (*optind < 1) + return 1; + optnext = optfirst + *optind - 1; + + if (*optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff) + p = NULL; + else + p = optnext[-1] + *optoff; + if (p == NULL || *p == '\0') { + /* Current word is done, advance */ + p = *optnext; + if (p == NULL || *p != '-' || *++p == '\0') { +atend: + p = NULL; + done = 1; + goto out; + } + optnext++; + if (p[0] == '-' && p[1] == '\0') /* check for "--" */ + goto atend; + } + + c = *p++; + for (q = optstr; *q != c; ) { + if (*q == '\0') { + if (optstr[0] == ':') { + s[0] = c; + s[1] = '\0'; + err |= setvarsafe("OPTARG", s, 0); + } else { + outfmt(&errout, "Illegal option -%c\n", c); + (void) unsetvar("OPTARG"); + } + c = '?'; + goto out; + } + if (*++q == ':') + q++; + } + + if (*++q == ':') { + if (*p == '\0' && (p = *optnext) == NULL) { + if (optstr[0] == ':') { + s[0] = c; + s[1] = '\0'; + err |= setvarsafe("OPTARG", s, 0); + c = ':'; + } else { + outfmt(&errout, "No arg for -%c option\n", c); + (void) unsetvar("OPTARG"); + c = '?'; + } + goto out; + } + + if (p == *optnext) + optnext++; + err |= setvarsafe("OPTARG", p, 0); + p = NULL; + } else + err |= setvarsafe("OPTARG", nullstr, 0); + +out: + *optoff = p ? p - *(optnext - 1) : -1; + *optind = optnext - optfirst + 1; + fmtstr(s, sizeof(s), "%d", *optind); + err |= setvarsafe("OPTIND", s, VNOFUNC); + s[0] = c; + s[1] = '\0'; + err |= setvarsafe(optvar, s, 0); + if (err) { + *optind = 1; + *optoff = -1; + flushall(); + exraise(EXERROR); + } + return done; +} + +/* + * XXX - should get rid of. have all builtins use getopt(3). the + * library getopt must have the BSD extension static variable "optreset" + * otherwise it can't be used within the shell safely. + * + * Standard option processing (a la getopt) for builtin routines. The + * only argument that is passed to nextopt is the option string; the + * other arguments are unnecessary. It return the character, or '\0' on + * end of input. + */ + +int +nextopt(const char *optstring) +{ + char *p; + const char *q; + char c; + + if ((p = optptr) == NULL || *p == '\0') { + p = *argptr; + if (p == NULL || *p != '-' || *++p == '\0') + return '\0'; + argptr++; + if (p[0] == '-' && p[1] == '\0') /* check for "--" */ + return '\0'; + } + c = *p++; + for (q = optstring ; *q != c ; ) { + if (*q == '\0') + sh_error("Illegal option -%c", c); + if (*++q == ':') + q++; + } + if (*++q == ':') { + if (*p == '\0' && (p = *argptr++) == NULL) + sh_error("No arg for -%c option", c); + optionarg = p; + p = NULL; + } + optptr = p; + return c; +} diff -puN /dev/null usr/dash/options.h --- /dev/null +++ a/usr/dash/options.h @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)options.h 8.2 (Berkeley) 5/4/95 + */ + +struct shparam { + int nparam; /* # of positional parameters (without $0) */ + unsigned char malloc; /* if parameter list dynamically allocated */ + char **p; /* parameter list */ + int optind; /* next parameter to be processed by getopts */ + int optoff; /* used by getopts */ +}; + + + +#define eflag optlist[0] +#define fflag optlist[1] +#define Iflag optlist[2] +#define iflag optlist[3] +#define mflag optlist[4] +#define nflag optlist[5] +#define sflag optlist[6] +#define xflag optlist[7] +#define vflag optlist[8] +#define Vflag optlist[9] +#define Eflag optlist[10] +#define Cflag optlist[11] +#define aflag optlist[12] +#define bflag optlist[13] +#define uflag optlist[14] +#define nolog optlist[15] +#define debug optlist[16] + +#define NOPTS 17 + +extern const char optletters[NOPTS]; +extern char optlist[NOPTS]; + + +extern char *minusc; /* argument to -c option */ +extern char *arg0; /* $0 */ +extern struct shparam shellparam; /* $@ */ +extern char **argptr; /* argument list for builtin commands */ +extern char *optionarg; /* set by nextopt */ +extern char *optptr; /* used by nextopt */ + +void procargs(int, char **); +void optschanged(void); +void setparam(char **); +void freeparam(volatile struct shparam *); +int shiftcmd(int, char **); +int setcmd(int, char **); +int getoptscmd(int, char **); +int nextopt(const char *); +void getoptsreset(const char *); diff -puN /dev/null usr/dash/output.c --- /dev/null +++ a/usr/dash/output.c @@ -0,0 +1,385 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Shell output routines. We use our own output routines because: + * When a builtin command is interrupted we have to discard + * any pending output. + * When a builtin command appears in back quotes, we want to + * save the output of the command in a region obtained + * via malloc, rather than doing a fork and reading the + * output of the command via a pipe. + * Our output routines may be smaller than the stdio routines. + */ + +#include /* quad_t */ +#include /* BSD4_4 */ +#include + +#include /* defines BUFSIZ */ +#include +#include +#include +#ifdef USE_GLIBC_STDIO +#include +#endif +#include + +#include "shell.h" +#include "syntax.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "main.h" +#include "system.h" + + +#define OUTBUFSIZ BUFSIZ +#define MEM_OUT -3 /* output to dynamically allocated memory */ + + +#ifdef USE_GLIBC_STDIO +struct output output = { + stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 1, flags: 0 +}; +struct output errout = { + stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0 +} +#ifdef notyet +struct output memout = { + stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0 +}; +#endif +#else +struct output output = { + nextc: 0, end: 0, buf: 0, bufsize: OUTBUFSIZ, fd: 1, flags: 0 +}; +struct output errout = { + nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0 +}; +struct output preverrout; +#ifdef notyet +struct output memout = { + nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0 +}; +#endif +#endif +struct output *out1 = &output; +struct output *out2 = &errout; + + +#ifndef USE_GLIBC_STDIO +static void __outstr(const char *, size_t, struct output *); +#endif +static int xvsnprintf(char *, size_t, const char *, va_list); + + +#ifdef mkinit + +INCLUDE "output.h" +INCLUDE "memalloc.h" + +INIT { +#ifdef USE_GLIBC_STDIO + initstreams(); +#endif +} + +RESET { +#ifdef notyet + out1 = &output; + out2 = &errout; +#ifdef USE_GLIBC_STDIO + if (memout.stream != NULL) + __closememout(); +#endif + if (memout.buf != NULL) { + ckfree(memout.buf); + memout.buf = NULL; + } +#endif +} + +#endif + + +#ifndef USE_GLIBC_STDIO +static void +__outstr(const char *p, size_t len, struct output *dest) +{ + size_t bufsize; + size_t offset; + size_t nleft; + + nleft = dest->end - dest->nextc; + if (nleft >= len) { +buffered: + dest->nextc = mempcpy(dest->nextc, p, len); + return; + } + + bufsize = dest->bufsize; + if (!bufsize) { + ; + } else if (dest->buf == NULL) { + if (dest->fd == MEM_OUT && len > bufsize) { + bufsize = len; + } + offset = 0; + goto alloc; + } else if (dest->fd == MEM_OUT) { + offset = bufsize; + if (bufsize >= len) { + bufsize <<= 1; + } else { + bufsize += len; + } + if (bufsize < offset) + goto err; +alloc: + INTOFF; + dest->buf = ckrealloc(dest->buf, bufsize); + dest->bufsize = bufsize; + dest->end = dest->buf + bufsize; + dest->nextc = dest->buf + offset; + INTON; + } else { + flushout(dest); + } + + nleft = dest->end - dest->nextc; + if (nleft > len) + goto buffered; + + if ((xwrite(dest->fd, p, len))) { +err: + dest->flags |= OUTPUT_ERR; + } +} +#endif + + +void +outstr(const char *p, struct output *file) +{ +#ifdef USE_GLIBC_STDIO + INTOFF; + fputs(p, file->stream); + INTON; +#else + size_t len; + + len = strlen(p); + __outstr(p, len, file); +#endif +} + + +#ifndef USE_GLIBC_STDIO + + +void +outcslow(int c, struct output *dest) +{ + char buf = c; + __outstr(&buf, 1, dest); +} +#endif + + +void +flushall(void) +{ + flushout(&output); +#ifdef FLUSHERR + flushout(&errout); +#endif +} + + +void +flushout(struct output *dest) +{ +#ifdef USE_GLIBC_STDIO + INTOFF; + fflush(dest->stream); + INTON; +#else + size_t len; + + len = dest->nextc - dest->buf; + if (!len || dest->fd < 0) + return; + dest->nextc = dest->buf; + if ((xwrite(dest->fd, dest->buf, len))) + dest->flags |= OUTPUT_ERR; +#endif +} + + +void +outfmt(struct output *file, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + doformat(file, fmt, ap); + va_end(ap); +} + + +void +out1fmt(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + doformat(out1, fmt, ap); + va_end(ap); +} + + +int +fmtstr(char *outbuf, size_t length, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = xvsnprintf(outbuf, length, fmt, ap); + va_end(ap); + return ret; +} + + +#ifndef USE_GLIBC_STDIO +void +doformat(struct output *dest, const char *f, va_list ap) +{ + struct stackmark smark; + char *s; + int len, ret; + size_t size; + va_list ap2; + + va_copy(ap2, ap); + size = dest->end - dest->nextc; + len = xvsnprintf(dest->nextc, size, f, ap2); + va_end(ap2); + if (len < 0) { + dest->flags |= OUTPUT_ERR; + return; + } + if (len < size) { + dest->nextc += len; + return; + } + setstackmark(&smark); + s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1); + ret = xvsnprintf(s, len + 1, f, ap); + if (ret == len) + __outstr(s, len, dest); + else + dest->flags |= OUTPUT_ERR; + popstackmark(&smark); +} +#endif + + + +/* + * Version of write which resumes after a signal is caught. + */ + +int +xwrite(int fd, const void *p, size_t n) +{ + const char *buf = p; + + while (n) { + ssize_t i; + size_t m; + + m = n; + if (m > SSIZE_MAX) + m = SSIZE_MAX; + do { + i = write(fd, buf, m); + } while (i < 0 && errno == EINTR); + if (i < 0) + return -1; + buf += i; + n -= i; + } + return 0; +} + + +#ifdef notyet +#ifdef USE_GLIBC_STDIO +void initstreams() { + output.stream = stdout; + errout.stream = stderr; +} + + +void +openmemout(void) { + INTOFF; + memout.stream = open_memstream(&memout.buf, &memout.bufsize); + INTON; +} + + +int +__closememout(void) { + int error; + error = fclose(memout.stream); + memout.stream = NULL; + return error; +} +#endif +#endif + + +static int +xvsnprintf(char *outbuf, size_t length, const char *fmt, va_list ap) +{ + int ret; + + INTOFF; + ret = vsnprintf(outbuf, length, fmt, ap); + INTON; + return ret; +} diff -puN /dev/null usr/dash/output.h --- /dev/null +++ a/usr/dash/output.h @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)output.h 8.2 (Berkeley) 5/4/95 + */ + +#ifndef OUTPUT_INCL + +#include +#ifdef USE_GLIBC_STDIO +#include +#endif +#include + +struct output { +#ifdef USE_GLIBC_STDIO + FILE *stream; +#endif + char *nextc; + char *end; + char *buf; + size_t bufsize; + int fd; + int flags; +}; + +extern struct output output; +extern struct output errout; +extern struct output preverrout; +#ifdef notyet +extern struct output memout; +#endif +extern struct output *out1; +extern struct output *out2; + +void outstr(const char *, struct output *); +#ifndef USE_GLIBC_STDIO +void outcslow(int, struct output *); +#endif +void flushall(void); +void flushout(struct output *); +void outfmt(struct output *, const char *, ...) + __attribute__((__format__(__printf__,2,3))); +void out1fmt(const char *, ...) + __attribute__((__format__(__printf__,1,2))); +int fmtstr(char *, size_t, const char *, ...) + __attribute__((__format__(__printf__,3,4))); +#ifndef USE_GLIBC_STDIO +void doformat(struct output *, const char *, va_list); +#endif +int xwrite(int, const void *, size_t); +#ifdef notyet +#ifdef USE_GLIBC_STDIO +void initstreams(void); +void openmemout(void); +int __closememout(void); +#endif +#endif + +static inline void +freestdout() +{ + output.nextc = output.buf; + output.flags = 0; +} + +#define OUTPUT_ERR 01 /* error occurred on output */ + +#ifdef USE_GLIBC_STDIO +#define outc(c, o) putc((c), (o)->stream) +#define doformat(d, f, a) vfprintf((d)->stream, (f), (a)) +#else +#define outc(c, file) ((file)->nextc == (file)->end ? outcslow((c), (file)) : (*(file)->nextc = (c), (file)->nextc++)) +#endif +#define out1c(c) outc((c), out1) +#define out2c(c) outcslow((c), out2) +#define out1str(s) outstr((s), out1) +#define out2str(s) outstr((s), out2) +#define outerr(f) (f)->flags + +#define OUTPUT_INCL +#endif diff -puN /dev/null usr/dash/parser.c --- /dev/null +++ a/usr/dash/parser.c @@ -0,0 +1,1556 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "shell.h" +#include "parser.h" +#include "nodes.h" +#include "expand.h" /* defines rmescapes() */ +#include "redir.h" /* defines copyfd() */ +#include "exec.h" /* defines find_builtin() */ +#include "syntax.h" +#include "options.h" +#include "input.h" +#include "output.h" +#include "var.h" +#include "error.h" +#include "memalloc.h" +#include "mystring.h" +#include "alias.h" +#include "show.h" +#include "builtins.h" +#ifndef SMALL +#include "myhistedit.h" +#endif + +/* + * Shell command parser. + */ + +#define EOFMARKLEN 79 + +/* values returned by readtoken */ +#include "token.h" + + + +struct heredoc { + struct heredoc *next; /* next here document in list */ + union node *here; /* redirection node */ + char *eofmark; /* string indicating end of input */ + int striptabs; /* if set, strip leading tabs */ +}; + + + +struct heredoc *heredoclist; /* list of here documents to read */ +int doprompt; /* if set, prompt the user */ +int needprompt; /* true if interactive and at start of line */ +int lasttoken; /* last token read */ +MKINIT int tokpushback; /* last token pushed back */ +char *wordtext; /* text of last word returned by readtoken */ +int checkkwd; +struct nodelist *backquotelist; +union node *redirnode; +struct heredoc *heredoc; +int quoteflag; /* set if (part of) last token was quoted */ +int startlinno; /* line # where last token started */ + + +STATIC union node *list(int); +STATIC union node *andor(void); +STATIC union node *pipeline(void); +STATIC union node *command(void); +STATIC union node *simplecmd(void); +STATIC union node *makename(void); +STATIC void parsefname(void); +STATIC void parseheredoc(void); +STATIC int peektoken(void); +STATIC int readtoken(void); +STATIC int xxreadtoken(void); +STATIC int readtoken1(int, char const *, char *, int); +STATIC int noexpand(char *); +STATIC void synexpect(int) __attribute__((__noreturn__)); +STATIC void synerror(const char *) __attribute__((__noreturn__)); +STATIC void setprompt(int); + + +static inline int +isassignment(const char *p) +{ + const char *q = endofname(p); + if (p == q) + return 0; + return *q == '='; +} + + +/* + * Read and parse a command. Returns NEOF on end of file. (NULL is a + * valid parse tree indicating a blank line.) + */ + +union node * +parsecmd(int interact) +{ + int t; + + tokpushback = 0; + doprompt = interact; + if (doprompt) + setprompt(doprompt); + needprompt = 0; + t = readtoken(); + if (t == TEOF) + return NEOF; + if (t == TNL) + return NULL; + tokpushback++; + return list(1); +} + + +STATIC union node * +list(int nlflag) +{ + union node *n1, *n2, *n3; + int tok; + + checkkwd = CHKNL | CHKKWD | CHKALIAS; + if (nlflag == 2 && tokendlist[peektoken()]) + return NULL; + n1 = NULL; + for (;;) { + n2 = andor(); + tok = readtoken(); + if (tok == TBACKGND) { + if (n2->type == NPIPE) { + n2->npipe.backgnd = 1; + } else { + if (n2->type != NREDIR) { + n3 = stalloc(sizeof(struct nredir)); + n3->nredir.n = n2; + n3->nredir.redirect = NULL; + n2 = n3; + } + n2->type = NBACKGND; + } + } + if (n1 == NULL) { + n1 = n2; + } + else { + n3 = (union node *)stalloc(sizeof (struct nbinary)); + n3->type = NSEMI; + n3->nbinary.ch1 = n1; + n3->nbinary.ch2 = n2; + n1 = n3; + } + switch (tok) { + case TBACKGND: + case TSEMI: + tok = readtoken(); + /* fall through */ + case TNL: + if (tok == TNL) { + parseheredoc(); + if (nlflag == 1) + return n1; + } else { + tokpushback++; + } + checkkwd = CHKNL | CHKKWD | CHKALIAS; + if (tokendlist[peektoken()]) + return n1; + break; + case TEOF: + if (heredoclist) + parseheredoc(); + else + pungetc(); /* push back EOF on input */ + return n1; + default: + if (nlflag == 1) + synexpect(-1); + tokpushback++; + return n1; + } + } +} + + + +STATIC union node * +andor(void) +{ + union node *n1, *n2, *n3; + int t; + + n1 = pipeline(); + for (;;) { + if ((t = readtoken()) == TAND) { + t = NAND; + } else if (t == TOR) { + t = NOR; + } else { + tokpushback++; + return n1; + } + checkkwd = CHKNL | CHKKWD | CHKALIAS; + n2 = pipeline(); + n3 = (union node *)stalloc(sizeof (struct nbinary)); + n3->type = t; + n3->nbinary.ch1 = n1; + n3->nbinary.ch2 = n2; + n1 = n3; + } +} + + + +STATIC union node * +pipeline(void) +{ + union node *n1, *n2, *pipenode; + struct nodelist *lp, *prev; + int negate; + + negate = 0; + TRACE(("pipeline: entered\n")); + if (readtoken() == TNOT) { + negate = !negate; + checkkwd = CHKKWD | CHKALIAS; + } else + tokpushback++; + n1 = command(); + if (readtoken() == TPIPE) { + pipenode = (union node *)stalloc(sizeof (struct npipe)); + pipenode->type = NPIPE; + pipenode->npipe.backgnd = 0; + lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); + pipenode->npipe.cmdlist = lp; + lp->n = n1; + do { + prev = lp; + lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); + checkkwd = CHKNL | CHKKWD | CHKALIAS; + lp->n = command(); + prev->next = lp; + } while (readtoken() == TPIPE); + lp->next = NULL; + n1 = pipenode; + } + tokpushback++; + if (negate) { + n2 = (union node *)stalloc(sizeof (struct nnot)); + n2->type = NNOT; + n2->nnot.com = n1; + return n2; + } else + return n1; +} + + + +STATIC union node * +command(void) +{ + union node *n1, *n2; + union node *ap, **app; + union node *cp, **cpp; + union node *redir, **rpp; + union node **rpp2; + int t; + + redir = NULL; + rpp2 = &redir; + + switch (readtoken()) { + default: + synexpect(-1); + /* NOTREACHED */ + case TIF: + n1 = (union node *)stalloc(sizeof (struct nif)); + n1->type = NIF; + n1->nif.test = list(0); + if (readtoken() != TTHEN) + synexpect(TTHEN); + n1->nif.ifpart = list(0); + n2 = n1; + while (readtoken() == TELIF) { + n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif)); + n2 = n2->nif.elsepart; + n2->type = NIF; + n2->nif.test = list(0); + if (readtoken() != TTHEN) + synexpect(TTHEN); + n2->nif.ifpart = list(0); + } + if (lasttoken == TELSE) + n2->nif.elsepart = list(0); + else { + n2->nif.elsepart = NULL; + tokpushback++; + } + t = TFI; + break; + case TWHILE: + case TUNTIL: { + int got; + n1 = (union node *)stalloc(sizeof (struct nbinary)); + n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; + n1->nbinary.ch1 = list(0); + if ((got=readtoken()) != TDO) { +TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); + synexpect(TDO); + } + n1->nbinary.ch2 = list(0); + t = TDONE; + break; + } + case TFOR: + if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) + synerror("Bad for loop variable"); + n1 = (union node *)stalloc(sizeof (struct nfor)); + n1->type = NFOR; + n1->nfor.var = wordtext; + checkkwd = CHKKWD | CHKALIAS; + if (readtoken() == TIN) { + app = ≈ + while (readtoken() == TWORD) { + n2 = (union node *)stalloc(sizeof (struct narg)); + n2->type = NARG; + n2->narg.text = wordtext; + n2->narg.backquote = backquotelist; + *app = n2; + app = &n2->narg.next; + } + *app = NULL; + n1->nfor.args = ap; + if (lasttoken != TNL && lasttoken != TSEMI) + synexpect(-1); + } else { + n2 = (union node *)stalloc(sizeof (struct narg)); + n2->type = NARG; + n2->narg.text = (char *)dolatstr; + n2->narg.backquote = NULL; + n2->narg.next = NULL; + n1->nfor.args = n2; + /* + * Newline or semicolon here is optional (but note + * that the original Bourne shell only allowed NL). + */ + if (lasttoken != TNL && lasttoken != TSEMI) + tokpushback++; + } + checkkwd = CHKNL | CHKKWD | CHKALIAS; + if (readtoken() != TDO) + synexpect(TDO); + n1->nfor.body = list(0); + t = TDONE; + break; + case TCASE: + n1 = (union node *)stalloc(sizeof (struct ncase)); + n1->type = NCASE; + if (readtoken() != TWORD) + synexpect(TWORD); + n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg)); + n2->type = NARG; + n2->narg.text = wordtext; + n2->narg.backquote = backquotelist; + n2->narg.next = NULL; + do { + checkkwd = CHKKWD | CHKALIAS; + } while (readtoken() == TNL); + if (lasttoken != TIN) + synexpect(TIN); + cpp = &n1->ncase.cases; +next_case: + checkkwd = CHKNL | CHKKWD; + t = readtoken(); + while(t != TESAC) { + if (lasttoken == TLP) + readtoken(); + *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); + cp->type = NCLIST; + app = &cp->nclist.pattern; + for (;;) { + *app = ap = (union node *)stalloc(sizeof (struct narg)); + ap->type = NARG; + ap->narg.text = wordtext; + ap->narg.backquote = backquotelist; + if (readtoken() != TPIPE) + break; + app = &ap->narg.next; + readtoken(); + } + ap->narg.next = NULL; + if (lasttoken != TRP) + synexpect(TRP); + cp->nclist.body = list(2); + + cpp = &cp->nclist.next; + + checkkwd = CHKNL | CHKKWD; + if ((t = readtoken()) != TESAC) { + if (t != TENDCASE) + synexpect(TENDCASE); + else + goto next_case; + } + } + *cpp = NULL; + goto redir; + case TLP: + n1 = (union node *)stalloc(sizeof (struct nredir)); + n1->type = NSUBSHELL; + n1->nredir.n = list(0); + n1->nredir.redirect = NULL; + t = TRP; + break; + case TBEGIN: + n1 = list(0); + t = TEND; + break; + case TWORD: + case TREDIR: + tokpushback++; + return simplecmd(); + } + + if (readtoken() != t) + synexpect(t); + +redir: + /* Now check for redirection which may follow command */ + checkkwd = CHKKWD | CHKALIAS; + rpp = rpp2; + while (readtoken() == TREDIR) { + *rpp = n2 = redirnode; + rpp = &n2->nfile.next; + parsefname(); + } + tokpushback++; + *rpp = NULL; + if (redir) { + if (n1->type != NSUBSHELL) { + n2 = (union node *)stalloc(sizeof (struct nredir)); + n2->type = NREDIR; + n2->nredir.n = n1; + n1 = n2; + } + n1->nredir.redirect = redir; + } + + return n1; +} + + +STATIC union node * +simplecmd(void) { + union node *args, **app; + union node *n = NULL; + union node *vars, **vpp; + union node **rpp, *redir; + int savecheckkwd; + + args = NULL; + app = &args; + vars = NULL; + vpp = &vars; + redir = NULL; + rpp = &redir; + + savecheckkwd = CHKALIAS; + for (;;) { + checkkwd = savecheckkwd; + switch (readtoken()) { + case TWORD: + n = (union node *)stalloc(sizeof (struct narg)); + n->type = NARG; + n->narg.text = wordtext; + n->narg.backquote = backquotelist; + if (savecheckkwd && isassignment(wordtext)) { + *vpp = n; + vpp = &n->narg.next; + } else { + *app = n; + app = &n->narg.next; + savecheckkwd = 0; + } + break; + case TREDIR: + *rpp = n = redirnode; + rpp = &n->nfile.next; + parsefname(); /* read name of redirection file */ + break; + case TLP: + if ( + args && app == &args->narg.next && + !vars && !redir + ) { + struct builtincmd *bcmd; + const char *name; + + /* We have a function */ + if (readtoken() != TRP) + synexpect(TRP); + name = n->narg.text; + if ( + !goodname(name) || ( + (bcmd = find_builtin(name)) && + bcmd->flags & BUILTIN_SPECIAL + ) + ) + synerror("Bad function name"); + n->type = NDEFUN; + checkkwd = CHKNL | CHKKWD | CHKALIAS; + n->narg.next = command(); + return n; + } + /* fall through */ + default: + tokpushback++; + goto out; + } + } +out: + *app = NULL; + *vpp = NULL; + *rpp = NULL; + n = (union node *)stalloc(sizeof (struct ncmd)); + n->type = NCMD; + n->ncmd.args = args; + n->ncmd.assign = vars; + n->ncmd.redirect = redir; + return n; +} + +STATIC union node * +makename(void) +{ + union node *n; + + n = (union node *)stalloc(sizeof (struct narg)); + n->type = NARG; + n->narg.next = NULL; + n->narg.text = wordtext; + n->narg.backquote = backquotelist; + return n; +} + +void fixredir(union node *n, const char *text, int err) + { + TRACE(("Fix redir %s %d\n", text, err)); + if (!err) + n->ndup.vname = NULL; + + if (is_digit(text[0]) && text[1] == '\0') + n->ndup.dupfd = digit_val(text[0]); + else if (text[0] == '-' && text[1] == '\0') + n->ndup.dupfd = -1; + else { + + if (err) + synerror("Bad fd number"); + else + n->ndup.vname = makename(); + } +} + + +STATIC void +parsefname(void) +{ + union node *n = redirnode; + + if (readtoken() != TWORD) + synexpect(-1); + if (n->type == NHERE) { + struct heredoc *here = heredoc; + struct heredoc *p; + int i; + + if (quoteflag == 0) + n->type = NXHERE; + TRACE(("Here document %d\n", n->type)); + if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) + synerror("Illegal eof marker for << redirection"); + rmescapes(wordtext); + here->eofmark = wordtext; + here->next = NULL; + if (heredoclist == NULL) + heredoclist = here; + else { + for (p = heredoclist ; p->next ; p = p->next); + p->next = here; + } + } else if (n->type == NTOFD || n->type == NFROMFD) { + fixredir(n, wordtext, 0); + } else { + n->nfile.fname = makename(); + } +} + + +/* + * Input any here documents. + */ + +STATIC void +parseheredoc(void) +{ + struct heredoc *here; + union node *n; + + here = heredoclist; + heredoclist = 0; + + while (here) { + if (needprompt) { + setprompt(2); + } + readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, + here->eofmark, here->striptabs); + n = (union node *)stalloc(sizeof (struct narg)); + n->narg.type = NARG; + n->narg.next = NULL; + n->narg.text = wordtext; + n->narg.backquote = backquotelist; + here->here->nhere.doc = n; + here = here->next; + } +} + +STATIC int +peektoken(void) +{ + int t; + + t = readtoken(); + tokpushback++; + return (t); +} + +STATIC int +readtoken(void) +{ + int t; +#ifdef DEBUG + int alreadyseen = tokpushback; +#endif + +top: + t = xxreadtoken(); + + /* + * eat newlines + */ + if (checkkwd & CHKNL) { + while (t == TNL) { + parseheredoc(); + t = xxreadtoken(); + } + } + + if (t != TWORD || quoteflag) { + goto out; + } + + /* + * check for keywords + */ + if (checkkwd & CHKKWD) { + const char *const *pp; + + if ((pp = findkwd(wordtext))) { + lasttoken = t = pp - parsekwd + KWDOFFSET; + TRACE(("keyword %s recognized\n", tokname[t])); + goto out; + } + } + + if (checkkwd & CHKALIAS) { + struct alias *ap; + if ((ap = lookupalias(wordtext, 1)) != NULL) { + if (*ap->val) { + pushstring(ap->val, ap); + } + goto top; + } + } +out: + checkkwd = 0; +#ifdef DEBUG + if (!alreadyseen) + TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); + else + TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); +#endif + return (t); +} + + +/* + * Read the next input token. + * If the token is a word, we set backquotelist to the list of cmds in + * backquotes. We set quoteflag to true if any part of the word was + * quoted. + * If the token is TREDIR, then we set redirnode to a structure containing + * the redirection. + * In all cases, the variable startlinno is set to the number of the line + * on which the token starts. + * + * [Change comment: here documents and internal procedures] + * [Readtoken shouldn't have any arguments. Perhaps we should make the + * word parsing code into a separate routine. In this case, readtoken + * doesn't need to have any internal procedures, but parseword does. + * We could also make parseoperator in essence the main routine, and + * have parseword (readtoken1?) handle both words and redirection.] + */ + +#define RETURN(token) return lasttoken = token + +STATIC int +xxreadtoken(void) +{ + int c; + + if (tokpushback) { + tokpushback = 0; + return lasttoken; + } + if (needprompt) { + setprompt(2); + } + startlinno = plinno; + for (;;) { /* until token or start of word found */ + c = pgetc_macro(); + switch (c) { + case ' ': case '\t': + case PEOA: + continue; + case '#': + while ((c = pgetc()) != '\n' && c != PEOF); + pungetc(); + continue; + case '\\': + if (pgetc() == '\n') { + startlinno = ++plinno; + if (doprompt) + setprompt(2); + continue; + } + pungetc(); + goto breakloop; + case '\n': + plinno++; + needprompt = doprompt; + RETURN(TNL); + case PEOF: + RETURN(TEOF); + case '&': + if (pgetc() == '&') + RETURN(TAND); + pungetc(); + RETURN(TBACKGND); + case '|': + if (pgetc() == '|') + RETURN(TOR); + pungetc(); + RETURN(TPIPE); + case ';': + if (pgetc() == ';') + RETURN(TENDCASE); + pungetc(); + RETURN(TSEMI); + case '(': + RETURN(TLP); + case ')': + RETURN(TRP); + default: + goto breakloop; + } + } +breakloop: + return readtoken1(c, BASESYNTAX, (char *)NULL, 0); +#undef RETURN +} + + + +/* + * If eofmark is NULL, read a word or a redirection symbol. If eofmark + * is not NULL, read a here document. In the latter case, eofmark is the + * word which marks the end of the document and striptabs is true if + * leading tabs should be stripped from the document. The argument firstc + * is the first character of the input token or document. + * + * Because C does not have internal subroutines, I have simulated them + * using goto's to implement the subroutine linkage. The following macros + * will run code that appears at the end of readtoken1. + */ + +#define CHECKEND() {goto checkend; checkend_return:;} +#define PARSEREDIR() {goto parseredir; parseredir_return:;} +#define PARSESUB() {goto parsesub; parsesub_return:;} +#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} +#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} +#define PARSEARITH() {goto parsearith; parsearith_return:;} + +STATIC int +readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) +{ + int c = firstc; + char *out; + int len; + char line[EOFMARKLEN + 1]; + struct nodelist *bqlist; + int quotef; + int dblquote; + int varnest; /* levels of variables expansion */ + int arinest; /* levels of arithmetic expansion */ + int parenlevel; /* levels of parens in arithmetic */ + int dqvarnest; /* levels of variables expansion within double quotes */ + int oldstyle; + char const *prevsyntax = NULL; /* syntax before arithmetic */ + + startlinno = plinno; + dblquote = 0; + if (syntax == DQSYNTAX) + dblquote = 1; + quotef = 0; + bqlist = NULL; + varnest = 0; + arinest = 0; + parenlevel = 0; + dqvarnest = 0; + + STARTSTACKSTR(out); + loop: { /* for each line, until end of word */ +#if ATTY + if (c == '\034' && doprompt + && attyset() && ! equal(termval(), "emacs")) { + attyline(); + if (syntax == BASESYNTAX) + return readtoken(); + c = pgetc(); + goto loop; + } +#endif + CHECKEND(); /* set c to PEOF if at end of here document */ + for (;;) { /* until end of line or end of word */ + CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ + switch(syntax[c]) { + case CNL: /* '\n' */ + if (syntax == BASESYNTAX) + goto endword; /* exit outer loop */ + USTPUTC(c, out); + plinno++; + if (doprompt) + setprompt(2); + c = pgetc(); + goto loop; /* continue outer loop */ + case CWORD: + USTPUTC(c, out); + break; + case CCTL: + if (eofmark == NULL || dblquote) + USTPUTC(CTLESC, out); + USTPUTC(c, out); + break; + case CBACK: /* backslash */ + c = pgetc2(); + if (c == PEOF) { + USTPUTC(CTLESC, out); + USTPUTC('\\', out); + pungetc(); + } else if (c == '\n') { + if (doprompt) + setprompt(2); + } else { + if ( + dblquote && + c != '\\' && c != '`' && + c != '$' && ( + c != '"' || + eofmark != NULL + ) + ) { + USTPUTC(CTLESC, out); + USTPUTC('\\', out); + } + if (SQSYNTAX[c] == CCTL) + USTPUTC(CTLESC, out); + USTPUTC(c, out); + quotef++; + } + break; + case CSQUOTE: + syntax = SQSYNTAX; +quotemark: + if (eofmark == NULL) { + USTPUTC(CTLQUOTEMARK, out); + } + break; + case CDQUOTE: + syntax = DQSYNTAX; + dblquote = 1; + goto quotemark; + case CENDQUOTE: + if (eofmark != NULL && arinest == 0 && + varnest == 0) { + USTPUTC(c, out); + } else { + if (dqvarnest == 0) { + syntax = BASESYNTAX; + dblquote = 0; + } + quotef++; + goto quotemark; + } + break; + case CVAR: /* '$' */ + PARSESUB(); /* parse substitution */ + break; + case CENDVAR: /* '}' */ + if (varnest > 0) { + varnest--; + if (dqvarnest > 0) { + dqvarnest--; + } + USTPUTC(CTLENDVAR, out); + } else { + USTPUTC(c, out); + } + break; + case CLP: /* '(' in arithmetic */ + parenlevel++; + USTPUTC(c, out); + break; + case CRP: /* ')' in arithmetic */ + if (parenlevel > 0) { + USTPUTC(c, out); + --parenlevel; + } else { + if (pgetc() == ')') { + if (--arinest == 0) { + USTPUTC(CTLENDARI, out); + syntax = prevsyntax; + if (syntax == DQSYNTAX) + dblquote = 1; + else + dblquote = 0; + } else + USTPUTC(')', out); + } else { + /* + * unbalanced parens + * (don't 2nd guess - no error) + */ + pungetc(); + USTPUTC(')', out); + } + } + break; + case CBQUOTE: /* '`' */ + PARSEBACKQOLD(); + break; + case CEOF: + goto endword; /* exit outer loop */ + case CIGN: + break; + default: + if (varnest == 0) + goto endword; /* exit outer loop */ + if (c != PEOA) { + USTPUTC(c, out); + } + } + c = pgetc_macro(); + } + } +endword: + if (syntax == ARISYNTAX) + synerror("Missing '))'"); + if (syntax != BASESYNTAX && eofmark == NULL) + synerror("Unterminated quoted string"); + if (varnest != 0) { + startlinno = plinno; + /* { */ + synerror("Missing '}'"); + } + USTPUTC('\0', out); + len = out - (char *)stackblock(); + out = stackblock(); + if (eofmark == NULL) { + if ((c == '>' || c == '<') + && quotef == 0 + && len <= 2 + && (*out == '\0' || is_digit(*out))) { + PARSEREDIR(); + return lasttoken = TREDIR; + } else { + pungetc(); + } + } + quoteflag = quotef; + backquotelist = bqlist; + grabstackblock(len); + wordtext = out; + return lasttoken = TWORD; +/* end of readtoken routine */ + + + +/* + * Check to see whether we are at the end of the here document. When this + * is called, c is set to the first character of the next input line. If + * we are at the end of the here document, this routine sets the c to PEOF. + */ + +checkend: { + if (eofmark) { + if (c == PEOA) { + c = pgetc2(); + } + if (striptabs) { + while (c == '\t') { + c = pgetc2(); + } + } + if (c == *eofmark) { + if (pfgets(line, sizeof line) != NULL) { + char *p, *q; + + p = line; + for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); + if (*p == '\n' && *q == '\0') { + c = PEOF; + plinno++; + needprompt = doprompt; + } else { + pushstring(line, NULL); + } + } + } + } + goto checkend_return; +} + + +/* + * Parse a redirection operator. The variable "out" points to a string + * specifying the fd to be redirected. The variable "c" contains the + * first character of the redirection operator. + */ + +parseredir: { + char fd = *out; + union node *np; + + np = (union node *)stalloc(sizeof (struct nfile)); + if (c == '>') { + np->nfile.fd = 1; + c = pgetc(); + if (c == '>') + np->type = NAPPEND; + else if (c == '|') + np->type = NCLOBBER; + else if (c == '&') + np->type = NTOFD; + else { + np->type = NTO; + pungetc(); + } + } else { /* c == '<' */ + np->nfile.fd = 0; + switch (c = pgetc()) { + case '<': + if (sizeof (struct nfile) != sizeof (struct nhere)) { + np = (union node *)stalloc(sizeof (struct nhere)); + np->nfile.fd = 0; + } + np->type = NHERE; + heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); + heredoc->here = np; + if ((c = pgetc()) == '-') { + heredoc->striptabs = 1; + } else { + heredoc->striptabs = 0; + pungetc(); + } + break; + + case '&': + np->type = NFROMFD; + break; + + case '>': + np->type = NFROMTO; + break; + + default: + np->type = NFROM; + pungetc(); + break; + } + } + if (fd != '\0') + np->nfile.fd = digit_val(fd); + redirnode = np; + goto parseredir_return; +} + + +/* + * Parse a substitution. At this point, we have read the dollar sign + * and nothing else. + */ + +parsesub: { + int subtype; + int typeloc; + int flags; + char *p; + static const char types[] = "}-+?="; + + c = pgetc(); + if ( + c <= PEOA || + (c != '(' && c != '{' && !is_name(c) && !is_special(c)) + ) { + USTPUTC('$', out); + pungetc(); + } else if (c == '(') { /* $(command) or $((arith)) */ + if (pgetc() == '(') { + PARSEARITH(); + } else { + pungetc(); + PARSEBACKQNEW(); + } + } else { + USTPUTC(CTLVAR, out); + typeloc = out - (char *)stackblock(); + USTPUTC(VSNORMAL, out); + subtype = VSNORMAL; + if (c == '{') { + c = pgetc(); + if (c == '#') { + if ((c = pgetc()) == '}') + c = '#'; + else + subtype = VSLENGTH; + } + else + subtype = 0; + } + if (c > PEOA && is_name(c)) { + do { + STPUTC(c, out); + c = pgetc(); + } while (c > PEOA && is_in_name(c)); + } else if (is_digit(c)) { + do { + STPUTC(c, out); + c = pgetc(); + } while (is_digit(c)); + } + else if (is_special(c)) { + USTPUTC(c, out); + c = pgetc(); + } + else +badsub: synerror("Bad substitution"); + + STPUTC('=', out); + flags = 0; + if (subtype == 0) { + switch (c) { + case ':': + flags = VSNUL; + c = pgetc(); + /*FALLTHROUGH*/ + default: + p = strchr(types, c); + if (p == NULL) + goto badsub; + subtype = p - types + VSNORMAL; + break; + case '%': + case '#': + { + int cc = c; + subtype = c == '#' ? VSTRIMLEFT : + VSTRIMRIGHT; + c = pgetc(); + if (c == cc) + subtype++; + else + pungetc(); + break; + } + } + } else { + pungetc(); + } + if (dblquote || arinest) + flags |= VSQUOTE; + *((char *)stackblock() + typeloc) = subtype | flags; + if (subtype != VSNORMAL) { + varnest++; + if (dblquote || arinest) { + dqvarnest++; + } + } + } + goto parsesub_return; +} + + +/* + * Called to parse command substitutions. Newstyle is set if the command + * is enclosed inside $(...); nlpp is a pointer to the head of the linked + * list of commands (passed by reference), and savelen is the number of + * characters on the top of the stack which must be preserved. + */ + +parsebackq: { + struct nodelist **nlpp; + union node *n; + char *str; + size_t savelen; + int saveprompt = 0; + + str = NULL; + savelen = out - (char *)stackblock(); + if (savelen > 0) { + str = alloca(savelen); + memcpy(str, stackblock(), savelen); + } + if (oldstyle) { + /* We must read until the closing backquote, giving special + treatment to some slashes, and then push the string and + reread it as input, interpreting it normally. */ + char *pout; + int pc; + size_t psavelen; + char *pstr; + + + STARTSTACKSTR(pout); + for (;;) { + if (needprompt) { + setprompt(2); + } + switch (pc = pgetc()) { + case '`': + goto done; + + case '\\': + if ((pc = pgetc()) == '\n') { + plinno++; + if (doprompt) + setprompt(2); + /* + * If eating a newline, avoid putting + * the newline into the new character + * stream (via the STPUTC after the + * switch). + */ + continue; + } + if (pc != '\\' && pc != '`' && pc != '$' + && (!dblquote || pc != '"')) + STPUTC('\\', pout); + if (pc > PEOA) { + break; + } + /* fall through */ + + case PEOF: + case PEOA: + startlinno = plinno; + synerror("EOF in backquote substitution"); + + case '\n': + plinno++; + needprompt = doprompt; + break; + + default: + break; + } + STPUTC(pc, pout); + } +done: + STPUTC('\0', pout); + psavelen = pout - (char *)stackblock(); + if (psavelen > 0) { + pstr = grabstackstr(pout); + setinputstring(pstr); + } + } + nlpp = &bqlist; + while (*nlpp) + nlpp = &(*nlpp)->next; + *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); + (*nlpp)->next = NULL; + + if (oldstyle) { + saveprompt = doprompt; + doprompt = 0; + } + + n = list(2); + + if (oldstyle) + doprompt = saveprompt; + else { + if (readtoken() != TRP) + synexpect(TRP); + } + + (*nlpp)->n = n; + if (oldstyle) { + /* + * Start reading from old file again, ignoring any pushed back + * tokens left from the backquote parsing + */ + popfile(); + tokpushback = 0; + } + while (stackblocksize() <= savelen) + growstackblock(); + STARTSTACKSTR(out); + if (str) { + memcpy(out, str, savelen); + STADJUST(savelen, out); + } + if (arinest || dblquote) + USTPUTC(CTLBACKQ | CTLQUOTE, out); + else + USTPUTC(CTLBACKQ, out); + if (oldstyle) + goto parsebackq_oldreturn; + else + goto parsebackq_newreturn; +} + +/* + * Parse an arithmetic expansion (indicate start of one and set state) + */ +parsearith: { + + if (++arinest == 1) { + prevsyntax = syntax; + syntax = ARISYNTAX; + USTPUTC(CTLARI, out); + if (dblquote) + USTPUTC('"',out); + else + USTPUTC(' ',out); + } else { + /* + * we collapse embedded arithmetic expansion to + * parenthesis, which should be equivalent + */ + USTPUTC('(', out); + } + goto parsearith_return; +} + +} /* end of readtoken */ + + + +#ifdef mkinit +INCLUDE "parser.h" +RESET { + tokpushback = 0; + checkkwd = 0; +} +#endif + +/* + * Returns true if the text contains nothing to expand (no dollar signs + * or backquotes). + */ + +STATIC int +noexpand(char *text) +{ + char *p; + signed char c; + + p = text; + while ((c = *p++) != '\0') { + if (c == CTLQUOTEMARK) + continue; + if (c == CTLESC) + p++; + else if (BASESYNTAX[(int)c] == CCTL) + return 0; + } + return 1; +} + + +/* + * Return of a legal variable name (a letter or underscore followed by zero or + * more letters, underscores, and digits). + */ + +char * +endofname(const char *name) + { + char *p; + + p = (char *) name; + if (! is_name(*p)) + return p; + while (*++p) { + if (! is_in_name(*p)) + break; + } + return p; +} + + +/* + * Called when an unexpected token is read during the parse. The argument + * is the token that is expected, or -1 if more than one type of token can + * occur at this point. + */ + +STATIC void +synexpect(int token) +{ + char msg[64]; + + if (token >= 0) { + fmtstr(msg, 64, "%s unexpected (expecting %s)", + tokname[lasttoken], tokname[token]); + } else { + fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); + } + synerror(msg); + /* NOTREACHED */ +} + + +STATIC void +synerror(const char *msg) +{ + sh_error("Syntax error: %s", msg); + /* NOTREACHED */ +} + +STATIC void +setprompt(int which) +{ + struct stackmark smark; + int show; + + needprompt = 0; + whichprompt = which; + +#ifdef SMALL + show = 1; +#else + show = !el; +#endif + if (show) { + setstackmark(&smark); + stalloc(stackblocksize()); + out2str(getprompt(NULL)); + popstackmark(&smark); + } +} + +const char * +expandstr(const char *ps) +{ + union node n; + + /* XXX Fix (char *) cast. */ + setinputstring((char *)ps); + readtoken1(pgetc(), DQSYNTAX, nullstr, 0); + popfile(); + + n.narg.type = NARG; + n.narg.next = NULL; + n.narg.text = wordtext; + n.narg.backquote = backquotelist; + + expandarg(&n, NULL, 0); + return stackblock(); +} + +/* + * called by editline -- any expansions to the prompt + * should be added here. + */ +const char * +getprompt(void *unused) +{ + const char *prompt; + + switch (whichprompt) { + default: +#ifdef DEBUG + return ""; +#endif + case 0: + return nullstr; + case 1: + prompt = ps1val(); + break; + case 2: + prompt = ps2val(); + break; + } + + return expandstr(prompt); +} + +const char *const * +findkwd(const char *s) +{ + return findstring( + s, parsekwd, sizeof(parsekwd) / sizeof(const char *) + ); +} diff -puN /dev/null usr/dash/parser.h --- /dev/null +++ a/usr/dash/parser.h @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)parser.h 8.3 (Berkeley) 5/4/95 + */ + +/* control characters in argument strings */ +#define CTL_FIRST -127 /* first 'special' character */ +#define CTLESC -127 /* escape next character */ +#define CTLVAR -126 /* variable defn */ +#define CTLENDVAR -125 +#define CTLBACKQ -124 +#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ +/* CTLBACKQ | CTLQUOTE == 133 */ +#define CTLARI -122 /* arithmetic expression */ +#define CTLENDARI -121 +#define CTLQUOTEMARK -120 +#define CTL_LAST -120 /* last 'special' character */ + +/* variable substitution byte (follows CTLVAR) */ +#define VSTYPE 0x0f /* type of variable substitution */ +#define VSNUL 0x10 /* colon--treat the empty string as unset */ +#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ + +/* values of VSTYPE field */ +#define VSNORMAL 0x1 /* normal variable: $var or ${var} */ +#define VSMINUS 0x2 /* ${var-text} */ +#define VSPLUS 0x3 /* ${var+text} */ +#define VSQUESTION 0x4 /* ${var?message} */ +#define VSASSIGN 0x5 /* ${var=text} */ +#define VSTRIMRIGHT 0x6 /* ${var%pattern} */ +#define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */ +#define VSTRIMLEFT 0x8 /* ${var#pattern} */ +#define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ +#define VSLENGTH 0xa /* ${#var} */ + +/* values of checkkwd variable */ +#define CHKALIAS 0x1 +#define CHKKWD 0x2 +#define CHKNL 0x4 + + +/* + * NEOF is returned by parsecmd when it encounters an end of file. It + * must be distinct from NULL, so we use the address of a variable that + * happens to be handy. + */ +extern int tokpushback; +#define NEOF ((union node *)&tokpushback) +extern int whichprompt; /* 1 == PS1, 2 == PS2 */ +extern int checkkwd; +extern int startlinno; /* line # where last token started */ + + +union node *parsecmd(int); +void fixredir(union node *, const char *, int); +const char *getprompt(void *); +const char *const *findkwd(const char *); +char *endofname(const char *); +const char *expandstr(const char *); + +static inline int +goodname(const char *p) +{ + return !*endofname(p); +} diff -puN /dev/null usr/dash/README.klibc --- /dev/null +++ a/usr/dash/README.klibc @@ -0,0 +1,7 @@ +This version of dash was obtained from + +http://gondor.apana.org.au/~herbert/dash/dash.git/ + +It corresponds to changeset 3c98399cdf8d376b2c1ebd9cd32ca5d8c84f3ac9. + +The only changes made are the addition of config.h and a new Makefile. diff -puN /dev/null usr/dash/redir.c --- /dev/null +++ a/usr/dash/redir.c @@ -0,0 +1,475 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include /* PIPE_BUF */ +#include +#include +#include +#include +#include + +/* + * Code for dealing with input/output redirection. + */ + +#include "main.h" +#include "shell.h" +#include "nodes.h" +#include "jobs.h" +#include "options.h" +#include "expand.h" +#include "redir.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" + + +#define EMPTY -2 /* marks an unused slot in redirtab */ +#ifndef PIPE_BUF +# define PIPESIZE 4096 /* amount of buffering in a pipe */ +#else +# define PIPESIZE PIPE_BUF +#endif + + +MKINIT +struct redirtab { + struct redirtab *next; + int renamed[10]; + int nullredirs; +}; + + +MKINIT struct redirtab *redirlist; +MKINIT int nullredirs; + +STATIC int openredirect(union node *); +#ifdef notyet +STATIC void dupredirect(union node *, int, char[10]); +#else +STATIC void dupredirect(union node *, int); +#endif +STATIC int openhere(union node *); +STATIC int noclobberopen(const char *); + + +/* + * Process a list of redirection commands. If the REDIR_PUSH flag is set, + * old file descriptors are stashed away so that the redirection can be + * undone by calling popredir. If the REDIR_BACKQ flag is set, then the + * standard output, and the standard error if it becomes a duplicate of + * stdout, is saved in memory. + */ + +void +redirect(union node *redir, int flags) +{ + union node *n; + struct redirtab *sv; + int i; + int fd; + int newfd; + int *p; +#if notyet + char memory[10]; /* file descriptors to write to memory */ + + for (i = 10 ; --i >= 0 ; ) + memory[i] = 0; + memory[1] = flags & REDIR_BACKQ; +#endif + nullredirs++; + if (!redir) { + return; + } + sv = NULL; + INTOFF; + if (flags & REDIR_PUSH) { + struct redirtab *q; + q = ckmalloc(sizeof (struct redirtab)); + q->next = redirlist; + redirlist = q; + q->nullredirs = nullredirs - 1; + for (i = 0 ; i < 10 ; i++) + q->renamed[i] = EMPTY; + nullredirs = 0; + sv = q; + } + n = redir; + do { + fd = n->nfile.fd; + if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && + n->ndup.dupfd == fd) + continue; /* redirect from/to same file descriptor */ + + newfd = openredirect(n); + if (fd == newfd) + continue; + if (sv && *(p = &sv->renamed[fd]) == EMPTY) { + int i = fcntl(fd, F_DUPFD, 10); + if (i == -1) { + i = errno; + if (i != EBADF) { + const char *m = strerror(i); + close(newfd); + sh_error("%d: %s", fd, m); + /* NOTREACHED */ + } + } else { + *p = i; + close(fd); + } + } else { + close(fd); + } +#ifdef notyet + dupredirect(n, newfd, memory); +#else + dupredirect(n, newfd); +#endif + } while ((n = n->nfile.next)); + INTON; +#ifdef notyet + if (memory[1]) + out1 = &memout; + if (memory[2]) + out2 = &memout; +#endif + if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0) + preverrout.fd = sv->renamed[2]; +} + + +STATIC int +openredirect(union node *redir) +{ + char *fname; + int f; + + switch (redir->nfile.type) { + case NFROM: + fname = redir->nfile.expfname; + if ((f = open64(fname, O_RDONLY)) < 0) + goto eopen; + break; + case NFROMTO: + fname = redir->nfile.expfname; + if ((f = open64(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) + goto ecreate; + break; + case NTO: + /* Take care of noclobber mode. */ + if (Cflag) { + fname = redir->nfile.expfname; + if ((f = noclobberopen(fname)) < 0) + goto ecreate; + break; + } + /* FALLTHROUGH */ + case NCLOBBER: + fname = redir->nfile.expfname; + if ((f = open64(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + goto ecreate; + break; + case NAPPEND: + fname = redir->nfile.expfname; + if ((f = open64(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) + goto ecreate; + break; + default: +#ifdef DEBUG + abort(); +#endif + /* Fall through to eliminate warning. */ + case NTOFD: + case NFROMFD: + f = -1; + break; + case NHERE: + case NXHERE: + f = openhere(redir); + break; + } + + return f; +ecreate: + sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); +eopen: + sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); +} + + +STATIC void +#ifdef notyet +dupredirect(redir, f, memory) +#else +dupredirect(redir, f) +#endif + union node *redir; + int f; +#ifdef notyet + char memory[10]; +#endif + { + int fd = redir->nfile.fd; + +#ifdef notyet + memory[fd] = 0; +#endif + if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { + if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ +#ifdef notyet + if (memory[redir->ndup.dupfd]) + memory[fd] = 1; + else +#endif + copyfd(redir->ndup.dupfd, fd); + } + return; + } + + if (f != fd) { + copyfd(f, fd); + close(f); + } + return; +} + + +/* + * Handle here documents. Normally we fork off a process to write the + * data to a pipe. If the document is short, we can stuff the data in + * the pipe without forking. + */ + +STATIC int +openhere(union node *redir) +{ + int pip[2]; + size_t len = 0; + + if (pipe(pip) < 0) + sh_error("Pipe call failed"); + if (redir->type == NHERE) { + len = strlen(redir->nhere.doc->narg.text); + if (len <= PIPESIZE) { + xwrite(pip[1], redir->nhere.doc->narg.text, len); + goto out; + } + } + if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { + close(pip[0]); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGHUP, SIG_IGN); +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); +#endif + signal(SIGPIPE, SIG_DFL); + if (redir->type == NHERE) + xwrite(pip[1], redir->nhere.doc->narg.text, len); + else + expandhere(redir->nhere.doc, pip[1]); + _exit(0); + } +out: + close(pip[1]); + return pip[0]; +} + + + +/* + * Undo the effects of the last redirection. + */ + +void +popredir(int drop) +{ + struct redirtab *rp; + int i; + + if (--nullredirs >= 0) + return; + INTOFF; + rp = redirlist; + for (i = 0 ; i < 10 ; i++) { + if (rp->renamed[i] != EMPTY) { + if (!drop) { + close(i); + copyfd(rp->renamed[i], i); + } + close(rp->renamed[i]); + } + } + redirlist = rp->next; + nullredirs = rp->nullredirs; + ckfree(rp); + INTON; +} + +/* + * Undo all redirections. Called on error or interrupt. + */ + +#ifdef mkinit + +INCLUDE "redir.h" + +RESET { + clearredir(0); +} + +#endif + +/* + * Discard all saved file descriptors. + */ + +void +clearredir(int drop) +{ + for (;;) { + nullredirs = 0; + if (!redirlist) + break; + popredir(drop); + } +} + + + +/* + * Copy a file descriptor to be >= to. Returns -1 + * if the source file descriptor is closed, EMPTY if there are no unused + * file descriptors left. + */ + +int +copyfd(int from, int to) +{ + int newfd; + + newfd = fcntl(from, F_DUPFD, to); + if (newfd < 0) { + int errno2 = errno; + if (errno2 == EMFILE) + return EMPTY; + else + sh_error("%d: %s", from, strerror(errno2)); + } + return newfd; +} + + +/* + * Open a file in noclobber mode. + * The code was copied from bash. + */ +int +noclobberopen(fname) + const char *fname; +{ + int r, fd; + struct stat64 finfo, finfo2; + + /* + * If the file exists and is a regular file, return an error + * immediately. + */ + r = stat64(fname, &finfo); + if (r == 0 && S_ISREG(finfo.st_mode)) { + errno = EEXIST; + return -1; + } + + /* + * If the file was not present (r != 0), make sure we open it + * exclusively so that if it is created before we open it, our open + * will fail. Make sure that we do not truncate an existing file. + * Note that we don't turn on O_EXCL unless the stat failed -- if the + * file was not a regular file, we leave O_EXCL off. + */ + if (r != 0) + return open64(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); + fd = open64(fname, O_WRONLY|O_CREAT, 0666); + + /* If the open failed, return the file descriptor right away. */ + if (fd < 0) + return fd; + + /* + * OK, the open succeeded, but the file may have been changed from a + * non-regular file to a regular file between the stat and the open. + * We are assuming that the O_EXCL open handles the case where FILENAME + * did not exist and is symlinked to an existing file between the stat + * and open. + */ + + /* + * If we can open it and fstat the file descriptor, and neither check + * revealed that it was a regular file, and the file has not been + * replaced, return the file descriptor. + */ + if (fstat64(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) && + finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino) + return fd; + + /* The file has been replaced. badness. */ + close(fd); + errno = EEXIST; + return -1; +} + + +int +redirectsafe(union node *redir, int flags) +{ + int err; + volatile int saveint; + struct jmploc *volatile savehandler = handler; + struct jmploc jmploc; + + SAVEINT(saveint); + if (!(err = setjmp(jmploc.loc) * 2)) { + handler = &jmploc; + redirect(redir, flags); + } + handler = savehandler; + if (err && exception != EXERROR) + longjmp(handler->loc, 1); + RESTOREINT(saveint); + return err; +} diff -puN /dev/null usr/dash/redir.h --- /dev/null +++ a/usr/dash/redir.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)redir.h 8.2 (Berkeley) 5/4/95 + */ + +/* flags passed to redirect */ +#define REDIR_PUSH 01 /* save previous values of file descriptors */ +#ifdef notyet +#define REDIR_BACKQ 02 /* save the command output in memory */ +#endif +#define REDIR_SAVEFD2 03 /* set preverrout */ + +union node; +void redirect(union node *, int); +void popredir(int); +void clearredir(int); +int copyfd(int, int); +int redirectsafe(union node *, int); diff -puN /dev/null usr/dash/sh.1 --- /dev/null +++ a/usr/dash/sh.1 @@ -0,0 +1,2332 @@ +.\" Copyright (c) 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1997-2005 +.\" Herbert Xu . All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Kenneth Almquist. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)sh.1 8.6 (Berkeley) 5/4/95 +.\" +.Dd January 19, 2003 +.Os +.Dt SH 1 +.Sh NAME +.Nm sh +.Nd command interpreter (shell) +.Sh SYNOPSIS +.Nm +.Bk -words +.Op Fl aCefnuvxIimqVEb +.Op Cm +aCefnuvxIimqVEb +.Ek +.Bk -words +.Op Fl o Ar option_name +.Op Cm +o Ar option_name +.Ek +.Bk -words +.Op Ar command_file Oo Ar argument ... Oc +.Ek +.Nm +.Fl c +.Bk -words +.Op Fl aCefnuvxIimqVEb +.Op Cm +aCefnuvxIimqVEb +.Ek +.Bk -words +.Op Fl o Ar option_name +.Op Cm +o Ar option_name +.Ek +.Bk -words +.Ar command_string +.Op Ar command_name Oo Ar argument ... Oc +.Ek +.Nm +.Fl s +.Bk -words +.Op Fl aCefnuvxIimqVEb +.Op Cm +aCefnuvxIimqVEb +.Ek +.Bk -words +.Op Fl o Ar option_name +.Op Cm +o Ar option_name +.Ek +.Bk -words +.Op Ar argument ... +.Ek +.Sh DESCRIPTION +.Nm +is the standard command interpreter for the system. +The current version of +.Nm +is in the process of being changed to conform with the +.Tn POSIX +1003.2 and 1003.2a specifications for the shell. +This version has many +features which make it appear similar in some respects to the Korn shell, +but it is not a Korn shell clone (see +.Xr ksh 1 ) . +Only features designated by +.Tn POSIX , +plus a few Berkeley extensions, are being incorporated into this shell. +We expect +.Tn POSIX +conformance by the time 4.4 BSD is released. +This man page is not intended +to be a tutorial or a complete specification of the shell. +.Ss Overview +The shell is a command that reads lines from either a file or the +terminal, interprets them, and generally executes other commands. +It is the program that is running when a user logs into the system +(although a user can select a different shell with the +.Xr chsh 1 +command). +The shell implements a language that has flow control +constructs, a macro facility that provides a variety of features in +addition to data storage, along with built in history and line editing +capabilities. +It incorporates many features to aid interactive use and +has the advantage that the interpretative language is common to both +interactive and non-interactive use (shell scripts). +That is, commands +can be typed directly to the running shell or can be put into a file and +the file can be executed directly by the shell. +.Ss Invocation +If no args are present and if the standard input of the shell +is connected to a terminal (or if the +.Fl i +flag is set), +and the +.Fl c +option is not present, the shell is considered an interactive shell. +An interactive shell generally prompts before each command and handles +programming and command errors differently (as described below). +When first starting, +the shell inspects argument 0, and if it begins with a dash +.Sq - , +the shell is also considered +a login shell. +This is normally done automatically by the system +when the user first logs in. +A login shell first reads commands +from the files +.Pa /etc/profile +and +.Pa .profile +if they exist. +If the environment variable +.Ev ENV +is set on entry to an interactive shell, or is set in the +.Pa .profile +of a login shell, the shell next reads +commands from the file named in +.Ev ENV . +Therefore, a user should place commands that are to be executed only at +login time in the +.Pa .profile +file, and commands that are executed for every interactive shell inside the +.Ev ENV +file. +To set the +.Ev ENV +variable to some file, place the following line in your +.Pa .profile +of your home directory +.Pp +.Dl ENV=$HOME/.shinit; export ENV +.Pp +substituting for +.Dq .shinit +any filename you wish. +.Pp +If command line arguments besides the options have been specified, then +the shell treats the first argument as the name of a file from which to +read commands (a shell script), and the remaining arguments are set as the +positional parameters of the shell ($1, $2, etc). +Otherwise, the shell +reads commands from its standard input. +.Ss Argument List Processing +All of the single letter options have a corresponding name that can be +used as an argument to the +.Fl o +option. +The set +.Fl o +name is provided next to the single letter option in +the description below. +Specifying a dash +.Dq - +turns the option on, while using a plus +.Dq + +disables the option. +The following options can be set from the command line or +with the +.Ic set +builtin (described later). +.Bl -tag -width aaaallexportfoo -offset indent +.It Fl a Em allexport +Export all variables assigned to. +.It Fl c +Read commands from the +.Ar command_string +operand instead of from the standard input. +Special parameter 0 will be set from the +.Ar command_name +operand and the positional parameters ($1, $2, etc.) +set from the remaining argument operands. +.It Fl C Em noclobber +Don't overwrite existing files with +.Dq \*[Gt] . +.It Fl e Em errexit +If not interactive, exit immediately if any untested command fails. +The exit status of a command is considered to be +explicitly tested if the command is used to control an +.Ic if , +.Ic elif , +.Ic while , +or +.Ic until ; +or if the command is the left hand operand of an +.Dq && +or +.Dq || +operator. +.It Fl f Em noglob +Disable pathname expansion. +.It Fl n Em noexec +If not interactive, read commands but do not execute them. +This is useful for checking the syntax of shell scripts. +.It Fl u Em nounset +Write a message to standard error when attempting to expand a variable +that is not set, and if the shell is not interactive, exit immediately. +.It Fl v Em verbose +The shell writes its input to standard error as it is read. +Useful for debugging. +.It Fl x Em xtrace +Write each command to standard error (preceded by a +.Sq +\ ) +before it is executed. +Useful for debugging. +.It Fl I Em ignoreeof +Ignore EOF's from input when interactive. +.It Fl i Em interactive +Force the shell to behave interactively. +.It Fl m Em monitor +Turn on job control (set automatically when interactive). +.It Fl s Em stdin +Read commands from standard input (set automatically if no file arguments +are present). +This option has no effect when set after the shell has +already started running (i.e. with +.Ic set ) . +.It Fl V Em vi +Enable the built-in +.Xr vi 1 +command line editor (disables +.Fl E +if it has been set). +.It Fl E Em emacs +Enable the built-in +.Xr emacs 1 +command line editor (disables +.Fl V +if it has been set). +.It Fl b Em notify +Enable asynchronous notification of background job completion. +(UNIMPLEMENTED for 4.4alpha) +.El +.Ss Lexical Structure +The shell reads input in terms of lines from a file and breaks it up into +words at whitespace (blanks and tabs), and at certain sequences of +characters that are special to the shell called +.Dq operators . +There are two types of operators: control operators and redirection +operators (their meaning is discussed later). +Following is a list of operators: +.Bl -ohang -offset indent +.It "Control operators:" +.Dl & && \&( \&) \&; ;; | || \*[Lt]newline\*[Gt] +.It "Redirection operators:" +.Dl \*[Lt] \*[Gt] \*[Gt]| \*[Lt]\*[Lt] \*[Gt]\*[Gt] \*[Lt]& \*[Gt]& \*[Lt]\*[Lt]- \*[Lt]\*[Gt] +.El +.Ss Quoting +Quoting is used to remove the special meaning of certain characters or +words to the shell, such as operators, whitespace, or keywords. +There are three types of quoting: matched single quotes, +matched double quotes, and backslash. +.Ss Backslash +A backslash preserves the literal meaning of the following +character, with the exception of +.Aq newline . +A backslash preceding a +.Aq newline +is treated as a line continuation. +.Ss Single Quotes +Enclosing characters in single quotes preserves the literal meaning of all +the characters (except single quotes, making it impossible to put +single-quotes in a single-quoted string). +.Ss Double Quotes +Enclosing characters within double quotes preserves the literal +meaning of all characters except dollarsign +.Pq $ , +backquote +.Pq ` , +and backslash +.Pq \e . +The backslash inside double quotes is historically weird, and serves to +quote only the following characters: +.Dl $ ` \*q \e \*[Lt]newline\*[Gt] . +Otherwise it remains literal. +.Ss Reserved Words +Reserved words are words that have special meaning to the +shell and are recognized at the beginning of a line and +after a control operator. +The following are reserved words: +.Bl -column while while while while while -offset indent +.It ! Ta elif Ta fi Ta while Ta case +.It else Ta for Ta then Ta { Ta } +.It do Ta done Ta until Ta if Ta esac +.El +.Pp +Their meaning is discussed later. +.Ss Aliases +An alias is a name and corresponding value set using the +.Xr alias 1 +builtin command. +Whenever a reserved word may occur (see above), +and after checking for reserved words, the shell +checks the word to see if it matches an alias. +If it does, it replaces it in the input stream with its value. +For example, if there is an alias called +.Dq lf +with the value +.Dq "ls -F" , +then the input: +.Pp +.Dl lf foobar Aq return +.Pp +would become +.Pp +.Dl ls -F foobar Aq return +.Pp +Aliases provide a convenient way for naive users to create shorthands for +commands without having to learn how to create functions with arguments. +They can also be used to create lexically obscure code. +This use is discouraged. +.Ss Commands +The shell interprets the words it reads according to a language, the +specification of which is outside the scope of this man page (refer to the +BNF in the +.Tn POSIX +1003.2 document). +Essentially though, a line is read and if the first +word of the line (or after a control operator) is not a reserved word, +then the shell has recognized a simple command. +Otherwise, a complex +command or some other special construct may have been recognized. +.Ss Simple Commands +If a simple command has been recognized, the shell performs +the following actions: +.Bl -enum -offset indent +.It +Leading words of the form +.Dq name=value +are stripped off and assigned to the environment of the simple command. +Redirection operators and their arguments (as described below) are +stripped off and saved for processing. +.It +The remaining words are expanded as described in +the section called +.Dq Expansions , +and the first remaining word is considered the command name and the +command is located. +The remaining words are considered the arguments of the command. +If no command name resulted, then the +.Dq name=value +variable assignments recognized in item 1 affect the current shell. +.It +Redirections are performed as described in the next section. +.El +.Ss Redirections +Redirections are used to change where a command reads its input or sends +its output. +In general, redirections open, close, or duplicate an +existing reference to a file. +The overall format used for redirection is: +.Pp +.Dl [n] Va redir-op Ar file +.Pp +where +.Va redir-op +is one of the redirection operators mentioned previously. +Following is a list of the possible redirections. +The +.Bq n +is an optional number, as in +.Sq 3 +(not +.Sq Bq 3 , +that refers to a file descriptor. +.Bl -tag -width aaabsfiles -offset indent +.It [n] Ns \*[Gt] file +Redirect standard output (or n) to file. +.It [n] Ns \*[Gt]| file +Same, but override the +.Fl C +option. +.It [n] Ns \*[Gt]\*[Gt] file +Append standard output (or n) to file. +.It [n] Ns \*[Lt] file +Redirect standard input (or n) from file. +.It [n1] Ns \*[Lt]& Ns n2 +Duplicate standard input (or n1) from file descriptor n2. +.It [n] Ns \*[Lt]&- +Close standard input (or n). +.It [n1] Ns \*[Gt]& Ns n2 +Duplicate standard output (or n1) to n2. +.It [n] Ns \*[Gt]&- +Close standard output (or n). +.It [n] Ns \*[Lt]\*[Gt] file +Open file for reading and writing on standard input (or n). +.El +.Pp +The following redirection is often called a +.Dq here-document . +.Bl -item -offset indent +.It +.Li [n]\*[Lt]\*[Lt] delimiter +.Dl here-doc-text ... +.Li delimiter +.El +.Pp +All the text on successive lines up to the delimiter is saved away and +made available to the command on standard input, or file descriptor n if +it is specified. +If the delimiter as specified on the initial line is +quoted, then the here-doc-text is treated literally, otherwise the text is +subjected to parameter expansion, command substitution, and arithmetic +expansion (as described in the section on +.Dq Expansions ) . +If the operator is +.Dq \*[Lt]\*[Lt]- +instead of +.Dq \*[Lt]\*[Lt] , +then leading tabs in the here-doc-text are stripped. +.Ss Search and Execution +There are three types of commands: shell functions, builtin commands, and +normal programs -- and the command is searched for (by name) in that order. +They each are executed in a different way. +.Pp +When a shell function is executed, all of the shell positional parameters +(except $0, which remains unchanged) are set to the arguments of the shell +function. +The variables which are explicitly placed in the environment of +the command (by placing assignments to them before the function name) are +made local to the function and are set to the values given. +Then the command given in the function definition is executed. +The positional parameters are restored to their original values +when the command completes. +This all occurs within the current shell. +.Pp +Shell builtins are executed internally to the shell, without spawning a +new process. +.Pp +Otherwise, if the command name doesn't match a function or builtin, the +command is searched for as a normal program in the file system (as +described in the next section). +When a normal program is executed, the shell runs the program, +passing the arguments and the environment to the program. +If the program is not a normal executable file (i.e., if it does +not begin with the "magic number" whose +.Tn ASCII +representation is "#!", so +.Xr execve 2 +returns +.Er ENOEXEC +then) the shell will interpret the program in a subshell. +The child shell will reinitialize itself in this case, +so that the effect will be as if a +new shell had been invoked to handle the ad-hoc shell script, except that +the location of hashed commands located in the parent shell will be +remembered by the child. +.Pp +Note that previous versions of this document and the source code itself +misleadingly and sporadically refer to a shell script without a magic +number as a "shell procedure". +.Ss Path Search +When locating a command, the shell first looks to see if it has a shell +function by that name. +Then it looks for a builtin command by that name. +If a builtin command is not found, one of two things happen: +.Bl -enum +.It +Command names containing a slash are simply executed without performing +any searches. +.It +The shell searches each entry in +.Ev PATH +in turn for the command. +The value of the +.Ev PATH +variable should be a series of entries separated by colons. +Each entry consists of a directory name. +The current directory may be indicated +implicitly by an empty directory name, or explicitly by a single period. +.El +.Ss Command Exit Status +Each command has an exit status that can influence the behaviour +of other shell commands. +The paradigm is that a command exits +with zero for normal or success, and non-zero for failure, +error, or a false indication. +The man page for each command +should indicate the various exit codes and what they mean. +Additionally, the builtin commands return exit codes, as does +an executed shell function. +.Pp +If a command consists entirely of variable assignments then the +exit status of the command is that of the last command substitution +if any, otherwise 0. +.Ss Complex Commands +Complex commands are combinations of simple commands with control +operators or reserved words, together creating a larger complex command. +More generally, a command is one of the following: +.Bl -bullet +.It +simple command +.It +pipeline +.It +list or compound-list +.It +compound command +.It +function definition +.El +.Pp +Unless otherwise stated, the exit status of a command is that of the last +simple command executed by the command. +.Ss Pipelines +A pipeline is a sequence of one or more commands separated +by the control operator |. +The standard output of all but +the last command is connected to the standard input +of the next command. +The standard output of the last +command is inherited from the shell, as usual. +.Pp +The format for a pipeline is: +.Pp +.Dl [!] command1 [ | command2 ...] +.Pp +The standard output of command1 is connected to the standard input of +command2. +The standard input, standard output, or both of a command is +considered to be assigned by the pipeline before any redirection specified +by redirection operators that are part of the command. +.Pp +If the pipeline is not in the background (discussed later), the shell +waits for all commands to complete. +.Pp +If the reserved word ! does not precede the pipeline, the exit status is +the exit status of the last command specified in the pipeline. +Otherwise, the exit status is the logical NOT of the exit status of the +last command. +That is, if the last command returns zero, the exit status +is 1; if the last command returns greater than zero, the exit status is +zero. +.Pp +Because pipeline assignment of standard input or standard output or both +takes place before redirection, it can be modified by redirection. +For example: +.Pp +.Dl $ command1 2\*[Gt]&1 | command2 +.Pp +sends both the standard output and standard error of command1 +to the standard input of command2. +.Pp +A ; or +.Aq newline +terminator causes the preceding AND-OR-list (described +next) to be executed sequentially; a & causes asynchronous execution of +the preceding AND-OR-list. +.Pp +Note that unlike some other shells, each process in the pipeline is a +child of the invoking shell (unless it is a shell builtin, in which case +it executes in the current shell -- but any effect it has on the +environment is wiped). +.Ss Background Commands -- & +If a command is terminated by the control operator ampersand (&), the +shell executes the command asynchronously -- that is, the shell does not +wait for the command to finish before executing the next command. +.Pp +The format for running a command in background is: +.Pp +.Dl command1 & [command2 & ...] +.Pp +If the shell is not interactive, the standard input of an asynchronous +command is set to +.Pa /dev/null . +.Ss Lists -- Generally Speaking +A list is a sequence of zero or more commands separated by newlines, +semicolons, or ampersands, and optionally terminated by one of these three +characters. +The commands in a list are executed in the order they are written. +If command is followed by an ampersand, the shell starts the +command and immediately proceed onto the next command; otherwise it waits +for the command to terminate before proceeding to the next one. +.Ss Short-Circuit List Operators +.Dq && +and +.Dq || +are AND-OR list operators. +.Dq && +executes the first command, and then executes the second command iff the +exit status of the first command is zero. +.Dq || +is similar, but executes the second command iff the exit status of the first +command is nonzero. +.Dq && +and +.Dq || +both have the same priority. +.Ss Flow-Control Constructs -- if, while, for, case +The syntax of the if command is +.Bd -literal -offset indent +if list +then list +[ elif list +then list ] ... +[ else list ] +fi +.Ed +.Pp +The syntax of the while command is +.Bd -literal -offset indent +while list +do list +done +.Ed +.Pp +The two lists are executed repeatedly while the exit status of the +first list is zero. +The until command is similar, but has the word +until in place of while, which causes it to +repeat until the exit status of the first list is zero. +.Pp +The syntax of the for command is +.Bd -literal -offset indent +for variable in word ... +do list +done +.Ed +.Pp +The words are expanded, and then the list is executed repeatedly with the +variable set to each word in turn. +do and done may be replaced with +.Dq { +and +.Dq } . +.Pp +The syntax of the break and continue command is +.Bd -literal -offset indent +break [ num ] +continue [ num ] +.Ed +.Pp +Break terminates the num innermost for or while loops. +Continue continues with the next iteration of the innermost loop. +These are implemented as builtin commands. +.Pp +The syntax of the case command is +.Bd -literal -offset indent +case word in +pattern) list ;; +\&... +esac +.Ed +.Pp +The pattern can actually be one or more patterns (see +.Sx Shell Patterns +described later), separated by +.Dq \*(Ba +characters. +.Ss Grouping Commands Together +Commands may be grouped by writing either +.Pp +.Dl (list) +.Pp +or +.Pp +.Dl { list; } +.Pp +The first of these executes the commands in a subshell. +Builtin commands grouped into a (list) will not affect the current shell. +The second form does not fork another shell so is slightly more efficient. +Grouping commands together this way allows you to redirect +their output as though they were one program: +.Pp +.Bd -literal -offset indent +{ printf \*q hello \*q ; printf \*q world\\n" ; } \*[Gt] greeting +.Ed +.Pp +Note that +.Dq } +must follow a control operator (here, +.Dq \&; ) +so that it is recognized as a reserved word and not as another command argument. +.Ss Functions +The syntax of a function definition is +.Pp +.Dl name ( ) command +.Pp +A function definition is an executable statement; when executed it +installs a function named name and returns an exit status of zero. +The command is normally a list enclosed between +.Dq { +and +.Dq } . +.Pp +Variables may be declared to be local to a function by using a local +command. +This should appear as the first statement of a function, and the syntax is +.Pp +.Dl local [ variable | - ] ... +.Pp +Local is implemented as a builtin command. +.Pp +When a variable is made local, it inherits the initial value and exported +and readonly flags from the variable with the same name in the surrounding +scope, if there is one. +Otherwise, the variable is initially unset. +The shell uses dynamic scoping, so that if you make the variable x local to +function f, which then calls function g, references to the variable x made +inside g will refer to the variable x declared inside f, not to the global +variable named x. +.Pp +The only special parameter that can be made local is +.Dq - . +Making +.Dq - +local any shell options that are changed via the set command inside the +function to be restored to their original values when the function +returns. +.Pp +The syntax of the return command is +.Pp +.Dl return [ exitstatus ] +.Pp +It terminates the currently executing function. +Return is implemented as a builtin command. +.Ss Variables and Parameters +The shell maintains a set of parameters. +A parameter denoted by a name is called a variable. +When starting up, the shell turns all the environment +variables into shell variables. +New variables can be set using the form +.Pp +.Dl name=value +.Pp +Variables set by the user must have a name consisting solely of +alphabetics, numerics, and underscores - the first of which must not be +numeric. +A parameter can also be denoted by a number or a special +character as explained below. +.Ss Positional Parameters +A positional parameter is a parameter denoted by a number (n \*[Gt] 0). +The shell sets these initially to the values of its command line arguments +that follow the name of the shell script. +The +.Ic set +builtin can also be used to set or reset them. +.Ss Special Parameters +A special parameter is a parameter denoted by one of the following special +characters. +The value of the parameter is listed next to its character. +.Bl -tag -width thinhyphena +.It * +Expands to the positional parameters, starting from one. +When the +expansion occurs within a double-quoted string it expands to a single +field with the value of each parameter separated by the first character of +the +.Ev IFS +variable, or by a +.Aq space +if +.Ev IFS +is unset. +.It @ +Expands to the positional parameters, starting from one. +When the expansion occurs within double-quotes, each positional +parameter expands as a separate argument. +If there are no positional parameters, the +expansion of @ generates zero arguments, even when @ is +double-quoted. +What this basically means, for example, is +if $1 is +.Dq abc +and $2 is +.Dq def ghi , +then +.Qq $@ +expands to +the two arguments: +.Pp +.Sm off +.Dl \*q abc \*q \ \*q def\ ghi \*q +.Sm on +.It # +Expands to the number of positional parameters. +.It ? +Expands to the exit status of the most recent pipeline. +.It - (Hyphen.) +Expands to the current option flags (the single-letter +option names concatenated into a string) as specified on +invocation, by the set builtin command, or implicitly +by the shell. +.It $ +Expands to the process ID of the invoked shell. +A subshell retains the same value of $ as its parent. +.It ! +Expands to the process ID of the most recent background +command executed from the current shell. +For a pipeline, the process ID is that of the last command in the pipeline. +.It 0 (Zero.) +Expands to the name of the shell or shell script. +.El +.Ss Word Expansions +This clause describes the various expansions that are performed on words. +Not all expansions are performed on every word, as explained later. +.Pp +Tilde expansions, parameter expansions, command substitutions, arithmetic +expansions, and quote removals that occur within a single word expand to a +single field. +It is only field splitting or pathname expansion that can +create multiple fields from a single word. +The single exception to this +rule is the expansion of the special parameter @ within double-quotes, as +was described above. +.Pp +The order of word expansion is: +.Bl -enum +.It +Tilde Expansion, Parameter Expansion, Command Substitution, +Arithmetic Expansion (these all occur at the same time). +.It +Field Splitting is performed on fields +generated by step (1) unless the +.Ev IFS +variable is null. +.It +Pathname Expansion (unless set +.Fl f +is in effect). +.It +Quote Removal. +.El +.Pp +The $ character is used to introduce parameter expansion, command +substitution, or arithmetic evaluation. +.Ss Tilde Expansion (substituting a user's home directory) +A word beginning with an unquoted tilde character (~) is +subjected to tilde expansion. +All the characters up to +a slash (/) or the end of the word are treated as a username +and are replaced with the user's home directory. +If the username is missing (as in +.Pa ~/foobar ) , +the tilde is replaced with the value of the +.Va HOME +variable (the current user's home directory). +.Ss Parameter Expansion +The format for parameter expansion is as follows: +.Pp +.Dl ${expression} +.Pp +where expression consists of all characters until the matching +.Dq } . +Any +.Dq } +escaped by a backslash or within a quoted string, and characters in +embedded arithmetic expansions, command substitutions, and variable +expansions, are not examined in determining the matching +.Dq } . +.Pp +The simplest form for parameter expansion is: +.Pp +.Dl ${parameter} +.Pp +The value, if any, of parameter is substituted. +.Pp +The parameter name or symbol can be enclosed in braces, which are +optional except for positional parameters with more than one digit or +when parameter is followed by a character that could be interpreted as +part of the name. +If a parameter expansion occurs inside double-quotes: +.Bl -enum +.It +Pathname expansion is not performed on the results of the expansion. +.It +Field splitting is not performed on the results of the +expansion, with the exception of @. +.El +.Pp +In addition, a parameter expansion can be modified by using one of the +following formats. +.Bl -tag -width aaparameterwordaaaaa +.It ${parameter:-word} +Use Default Values. +If parameter is unset or null, the expansion of word +is substituted; otherwise, the value of parameter is substituted. +.It ${parameter:=word} +Assign Default Values. +If parameter is unset or null, the expansion of +word is assigned to parameter. +In all cases, the final value of parameter is substituted. +Only variables, not positional parameters or special +parameters, can be assigned in this way. +.It ${parameter:?[word]} +Indicate Error if Null or Unset. +If parameter is unset or null, the +expansion of word (or a message indicating it is unset if word is omitted) +is written to standard error and the shell exits with a nonzero exit status. +Otherwise, the value of parameter is substituted. +An interactive shell need not exit. +.It ${parameter:+word} +Use Alternative Value. +If parameter is unset or null, null is +substituted; otherwise, the expansion of word is substituted. +.El +.Pp +In the parameter expansions shown previously, use of the colon in the +format results in a test for a parameter that is unset or null; omission +of the colon results in a test for a parameter that is only unset. +.Bl -tag -width aaparameterwordaaaaa +.It ${#parameter} +String Length. +The length in characters of the value of parameter. +.El +.Pp +The following four varieties of parameter expansion provide for substring +processing. +In each case, pattern matching notation (see +.Sx Shell Patterns ) , +rather than regular expression notation, is used to evaluate the patterns. +If parameter is * or @, the result of the expansion is unspecified. +Enclosing the full parameter expansion string in double-quotes does not +cause the following four varieties of pattern characters to be quoted, +whereas quoting characters within the braces has this effect. +.Bl -tag -width aaparameterwordaaaaa +.It ${parameter%word} +Remove Smallest Suffix Pattern. +The word is expanded to produce a pattern. +The parameter expansion then results in parameter, with the +smallest portion of the suffix matched by the pattern deleted. +.It ${parameter%%word} +Remove Largest Suffix Pattern. +The word is expanded to produce a pattern. +The parameter expansion then results in parameter, with the largest +portion of the suffix matched by the pattern deleted. +.It ${parameter#word} +Remove Smallest Prefix Pattern. +The word is expanded to produce a pattern. +The parameter expansion then results in parameter, with the +smallest portion of the prefix matched by the pattern deleted. +.It ${parameter##word} +Remove Largest Prefix Pattern. +The word is expanded to produce a pattern. +The parameter expansion then results in parameter, with the largest +portion of the prefix matched by the pattern deleted. +.El +.Ss Command Substitution +Command substitution allows the output of a command to be substituted in +place of the command name itself. +Command substitution occurs when the command is enclosed as follows: +.Pp +.Dl $(command) +.Pp +or +.Po +.Dq backquoted +version +.Pc : +.Pp +.Dl `command` +.Pp +The shell expands the command substitution by executing command in a +subshell environment and replacing the command substitution with the +standard output of the command, removing sequences of one or more +.Ao newline Ac Ns s +at the end of the substitution. +(Embedded +.Ao newline Ac Ns s +before +the end of the output are not removed; however, during field splitting, +they may be translated into +.Ao space Ac Ns s , +depending on the value of +.Ev IFS +and quoting that is in effect.) +.Ss Arithmetic Expansion +Arithmetic expansion provides a mechanism for evaluating an arithmetic +expression and substituting its value. +The format for arithmetic expansion is as follows: +.Pp +.Dl $((expression)) +.Pp +The expression is treated as if it were in double-quotes, except +that a double-quote inside the expression is not treated specially. +The shell expands all tokens in the expression for parameter expansion, +command substitution, and quote removal. +.Pp +Next, the shell treats this as an arithmetic expression and +substitutes the value of the expression. +.Ss White Space Splitting (Field Splitting) +After parameter expansion, command substitution, and +arithmetic expansion the shell scans the results of +expansions and substitutions that did not occur in double-quotes for +field splitting and multiple fields can result. +.Pp +The shell treats each character of the +.Ev IFS +as a delimiter and uses the delimiters to split the results of parameter +expansion and command substitution into fields. +.Ss Pathname Expansion (File Name Generation) +Unless the +.Fl f +flag is set, file name generation is performed after word splitting is +complete. +Each word is viewed as a series of patterns, separated by slashes. +The process of expansion replaces the word with the names of all +existing files whose names can be formed by replacing each pattern with a +string that matches the specified pattern. +There are two restrictions on +this: first, a pattern cannot match a string containing a slash, and +second, a pattern cannot match a string starting with a period unless the +first character of the pattern is a period. +The next section describes the +patterns used for both Pathname Expansion and the +.Ic case +command. +.Ss Shell Patterns +A pattern consists of normal characters, which match themselves, +and meta-characters. +The meta-characters are +.Dq \&! , +.Dq * , +.Dq \&? , +and +.Dq \&[ . +These characters lose their special meanings if they are quoted. +When command or variable substitution is performed +and the dollar sign or back quotes are not double quoted, +the value of the variable or the output of +the command is scanned for these characters and they are turned into +meta-characters. +.Pp +An asterisk +.Pq Dq * +matches any string of characters. +A question mark matches any single character. +A left bracket +.Pq Dq \&[ +introduces a character class. +The end of the character class is indicated by a +.Pq Dq \&] ; +if the +.Dq \&] +is missing then the +.Dq \&[ +matches a +.Dq \&[ +rather than introducing a character class. +A character class matches any of the characters between the square brackets. +A range of characters may be specified using a minus sign. +The character class may be complemented +by making an exclamation point the first character of the character class. +.Pp +To include a +.Dq \&] +in a character class, make it the first character listed (after the +.Dq \&! , +if any). +To include a minus sign, make it the first or last character listed. +.Ss Builtins +This section lists the builtin commands which are builtin because they +need to perform some operation that can't be performed by a separate +process. +In addition to these, there are several other commands that may +be builtin for efficiency (e.g. +.Xr printf 1 , +.Xr echo 1 , +.Xr test 1 , +etc). +.Bl -tag -width 5n +.It : +.It true +A null command that returns a 0 (true) exit value. +.It \&. file +The commands in the specified file are read and executed by the shell. +.It alias Op Ar name Ns Op Ar "=string ..." +If +.Ar name=string +is specified, the shell defines the alias +.Ar name +with value +.Ar string . +If just +.Ar name +is specified, the value of the alias +.Ar name +is printed. +With no arguments, the +.Ic alias +builtin prints the +names and values of all defined aliases (see +.Ic unalias ) . +.It bg [ Ar job ] ... +Continue the specified jobs (or the current job if no +jobs are given) in the background. +.It Xo command +.Op Fl p +.Op Fl v +.Op Fl V +.Ar command +.Op Ar arg ... +.Xc +Execute the specified command but ignore shell functions when searching +for it. +(This is useful when you +have a shell function with the same name as a builtin command.) +.Bl -tag -width 5n +.It Fl p +search for command using a +.Ev PATH +that guarantees to find all the standard utilities. +.It Fl V +Do not execute the command but +search for the command and print the resolution of the +command search. +This is the same as the type builtin. +.It Fl v +Do not execute the command but +search for the command and print the absolute pathname +of utilities, the name for builtins or the expansion of aliases. +.El +.It cd Ar - +.It Xo cd Op Fl LP +.Op Ar directory +.Xc +Switch to the specified directory (default +.Ev HOME ) . +If an entry for +.Ev CDPATH +appears in the environment of the +.Ic cd +command or the shell variable +.Ev CDPATH +is set and the directory name does not begin with a slash, then the +directories listed in +.Ev CDPATH +will be searched for the specified directory. +The format of +.Ev CDPATH +is the same as that of +.Ev PATH . +If a single dash is specified as the argument, it will be replaced by the +value of +.Ev OLDPWD . +The +.Ic cd +command will print out the name of the +directory that it actually switched to if this is different from the name +that the user gave. +These may be different either because the +.Ev CDPATH +mechanism was used or because the argument is a single dash. +The +.Fl P +option causes the physical directory structure to be used, that is, all +symbolic links are resolved to their respective values. The +.Fl L +option turns off the effect of any preceding +.Fl P +options. +.It Xo echo Op Fl n +.Ar args... +.Xc +Print the arguments on the standard output, separated by spaces. +Unless the +.Fl n +option is present, a newline is output following the arguments. +.Pp +If any of the following sequences of characters is encountered during +output, the sequence is not output. Instead, the specified action is +performed: +.Bl -tag -width indent +.It Li \eb +A backspace character is output. +.It Li \ec +Subsequent output is suppressed. This is normally used at the end of the +last argument to suppress the trailing newline that +.Ic echo +would otherwise output. +.It Li \ef +Output a form feed. +.It Li \en +Output a newline character. +.It Li \er +Output a carriage return. +.It Li \et +Output a (horizontal) tab character. +.It Li \ev +Output a vertical tab. +.It Li \e0 Ns Ar digits +Output the character whose value is given by zero to three octal digits. +If there are zero digits, a nul character is output. +.It Li \e\e +Output a backslash. +.El +.Pp +All other backslash sequences elicit undefined behaviour. +.It eval Ar string ... +Concatenate all the arguments with spaces. +Then re-parse and execute the command. +.It exec Op Ar command arg ... +Unless command is omitted, the shell process is replaced with the +specified program (which must be a real program, not a shell builtin or +function). +Any redirections on the +.Ic exec +command are marked as permanent, so that they are not undone when the +.Ic exec +command finishes. +.It exit Op Ar exitstatus +Terminate the shell process. +If +.Ar exitstatus +is given it is used as the exit status of the shell; otherwise the +exit status of the preceding command is used. +.It export Ar name ... +.It export Fl p +The specified names are exported so that they will appear in the +environment of subsequent commands. +The only way to un-export a variable is to unset it. +The shell allows the value of a variable to be set at the +same time it is exported by writing +.Pp +.Dl export name=value +.Pp +With no arguments the export command lists the names of all exported variables. +With the +.Fl p +option specified the output will be formatted suitably for non-interactive use. +.It Xo fc Op Fl e Ar editor +.Op Ar first Op Ar last +.Xc +.It Xo fc Fl l +.Op Fl nr +.Op Ar first Op Ar last +.Xc +.It Xo fc Fl s Op Ar old=new +.Op Ar first +.Xc +The +.Ic fc +builtin lists, or edits and re-executes, commands previously entered +to an interactive shell. +.Bl -tag -width 5n +.It Fl e No editor +Use the editor named by editor to edit the commands. +The editor string is a command name, subject to search via the +.Ev PATH +variable. +The value in the +.Ev FCEDIT +variable is used as a default when +.Fl e +is not specified. +If +.Ev FCEDIT +is null or unset, the value of the +.Ev EDITOR +variable is used. +If +.Ev EDITOR +is null or unset, +.Xr ed 1 +is used as the editor. +.It Fl l No (ell) +List the commands rather than invoking an editor on them. +The commands are written in the sequence indicated by +the first and last operands, as affected by +.Fl r , +with each command preceded by the command number. +.It Fl n +Suppress command numbers when listing with -l. +.It Fl r +Reverse the order of the commands listed (with +.Fl l ) +or edited (with neither +.Fl l +nor +.Fl s ) . +.It Fl s +Re-execute the command without invoking an editor. +.It first +.It last +Select the commands to list or edit. +The number of previous commands that +can be accessed are determined by the value of the +.Ev HISTSIZE +variable. +The value of first or last or both are one of the following: +.Bl -tag -width 5n +.It [+]number +A positive number representing a command number; command numbers can be +displayed with the +.Fl l +option. +.It Fl number +A negative decimal number representing the command that was executed +number of commands previously. +For example, \-1 is the immediately previous command. +.El +.It string +A string indicating the most recently entered command that begins with +that string. +If the old=new operand is not also specified with +.Fl s , +the string form of the first operand cannot contain an embedded equal sign. +.El +.Pp +The following environment variables affect the execution of fc: +.Bl -tag -width HISTSIZE +.It Ev FCEDIT +Name of the editor to use. +.It Ev HISTSIZE +The number of previous commands that are accessible. +.El +.It fg Op Ar job +Move the specified job or the current job to the foreground. +.It getopts Ar optstring var +The +.Tn POSIX +.Ic getopts +command, not to be confused with the +.Em Bell Labs +-derived +.Xr getopt 1 . +.Pp +The first argument should be a series of letters, each of which may be +optionally followed by a colon to indicate that the option requires an +argument. +The variable specified is set to the parsed option. +.Pp +The +.Ic getopts +command deprecates the older +.Xr getopt 1 +utility due to its handling of arguments containing whitespace. +.Pp +The +.Ic getopts +builtin may be used to obtain options and their arguments +from a list of parameters. +When invoked, +.Ic getopts +places the value of the next option from the option string in the list in +the shell variable specified by +.Va var +and its index in the shell variable +.Ev OPTIND . +When the shell is invoked, +.Ev OPTIND +is initialized to 1. +For each option that requires an argument, the +.Ic getopts +builtin will place it in the shell variable +.Ev OPTARG . +If an option is not allowed for in the +.Va optstring , +then +.Ev OPTARG +will be unset. +.Pp +.Va optstring +is a string of recognized option letters (see +.Xr getopt 3 ) . +If a letter is followed by a colon, the option is expected to have an +argument which may or may not be separated from it by white space. +If an option character is not found where expected, +.Ic getopts +will set the variable +.Va var +to a +.Dq \&? ; +.Ic getopts +will then unset +.Ev OPTARG +and write output to standard error. +By specifying a colon as the first character of +.Va optstring +all errors will be ignored. +.Pp +A nonzero value is returned when the last option is reached. +If there are no remaining arguments, +.Ic getopts +will set +.Va var +to the special option, +.Dq -- , +otherwise, it will set +.Va var +to +.Dq \&? . +.Pp +The following code fragment shows how one might process the arguments +for a command that can take the options +.Op a +and +.Op b , +and the option +.Op c , +which requires an argument. +.Pp +.Bd -literal -offset indent +while getopts abc: f +do + case $f in + a | b) flag=$f;; + c) carg=$OPTARG;; + \\?) echo $USAGE; exit 1;; + esac +done +shift `expr $OPTIND - 1` +.Ed +.Pp +This code will accept any of the following as equivalent: +.Pp +.Bd -literal -offset indent +cmd \-acarg file file +cmd \-a \-c arg file file +cmd \-carg -a file file +cmd \-a \-carg \-\- file file +.Ed +.It hash Fl rv Ar command ... +The shell maintains a hash table which remembers the +locations of commands. +With no arguments whatsoever, +the +.Ic hash +command prints out the contents of this table. +Entries which have not been looked at since the last +.Ic cd +command are marked with an asterisk; it is possible for these entries +to be invalid. +.Pp +With arguments, the +.Ic hash +command removes the specified commands from the hash table (unless +they are functions) and then locates them. +With the +.Fl v +option, hash prints the locations of the commands as it finds them. +The +.Fl r +option causes the hash command to delete all the entries in the hash table +except for functions. +.It pwd Op Fl LP +builtin command remembers what the current directory +is rather than recomputing it each time. +This makes it faster. +However, if the current directory is renamed, the builtin version of +.Ic pwd +will continue to print the old name for the directory. +The +.Fl P +option causes the physical value of the current working directory to be shown, +that is, all symbolic links are resolved to their respective values. The +.Fl L +option turns off the effect of any preceding +.Fl P +options. +.It Xo read Op Fl p Ar prompt +.Op Fl r +.Ar variable +.Op Ar ... +.Xc +The prompt is printed if the +.Fl p +option is specified and the standard input is a terminal. +Then a line is read from the standard input. +The trailing newline is deleted from the +line and the line is split as described in the section on word splitting +above, and the pieces are assigned to the variables in order. +At least one variable must be specified. +If there are more pieces than variables, the remaining pieces +(along with the characters in +.Ev IFS +that separated them) are assigned to the last variable. +If there are more variables than pieces, +the remaining variables are assigned the null string. +The +.Ic read +builtin will indicate success unless EOF is encountered on input, in +which case failure is returned. +.Pp +By default, unless the +.Fl r +option is specified, the backslash +.Dq \e +acts as an escape character, causing the following character to be treated +literally. +If a backslash is followed by a newline, the backslash and the +newline will be deleted. +.It readonly Ar name ... +.It readonly Fl p +The specified names are marked as read only, so that they cannot be +subsequently modified or unset. +The shell allows the value of a variable +to be set at the same time it is marked read only by writing +.Pp +.Dl readonly name=value +.Pp +With no arguments the readonly command lists the names of all read only +variables. +With the +.Fl p +option specified the output will be formatted suitably for non-interactive use. +.Pp +.It Xo printf Ar format +.Op Ar arguments ... +.Xc +.Ic printf +formats and prints its arguments, after the first, under control +of the +.Ar format . +The +.Ar format +is a character string which contains three types of objects: plain characters, +which are simply copied to standard output, character escape sequences which +are converted and copied to the standard output, and format specifications, +each of which causes printing of the next successive +.Ar argument . +.Pp +The +.Ar arguments +after the first are treated as strings if the corresponding format is +either +.Cm b , +.Cm c +or +.Cm s ; +otherwise it is evaluated as a C constant, with the following extensions: +.Pp +.Bl -bullet -offset indent -compact +.It +A leading plus or minus sign is allowed. +.It +If the leading character is a single or double quote, the value is the +.Tn ASCII +code of the next character. +.El +.Pp +The format string is reused as often as necessary to satisfy the +.Ar arguments . +Any extra format specifications are evaluated with zero or the null +string. +.Pp +Character escape sequences are in backslash notation as defined in +.St -ansiC . +The characters and their meanings are as follows: +.Bl -tag -width Ds -offset indent +.It Cm \ea +Write a \*[Lt]bell\*[Gt] character. +.It Cm \eb +Write a \*[Lt]backspace\*[Gt] character. +.It Cm \ef +Write a \*[Lt]form-feed\*[Gt] character. +.It Cm \en +Write a \*[Lt]new-line\*[Gt] character. +.It Cm \er +Write a \*[Lt]carriage return\*[Gt] character. +.It Cm \et +Write a \*[Lt]tab\*[Gt] character. +.It Cm \ev +Write a \*[Lt]vertical tab\*[Gt] character. +.It Cm \e\e +Write a backslash character. +.It Cm \e Ns Ar num +Write an 8\-bit character whose +.Tn ASCII +value is the 1\-, 2\-, or 3\-digit +octal number +.Ar num . +.El +.Pp +Each format specification is introduced by the percent character +(``%''). +The remainder of the format specification includes, +in the following order: +.Bl -tag -width Ds +.It "Zero or more of the following flags:" +.Bl -tag -width Ds +.It Cm # +A `#' character +specifying that the value should be printed in an ``alternative form''. +For +.Cm b , +.Cm c , +.Cm d , +and +.Cm s +formats, this option has no effect. +For the +.Cm o +format the precision of the number is increased to force the first +character of the output string to a zero. +For the +.Cm x +.Pq Cm X +format, a non-zero result has the string +.Li 0x +.Pq Li 0X +prepended to it. +For +.Cm e , +.Cm E , +.Cm f , +.Cm g , +and +.Cm G +formats, the result will always contain a decimal point, even if no +digits follow the point (normally, a decimal point only appears in the +results of those formats if a digit follows the decimal point). +For +.Cm g +and +.Cm G +formats, trailing zeros are not removed from the result as they +would otherwise be. +.It Cm \&\- +A minus sign `\-' which specifies +.Em left adjustment +of the output in the indicated field; +.It Cm \&+ +A `+' character specifying that there should always be +a sign placed before the number when using signed formats. +.It Sq \&\ \& +A space specifying that a blank should be left before a positive number +for a signed format. +A `+' overrides a space if both are used; +.It Cm \&0 +A zero `0' character indicating that zero-padding should be used +rather than blank-padding. +A `\-' overrides a `0' if both are used; +.El +.It "Field Width:" +An optional digit string specifying a +.Em field width ; +if the output string has fewer characters than the field width it will +be blank-padded on the left (or right, if the left-adjustment indicator +has been given) to make up the field width (note that a leading zero +is a flag, but an embedded zero is part of a field width); +.It Precision : +An optional period, +.Sq Cm \&.\& , +followed by an optional digit string giving a +.Em precision +which specifies the number of digits to appear after the decimal point, +for +.Cm e +and +.Cm f +formats, or the maximum number of characters to be printed +from a string +.Sm off +.Pf ( Cm b +.Sm on +and +.Cm s +formats); if the digit string is missing, the precision is treated +as zero; +.It Format : +A character which indicates the type of format to use (one of +.Cm diouxXfwEgGbcs ) . +.El +.Pp +A field width or precision may be +.Sq Cm \&* +instead of a digit string. +In this case an +.Ar argument +supplies the field width or precision. +.Pp +The format characters and their meanings are: +.Bl -tag -width Fl +.It Cm diouXx +The +.Ar argument +is printed as a signed decimal (d or i), unsigned octal, unsigned decimal, +or unsigned hexadecimal (X or x), respectively. +.It Cm f +The +.Ar argument +is printed in the style +.Sm off +.Pf [\-]ddd Cm \&. No ddd +.Sm on +where the number of d's +after the decimal point is equal to the precision specification for +the argument. +If the precision is missing, 6 digits are given; if the precision +is explicitly 0, no digits and no decimal point are printed. +.It Cm eE +The +.Ar argument +is printed in the style +.Sm off +.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd +.Sm on +where there +is one digit before the decimal point and the number after is equal to +the precision specification for the argument; when the precision is +missing, 6 digits are produced. +An upper-case E is used for an `E' format. +.It Cm gG +The +.Ar argument +is printed in style +.Cm f +or in style +.Cm e +.Pq Cm E +whichever gives full precision in minimum space. +.It Cm b +Characters from the string +.Ar argument +are printed with backslash-escape sequences expanded. +.br +The following additional backslash-escape sequences are supported: +.Bl -tag -width Ds +.It Cm \ec +Causes +.Nm +to ignore any remaining characters in the string operand containing it, +any remaining string operands, and any additional characters in +the format operand. +.It Cm \e0 Ns Ar num +Write an 8\-bit character whose +.Tn ASCII +value is the 1\-, 2\-, or 3\-digit +octal number +.Ar num . +.El +.It Cm c +The first character of +.Ar argument +is printed. +.It Cm s +Characters from the string +.Ar argument +are printed until the end is reached or until the number of characters +indicated by the precision specification is reached; if the +precision is omitted, all characters in the string are printed. +.It Cm \&% +Print a `%'; no argument is used. +.El +.Pp +In no case does a non-existent or small field width cause truncation of +a field; padding takes place only if the specified field width exceeds +the actual width. +.It Xo set +.Oo { +.Fl options | Cm +options | Cm -- } +.Oc Ar arg ... +.Xc +The +.Ic set +command performs three different functions. +.Pp +With no arguments, it lists the values of all shell variables. +.Pp +If options are given, it sets the specified option +flags, or clears them as described in the section called +.Sx Argument List Processing . +.Pp +The third use of the set command is to set the values of the shell's +positional parameters to the specified args. +To change the positional +parameters without changing any options, use +.Dq -- +as the first argument to set. +If no args are present, the set command +will clear all the positional parameters (equivalent to executing +.Dq shift $# . ) +.It shift Op Ar n +Shift the positional parameters n times. +A +.Ic shift +sets the value of +.Va $1 +to the value of +.Va $2 , +the value of +.Va $2 +to the value of +.Va $3 , +and so on, decreasing +the value of +.Va $# +by one. +If n is greater than the number of positional parameters, +.Ic shift +will issue an error message, and exit with return status 2. +.It test Ar expression +.It \&[ Ar expression Cm ] +The +.Ic test +utility evaluates the expression and, if it evaluates +to true, returns a zero (true) exit status; otherwise +it returns 1 (false). +If there is no expression, test also +returns 1 (false). +.Pp +All operators and flags are separate arguments to the +.Ic test +utility. +.Pp +The following primaries are used to construct expression: +.Bl -tag -width Ar +.It Fl b Ar file +True if +.Ar file +exists and is a block special +file. +.It Fl c Ar file +True if +.Ar file +exists and is a character +special file. +.It Fl d Ar file +True if +.Ar file +exists and is a directory. +.It Fl e Ar file +True if +.Ar file +exists (regardless of type). +.It Fl f Ar file +True if +.Ar file +exists and is a regular file. +.It Fl g Ar file +True if +.Ar file +exists and its set group ID flag +is set. +.It Fl h Ar file +True if +.Ar file +exists and is a symbolic link. +.It Fl k Ar file +True if +.Ar file +exists and its sticky bit is set. +.It Fl n Ar string +True if the length of +.Ar string +is nonzero. +.It Fl p Ar file +True if +.Ar file +is a named pipe +.Po Tn FIFO Pc . +.It Fl r Ar file +True if +.Ar file +exists and is readable. +.It Fl s Ar file +True if +.Ar file +exists and has a size greater +than zero. +.It Fl t Ar file_descriptor +True if the file whose file descriptor number +is +.Ar file_descriptor +is open and is associated with a terminal. +.It Fl u Ar file +True if +.Ar file +exists and its set user ID flag +is set. +.It Fl w Ar file +True if +.Ar file +exists and is writable. +True +indicates only that the write flag is on. +The file is not writable on a read-only file +system even if this test indicates true. +.It Fl x Ar file +True if +.Ar file +exists and is executable. +True +indicates only that the execute flag is on. +If +.Ar file +is a directory, true indicates that +.Ar file +can be searched. +.It Fl z Ar string +True if the length of +.Ar string +is zero. +.It Fl L Ar file +True if +.Ar file +exists and is a symbolic link. +This operator is retained for compatibility with previous versions of +this program. +Do not rely on its existence; use +.Fl h +instead. +.It Fl O Ar file +True if +.Ar file +exists and its owner matches the effective user id of this process. +.It Fl G Ar file +True if +.Ar file +exists and its group matches the effective group id of this process. +.It Fl S Ar file +True if +.Ar file +exists and is a socket. +.It Ar file1 Fl nt Ar file2 +True if +.Ar file1 +exists and is newer than +.Ar file2 . +.It Ar file1 Fl ot Ar file2 +True if +.Ar file1 +exists and is older than +.Ar file2 . +.It Ar file1 Fl ef Ar file2 +True if +.Ar file1 +and +.Ar file2 +exist and refer to the same file. +.It Ar string +True if +.Ar string +is not the null +string. +.It Ar \&s\&1 Cm \&= Ar \&s\&2 +True if the strings +.Ar \&s\&1 +and +.Ar \&s\&2 +are identical. +.It Ar \&s\&1 Cm \&!= Ar \&s\&2 +True if the strings +.Ar \&s\&1 +and +.Ar \&s\&2 +are not identical. +.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2 +True if string +.Ar \&s\&1 +comes before +.Ar \&s\&2 +based on the ASCII value of their characters. +.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2 +True if string +.Ar \&s\&1 +comes after +.Ar \&s\&2 +based on the ASCII value of their characters. +.It Ar \&n\&1 Fl \&eq Ar \&n\&2 +True if the integers +.Ar \&n\&1 +and +.Ar \&n\&2 +are algebraically +equal. +.It Ar \&n\&1 Fl \&ne Ar \&n\&2 +True if the integers +.Ar \&n\&1 +and +.Ar \&n\&2 +are not +algebraically equal. +.It Ar \&n\&1 Fl \> Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically +greater than the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \&ge Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically +greater than or equal to the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \< Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically less +than the integer +.Ar \&n\&2 . +.It Ar \&n\&1 Fl \&le Ar \&n\&2 +True if the integer +.Ar \&n\&1 +is algebraically less +than or equal to the integer +.Ar \&n\&2 . +.El +.Pp +These primaries can be combined with the following operators: +.Bl -tag -width Ar +.It Cm \&! Ar expression +True if +.Ar expression +is false. +.It Ar expression1 Fl a Ar expression2 +True if both +.Ar expression1 +and +.Ar expression2 +are true. +.It Ar expression1 Fl o Ar expression2 +True if either +.Ar expression1 +or +.Ar expression2 +are true. +.It Cm \&( Ns Ar expression Ns Cm \&) +True if expression is true. +.El +.Pp +The +.Fl a +operator has higher precedence than the +.Fl o +operator. +.It times +Print the accumulated user and system times for the shell and for processes +run from the shell. The return status is 0. +.It Xo trap +.Op Ar action Ar signal ... +.Xc +Cause the shell to parse and execute action when any of the specified +signals are received. +The signals are specified by signal number or as the name of the signal. +If +.Ar signal +is +.Li 0 , +the action is executed when the shell exits. +.Ar action +may be null, which cause the specified signals to be ignored. +With +.Ar action +omitted or set to `-' the specified signals are set to their default action. +When the shell forks off a subshell, it resets trapped (but not ignored) +signals to the default action. +The +.Ic trap +command has no effect on signals that were +ignored on entry to the shell. +.Ic trap +without any arguments cause it to write a list of signals and their +associated action to the standard output in a format that is suitable +as an input to the shell that achieves the same trapping results. +.Pp +Examples: +.Pp +.Dl trap +.Pp +List trapped signals and their corresponding action +.Pp +.Dl trap '' INT QUIT tstp 30 +.Pp +Ignore signals INT QUIT TSTP USR1 +.Pp +.Dl trap date INT +.Pp +Print date upon receiving signal INT +.It type Op Ar name ... +Interpret each name as a command and print the resolution of the command +search. +Possible resolutions are: +shell keyword, alias, shell builtin, +command, tracked alias and not found. +For aliases the alias expansion is +printed; for commands and tracked aliases the complete pathname of the +command is printed. +.It ulimit Xo +.Op Fl H \*(Ba Fl S +.Op Fl a \*(Ba Fl tfdscmlpn Op Ar value +.Xc +Inquire about or set the hard or soft limits on processes or set new +limits. +The choice between hard limit (which no process is allowed to +violate, and which may not be raised once it has been lowered) and soft +limit (which causes processes to be signaled but not necessarily killed, +and which may be raised) is made with these flags: +.Bl -tag -width Fl +.It Fl H +set or inquire about hard limits +.It Fl S +set or inquire about soft limits. +If neither +.Fl H +nor +.Fl S +is specified, the soft limit is displayed or both limits are set. +If both are specified, the last one wins. +.El +.Pp +.Bl -tag -width Fl +The limit to be interrogated or set, then, is chosen by specifying +any one of these flags: +.It Fl a +show all the current limits +.It Fl t +show or set the limit on CPU time (in seconds) +.It Fl f +show or set the limit on the largest file that can be created +(in 512-byte blocks) +.It Fl d +show or set the limit on the data segment size of a process (in kilobytes) +.It Fl s +show or set the limit on the stack size of a process (in kilobytes) +.It Fl c +show or set the limit on the largest core dump size that can be produced +(in 512-byte blocks) +.It Fl m +show or set the limit on the total physical memory that can be +in use by a process (in kilobytes) +.It Fl l +show or set the limit on how much memory a process can lock with +.Xr mlock 2 +(in kilobytes) +.It Fl p +show or set the limit on the number of processes this user can +have at one time +.It Fl n +show or set the limit on the number files a process can have open at once +.El +.Pp +If none of these is specified, it is the limit on file size that is shown +or set. +If value is specified, the limit is set to that number; otherwise +the current limit is displayed. +.Pp +Limits of an arbitrary process can be displayed or set using the +.Xr sysctl 8 +utility. +.Pp +.It umask Op Ar mask +Set the value of umask (see +.Xr umask 2 ) +to the specified octal value. +If the argument is omitted, the umask value is printed. +.It unalias Xo +.Op Fl a +.Op Ar name +.Xc +If +.Ar name +is specified, the shell removes that alias. +If +.Fl a +is specified, all aliases are removed. +.It unset Xo +.Op Fl fv +.Ar name ... +.Xc +The specified variables and functions are unset and unexported. +If +.Fl f +or +.Fl v +is specified, the corresponding function or variable is unset, respectively. +If a given name corresponds to both a variable and a function, and no +options are given, only the variable is unset. +.It wait Op Ar job +Wait for the specified job to complete and return the exit status of the +last process in the job. +If the argument is omitted, wait for all jobs to +complete and the return an exit status of zero. +.El +.Ss Command Line Editing +When +.Nm +is being used interactively from a terminal, the current command +and the command history (see +.Ic fc +in +.Sx Builtins ) +can be edited using vi-mode command-line editing. +This mode uses commands, described below, +similar to a subset of those described in the vi man page. +The command +.Ql set -o vi +enables vi-mode editing and place sh into vi insert mode. +With vi-mode +enabled, sh can be switched between insert mode and command mode. +The editor is not described in full here, but will be in a later document. +It's similar to vi: typing +.Aq ESC +will throw you into command VI command mode. +Hitting +.Aq return +while in command mode will pass the line to the shell. +.Sh EXIT STATUS +Errors that are detected by the shell, such as a syntax error, will cause the +shell to exit with a non-zero exit status. +If the shell is not an +interactive shell, the execution of the shell file will be aborted. +Otherwise +the shell will return the exit status of the last command executed, or +if the exit builtin is used with a numeric argument, it will return the +argument. +.Sh ENVIRONMENT +.Bl -tag -width MAILCHECK +.It Ev HOME +Set automatically by +.Xr login 1 +from the user's login directory in the password file +.Pq Xr passwd 4 . +This environment variable also functions as the default argument for the +cd builtin. +.It Ev PATH +The default search path for executables. +See the above section +.Sx Path Search . +.It Ev CDPATH +The search path used with the cd builtin. +.It Ev MAIL +The name of a mail file, that will be checked for the arrival of new mail. +Overridden by +.Ev MAILPATH . +.It Ev MAILCHECK +The frequency in seconds that the shell checks for the arrival of mail +in the files specified by the +.Ev MAILPATH +or the +.Ev MAIL +file. +If set to 0, the check will occur at each prompt. +.It Ev MAILPATH +A colon +.Dq \&: +separated list of file names, for the shell to check for incoming mail. +This environment setting overrides the +.Ev MAIL +setting. +There is a maximum of 10 mailboxes that can be monitored at once. +.It Ev PS1 +The primary prompt string, which defaults to +.Dq $ \ , +unless you are the superuser, in which case it defaults to +.Dq # \ . +.It Ev PS2 +The secondary prompt string, which defaults to +.Dq \*[Gt] \ . +.It Ev PS4 +Output before each line when execution trace (set -x) is enabled, +defaults to +.Dq + \ . +.It Ev IFS +Input Field Separators. +This is normally set to +.Aq space , +.Aq tab , +and +.Aq newline . +See the +.Sx White Space Splitting +section for more details. +.It Ev TERM +The default terminal setting for the shell. +This is inherited by +children of the shell, and is used in the history editing modes. +.It Ev HISTSIZE +The number of lines in the history buffer for the shell. +.It Ev PWD +The logical value of the current working directory. This is set by the +.Ic cd +command. +.It Ev OLDPWD +The previous logical value of the current working directory. This is set by +the +.Ic cd +command. +.It Ev PPID +The process ID of the parent process of the shell. +.El +.Sh FILES +.Bl -item -width HOMEprofilexxxx +.It +.Pa $HOME/.profile +.It +.Pa /etc/profile +.El +.Sh SEE ALSO +.Xr csh 1 , +.Xr echo 1 , +.Xr getopt 1 , +.Xr ksh 1 , +.Xr login 1 , +.Xr printf 1 , +.Xr test 1 , +.Xr getopt 3 , +.Xr passwd 5 , +.\" .Xr profile 4 , +.Xr environ 7 , +.Xr sysctl 8 +.Sh HISTORY +A +.Nm +command appeared in +.At v1 . +It was, however, unmaintainable so we wrote this one. +.Sh BUGS +Setuid shell scripts should be avoided at all costs, as they are a +significant security risk. +.Pp +PS1, PS2, and PS4 should be subject to parameter expansion before +being displayed. diff -puN /dev/null usr/dash/shell.h --- /dev/null +++ a/usr/dash/shell.h @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)shell.h 8.2 (Berkeley) 5/4/95 + */ + +/* + * The follow should be set to reflect the type of system you have: + * JOBS -> 1 if you have Berkeley job control, 0 otherwise. + * SHORTNAMES -> 1 if your linker cannot handle long names. + * define BSD if you are running 4.2 BSD or later. + * define SYSV if you are running under System V. + * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) + * define DEBUG=2 to compile in and turn on debugging. + * define DO_SHAREDVFORK to indicate that vfork(2) shares its address + * with its parent. + * + * When debugging is on, debugging info will be written to ./trace and + * a quit signal will generate a core dump. + */ + +#include + +#ifndef JOBS +#define JOBS 1 +#endif +#ifndef BSD +#define BSD 1 +#endif + +#ifndef DO_SHAREDVFORK +#if __NetBSD_Version__ >= 104000000 +#define DO_SHAREDVFORK +#endif +#endif + +typedef void *pointer; +#ifndef NULL +#define NULL (void *)0 +#endif +#define STATIC static +#define MKINIT /* empty */ + +extern char nullstr[1]; /* null string */ + + +#ifdef DEBUG +#define TRACE(param) trace param +#define TRACEV(param) tracev param +#else +#define TRACE(param) +#define TRACEV(param) +#endif + +#if defined(__GNUC__) && __GNUC__ < 3 +#define va_copy __va_copy +#endif + +#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) +#define __builtin_expect(x, expected_value) (x) +#endif + +#define likely(x) __builtin_expect(!!(x),1) +#define unlikely(x) __builtin_expect(!!(x),0) diff -puN /dev/null usr/dash/show.c --- /dev/null +++ a/usr/dash/show.c @@ -0,0 +1,403 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "shell.h" +#include "parser.h" +#include "nodes.h" +#include "mystring.h" +#include "show.h" +#include "options.h" + + +#ifdef DEBUG +static void shtree(union node *, int, char *, FILE*); +static void shcmd(union node *, FILE *); +static void sharg(union node *, FILE *); +static void indent(int, char *, FILE *); +static void trstring(char *); + + +void +showtree(union node *n) +{ + trputs("showtree called\n"); + shtree(n, 1, NULL, stdout); +} + + +static void +shtree(union node *n, int ind, char *pfx, FILE *fp) +{ + struct nodelist *lp; + const char *s; + + if (n == NULL) + return; + + indent(ind, pfx, fp); + switch(n->type) { + case NSEMI: + s = "; "; + goto binop; + case NAND: + s = " && "; + goto binop; + case NOR: + s = " || "; +binop: + shtree(n->nbinary.ch1, ind, NULL, fp); + /* if (ind < 0) */ + fputs(s, fp); + shtree(n->nbinary.ch2, ind, NULL, fp); + break; + case NCMD: + shcmd(n, fp); + if (ind >= 0) + putc('\n', fp); + break; + case NPIPE: + for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { + shcmd(lp->n, fp); + if (lp->next) + fputs(" | ", fp); + } + if (n->npipe.backgnd) + fputs(" &", fp); + if (ind >= 0) + putc('\n', fp); + break; + default: + fprintf(fp, "", n->type); + if (ind >= 0) + putc('\n', fp); + break; + } +} + + + +static void +shcmd(union node *cmd, FILE *fp) +{ + union node *np; + int first; + const char *s; + int dftfd; + + first = 1; + for (np = cmd->ncmd.args ; np ; np = np->narg.next) { + if (! first) + putchar(' '); + sharg(np, fp); + first = 0; + } + for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { + if (! first) + putchar(' '); + switch (np->nfile.type) { + case NTO: s = ">"; dftfd = 1; break; + case NCLOBBER: s = ">|"; dftfd = 1; break; + case NAPPEND: s = ">>"; dftfd = 1; break; + case NTOFD: s = ">&"; dftfd = 1; break; + case NFROM: s = "<"; dftfd = 0; break; + case NFROMFD: s = "<&"; dftfd = 0; break; + case NFROMTO: s = "<>"; dftfd = 0; break; + default: s = "*error*"; dftfd = 0; break; + } + if (np->nfile.fd != dftfd) + fprintf(fp, "%d", np->nfile.fd); + fputs(s, fp); + if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { + fprintf(fp, "%d", np->ndup.dupfd); + } else { + sharg(np->nfile.fname, fp); + } + first = 0; + } +} + + + +static void +sharg(union node *arg, FILE *fp) +{ + char *p; + struct nodelist *bqlist; + int subtype; + + if (arg->type != NARG) { + printf("\n", arg->type); + abort(); + } + bqlist = arg->narg.backquote; + for (p = arg->narg.text ; *p ; p++) { + switch ((signed char)*p) { + case CTLESC: + putc(*++p, fp); + break; + case CTLVAR: + putc('$', fp); + putc('{', fp); + subtype = *++p; + if (subtype == VSLENGTH) + putc('#', fp); + + while (*p != '=') + putc(*p++, fp); + + if (subtype & VSNUL) + putc(':', fp); + + switch (subtype & VSTYPE) { + case VSNORMAL: + putc('}', fp); + break; + case VSMINUS: + putc('-', fp); + break; + case VSPLUS: + putc('+', fp); + break; + case VSQUESTION: + putc('?', fp); + break; + case VSASSIGN: + putc('=', fp); + break; + case VSTRIMLEFT: + putc('#', fp); + break; + case VSTRIMLEFTMAX: + putc('#', fp); + putc('#', fp); + break; + case VSTRIMRIGHT: + putc('%', fp); + break; + case VSTRIMRIGHTMAX: + putc('%', fp); + putc('%', fp); + break; + case VSLENGTH: + break; + default: + printf("", subtype); + } + break; + case CTLENDVAR: + putc('}', fp); + break; + case CTLBACKQ: + case CTLBACKQ|CTLQUOTE: + putc('$', fp); + putc('(', fp); + shtree(bqlist->n, -1, NULL, fp); + putc(')', fp); + break; + default: + putc(*p, fp); + break; + } + } +} + + +static void +indent(int amount, char *pfx, FILE *fp) +{ + int i; + + for (i = 0 ; i < amount ; i++) { + if (pfx && i == amount - 1) + fputs(pfx, fp); + putc('\t', fp); + } +} + + + +/* + * Debugging stuff. + */ + + +FILE *tracefile; + + +void +trputc(int c) +{ + if (debug != 1) + return; + putc(c, tracefile); +} + +void +trace(const char *fmt, ...) +{ + va_list va; + + if (debug != 1) + return; + va_start(va, fmt); + (void) vfprintf(tracefile, fmt, va); + va_end(va); +} + +void +tracev(const char *fmt, va_list va) +{ + if (debug != 1) + return; + (void) vfprintf(tracefile, fmt, va); +} + + +void +trputs(const char *s) +{ + if (debug != 1) + return; + fputs(s, tracefile); +} + + +static void +trstring(char *s) +{ + char *p; + char c; + + if (debug != 1) + return; + putc('"', tracefile); + for (p = s ; *p ; p++) { + switch ((signed char)*p) { + case '\n': c = 'n'; goto backslash; + case '\t': c = 't'; goto backslash; + case '\r': c = 'r'; goto backslash; + case '"': c = '"'; goto backslash; + case '\\': c = '\\'; goto backslash; + case CTLESC: c = 'e'; goto backslash; + case CTLVAR: c = 'v'; goto backslash; + case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; + case CTLBACKQ: c = 'q'; goto backslash; + case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; +backslash: putc('\\', tracefile); + putc(c, tracefile); + break; + default: + if (*p >= ' ' && *p <= '~') + putc(*p, tracefile); + else { + putc('\\', tracefile); + putc(*p >> 6 & 03, tracefile); + putc(*p >> 3 & 07, tracefile); + putc(*p & 07, tracefile); + } + break; + } + } + putc('"', tracefile); +} + + +void +trargs(char **ap) +{ + if (debug != 1) + return; + while (*ap) { + trstring(*ap++); + if (*ap) + putc(' ', tracefile); + else + putc('\n', tracefile); + } +} + + +void +opentrace(void) +{ + char s[100]; +#ifdef O_APPEND + int flags; +#endif + + if (debug != 1) { + if (tracefile) + fflush(tracefile); + /* leave open because libedit might be using it */ + return; + } +#ifdef not_this_way + { + char *p; + if ((p = getenv(homestr)) == NULL) { + if (geteuid() == 0) + p = "/"; + else + p = "/tmp"; + } + scopy(p, s); + strcat(s, "/trace"); + } +#else + scopy("./trace", s); +#endif /* not_this_way */ + if (tracefile) { + if (!freopen(s, "a", tracefile)) { + fprintf(stderr, "Can't re-open %s\n", s); + debug = 0; + return; + } + } else { + if ((tracefile = fopen(s, "a")) == NULL) { + fprintf(stderr, "Can't open %s\n", s); + debug = 0; + return; + } + } +#ifdef O_APPEND + if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) + fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); +#endif + setlinebuf(tracefile); + fputs("\nTracing started.\n", tracefile); +} +#endif /* DEBUG */ diff -puN /dev/null usr/dash/show.h --- /dev/null +++ a/usr/dash/show.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 1995 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)show.h 1.1 (Berkeley) 5/4/95 + */ + +#include + +#ifdef DEBUG +union node; +void showtree(union node *); +void trace(const char *, ...); +void tracev(const char *, va_list); +void trargs(char **); +void trputc(int); +void trputs(const char *); +void opentrace(void); +#endif diff -puN /dev/null usr/dash/system.c --- /dev/null +++ a/usr/dash/system.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2004 + * Herbert Xu . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef HAVE_ISALPHA +#define isalnum _isalnum +#define iscntrl _iscntrl +#define islower _islower +#define isspace _isspace +#define isalpha _isalpha +#define isdigit _isdigit +#define isprint _isprint +#define isupper _isupper +#define isblank _isblank +#define isgraph _isgraph +#define ispunct _ispunct +#define isxdigit _isxdigit +#include +#undef isalnum +#undef iscntrl +#undef islower +#undef isspace +#undef isalpha +#undef isdigit +#undef isprint +#undef isupper +#undef isblank +#undef isgraph +#undef ispunct +#undef isxdigit +#endif + +#include +#include + +#include "error.h" +#include "output.h" +#include "system.h" + +#ifndef HAVE_MEMPCPY +void *mempcpy(void *dest, const void *src, size_t n) +{ + return memcpy(dest, src, n) + n; +} +#endif + +#ifndef HAVE_STPCPY +char *stpcpy(char *dest, const char *src) +{ + size_t len = strlen(src); + dest[len] = 0; + return mempcpy(dest, src, len); +} +#endif + +#ifndef HAVE_STRCHRNUL +char *strchrnul(const char *s, int c) +{ + char *p = strchr(s, c); + if (!p) + p = (char *)s + strlen(s); + return p; +} +#endif + +#ifndef HAVE_STRSIGNAL +char *strsignal(int sig) +{ + static char buf[19]; + + if ((unsigned)sig < NSIG && sys_siglist[sig]) + return (char *)sys_siglist[sig]; + fmtstr(buf, sizeof(buf), "Signal %d", sig); + return buf; +} +#endif + +#ifndef HAVE_BSEARCH +void *bsearch(const void *key, const void *base, size_t nmemb, + size_t size, int (*cmp)(const void *, const void *)) +{ + while (nmemb) { + size_t mididx = nmemb / 2; + const void *midobj = base + mididx * size; + int diff = cmp(key, midobj); + + if (diff == 0) + return (void *)midobj; + + if (diff > 0) { + base = midobj + size; + nmemb -= mididx + 1; + } else + nmemb = mididx; + } + + return 0; +} +#endif + +#ifndef HAVE_SYSCONF +long sysconf(int name) +{ + sh_error("no sysconf for: %d", name); +} +#endif + +#ifndef HAVE_ISALPHA +int isalnum(int c) { + return _isalnum(c); +} + + +int iscntrl(int c) { + return _iscntrl(c); +} + + +int islower(int c) { + return _islower(c); +} + + +int isspace(int c) { + return _isspace(c); +} + + +int isalpha(int c) { + return _isalpha(c); +} + + +int isdigit(int c) { + return _isdigit(c); +} + + +int isprint(int c) { + return _isprint(c); +} + + +int isupper(int c) { + return _isupper(c); +} + + +int isblank(int c) { + return _isblank(c); +} + + +int isgraph(int c) { + return _isgraph(c); +} + + +int ispunct(int c) { + return _ispunct(c); +} + + +int isxdigit(int c) { + return _isxdigit(c); +} +#endif diff -puN /dev/null usr/dash/system.h --- /dev/null +++ a/usr/dash/system.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2004 + * Herbert Xu . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#ifndef SSIZE_MAX +#define SSIZE_MAX ((ssize_t)((size_t)-1 >> 1)) +#endif + +static inline void sigclearmask(void) +{ +#ifdef HAVE_SIGSETMASK + sigsetmask(0); +#else + sigset_t set; + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, 0); +#endif +} + +#ifndef HAVE_MEMPCPY +void *mempcpy(void *, const void *, size_t); +#endif + +#ifndef HAVE_STPCPY +char *stpcpy(char *, const char *); +#endif + +#ifndef HAVE_STRCHRNUL +char *strchrnul(const char *, int); +#endif + +#ifndef HAVE_STRSIGNAL +char *strsignal(int); +#endif + +#ifndef HAVE_STRTOIMAX +#define strtoimax strtoll +#endif + +#ifndef HAVE_STRTOUMAX +#define strtoumax strtoull +#endif + +#ifndef HAVE_BSEARCH +void *bsearch(const void *, const void *, size_t, size_t, + int (*)(const void *, const void *)); +#endif + +#ifndef HAVE_KILLPG +static inline int killpg(pid_t pid, int signal) +{ +#ifdef DEBUG + if (pid < 0) + abort(); +#endif + return kill(-pid, signal); +} +#endif + +#ifndef HAVE_SYSCONF +#define _SC_CLK_TCK 2 +long sysconf(int) __attribute__((__noreturn__)); +#endif diff -puN /dev/null usr/dash/TOUR --- /dev/null +++ a/usr/dash/TOUR @@ -0,0 +1,356 @@ +# @(#)TOUR 8.1 (Berkeley) 5/31/93 + +NOTE -- This is the original TOUR paper distributed with ash and +does not represent the current state of the shell. It is provided anyway +since it provides helpful information for how the shell is structured, +but be warned that things have changed -- the current shell is +still under development. + +================================================================ + + A Tour through Ash + + Copyright 1989 by Kenneth Almquist. + + +DIRECTORIES: The subdirectory bltin contains commands which can +be compiled stand-alone. The rest of the source is in the main +ash directory. + +SOURCE CODE GENERATORS: Files whose names begin with "mk" are +programs that generate source code. A complete list of these +programs is: + + program intput files generates + ------- ------------ --------- + mkbuiltins builtins builtins.h builtins.c + mkinit *.c init.c + mknodes nodetypes nodes.h nodes.c + mksignames - signames.h signames.c + mksyntax - syntax.h syntax.c + mktokens - token.h + bltin/mkexpr unary_op binary_op operators.h operators.c + +There are undoubtedly too many of these. Mkinit searches all the +C source files for entries looking like: + + INIT { + x = 1; /* executed during initialization */ + } + + RESET { + x = 2; /* executed when the shell does a longjmp + back to the main command loop */ + } + + SHELLPROC { + x = 3; /* executed when the shell runs a shell procedure */ + } + +It pulls this code out into routines which are when particular +events occur. The intent is to improve modularity by isolating +the information about which modules need to be explicitly +initialized/reset within the modules themselves. + +Mkinit recognizes several constructs for placing declarations in +the init.c file. + INCLUDE "file.h" +includes a file. The storage class MKINIT makes a declaration +available in the init.c file, for example: + MKINIT int funcnest; /* depth of function calls */ +MKINIT alone on a line introduces a structure or union declara- +tion: + MKINIT + struct redirtab { + short renamed[10]; + }; +Preprocessor #define statements are copied to init.c without any +special action to request this. + +INDENTATION: The ash source is indented in multiples of six +spaces. The only study that I have heard of on the subject con- +cluded that the optimal amount to indent is in the range of four +to six spaces. I use six spaces since it is not too big a jump +from the widely used eight spaces. If you really hate six space +indentation, use the adjind (source included) program to change +it to something else. + +EXCEPTIONS: Code for dealing with exceptions appears in +exceptions.c. The C language doesn't include exception handling, +so I implement it using setjmp and longjmp. The global variable +exception contains the type of exception. EXERROR is raised by +calling error. EXINT is an interrupt. EXSHELLPROC is an excep- +tion which is raised when a shell procedure is invoked. The pur- +pose of EXSHELLPROC is to perform the cleanup actions associated +with other exceptions. After these cleanup actions, the shell +can interpret a shell procedure itself without exec'ing a new +copy of the shell. + +INTERRUPTS: In an interactive shell, an interrupt will cause an +EXINT exception to return to the main command loop. (Exception: +EXINT is not raised if the user traps interrupts using the trap +command.) The INTOFF and INTON macros (defined in exception.h) +provide uninterruptable critical sections. Between the execution +of INTOFF and the execution of INTON, interrupt signals will be +held for later delivery. INTOFF and INTON can be nested. + +MEMALLOC.C: Memalloc.c defines versions of malloc and realloc +which call error when there is no memory left. It also defines a +stack oriented memory allocation scheme. Allocating off a stack +is probably more efficient than allocation using malloc, but the +big advantage is that when an exception occurs all we have to do +to free up the memory in use at the time of the exception is to +restore the stack pointer. The stack is implemented using a +linked list of blocks. + +STPUTC: If the stack were contiguous, it would be easy to store +strings on the stack without knowing in advance how long the +string was going to be: + p = stackptr; + *p++ = c; /* repeated as many times as needed */ + stackptr = p; +The folloing three macros (defined in memalloc.h) perform these +operations, but grow the stack if you run off the end: + STARTSTACKSTR(p); + STPUTC(c, p); /* repeated as many times as needed */ + grabstackstr(p); + +We now start a top-down look at the code: + +MAIN.C: The main routine performs some initialization, executes +the user's profile if necessary, and calls cmdloop. Cmdloop is +repeatedly parses and executes commands. + +OPTIONS.C: This file contains the option processing code. It is +called from main to parse the shell arguments when the shell is +invoked, and it also contains the set builtin. The -i and -j op- +tions (the latter turns on job control) require changes in signal +handling. The routines setjobctl (in jobs.c) and setinteractive +(in trap.c) are called to handle changes to these options. + +PARSING: The parser code is all in parser.c. A recursive des- +cent parser is used. Syntax tables (generated by mksyntax) are +used to classify characters during lexical analysis. There are +three tables: one for normal use, one for use when inside single +quotes, and one for use when inside double quotes. The tables +are machine dependent because they are indexed by character vari- +ables and the range of a char varies from machine to machine. + +PARSE OUTPUT: The output of the parser consists of a tree of +nodes. The various types of nodes are defined in the file node- +types. + +Nodes of type NARG are used to represent both words and the con- +tents of here documents. An early version of ash kept the con- +tents of here documents in temporary files, but keeping here do- +cuments in memory typically results in significantly better per- +formance. It would have been nice to make it an option to use +temporary files for here documents, for the benefit of small +machines, but the code to keep track of when to delete the tem- +porary files was complex and I never fixed all the bugs in it. +(AT&T has been maintaining the Bourne shell for more than ten +years, and to the best of my knowledge they still haven't gotten +it to handle temporary files correctly in obscure cases.) + +The text field of a NARG structure points to the text of the +word. The text consists of ordinary characters and a number of +special codes defined in parser.h. The special codes are: + + CTLVAR Variable substitution + CTLENDVAR End of variable substitution + CTLBACKQ Command substitution + CTLBACKQ|CTLQUOTE Command substitution inside double quotes + CTLESC Escape next character + +A variable substitution contains the following elements: + + CTLVAR type name '=' [ alternative-text CTLENDVAR ] + +The type field is a single character specifying the type of sub- +stitution. The possible types are: + + VSNORMAL $var + VSMINUS ${var-text} + VSMINUS|VSNUL ${var:-text} + VSPLUS ${var+text} + VSPLUS|VSNUL ${var:+text} + VSQUESTION ${var?text} + VSQUESTION|VSNUL ${var:?text} + VSASSIGN ${var=text} + VSASSIGN|VSNUL ${var=text} + +In addition, the type field will have the VSQUOTE flag set if the +variable is enclosed in double quotes. The name of the variable +comes next, terminated by an equals sign. If the type is not +VSNORMAL, then the text field in the substitution follows, ter- +minated by a CTLENDVAR byte. + +Commands in back quotes are parsed and stored in a linked list. +The locations of these commands in the string are indicated by +CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether +the back quotes were enclosed in double quotes. + +The character CTLESC escapes the next character, so that in case +any of the CTL characters mentioned above appear in the input, +they can be passed through transparently. CTLESC is also used to +escape '*', '?', '[', and '!' characters which were quoted by the +user and thus should not be used for file name generation. + +CTLESC characters have proved to be particularly tricky to get +right. In the case of here documents which are not subject to +variable and command substitution, the parser doesn't insert any +CTLESC characters to begin with (so the contents of the text +field can be written without any processing). Other here docu- +ments, and words which are not subject to splitting and file name +generation, have the CTLESC characters removed during the vari- +able and command substitution phase. Words which are subject +splitting and file name generation have the CTLESC characters re- +moved as part of the file name phase. + +EXECUTION: Command execution is handled by the following files: + eval.c The top level routines. + redir.c Code to handle redirection of input and output. + jobs.c Code to handle forking, waiting, and job control. + exec.c Code to to path searches and the actual exec sys call. + expand.c Code to evaluate arguments. + var.c Maintains the variable symbol table. Called from expand.c. + +EVAL.C: Evaltree recursively executes a parse tree. The exit +status is returned in the global variable exitstatus. The alter- +native entry evalbackcmd is called to evaluate commands in back +quotes. It saves the result in memory if the command is a buil- +tin; otherwise it forks off a child to execute the command and +connects the standard output of the child to a pipe. + +JOBS.C: To create a process, you call makejob to return a job +structure, and then call forkshell (passing the job structure as +an argument) to create the process. Waitforjob waits for a job +to complete. These routines take care of process groups if job +control is defined. + +REDIR.C: Ash allows file descriptors to be redirected and then +restored without forking off a child process. This is accom- +plished by duplicating the original file descriptors. The redir- +tab structure records where the file descriptors have be dupli- +cated to. + +EXEC.C: The routine find_command locates a command, and enters +the command in the hash table if it is not already there. The +third argument specifies whether it is to print an error message +if the command is not found. (When a pipeline is set up, +find_command is called for all the commands in the pipeline be- +fore any forking is done, so to get the commands into the hash +table of the parent process. But to make command hashing as +transparent as possible, we silently ignore errors at that point +and only print error messages if the command cannot be found +later.) + +The routine shellexec is the interface to the exec system call. + +EXPAND.C: Arguments are processed in three passes. The first +(performed by the routine argstr) performs variable and command +substitution. The second (ifsbreakup) performs word splitting +and the third (expandmeta) performs file name generation. If the +"/u" directory is simulated, then when "/u/username" is replaced +by the user's home directory, the flag "didudir" is set. This +tells the cd command that it should print out the directory name, +just as it would if the "/u" directory were implemented using +symbolic links. + +VAR.C: Variables are stored in a hash table. Probably we should +switch to extensible hashing. The variable name is stored in the +same string as the value (using the format "name=value") so that +no string copying is needed to create the environment of a com- +mand. Variables which the shell references internally are preal- +located so that the shell can reference the values of these vari- +ables without doing a lookup. + +When a program is run, the code in eval.c sticks any environment +variables which precede the command (as in "PATH=xxx command") in +the variable table as the simplest way to strip duplicates, and +then calls "environment" to get the value of the environment. +There are two consequences of this. First, if an assignment to +PATH precedes the command, the value of PATH before the assign- +ment must be remembered and passed to shellexec. Second, if the +program turns out to be a shell procedure, the strings from the +environment variables which preceded the command must be pulled +out of the table and replaced with strings obtained from malloc, +since the former will automatically be freed when the stack (see +the entry on memalloc.c) is emptied. + +BUILTIN COMMANDS: The procedures for handling these are scat- +tered throughout the code, depending on which location appears +most appropriate. They can be recognized because their names al- +ways end in "cmd". The mapping from names to procedures is +specified in the file builtins, which is processed by the mkbuil- +tins command. + +A builtin command is invoked with argc and argv set up like a +normal program. A builtin command is allowed to overwrite its +arguments. Builtin routines can call nextopt to do option pars- +ing. This is kind of like getopt, but you don't pass argc and +argv to it. Builtin routines can also call error. This routine +normally terminates the shell (or returns to the main command +loop if the shell is interactive), but when called from a builtin +command it causes the builtin command to terminate with an exit +status of 2. + +The directory bltins contains commands which can be compiled in- +dependently but can also be built into the shell for efficiency +reasons. The makefile in this directory compiles these programs +in the normal fashion (so that they can be run regardless of +whether the invoker is ash), but also creates a library named +bltinlib.a which can be linked with ash. The header file bltin.h +takes care of most of the differences between the ash and the +stand-alone environment. The user should call the main routine +"main", and #define main to be the name of the routine to use +when the program is linked into ash. This #define should appear +before bltin.h is included; bltin.h will #undef main if the pro- +gram is to be compiled stand-alone. + +CD.C: This file defines the cd and pwd builtins. The pwd com- +mand runs /bin/pwd the first time it is invoked (unless the user +has already done a cd to an absolute pathname), but then +remembers the current directory and updates it when the cd com- +mand is run, so subsequent pwd commands run very fast. The main +complication in the cd command is in the docd command, which +resolves symbolic links into actual names and informs the user +where the user ended up if he crossed a symbolic link. + +SIGNALS: Trap.c implements the trap command. The routine set- +signal figures out what action should be taken when a signal is +received and invokes the signal system call to set the signal ac- +tion appropriately. When a signal that a user has set a trap for +is caught, the routine "onsig" sets a flag. The routine dotrap +is called at appropriate points to actually handle the signal. +When an interrupt is caught and no trap has been set for that +signal, the routine "onint" in error.c is called. + +OUTPUT: Ash uses it's own output routines. There are three out- +put structures allocated. "Output" represents the standard out- +put, "errout" the standard error, and "memout" contains output +which is to be stored in memory. This last is used when a buil- +tin command appears in backquotes, to allow its output to be col- +lected without doing any I/O through the UNIX operating system. +The variables out1 and out2 normally point to output and errout, +respectively, but they are set to point to memout when appropri- +ate inside backquotes. + +INPUT: The basic input routine is pgetc, which reads from the +current input file. There is a stack of input files; the current +input file is the top file on this stack. The code allows the +input to come from a string rather than a file. (This is for the +-c option and the "." and eval builtin commands.) The global +variable plinno is saved and restored when files are pushed and +popped from the stack. The parser routines store the number of +the current line in this variable. + +DEBUGGING: If DEBUG is defined in shell.h, then the shell will +write debugging information to the file $HOME/trace. Most of +this is done using the TRACE macro, which takes a set of printf +arguments inside two sets of parenthesis. Example: +"TRACE(("n=%d0, n))". The double parenthesis are necessary be- +cause the preprocessor can't handle functions with a variable +number of arguments. Defining DEBUG also causes the shell to +generate a core dump if it is sent a quit signal. The tracing +code is in show.c. diff -puN /dev/null usr/dash/trap.c --- /dev/null +++ a/usr/dash/trap.c @@ -0,0 +1,443 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include "shell.h" +#include "main.h" +#include "nodes.h" /* for other headers */ +#include "eval.h" +#include "jobs.h" +#include "show.h" +#include "options.h" +#include "syntax.h" +#include "output.h" +#include "memalloc.h" +#include "error.h" +#include "trap.h" +#include "mystring.h" + +#ifdef HETIO +#include "hetio.h" +#endif + +/* + * Sigmode records the current value of the signal handlers for the various + * modes. A value of zero means that the current handler is not known. + * S_HARD_IGN indicates that the signal was ignored on entry to the shell, + */ + +#define S_DFL 1 /* default signal handling (SIG_DFL) */ +#define S_CATCH 2 /* signal is caught */ +#define S_IGN 3 /* signal is ignored (SIG_IGN) */ +#define S_HARD_IGN 4 /* signal is ignored permenantly */ +#define S_RESET 5 /* temporary - to reset a hard ignored sig */ + + +/* trap handler commands */ +char *trap[NSIG]; +/* current value of signal */ +static char sigmode[NSIG - 1]; +/* indicates specified signal received */ +char gotsig[NSIG - 1]; +/* last pending signal */ +volatile sig_atomic_t pendingsigs; +/* do we generate EXSIG events */ +int exsig; + +#ifdef mkinit +INCLUDE +INIT { + signal(SIGCHLD, SIG_DFL); +} +#endif + +/* + * The trap builtin. + */ + +int +trapcmd(int argc, char **argv) +{ + char *action; + char **ap; + int signo; + + nextopt(nullstr); + ap = argptr; + if (!*ap) { + for (signo = 0 ; signo < NSIG ; signo++) { + if (trap[signo] != NULL) { + out1fmt( + "trap -- %s %s\n", + single_quote(trap[signo]), + signal_name(signo) + ); + } + } + return 0; + } + if (!ap[1]) + action = NULL; + else + action = *ap++; + while (*ap) { + if ((signo = decode_signal(*ap, 0)) < 0) + sh_error("%s: bad trap", *ap); + INTOFF; + if (action) { + if (action[0] == '-' && action[1] == '\0') + action = NULL; + else + action = savestr(action); + } + if (trap[signo]) + ckfree(trap[signo]); + trap[signo] = action; + if (signo != 0) + setsignal(signo); + INTON; + ap++; + } + return 0; +} + + + +/* + * Clear traps on a fork. + */ + +void +clear_traps(void) +{ + char **tp; + + for (tp = trap ; tp < &trap[NSIG] ; tp++) { + if (*tp && **tp) { /* trap not NULL or SIG_IGN */ + INTOFF; + ckfree(*tp); + *tp = NULL; + if (tp != &trap[0]) + setsignal(tp - trap); + INTON; + } + } +} + + + +/* + * Set the signal handler for the specified signal. The routine figures + * out what it should be set to. + */ + +void +setsignal(int signo) +{ + int action; + char *t, tsig; + struct sigaction act; + + if ((t = trap[signo]) == NULL) + action = S_DFL; + else if (*t != '\0') + action = S_CATCH; + else + action = S_IGN; + if (rootshell && action == S_DFL) { + switch (signo) { + case SIGINT: + if (iflag || minusc || sflag == 0) + action = S_CATCH; + break; + case SIGQUIT: +#ifdef DEBUG + if (debug) + break; +#endif + /* FALLTHROUGH */ + case SIGTERM: + if (iflag) + action = S_IGN; + break; +#if JOBS + case SIGTSTP: + case SIGTTOU: + if (mflag) + action = S_IGN; + break; +#endif + } + } + + t = &sigmode[signo - 1]; + tsig = *t; + if (tsig == 0) { + /* + * current setting unknown + */ + if (sigaction(signo, 0, &act) == -1) { + /* + * Pretend it worked; maybe we should give a warning + * here, but other shells don't. We don't alter + * sigmode, so that we retry every time. + */ + return; + } + if (act.sa_handler == SIG_IGN) { + if (mflag && (signo == SIGTSTP || + signo == SIGTTIN || signo == SIGTTOU)) { + tsig = S_IGN; /* don't hard ignore these */ + } else + tsig = S_HARD_IGN; + } else { + tsig = S_RESET; /* force to be set */ + } + } + if (tsig == S_HARD_IGN || tsig == action) + return; + switch (action) { + case S_CATCH: + act.sa_handler = onsig; + break; + case S_IGN: + act.sa_handler = SIG_IGN; + break; + default: + act.sa_handler = SIG_DFL; + } + *t = action; + act.sa_flags = 0; + sigfillset(&act.sa_mask); + sigaction(signo, &act, 0); +} + +/* + * Ignore a signal. + */ + +void +ignoresig(int signo) +{ + if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { + signal(signo, SIG_IGN); + } + sigmode[signo - 1] = S_HARD_IGN; +} + + + +/* + * Signal handler. + */ + +void +onsig(int signo) +{ + gotsig[signo - 1] = 1; + pendingsigs = signo; + + if (exsig || (signo == SIGINT && !trap[SIGINT])) { + if (!suppressint) + onint(); + intpending = 1; + } +} + + + +/* + * Called to execute a trap. Perhaps we should avoid entering new trap + * handlers while we are executing a trap handler. + */ + +int +dotrap(void) +{ + char *p; + char *q; + int i; + int savestatus; + int skip = 0; + + savestatus = exitstatus; + pendingsigs = 0; + barrier(); + + for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) { + if (!*q) + continue; + *q = 0; + + p = trap[i + 1]; + if (!p) + continue; + skip = evalstring(p, SKIPEVAL); + exitstatus = savestatus; + if (skip) + break; + } + + return skip; +} + + + +/* + * Controls whether the shell is interactive or not. + */ + + +void +setinteractive(int on) +{ + static int is_interactive; + + if (++on == is_interactive) + return; + is_interactive = on; + setsignal(SIGINT); + setsignal(SIGQUIT); + setsignal(SIGTERM); +} + + + +/* + * Called to exit the shell. + */ + +void +exitshell(void) +{ + struct jmploc loc; + char *p; + int status; + +#ifdef HETIO + hetio_reset_term(); +#endif + status = exitstatus; + TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); + if (setjmp(loc.loc)) { + if (exception == EXEXIT) + _exit(exitstatus); + goto out; + } + handler = &loc; + if ((p = trap[0])) { + trap[0] = NULL; + evalstring(p, 0); + } + flushall(); +out: + _exit(status); + /* NOTREACHED */ +} + +/* + * Decode a signal name + */ +int decode_signal(const char *string, int minsig) +{ + int i; + + if (is_number(string)) { + i = atoi(string); + if (i >= NSIG) { + return -1; + } + return i; + } + + for ( i = minsig ; i < NSIG ; i++ ) { + if ( sys_sigabbrev[i] && + !strcasecmp(string, sys_sigabbrev[i]) ) + return i; + } + +#ifdef SIGRTMIN + if ( !strncasecmp(string, "RTMIN", 5) ) { + char *ep; + + if ( string[5] && string[5] != '+' ) + return -1; + i = SIGRTMIN + strtol(string+5, &ep, 10); + if ( *ep || i < SIGRTMIN || i > SIGRTMAX ) + return -1; + return i; + } + + if ( !strncasecmp(string, "RTMAX", 5) ) { + char *ep; + + if ( string[5] && string[5] != '-' ) + return -1; + i = SIGRTMAX + strtol(string+5, &ep, 10); + if ( *ep || i < SIGRTMIN || i > SIGRTMAX ) + return -1; + return i; + } +#endif + + return -1; +} + +/* + * Human-readable signal name + */ +const char * +signal_name(int sig) +{ + static char buf[64]; + + if ( sig < 0 || sig >= NSIG ) { + return NULL; + } else if ( sys_sigabbrev[sig] ) { + return sys_sigabbrev[sig]; +#ifdef SIGRTMIN + } else if ( sig >= SIGRTMIN && sig <= SIGRTMAX ) { + snprintf(buf, sizeof buf, "RTMIN+%d", sig-SIGRTMIN); + return buf; +#endif + } else { + snprintf(buf, sizeof buf, "%d", sig); + return buf; + } +} diff -puN /dev/null usr/dash/trap.h --- /dev/null +++ a/usr/dash/trap.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 8.3 (Berkeley) 6/5/95 + */ + +#include + +extern char *trap[]; +extern char gotsig[]; +extern volatile sig_atomic_t pendingsigs; + +int trapcmd(int, char **); +void clear_traps(void); +void setsignal(int); +void ignoresig(int); +void onsig(int); +int dotrap(void); +void setinteractive(int); +void exitshell(void) __attribute__((__noreturn__)); +int decode_signal(const char *, int); +const char *signal_name(int); diff -puN /dev/null usr/dash/var.c --- /dev/null +++ a/usr/dash/var.c @@ -0,0 +1,676 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +/* + * Shell variables. + */ + +#include "shell.h" +#include "output.h" +#include "expand.h" +#include "nodes.h" /* for other headers */ +#include "eval.h" /* defines cmdenviron */ +#include "exec.h" +#include "syntax.h" +#include "options.h" +#include "mail.h" +#include "var.h" +#include "memalloc.h" +#include "error.h" +#include "mystring.h" +#include "parser.h" +#include "show.h" +#ifndef SMALL +#include "myhistedit.h" +#endif +#include "system.h" + + +#define VTABSIZE 39 + + +struct localvar *localvars; + +const char defpathvar[] = + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; +#ifdef IFS_BROKEN +const char defifsvar[] = "IFS= \t\n"; +#else +const char defifs[] = " \t\n"; +#endif + +struct var varinit[] = { +#if ATTY + { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY\0", 0 }, +#endif +#ifdef IFS_BROKEN + { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 }, +#else + { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 }, +#endif + { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail }, + { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail }, + { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath }, + { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 }, + { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 }, + { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 }, + { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, +#ifndef SMALL + { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM\0", 0 }, + { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE\0", sethistsize }, +#endif +}; + +STATIC struct var *vartab[VTABSIZE]; + +STATIC void mklocal(char *); +STATIC struct var **hashvar(const char *); +STATIC int vpcmp(const void *, const void *); +STATIC struct var **findvar(struct var **, const char *); + +/* + * Initialize the varable symbol tables and import the environment + */ + +#ifdef mkinit +INCLUDE +INCLUDE +INCLUDE +INCLUDE "cd.h" +INCLUDE "output.h" +INCLUDE "var.h" +MKINIT char **environ; +INIT { + char **envp; + static char ppid[32] = "PPID="; + const char *p; + struct stat st1, st2; + + initvar(); + for (envp = environ ; *envp ; envp++) { + if (strchr(*envp, '=')) { + setvareq(*envp, VEXPORT|VTEXTFIXED); + } + } + + fmtstr(ppid + 5, sizeof(ppid) - 5, "%ld", (long) getppid()); + setvareq(ppid, VTEXTFIXED); + + p = lookupvar("PWD"); + if (p) + if (*p != '/' || stat(p, &st1) || stat(".", &st2) || + st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) + p = 0; + setpwd(p, 0); +} +#endif + + +/* + * This routine initializes the builtin variables. It is called when the + * shell is initialized. + */ + +void +initvar(void) +{ + struct var *vp; + struct var *end; + struct var **vpp; + + vp = varinit; + end = vp + sizeof(varinit) / sizeof(varinit[0]); + do { + vpp = hashvar(vp->text); + vp->next = *vpp; + *vpp = vp; + } while (++vp < end); + /* + * PS1 depends on uid + */ + if (!geteuid()) + vps1.text = "PS1=# "; +} + +/* + * Safe version of setvar, returns 1 on success 0 on failure. + */ + +int +setvarsafe(const char *name, const char *val, int flags) +{ + int err; + volatile int saveint; + struct jmploc *volatile savehandler = handler; + struct jmploc jmploc; + + SAVEINT(saveint); + if (setjmp(jmploc.loc)) + err = 1; + else { + handler = &jmploc; + setvar(name, val, flags); + err = 0; + } + handler = savehandler; + RESTOREINT(saveint); + return err; +} + +/* + * Set the value of a variable. The flags argument is ored with the + * flags of the variable. If val is NULL, the variable is unset. + */ + +void +setvar(const char *name, const char *val, int flags) +{ + char *p, *q; + size_t namelen; + char *nameeq; + size_t vallen; + + q = endofname(name); + p = strchrnul(q, '='); + namelen = p - name; + if (!namelen || p != q) + sh_error("%.*s: bad variable name", namelen, name); + vallen = 0; + if (val == NULL) { + flags |= VUNSET; + } else { + vallen = strlen(val); + } + INTOFF; + p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen); + if (val) { + *p++ = '='; + p = mempcpy(p, val, vallen); + } + *p = '\0'; + setvareq(nameeq, flags | VNOSAVE); + INTON; +} + + + +/* + * Same as setvar except that the variable and value are passed in + * the first argument as name=value. Since the first argument will + * be actually stored in the table, it should not be a string that + * will go away. + * Called with interrupts off. + */ + +void +setvareq(char *s, int flags) +{ + struct var *vp, **vpp; + + vpp = hashvar(s); + flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); + vp = *findvar(vpp, s); + if (vp) { + if (vp->flags & VREADONLY) { + const char *n; + + if (flags & VNOSAVE) + free(s); + n = vp->text; + sh_error("%.*s: is read only", strchrnul(n, '=') - n, + n); + } + + if (flags & VNOSET) + return; + + if (vp->func && (flags & VNOFUNC) == 0) + (*vp->func)(strchrnul(s, '=') + 1); + + if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) + ckfree(vp->text); + + flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET); + } else { + if (flags & VNOSET) + return; + /* not found */ + vp = ckmalloc(sizeof (*vp)); + vp->next = *vpp; + vp->func = NULL; + *vpp = vp; + } + if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE))) + s = savestr(s); + vp->text = s; + vp->flags = flags; +} + + + +/* + * Process a linked list of variable assignments. + */ + +void +listsetvar(struct strlist *list, int flags) +{ + struct strlist *lp; + + lp = list; + if (!lp) + return; + INTOFF; + do { + setvareq(lp->text, flags); + } while ((lp = lp->next)); + INTON; +} + + +/* + * Find the value of a variable. Returns NULL if not set. + */ + +char * +lookupvar(const char *name) +{ + struct var *v; + + if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) { + return strchrnul(v->text, '=') + 1; + } + return NULL; +} + + + +/* + * Search the environment of a builtin command. + */ + +char * +bltinlookup(const char *name) +{ + struct strlist *sp; + + for (sp = cmdenviron ; sp ; sp = sp->next) { + if (varequal(sp->text, name)) + return strchrnul(sp->text, '=') + 1; + } + return lookupvar(name); +} + + + +/* + * Generate a list of variables satisfying the given conditions. + */ + +char ** +listvars(int on, int off, char ***end) +{ + struct var **vpp; + struct var *vp; + char **ep; + int mask; + + STARTSTACKSTR(ep); + vpp = vartab; + mask = on | off; + do { + for (vp = *vpp ; vp ; vp = vp->next) + if ((vp->flags & mask) == on) { + if (ep == stackstrend()) + ep = growstackstr(); + *ep++ = (char *) vp->text; + } + } while (++vpp < vartab + VTABSIZE); + if (ep == stackstrend()) + ep = growstackstr(); + if (end) + *end = ep; + *ep++ = NULL; + return grabstackstr(ep); +} + + + +/* + * POSIX requires that 'set' (but not export or readonly) output the + * variables in lexicographic order - by the locale's collating order (sigh). + * Maybe we could keep them in an ordered balanced binary tree + * instead of hashed lists. + * For now just roll 'em through qsort for printing... + */ + +int +showvars(const char *prefix, int on, int off) +{ + const char *sep; + char **ep, **epend; + + ep = listvars(on, off, &epend); + qsort(ep, epend - ep, sizeof(char *), vpcmp); + + sep = *prefix ? spcstr : prefix; + + for (; ep < epend; ep++) { + const char *p; + const char *q; + + p = strchrnul(*ep, '='); + q = nullstr; + if (*p) + q = single_quote(++p); + + out1fmt("%s%s%.*s%s\n", prefix, sep, (int)(p - *ep), *ep, q); + } + + return 0; +} + + + +/* + * The export and readonly commands. + */ + +int +exportcmd(int argc, char **argv) +{ + struct var *vp; + char *name; + const char *p; + char **aptr; + int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; + int notp; + + notp = nextopt("p") - 'p'; + if (notp && ((name = *(aptr = argptr)))) { + do { + if ((p = strchr(name, '=')) != NULL) { + p++; + } else { + if ((vp = *findvar(hashvar(name), name))) { + vp->flags |= flag; + continue; + } + } + setvar(name, p, flag); + } while ((name = *++aptr) != NULL); + } else { + showvars(argv[0], flag, 0); + } + return 0; +} + + +/* + * The "local" command. + */ + +int +localcmd(int argc, char **argv) +{ + char *name; + + argv = argptr; + while ((name = *argv++) != NULL) { + mklocal(name); + } + return 0; +} + + +/* + * Make a variable a local variable. When a variable is made local, it's + * value and flags are saved in a localvar structure. The saved values + * will be restored when the shell function returns. We handle the name + * "-" as a special case. + */ + +STATIC void +mklocal(char *name) +{ + struct localvar *lvp; + struct var **vpp; + struct var *vp; + + INTOFF; + lvp = ckmalloc(sizeof (struct localvar)); + if (name[0] == '-' && name[1] == '\0') { + char *p; + p = ckmalloc(sizeof(optlist)); + lvp->text = memcpy(p, optlist, sizeof(optlist)); + vp = NULL; + } else { + char *eq; + + vpp = hashvar(name); + vp = *findvar(vpp, name); + eq = strchr(name, '='); + if (vp == NULL) { + if (eq) + setvareq(name, VSTRFIXED); + else + setvar(name, NULL, VSTRFIXED); + vp = *vpp; /* the new variable */ + lvp->flags = VUNSET; + } else { + lvp->text = vp->text; + lvp->flags = vp->flags; + vp->flags |= VSTRFIXED|VTEXTFIXED; + if (eq) + setvareq(name, 0); + } + } + lvp->vp = vp; + lvp->next = localvars; + localvars = lvp; + INTON; +} + + +/* + * Called after a function returns. + * Interrupts must be off. + */ + +void +poplocalvars(void) +{ + struct localvar *lvp; + struct var *vp; + + while ((lvp = localvars) != NULL) { + localvars = lvp->next; + vp = lvp->vp; + TRACE(("poplocalvar %s", vp ? vp->text : "-")); + if (vp == NULL) { /* $- saved */ + memcpy(optlist, lvp->text, sizeof(optlist)); + ckfree(lvp->text); + optschanged(); + } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { + unsetvar(vp->text); + } else { + if (vp->func) + (*vp->func)(strchrnul(lvp->text, '=') + 1); + if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) + ckfree(vp->text); + vp->flags = lvp->flags; + vp->text = lvp->text; + } + ckfree(lvp); + } +} + + +/* + * The unset builtin command. We unset the function before we unset the + * variable to allow a function to be unset when there is a readonly variable + * with the same name. + */ + +int +unsetcmd(int argc, char **argv) +{ + char **ap; + int i; + int flag = 0; + int ret = 0; + + while ((i = nextopt("vf")) != '\0') { + flag = i; + } + + for (ap = argptr; *ap ; ap++) { + if (flag != 'f') { + i = unsetvar(*ap); + ret |= i; + if (!(i & 2)) + continue; + } + if (flag != 'v') + unsetfunc(*ap); + } + return ret & 1; +} + + +/* + * Unset the specified variable. + */ + +int +unsetvar(const char *s) +{ + struct var **vpp; + struct var *vp; + int retval; + + vpp = findvar(hashvar(s), s); + vp = *vpp; + retval = 2; + if (vp) { + int flags = vp->flags; + + retval = 1; + if (flags & VREADONLY) + goto out; + if (flags & VUNSET) + goto ok; + if ((flags & VSTRFIXED) == 0) { + INTOFF; + if ((flags & (VTEXTFIXED|VSTACK)) == 0) + ckfree(vp->text); + *vpp = vp->next; + ckfree(vp); + INTON; + } else { + setvar(s, 0, 0); + vp->flags &= ~VEXPORT; + } +ok: + retval = 0; + } + +out: + return retval; +} + + + +/* + * Find the appropriate entry in the hash table from the name. + */ + +STATIC struct var ** +hashvar(const char *p) +{ + unsigned int hashval; + + hashval = ((unsigned char) *p) << 4; + while (*p && *p != '=') + hashval += (unsigned char) *p++; + return &vartab[hashval % VTABSIZE]; +} + + + +/* + * Compares two strings up to the first = or '\0'. The first + * string must be terminated by '='; the second may be terminated by + * either '=' or '\0'. + */ + +int +varcmp(const char *p, const char *q) +{ + int c, d; + + while ((c = *p) == (d = *q)) { + if (!c || c == '=') + goto out; + p++; + q++; + } + if (c == '=') + c = 0; + if (d == '=') + d = 0; +out: + return c - d; +} + +STATIC int +vpcmp(const void *a, const void *b) +{ + return varcmp(*(const char **)a, *(const char **)b); +} + +STATIC struct var ** +findvar(struct var **vpp, const char *name) +{ + for (; *vpp; vpp = &(*vpp)->next) { + if (varequal((*vpp)->text, name)) { + break; + } + } + return vpp; +} diff -puN /dev/null usr/dash/var.h --- /dev/null +++ a/usr/dash/var.h @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kenneth Almquist. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)var.h 8.2 (Berkeley) 5/4/95 + */ + +/* + * Shell variables. + */ + +/* flags */ +#define VEXPORT 0x01 /* variable is exported */ +#define VREADONLY 0x02 /* variable cannot be modified */ +#define VSTRFIXED 0x04 /* variable struct is statically allocated */ +#define VTEXTFIXED 0x08 /* text is statically allocated */ +#define VSTACK 0x10 /* text is allocated on the stack */ +#define VUNSET 0x20 /* the variable is not set */ +#define VNOFUNC 0x40 /* don't call the callback function */ +#define VNOSET 0x80 /* do not set variable - just readonly test */ +#define VNOSAVE 0x100 /* when text is on the heap before setvareq */ + + +struct var { + struct var *next; /* next entry in hash list */ + int flags; /* flags are defined above */ + const char *text; /* name=value */ + void (*func)(const char *); + /* function to be called when */ + /* the variable gets set/unset */ +}; + + +struct localvar { + struct localvar *next; /* next local variable in list */ + struct var *vp; /* the variable that was made local */ + int flags; /* saved flags */ + const char *text; /* saved text */ +}; + + +extern struct localvar *localvars; +extern struct var varinit[]; + +#if ATTY +#define vatty varinit[0] +#define vifs varinit[1] +#else +#define vifs varinit[0] +#endif +#define vmail (&vifs)[1] +#define vmpath (&vmail)[1] +#define vpath (&vmpath)[1] +#define vps1 (&vpath)[1] +#define vps2 (&vps1)[1] +#define vps4 (&vps2)[1] +#define voptind (&vps4)[1] +#ifndef SMALL +#define vterm (&voptind)[1] +#define vhistsize (&vterm)[1] +#endif + +#ifdef IFS_BROKEN +extern const char defifsvar[]; +#define defifs (defifsvar + 4) +#else +extern const char defifs[]; +#endif +extern const char defpathvar[]; +#define defpath (defpathvar + 5) + +/* + * The following macros access the values of the above variables. + * They have to skip over the name. They return the null string + * for unset variables. + */ + +#define ifsval() (vifs.text + 4) +#define ifsset() ((vifs.flags & VUNSET) == 0) +#define mailval() (vmail.text + 5) +#define mpathval() (vmpath.text + 9) +#define pathval() (vpath.text + 5) +#define ps1val() (vps1.text + 4) +#define ps2val() (vps2.text + 4) +#define ps4val() (vps4.text + 4) +#define optindval() (voptind.text + 7) +#ifndef SMALL +#define histsizeval() (vhistsize.text + 9) +#define termval() (vterm.text + 5) +#endif + +#if ATTY +#define attyset() ((vatty.flags & VUNSET) == 0) +#endif +#define mpathset() ((vmpath.flags & VUNSET) == 0) + +void initvar(void); +void setvar(const char *, const char *, int); +void setvareq(char *, int); +struct strlist; +void listsetvar(struct strlist *, int); +char *lookupvar(const char *); +char *bltinlookup(const char *); +char **listvars(int, int, char ***); +#define environment() listvars(VEXPORT, VUNSET, 0) +int showvars(const char *, int, int); +int exportcmd(int, char **); +int localcmd(int, char **); +void poplocalvars(void); +int unsetcmd(int, char **); +int unsetvar(const char *); +int setvarsafe(const char *, const char *, int); +int varcmp(const char *, const char *); + +static inline int varequal(const char *a, const char *b) { + return !varcmp(a, b); +} diff -puN /dev/null usr/gzip/bits.c --- /dev/null +++ a/usr/gzip/bits.c @@ -0,0 +1,200 @@ +/* bits.c -- output variable-length bit strings + * Copyright (C) 1992-1993 Jean-loup Gailly + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + + +/* + * PURPOSE + * + * Output variable-length bit strings. Compression can be done + * to a file or to memory. (The latter is not supported in this version.) + * + * DISCUSSION + * + * The PKZIP "deflate" file format interprets compressed file data + * as a sequence of bits. Multi-bit strings in the file may cross + * byte boundaries without restriction. + * + * The first bit of each byte is the low-order bit. + * + * The routines in this file allow a variable-length bit value to + * be output right-to-left (useful for literal values). For + * left-to-right output (useful for code strings from the tree routines), + * the bits must have been reversed first with bi_reverse(). + * + * For in-memory compression, the compressed bit stream goes directly + * into the requested output buffer. The input data is read in blocks + * by the mem_read() function. The buffer is limited to 64K on 16 bit + * machines. + * + * INTERFACE + * + * void bi_init (FILE *zipfile) + * Initialize the bit string routines. + * + * void send_bits (int value, int length) + * Write out a bit string, taking the source bits right to + * left. + * + * int bi_reverse (int value, int length) + * Reverse the bits of a bit string, taking the source bits left to + * right and emitting them right to left. + * + * void bi_windup (void) + * Write out any remaining bits in an incomplete byte. + * + * void copy_block(char *buf, unsigned len, int header) + * Copy a stored block to the zip file, storing first the length and + * its one's complement if requested. + * + */ + +#include "tailor.h" +#include "gzip.h" + +#ifdef DEBUG +# include +#endif + +#ifdef RCSID +static char rcsid[] = "$Id: bits.c,v 1.1 2002/08/18 00:59:21 hpa Exp $"; +#endif + +/* =========================================================================== + * Local data used by the "bit string" routines. + */ + +local file_t zfile; /* output gzip file */ + +local unsigned short bi_buf; +/* Output buffer. bits are inserted starting at the bottom (least significant + * bits). + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +local int bi_valid; +/* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +int (*read_buf) OF((char *buf, unsigned size)); +/* Current input function. Set to mem_read for in-memory compression */ + +#ifdef DEBUG + ulg bits_sent; /* bit length of the compressed data */ +#endif + +/* =========================================================================== + * Initialize the bit string routines. + */ +void bi_init (zipfile) + file_t zipfile; /* output zip file, NO_FILE for in-memory compression */ +{ + zfile = zipfile; + bi_buf = 0; + bi_valid = 0; +#ifdef DEBUG + bits_sent = 0L; +#endif + + /* Set the defaults for file compression. They are set by memcompress + * for in-memory compression. + */ + if (zfile != NO_FILE) { + read_buf = file_read; + } +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +void send_bits(value, length) + int value; /* value to send */ + int length; /* number of bits */ +{ +#ifdef DEBUG + Tracev((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + bits_sent += (ulg)length; +#endif + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (bi_valid > (int)Buf_size - length) { + bi_buf |= (value << bi_valid); + put_short(bi_buf); + bi_buf = (ush)value >> (Buf_size - bi_valid); + bi_valid += length - Buf_size; + } else { + bi_buf |= value << bi_valid; + bi_valid += length; + } +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Write out any remaining bits in an incomplete byte. + */ +void bi_windup() +{ + if (bi_valid > 8) { + put_short(bi_buf); + } else if (bi_valid > 0) { + put_byte(bi_buf); + } + bi_buf = 0; + bi_valid = 0; +#ifdef DEBUG + bits_sent = (bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block to the zip file, storing first the length and its + * one's complement if requested. + */ +void copy_block(buf, len, header) + char *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(); /* align on byte boundary */ + + if (header) { + put_short((ush)len); + put_short((ush)~len); +#ifdef DEBUG + bits_sent += 2*16; +#endif + } +#ifdef DEBUG + bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(*buf++); + } +} diff -puN /dev/null usr/gzip/COPYING --- /dev/null +++ a/usr/gzip/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -puN /dev/null usr/gzip/deflate.c --- /dev/null +++ a/usr/gzip/deflate.c @@ -0,0 +1,759 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1992-1993 Jean-loup Gailly + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +/* + * PURPOSE + * + * Identify new text as repetitions of old text within a fixed- + * length sliding window trailing behind the new text. + * + * DISCUSSION + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many info-zippers for bug reports and testing. + * + * REFERENCES + * + * APPNOTE.TXT documentation file in PKZIP 1.93a distribution. + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + * INTERFACE + * + * void lm_init (int pack_level, ush *flags) + * Initialize the "longest match" routines for a new file + * + * ulg deflate (void) + * Processes a new input file and return its compressed length. Sets + * the compressed length, crc, deflate flags and internal file + * attributes. + */ + +#include + +#include "tailor.h" +#include "gzip.h" + +#ifdef RCSID +static char rcsid[] = "$Id: deflate.c,v 1.1 2002/08/18 00:59:21 hpa Exp $"; +#endif + +/* =========================================================================== + * Configuration parameters + */ + +/* Compile with MEDIUM_MEM to reduce the memory requirements or + * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the + * entire input file can be held in memory (not possible on 16 bit systems). + * Warning: defining these symbols affects HASH_BITS (see below) and thus + * affects the compression ratio. The compressed output + * is still correct, and might even be smaller in some cases. + */ + +#ifdef SMALL_MEM +# define HASH_BITS 13 /* Number of bits used to hash strings */ +#endif +#ifdef MEDIUM_MEM +# define HASH_BITS 14 +#endif +#ifndef HASH_BITS +# define HASH_BITS 15 + /* For portability to 16 bit machines, do not use values above 15. */ +#endif + +/* To save space (see unlzw.c), we overlay prev+head with tab_prefix and + * window with tab_suffix. Check that we can do this: + */ +#if (WSIZE<<1) > (1< BITS-1 + error: cannot overlay head with tab_prefix1 +#endif + +#define HASH_SIZE (unsigned)(1<= HASH_BITS + */ + +unsigned int prev_length; +/* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + unsigned strstart; /* start of string to insert */ + unsigned match_start; /* start of matching string */ +local int eofile; /* flag set at end of input file */ +local unsigned lookahead; /* number of valid bytes ahead in window */ + +unsigned max_chain_length; +/* To speed up deflation, hash chains are never searched beyond this length. + * A higher limit improves compression ratio but degrades the speed. + */ + +local unsigned int max_lazy_match; +/* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +#define max_insert_length max_lazy_match +/* Insert new strings in the hash table only if the match length + * is not greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + +local int compr_level; +/* compression level (1..9) */ + +unsigned good_match; +/* Use a faster search when the previous match is longer than this */ + + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ + +typedef struct config { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; +} config; + +#ifdef FULL_SEARCH +# define nice_match MAX_MATCH +#else + int nice_match; /* Stop searching when current match exceeds this */ +#endif + +local config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0}, /* store only */ +/* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8}, +/* 3 */ {4, 6, 32, 32}, + +/* 4 */ {4, 4, 16, 16}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32}, +/* 6 */ {8, 16, 128, 128}, +/* 7 */ {8, 32, 128, 256}, +/* 8 */ {32, 128, 258, 1024}, +/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +/* =========================================================================== + * Prototypes for local functions. + */ +local void fill_window OF((void)); +local ulg deflate_fast OF((void)); + + int longest_match OF((IPos cur_match)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ +#endif + +#ifdef DEBUG +local void check_match OF((IPos start, IPos match, int length)); +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(h,c) (h = (((h)< 9) error("bad pack level"); + compr_level = pack_level; + + /* Initialize the hash table. */ + memzero((char*)head, HASH_SIZE*sizeof(*head)); + + /* prev will be initialized on the fly */ + + /* Set the default configuration parameters: + */ + max_lazy_match = configuration_table[pack_level].max_lazy; + good_match = configuration_table[pack_level].good_length; +#ifndef FULL_SEARCH + nice_match = configuration_table[pack_level].nice_length; +#endif + max_chain_length = configuration_table[pack_level].max_chain; + if (pack_level == 1) { + *flags |= FAST; + } else if (pack_level == 9) { + *flags |= SLOW; + } + /* ??? reduce max_chain_length for binary files */ + + strstart = 0; + block_start = 0L; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif + + lookahead = read_buf((char*)window, + sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE); + + if (lookahead == 0 || lookahead == (unsigned)EOF) { + eofile = 1, lookahead = 0; + return; + } + eofile = 0; + /* Make sure that we always have enough lookahead. This is important + * if input comes from a device such as a tty. + */ + while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window(); + + ins_h = 0; + for (j=0; j= 1 + */ +#ifndef ASMV +/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or + * match.s. The code is functionally equivalent, so you can use the C version + * if desired. + */ +int longest_match(cur_match) + IPos cur_match; /* current match */ +{ + unsigned chain_length = max_chain_length; /* max hash chain length */ + register uch *scan = window + strstart; /* current string */ + register uch *match; /* matched string */ + register int len; /* length of current match */ + int best_len = prev_length; /* best match length so far */ + IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + +/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ +#if HASH_BITS < 8 || MAX_MATCH != 258 + error: Code too clever +#endif + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register uch *strend = window + strstart + MAX_MATCH - 1; + register ush scan_start = *(ush*)scan; + register ush scan_end = *(ush*)(scan+best_len-1); +#else + register uch *strend = window + strstart + MAX_MATCH; + register uch scan_end1 = scan[best_len-1]; + register uch scan_end = scan[best_len]; +#endif + + /* Do not waste too much time if we already have a good match: */ + if (prev_length >= good_match) { + chain_length >>= 2; + } + Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead"); + + do { + Assert(cur_match < strstart, "no future"); + match = window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ush*)(match+best_len-1) != scan_end || + *(ush*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + scan++, match++; + do { + } while (*(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= window+(unsigned)(window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ush*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & WMASK]) > limit + && --chain_length != 0); + + return best_len; +} +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(start, match, length) + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (memcmp((char*)window + match, + (char*)window + start, length) != EQUAL) { + fprintf(stderr, + " start %d, match %d, length %d\n", + start, match, length); + error("invalid match"); + } + if (verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead, and sets eofile if end of input file. + * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 + * OUT assertions: at least one byte has been read, or eofile is set; + * file reads are performed for at least two bytes (required for the + * translate_eol option). + */ +local void fill_window() +{ + register unsigned n, m; + unsigned more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart); + /* Amount of free space at the end of the window. */ + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (more == (unsigned)EOF) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + } else if (strstart >= WSIZE+MAX_DIST) { + /* By the IN assertion, the window is not empty so we can't confuse + * more == 0 with more == 64K on a 16 bit machine. + */ + Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM"); + + memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE); + match_start -= WSIZE; + strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ + + block_start -= (long) WSIZE; + + for (n = 0; n < HASH_SIZE; n++) { + m = head[n]; + head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); + } + for (n = 0; n < WSIZE; n++) { + m = prev[n]; + prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } + more += WSIZE; + } + /* At this point, more >= 2 */ + if (!eofile) { + n = read_buf((char*)window+strstart+lookahead, more); + if (n == 0 || n == (unsigned)EOF) { + eofile = 1; + } else { + lookahead += n; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK(eof) \ + flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \ + (char*)NULL, (long)strstart - block_start, (eof)) + +/* =========================================================================== + * Processes a new input file and return its compressed length. This + * function does not perform lazy evaluationof matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local ulg deflate_fast() +{ + IPos hash_head; /* head of the hash chain */ + int flush; /* set if current block must be flushed */ + unsigned match_length = 0; /* length of best match */ + + prev_length = MIN_MATCH-1; + while (lookahead != 0) { + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + INSERT_STRING(strstart, hash_head); + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && strstart - hash_head <= MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + match_length = longest_match (hash_head); + /* longest_match() sets match_start */ + if (match_length > lookahead) match_length = lookahead; + } + if (match_length >= MIN_MATCH) { + check_match(strstart, match_start, match_length); + + flush = ct_tally(strstart-match_start, match_length - MIN_MATCH); + + lookahead -= match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (match_length <= max_insert_length) { + match_length--; /* string at strstart already in hash table */ + do { + strstart++; + INSERT_STRING(strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since + * the next lookahead bytes will be emitted as literals. + */ + } while (--match_length != 0); + strstart++; + } else { + strstart += match_length; + match_length = 0; + ins_h = window[strstart]; + UPDATE_HASH(ins_h, window[strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c",window[strstart])); + flush = ct_tally (0, window[strstart]); + lookahead--; + strstart++; + } + if (flush) FLUSH_BLOCK(0), block_start = strstart; + + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window(); + + } + return FLUSH_BLOCK(1); /* eof */ +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +ulg deflate() +{ + IPos hash_head; /* head of hash chain */ + IPos prev_match; /* previous match */ + int flush; /* set if current block must be flushed */ + int match_available = 0; /* set if previous match exists */ + register unsigned match_length = MIN_MATCH-1; /* length of best match */ +#ifdef DEBUG + extern long isize; /* byte length of input file, for debug only */ +#endif + + if (compr_level <= 3) return deflate_fast(); /* optimized for speed */ + + /* Process the input block. */ + while (lookahead != 0) { + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + INSERT_STRING(strstart, hash_head); + + /* Find the longest match, discarding those <= prev_length. + */ + prev_length = match_length, prev_match = match_start; + match_length = MIN_MATCH-1; + + if (hash_head != NIL && prev_length < max_lazy_match && + strstart - hash_head <= MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + match_length = longest_match (hash_head); + /* longest_match() sets match_start */ + if (match_length > lookahead) match_length = lookahead; + + /* Ignore a length 3 match if it is too distant: */ + if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){ + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + match_length--; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (prev_length >= MIN_MATCH && match_length <= prev_length) { + + check_match(strstart-1, prev_match, prev_length); + + flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. + */ + lookahead -= prev_length-1; + prev_length -= 2; + do { + strstart++; + INSERT_STRING(strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since the + * next lookahead bytes will always be emitted as literals. + */ + } while (--prev_length != 0); + match_available = 0; + match_length = MIN_MATCH-1; + strstart++; + if (flush) FLUSH_BLOCK(0), block_start = strstart; + + } else if (match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c",window[strstart-1])); + if (ct_tally (0, window[strstart-1])) { + FLUSH_BLOCK(0), block_start = strstart; + } + strstart++; + lookahead--; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + match_available = 1; + strstart++; + lookahead--; + } + Assert (strstart <= isize && lookahead <= isize, "a bit too far"); + + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window(); + } + if (match_available) ct_tally (0, window[strstart-1]); + + return FLUSH_BLOCK(1); /* eof */ +} diff -puN /dev/null usr/gzip/gzip.c --- /dev/null +++ a/usr/gzip/gzip.c @@ -0,0 +1,1214 @@ +/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface + * Copyright (C) 1992-1993 Jean-loup Gailly + * The unzip code was written and put in the public domain by Mark Adler. + * Portions of the lzw code are derived from the public domain 'compress' + * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies, + * Ken Turkowski, Dave Mack and Peter Jannesen. + * + * See the license_msg below and the file COPYING for the software license. + * See the file algorithm.doc for the compression algorithms and file formats. + */ + +static char *license_msg[] = { +" Copyright (C) 1992-1993 Jean-loup Gailly", +" 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., 675 Mass Ave, Cambridge, MA 02139, USA.", +0}; + +/* Compress files with zip algorithm and 'compress' interface. + * See usage() and help() functions below for all options. + * Outputs: + * file.gz: compressed file with same mode, owner, and utimes + * or stdout with -c option or if stdin used as input. + * If the output file name had to be truncated, the original name is kept + * in the compressed file. + * On MSDOS, file.tmp -> file.tmz. On VMS, file.tmp -> file.tmp-gz. + * + * Using gz on MSDOS would create too many file name conflicts. For + * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for + * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz. + * I also considered 12345678.txt -> 12345txt.gz but this truncates the name + * too heavily. There is no ideal solution given the MSDOS 8+3 limitation. + * + * For the meaning of all compilation flags, see comments in Makefile.in. + */ + +#ifdef RCSID +static char rcsid[] = "$Id: gzip.c,v 1.3 2005/02/12 21:03:28 olh Exp $"; +#endif + +#include +#include +#include +#include +#include + +#include "tailor.h" +#include "gzip.h" +#include "revision.h" + +#include +#include +#include +#include + +#include + +typedef void (*sig_type) OF((int)); + +#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */ + +#ifndef MAX_PATH_LEN +# define MAX_PATH_LEN 1024 /* max pathname length */ +#endif + + /* global buffers */ + +DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA); +DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); +DECLARE(ush, d_buf, DIST_BUFSIZE); +DECLARE(uch, window, 2L*WSIZE); +DECLARE(ush, tab_prefix, 1L< MAX_SUFFIX) { + fprintf(stderr, "%s: incorrect suffix '%s'\n", + progname, optarg); + do_exit(ERROR); + } + + /* Allocate all global buffers (for DYN_ALLOC option) */ + ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA); + ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); + ALLOC(ush, d_buf, DIST_BUFSIZE); + ALLOC(uch, window, 2L*WSIZE); + ALLOC(ush, tab_prefix, 1L< 1 && !to_stdout && !force) { + WARN((stderr, "%s: %s has %d other link%c -- unchanged\n", + progname, ifname, + (int)istat.st_nlink - 1, istat.st_nlink > 2 ? 's' : ' ')); + return; + } + + ifile_size = istat.st_size; + time_stamp = no_time ? 0 : istat.st_mtime; + + /* Generate output file name. For -r and (-t or -l), skip files + * without a valid gzip suffix (check done in make_ofname). + */ + if (to_stdout && !test) { + strcpy(ofname, "stdout"); + + } else if (make_ofname() != OK) { + return; + } + + /* Open the input file and determine compression method. The mode + * parameter is ignored but required by some systems (VMS) and forbidden + * on other systems (MacOS). + */ + ifd = open(ifname, !decompress ? O_RDONLY : O_RDONLY, + RW_USER); + if (ifd == -1) { + fprintf(stderr, "%s: ", progname); + perror(ifname); + exit_code = ERROR; + return; + } + clear_bufs(); /* clear input and output buffers */ + part_nb = 0; + + if (decompress) { + method = get_method(); /* updates ofname if original given */ + if (method < 0) { + close(ifd); + return; /* error message already emitted */ + } + } + + /* If compressing to a file, check if ofname is not ambiguous + * because the operating system truncates names. Otherwise, generate + * a new ofname and save the original name in the compressed file. + */ + if (to_stdout) { + ofd = fileno(stdout); + /* keep remove_ofname as zero */ + } else { + if (create_outfile() != OK) return; + + if (!decompress && save_orig_name && !verbose && !quiet) { + fprintf(stderr, "%s: %s compressed to %s\n", + progname, ifname, ofname); + } + } + /* Keep the name even if not truncated except with --no-name: */ + if (!save_orig_name) save_orig_name = !no_name; + + if (verbose) { + fprintf(stderr, "%s:\t%s", ifname, (int)strlen(ifname) >= 15 ? + "" : ((int)strlen(ifname) >= 7 ? "\t" : "\t\t")); + } + + /* Actually do the compression/decompression. Loop over zipped members. + */ + for (;;) { + if ((*work)(ifd, ofd) != OK) { + method = -1; /* force cleanup */ + break; + } + if (!decompress || last_member || inptr == insize) break; + /* end of file */ + + method = get_method(); + if (method < 0) break; /* error message already emitted */ + bytes_out = 0; /* required for length check */ + } + + close(ifd); + if (!to_stdout && close(ofd)) { + write_error(); + } + if (method == -1) { + if (!to_stdout) unlink (ofname); + return; + } + /* Display statistics */ + if(verbose) { + if (test) { + fprintf(stderr, " OK"); + } else if (decompress) { + display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr); + } else { + display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr); + } + if (!test && !to_stdout) { + fprintf(stderr, " -- replaced with %s", ofname); + } + fprintf(stderr, "\n"); + } + /* Copy modes, times, ownership, and remove the input file */ + if (!to_stdout) { + copy_stat(&istat); + } +} + +/* ======================================================================== + * Create the output file. Return OK or ERROR. + * Try several times if necessary to avoid truncating the z_suffix. For + * example, do not create a compressed file of name "1234567890123." + * Sets save_orig_name to true if the file name has been truncated. + * IN assertions: the input file has already been open (ifd is set) and + * ofname has already been updated if there was an original name. + * OUT assertions: ifd and ofd are closed in case of error. + */ +local int create_outfile() +{ + struct stat ostat; /* stat for ofname */ + int flags = O_WRONLY | O_CREAT | O_EXCL; + + for (;;) { + /* Make sure that ofname is not an existing file */ + if (check_ofname() != OK) { + close(ifd); + return ERROR; + } + /* Create the output file */ + remove_ofname = 1; + ofd = open(ofname, flags, RW_USER); + if (ofd == -1) { + perror(ofname); + close(ifd); + exit_code = ERROR; + return ERROR; + } + + /* Check for name truncation on new file (1234567890123.gz) */ + if (fstat(ofd, &ostat) != 0) { + fprintf(stderr, "%s: ", progname); + perror(ofname); + close(ifd); close(ofd); + unlink(ofname); + exit_code = ERROR; + return ERROR; + } + if (!name_too_long(ofname, &ostat)) return OK; + + if (decompress) { + /* name might be too long if an original name was saved */ + WARN((stderr, "%s: %s: warning, name truncated\n", + progname, ofname)); + return OK; + } + close(ofd); + unlink(ofname); + shorten_name(ofname); + } +} + +/* ======================================================================== + * Use lstat if available, except for -c or -f. Use stat otherwise. + * This allows links when not removing the original file. + */ +local int do_stat(name, sbuf) + char *name; + struct stat *sbuf; +{ + errno = 0; + if (!to_stdout && !force) { + return lstat(name, sbuf); + } + return stat(name, sbuf); +} + +/* ======================================================================== + * Return a pointer to the 'z' suffix of a file name, or NULL. For all + * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are + * accepted suffixes, in addition to the value of the --suffix option. + * ".tgz" is a useful convention for tar.z files on systems limited + * to 3 characters extensions. On such systems, ".?z" and ".??z" are + * also accepted suffixes. For Unix, we do not want to accept any + * .??z suffix as indicating a compressed file; some people use .xyz + * to denote volume data. + * On systems allowing multiple versions of the same file (such as VMS), + * this function removes any version suffix in the given name. + */ +local char *get_suffix(name) + char *name; +{ + int nlen, slen; + char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */ + static char *known_suffixes[] = + {z_suffix, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z", + NULL}; + char **suf = known_suffixes; + + if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */ + + nlen = strlen(name); + if (nlen <= MAX_SUFFIX+2) { + strcpy(suffix, name); + } else { + strcpy(suffix, name+nlen-MAX_SUFFIX-2); + } + strlwr(suffix); + slen = strlen(suffix); + do { + int s = strlen(*suf); + if (slen > s && suffix[slen-s-1] != PATH_SEP + && strequ(suffix + slen - s, *suf)) { + return name+nlen-s; + } + } while (*++suf != NULL); + + return NULL; +} + + +/* ======================================================================== + * Set ifname to the input file name (with a suffix appended if necessary) + * and istat to its stats. For decompression, if no file exists with the + * original name, try adding successively z_suffix, .gz, .z, -z and .Z. + * For MSDOS, we try only z_suffix and z. + * Return OK or ERROR. + */ +local int get_istat(iname, sbuf) + char *iname; + struct stat *sbuf; +{ + int ilen; /* strlen(ifname) */ + static char *suffixes[] = {z_suffix, ".gz", ".z", "-z", ".Z", NULL}; + char **suf = suffixes; + char *s; + + strcpy(ifname, iname); + + /* If input file exists, return OK. */ + if (do_stat(ifname, sbuf) == 0) return OK; + + if (!decompress || errno != ENOENT) { + perror(ifname); + exit_code = ERROR; + return ERROR; + } + /* file.ext doesn't exist, try adding a suffix (after removing any + * version number for VMS). + */ + s = get_suffix(ifname); + if (s != NULL) { + perror(ifname); /* ifname already has z suffix and does not exist */ + exit_code = ERROR; + return ERROR; + } + ilen = strlen(ifname); + if (strequ(z_suffix, ".gz")) suf++; + + /* Search for all suffixes */ + do { + s = *suf; + strcat(ifname, s); + if (do_stat(ifname, sbuf) == 0) return OK; + ifname[ilen] = '\0'; + } while (*++suf != NULL); + + /* No suffix found, complain using z_suffix: */ + strcat(ifname, z_suffix); + perror(ifname); + exit_code = ERROR; + return ERROR; +} + +/* ======================================================================== + * Generate ofname given ifname. Return OK, or WARNING if file must be skipped. + * Sets save_orig_name to true if the file name has been truncated. + */ +local int make_ofname() +{ + char *suff; /* ofname z suffix */ + + strcpy(ofname, ifname); + /* strip a version number if any and get the gzip suffix if present: */ + suff = get_suffix(ofname); + + if (decompress) { + if (suff == NULL) { + /* Whith -t or -l, try all files (even without .gz suffix) + * except with -r (behave as with just -dr). + */ + if (test) return OK; + + /* Avoid annoying messages with -r */ + if (verbose || !quiet) { + WARN((stderr,"%s: %s: unknown suffix -- ignored\n", + progname, ifname)); + } + return WARNING; + } + /* Make a special case for .tgz and .taz: */ + strlwr(suff); + if (strequ(suff, ".tgz") || strequ(suff, ".taz")) { + strcpy(suff, ".tar"); + } else { + *suff = '\0'; /* strip the z suffix */ + } + /* ofname might be changed later if infile contains an original name */ + + } else if (suff != NULL) { + /* Avoid annoying messages with -r (see treat_dir()) */ + if (verbose || !quiet) { + fprintf(stderr, "%s: %s already has %s suffix -- unchanged\n", + progname, ifname, suff); + } + if (exit_code == OK) exit_code = WARNING; + return WARNING; + } else { + save_orig_name = 0; + strcat(ofname, z_suffix); + + } /* decompress ? */ + return OK; +} + + +/* ======================================================================== + * Check the magic number of the input file and update ofname if an + * original name was given and to_stdout is not set. + * Return the compression method, -1 for error, -2 for warning. + * Set inptr to the offset of the next byte to be processed. + * Updates time_stamp if there is one and --no-time is not used. + * This function may be called repeatedly for an input file consisting + * of several contiguous gzip'ed members. + * IN assertions: there is at least one remaining compressed member. + * If the member is a zip file, it must be the only one. + */ +local int get_method() +{ + uch flags; /* compression flags */ + char magic[2]; /* magic header */ + ulg stamp; /* time stamp */ + + /* If --force and --stdout, zcat == cat, so do not complain about + * premature end of file: use try_byte instead of get_byte. + */ + if (force && to_stdout) { + magic[0] = (char)try_byte(); + magic[1] = (char)try_byte(); + /* If try_byte returned EOF, magic[1] == 0xff */ + } else { + magic[0] = (char)get_byte(); + magic[1] = (char)get_byte(); + } + method = -1; /* unknown yet */ + part_nb++; /* number of parts in gzip file */ + header_bytes = 0; + last_member = RECORD_IO; + /* assume multiple members in gzip file except for record oriented I/O */ + + if (memcmp(magic, GZIP_MAGIC, 2) == 0 + || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) { + + method = (int)get_byte(); + if (method != DEFLATED) { + fprintf(stderr, + "%s: %s: unknown method %d -- get newer version of gzip\n", + progname, ifname, method); + exit_code = ERROR; + return -1; + } + work = unzip; + flags = (uch)get_byte(); + + if ((flags & ENCRYPTED) != 0) { + fprintf(stderr, + "%s: %s is encrypted -- get newer version of gzip\n", + progname, ifname); + exit_code = ERROR; + return -1; + } + if ((flags & CONTINUATION) != 0) { + fprintf(stderr, + "%s: %s is a a multi-part gzip file -- get newer version of gzip\n", + progname, ifname); + exit_code = ERROR; + if (force <= 1) return -1; + } + if ((flags & RESERVED) != 0) { + fprintf(stderr, + "%s: %s has flags 0x%x -- get newer version of gzip\n", + progname, ifname, flags); + exit_code = ERROR; + if (force <= 1) return -1; + } + stamp = (ulg)get_byte(); + stamp |= ((ulg)get_byte()) << 8; + stamp |= ((ulg)get_byte()) << 16; + stamp |= ((ulg)get_byte()) << 24; + if (stamp != 0 && !no_time) time_stamp = stamp; + + (void)get_byte(); /* Ignore extra flags for the moment */ + (void)get_byte(); /* Ignore OS type for the moment */ + + if ((flags & CONTINUATION) != 0) { + unsigned part = (unsigned)get_byte(); + part |= ((unsigned)get_byte())<<8; + if (verbose) { + fprintf(stderr,"%s: %s: part number %u\n", + progname, ifname, part); + } + } + if ((flags & EXTRA_FIELD) != 0) { + unsigned len = (unsigned)get_byte(); + len |= ((unsigned)get_byte())<<8; + if (verbose) { + fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n", + progname, ifname, len); + } + while (len--) (void)get_byte(); + } + + /* Get original file name if it was truncated */ + if ((flags & ORIG_NAME) != 0) { + if (no_name || to_stdout || part_nb > 1) { + /* Discard the old name */ + char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */ + do {c=get_byte();} while (c != 0); + } else { + /* Copy the base name. Keep a directory prefix intact. */ + char *p = basename(ofname); + for (;;) { + *p = (char)get_char(); + if (*p++ == '\0') break; + if (p >= ofname+sizeof(ofname)) { + error("corrupted input -- file name too large"); + } + } + } /* no_name || to_stdout */ + } /* ORIG_NAME */ + + /* Discard file comment if any */ + if ((flags & COMMENT) != 0) { + while (get_char() != 0) /* null */ ; + } + if (part_nb == 1) { + header_bytes = inptr + 2*sizeof(long); /* include crc and size */ + } + } else if (force && to_stdout) { /* pass input unchanged */ + method = STORED; + work = copy; + inptr = 0; + last_member = 1; + } + if (method >= 0) return method; + + if (part_nb == 1) { + fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname); + exit_code = ERROR; + return -1; + } else { + WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n", + progname, ifname)); + return -2; + } +} + + +/* ======================================================================== + * Return true if the two stat structures correspond to the same file. + */ +local int same_file(stat1, stat2) + struct stat *stat1; + struct stat *stat2; +{ + return stat1->st_ino == stat2->st_ino + && stat1->st_dev == stat2->st_dev +#ifdef NO_ST_INO + /* Can't rely on st_ino and st_dev, use other fields: */ + && stat1->st_mode == stat2->st_mode + && stat1->st_uid == stat2->st_uid + && stat1->st_gid == stat2->st_gid + && stat1->st_size == stat2->st_size + && stat1->st_atime == stat2->st_atime + && stat1->st_mtime == stat2->st_mtime + && stat1->st_ctime == stat2->st_ctime +#endif + ; +} + +/* ======================================================================== + * Return true if a file name is ambiguous because the operating system + * truncates file names. + */ +local int name_too_long(name, statb) + char *name; /* file name to check */ + struct stat *statb; /* stat buf for this file name */ +{ + int s = strlen(name); + char c = name[s-1]; + struct stat tstat; /* stat for truncated name */ + int res; + + tstat = *statb; /* Just in case OS does not fill all fields */ + name[s-1] = '\0'; + res = stat(name, &tstat) == 0 && same_file(statb, &tstat); + name[s-1] = c; + Trace((stderr, " too_long(%s) => %d\n", name, res)); + return res; +} + +/* ======================================================================== + * Shorten the given name by one character, or replace a .tar extension + * with .tgz. Truncate the last part of the name which is longer than + * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name + * has only parts shorter than MIN_PART truncate the longest part. + * For decompression, just remove the last character of the name. + * + * IN assertion: for compression, the suffix of the given name is z_suffix. + */ +local void shorten_name(name) + char *name; +{ + int len; /* length of name without z_suffix */ + char *trunc = NULL; /* character to be truncated */ + int plen; /* current part length */ + int min_part = MIN_PART; /* current minimum part length */ + char *p; + + len = strlen(name); + if (decompress) { + if (len <= 1) error("name too short"); + name[len-1] = '\0'; + return; + } + p = get_suffix(name); + if (p == NULL) error("can't recover suffix\n"); + *p = '\0'; + save_orig_name = 1; + + /* compress 1234567890.tar to 1234567890.tgz */ + if (len > 4 && strequ(p-4, ".tar")) { + strcpy(p-4, ".tgz"); + return; + } + /* Try keeping short extensions intact: + * 1234.678.012.gz -> 123.678.012.gz + */ + do { + p = strrchr(name, PATH_SEP); + p = p ? p+1 : name; + while (*p) { + plen = strcspn(p, "."); + p += plen; + if (plen > min_part) trunc = p-1; + if (*p) p++; + } + } while (trunc == NULL && --min_part != 0); + + if (trunc != NULL) { + do { + trunc[0] = trunc[1]; + } while (*trunc++); + trunc--; + } else { + trunc = strrchr(name, '.'); + if (trunc == NULL) error("internal error in shorten_name"); + if (trunc[1] == '\0') trunc--; /* force truncation */ + } + strcpy(trunc, z_suffix); +} + +/* ======================================================================== + * If compressing to a file, check if ofname is not ambiguous + * because the operating system truncates names. Otherwise, generate + * a new ofname and save the original name in the compressed file. + * If the compressed file already exists, ask for confirmation. + * The check for name truncation is made dynamically, because different + * file systems on the same OS might use different truncation rules (on SVR4 + * s5 truncates to 14 chars and ufs does not truncate). + * This function returns -1 if the file must be skipped, and + * updates save_orig_name if necessary. + * IN assertions: save_orig_name is already set if ofname has been + * already truncated because of NO_MULTIPLE_DOTS. The input file has + * already been open and istat is set. + */ +local int check_ofname() +{ + struct stat ostat; /* stat for ofname */ + +#ifdef ENAMETOOLONG + /* Check for strictly conforming Posix systems (which return ENAMETOOLONG + * instead of silently truncating filenames). + */ + errno = 0; + while (stat(ofname, &ostat) != 0) { + if (errno != ENAMETOOLONG) return 0; /* ofname does not exist */ + shorten_name(ofname); + } +#else + if (stat(ofname, &ostat) != 0) return 0; +#endif + /* Check for name truncation on existing file. Do this even on systems + * defining ENAMETOOLONG, because on most systems the strict Posix + * behavior is disabled by default (silent name truncation allowed). + */ + if (!decompress && name_too_long(ofname, &ostat)) { + shorten_name(ofname); + if (stat(ofname, &ostat) != 0) return 0; + } + + /* Check that the input and output files are different (could be + * the same by name truncation or links). + */ + if (same_file(&istat, &ostat)) { + if (strequ(ifname, ofname)) { + fprintf(stderr, "%s: %s: cannot %scompress onto itself\n", + progname, ifname, decompress ? "de" : ""); + } else { + fprintf(stderr, "%s: %s and %s are the same file\n", + progname, ifname, ofname); + } + exit_code = ERROR; + return ERROR; + } + /* Ask permission to overwrite the existing file */ + if (!force) { +#if 0 + char response[80]; + strcpy(response,"n"); + fprintf(stderr, "%s: %s already exists;", progname, ofname); + if (foreground && isatty(fileno(stdin))) { + fprintf(stderr, " do you wish to overwrite (y or n)? "); + (void)fgets(response, sizeof(response)-1, stdin); + } + if (tolow(*response) != 'y') { + fprintf(stderr, "\tnot overwritten\n"); +#endif + if (exit_code == OK) exit_code = WARNING; + return ERROR; +#if 0 + } +#endif + } + (void) chmod(ofname, 0777); + if (unlink(ofname)) { + fprintf(stderr, "%s: ", progname); + perror(ofname); + exit_code = ERROR; + return ERROR; + } + return OK; +} + + +/* ======================================================================== + * Set the access and modification times from the given stat buffer. + */ +local void reset_times (name, statb) + char *name; + struct stat *statb; +{ + struct utimbuf timep; + + /* Copy the time stamp */ + timep.actime = statb->st_atime; + timep.modtime = statb->st_mtime; + + /* Some systems (at least OS/2) do not support utime on directories */ + if (utime(name, &timep) && !S_ISDIR(statb->st_mode)) { + WARN((stderr, "%s: ", progname)); + if (!quiet) perror(ofname); + } +} + + +/* ======================================================================== + * Copy modes, times, ownership from input file to output file. + * IN assertion: to_stdout is false. + */ +local void copy_stat(ifstat) + struct stat *ifstat; +{ + if (decompress && time_stamp != 0 && ifstat->st_mtime != time_stamp) { + ifstat->st_mtime = time_stamp; + if (verbose > 1) { + fprintf(stderr, "%s: time stamp restored\n", ofname); + } + } + reset_times(ofname, ifstat); + + /* Copy the protection modes */ + if (chmod(ofname, ifstat->st_mode & 07777)) { + WARN((stderr, "%s: ", progname)); + if (!quiet) perror(ofname); + } + + chown(ofname, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */ + + remove_ofname = 0; + /* It's now safe to remove the input file: */ + (void) chmod(ifname, 0777); + if (unlink(ifname)) { + WARN((stderr, "%s: ", progname)); + if (!quiet) perror(ifname); + } +} + +/* ======================================================================== + * Free all dynamically allocated variables and exit with the given code. + */ +local void do_exit(exitcode) + int exitcode; +{ + static int in_exit = 0; + + if (in_exit) exit(exitcode); + in_exit = 1; + if (env != NULL) free(env), env = NULL; + if (args != NULL) free((char*)args), args = NULL; + FREE(inbuf); + FREE(outbuf); + FREE(d_buf); + FREE(window); + FREE(tab_prefix); + exit(exitcode); +} + +/* ======================================================================== + * Signal and error handler. + */ +void abort_gzip() +{ + if (remove_ofname) { + close(ofd); + unlink (ofname); + } + do_exit(ERROR); +} diff -puN /dev/null usr/gzip/gzip.h --- /dev/null +++ a/usr/gzip/gzip.h @@ -0,0 +1,298 @@ +/* gzip.h -- common declarations for all gzip modules + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +#if defined(__STDC__) || defined(PROTO) +# define OF(args) args +#else +# define OF(args) () +#endif + +#ifdef __STDC__ + typedef void *voidp; +#else + typedef char *voidp; +#endif + +/* I don't like nested includes, but the string and io functions are used + * too often + */ +#include +#include +#define memzero(s, n) memset ((voidp)(s), 0, (n)) + +#define local static + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +/* Return codes from gzip */ +#define OK 0 +#define ERROR 1 +#define WARNING 2 + +/* Compression methods (see algorithm.doc) */ +#define STORED 0 +#define COMPRESSED 1 +#define PACKED 2 +#define LZHED 3 +/* methods 4 to 7 reserved */ +#define DEFLATED 8 +#define MAX_METHODS 9 +extern int method; /* compression method */ + +/* To save memory for 16 bit systems, some arrays are overlaid between + * the various modules: + * deflate: prev+head window d_buf l_buf outbuf + * unlzw: tab_prefix tab_suffix stack inbuf outbuf + * inflate: window inbuf + * unpack: window inbuf prefix_len + * unlzh: left+right window c_table inbuf c_len + * For compression, input is done in window[]. For decompression, output + * is done in window except for unlzw. + */ + +#ifndef INBUFSIZ +# ifdef SMALL_MEM +# define INBUFSIZ 0x2000 /* input buffer size */ +# else +# define INBUFSIZ 0x8000 /* input buffer size */ +# endif +#endif +#define INBUF_EXTRA 64 /* required by unlzw() */ + +#ifndef OUTBUFSIZ +# ifdef SMALL_MEM +# define OUTBUFSIZ 8192 /* output buffer size */ +# else +# define OUTBUFSIZ 16384 /* output buffer size */ +# endif +#endif +#define OUTBUF_EXTRA 2048 /* required by unlzw() */ + +#ifndef DIST_BUFSIZE +# ifdef SMALL_MEM +# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */ +# else +# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ +# endif +#endif + +#ifdef DYN_ALLOC +# define EXTERN(type, array) extern type * near array +# define DECLARE(type, array, size) type * near array +# define ALLOC(type, array, size) { \ + array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \ + if (array == NULL) error("insufficient memory"); \ + } +# define FREE(array) {if (array != NULL) fcfree(array), array=NULL;} +#else +# define EXTERN(type, array) extern type array[] +# define DECLARE(type, array, size) type array[size] +# define ALLOC(type, array, size) +# define FREE(array) +#endif + +EXTERN(uch, inbuf); /* input buffer */ +EXTERN(uch, outbuf); /* output buffer */ +EXTERN(ush, d_buf); /* buffer for distances, see trees.c */ +EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */ +#define tab_suffix window +#ifndef MAXSEG_64K +# define tab_prefix prev /* hash link (see deflate.c) */ +# define head (prev+WSIZE) /* hash head (see deflate.c) */ + EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */ +#else +# define tab_prefix0 prev +# define head tab_prefix1 + EXTERN(ush, tab_prefix0); /* prefix for even codes */ + EXTERN(ush, tab_prefix1); /* prefix for odd codes */ +#endif + +extern unsigned insize; /* valid bytes in inbuf */ +extern unsigned inptr; /* index of next byte to be processed in inbuf */ +extern unsigned outcnt; /* bytes in output buffer */ + +extern long bytes_in; /* number of input bytes */ +extern long bytes_out; /* number of output bytes */ +extern long header_bytes;/* number of bytes in gzip header */ + +#define isize bytes_in +/* for compatibility with old zip sources (to be cleaned) */ + +extern int ifd; /* input file descriptor */ +extern int ofd; /* output file descriptor */ +extern char ifname[]; /* input file name or "stdin" */ +extern char ofname[]; /* output file name or "stdout" */ +extern char *progname; /* program name */ + +extern time_t time_stamp; /* original time stamp (modification time) */ +extern long ifile_size; /* input file size, -1 for devices (debug only) */ + +typedef int file_t; /* Do not use stdio */ +#define NO_FILE (-1) /* in memory compression */ + + +#define PACK_MAGIC "\037\036" /* Magic header for packed files */ +#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ +#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ +#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files*/ +#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +/* internal file attribute */ +#define UNKNOWN 0xffff +#define BINARY 0 +#define ASCII 1 + +#ifndef WSIZE +# define WSIZE 0x8000 /* window size--must be a power of two, and */ +#endif /* at least 32K for zip's deflate method */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +extern int decrypt; /* flag to turn on decryption */ +extern int exit_code; /* program exit code */ +extern int verbose; /* be verbose (-v) */ +extern int quiet; /* be quiet (-q) */ +extern int level; /* compression level */ +extern int test; /* check .z file integrity */ +extern int to_stdout; /* output to stdout (-c) */ +extern int save_orig_name; /* set if original name must be saved */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0)) +#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1)) + +/* put_byte is used for the compressed output, put_ubyte for the + * uncompressed output. However unlzw() uses window for its + * suffix table instead of its output buffer, so it does not use put_ubyte + * (to be cleaned up). + */ +#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\ + flush_outbuf();} +#define put_ubyte(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\ + flush_window();} + +/* Output a 16 bit value, lsb first */ +#define put_short(w) \ +{ if (outcnt < OUTBUFSIZ-2) { \ + outbuf[outcnt++] = (uch) ((w) & 0xff); \ + outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \ + } else { \ + put_byte((uch)((w) & 0xff)); \ + put_byte((uch)((ush)(w) >> 8)); \ + } \ +} + +/* Output a 32 bit value to the bit stream, lsb first */ +#define put_long(n) { \ + put_short((n) & 0xffff); \ + put_short(((ulg)(n)) >> 16); \ +} + +#define seekable() 0 /* force sequential output */ +#define translate_eol 0 /* no option -a yet */ + +#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */ + +/* Macros for getting two-byte and four-byte header values */ +#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) +#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#define WARN(msg) {if (!quiet) fprintf msg ; \ + if (exit_code == OK) exit_code = WARNING;} + + /* in zip.c: */ +extern int zip OF((int in, int out)); +extern int file_read OF((char *buf, unsigned size)); + + /* in unzip.c */ +extern int unzip OF((int in, int out)); +extern int check_zipfile OF((int in)); + + /* in gzip.c */ +void abort_gzip OF((void)); + + /* in deflate.c */ +void lm_init OF((int pack_level, ush *flags)); +ulg deflate OF((void)); + + /* in trees.c */ +void ct_init OF((ush *attr, int *method)); +int ct_tally OF((int dist, int lc)); +ulg flush_block OF((char *buf, ulg stored_len, int eof)); + + /* in bits.c */ +void bi_init OF((file_t zipfile)); +void send_bits OF((int value, int length)); +unsigned bi_reverse OF((unsigned value, int length)); +void bi_windup OF((void)); +void copy_block OF((char *buf, unsigned len, int header)); +extern int (*read_buf) OF((char *buf, unsigned size)); + + /* in util.c: */ +extern int copy OF((int in, int out)); +extern ulg updcrc OF((uch *s, unsigned n)); +extern void clear_bufs OF((void)); +extern int fill_inbuf OF((int eof_ok)); +extern void flush_outbuf OF((void)); +extern void flush_window OF((void)); +extern void write_buf OF((int fd, voidp buf, unsigned cnt)); +extern char *strlwr OF((char *s)); +extern char *basename OF((char *fname)); +extern void make_simple_name OF((char *name)); +extern char *add_envopt OF((int *argcp, char ***argvp, char *env)); +extern void error OF((char *m)); +extern void warn OF((char *a, char *b)); +extern void read_error OF((void)); +extern void write_error OF((void)); +extern void display_ratio OF((long num, long den, FILE *file)); +extern voidp xmalloc OF((unsigned int size)); + + /* in inflate.c */ +extern int inflate OF((void)); + +/* stuff from lzw.h */ +#ifndef BITS +# define BITS 16 +#endif diff -puN /dev/null usr/gzip/inflate.c --- /dev/null +++ a/usr/gzip/inflate.c @@ -0,0 +1,950 @@ +/* inflate.c -- Not copyrighted 1992 by Mark Adler + version c10p1, 10 January 1993 */ + +/* You can do whatever you like with this source file, though I would + prefer that if you modify it and redistribute it that you include + comments to that effect with your name and the date. Thank you. + [The history has been moved to the file ChangeLog.] + */ + +/* + Inflate deflated (PKZIP's method 8 compressed) data. The compression + method searches for as much of the current string of bytes (up to a + length of 258) in the previous 32K bytes. If it doesn't find any + matches (of at least length 3), it codes the next byte. Otherwise, it + codes the length of the matched string and its distance backwards from + the current position. There is a single Huffman code that codes both + single bytes (called "literals") and match lengths. A second Huffman + code codes the distance information, which follows a length code. Each + length or distance code actually represents a base value and a number + of "extra" (sometimes zero) bits to get to add to the base value. At + the end of each deflated block is a special end-of-block (EOB) literal/ + length code. The decoding process is basically: get a literal/length + code; if EOB then done; if a literal, emit the decoded byte; if a + length then get the distance and emit the referred-to bytes from the + sliding window of previously emitted data. + + There are (currently) three kinds of inflate blocks: stored, fixed, and + dynamic. The compressor deals with some chunk of data at a time, and + decides which method to use on a chunk-by-chunk basis. A chunk might + typically be 32K or 64K. If the chunk is uncompressible, then the + "stored" method is used. In this case, the bytes are simply stored as + is, eight bits per byte, with none of the above coding. The bytes are + preceded by a count, since there is no longer an EOB code. + + If the data is compressible, then either the fixed or dynamic methods + are used. In the dynamic method, the compressed data is preceded by + an encoding of the literal/length and distance Huffman codes that are + to be used to decode this block. The representation is itself Huffman + coded, and so is preceded by a description of that code. These code + descriptions take up a little space, and so for small blocks, there is + a predefined set of codes, called the fixed codes. The fixed method is + used if the block codes up smaller that way (usually for quite small + chunks), otherwise the dynamic method is used. In the latter case, the + codes are customized to the probabilities in the current block, and so + can code it much better than the pre-determined fixed codes. + + The Huffman codes themselves are decoded using a mutli-level table + lookup, in order to maximize the speed of decoding plus the speed of + building the decoding tables. See the comments below that precede the + lbits and dbits tuning parameters. + */ + + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarly, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + +#ifdef RCSID +static char rcsid[] = "$Id: inflate.c,v 1.1 2002/08/18 00:59:21 hpa Exp $"; +#endif + +#include +#include + +#include "tailor.h" +#include "gzip.h" +#define slide window + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). + Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16 + means that v is a literal, 16 < e < 32 means that v is a pointer to + the next table, which codes e - 16 bits, and lastly e == 99 indicates + an unused code. If a code with e == 99 is looked up, this implies an + error in the data. */ +struct huft { + uch e; /* number of extra bits or operation */ + uch b; /* number of bits in this code or subcode */ + union { + ush n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } v; +}; + + +/* Function prototypes */ +int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *, + struct huft **, int *)); +int huft_free OF((struct huft *)); +int inflate_codes OF((struct huft *, struct huft *, int, int)); +int inflate_stored OF((void)); +int inflate_fixed OF((void)); +int inflate_dynamic OF((void)); +int inflate_block OF((int *)); +int inflate OF((void)); + + +/* The inflate algorithm uses a sliding 32K byte window on the uncompressed + stream to find repeated byte strings. This is implemented here as a + circular buffer. The index is updated simply by incrementing and then + and'ing with 0x7fff (32K-1). */ +/* It is left to other modules to supply the 32K area. It is assumed + to be usable as if it were declared "uch slide[32768];" or as just + "uch *slide;" and then malloc'ed in the latter case. The definition + must be in unzip.h, included above. */ +/* unsigned wp; current position in slide */ +#define wp outcnt +#define flush_output(w) (wp=(w),flush_window()) + +/* Tables for deflate from PKZIP's appnote.txt. */ +static unsigned border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +static ush cplens[] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* note: see note #13 above about the 258 in this list. */ +static ush cplext[] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ +static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +static ush cpdext[] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed, and are initialized at the beginning of a + routine that uses these macros from a global bit buffer and count. + + If we assume that EOB will be the longest code, then we will never + ask for bits with NEEDBITS that are beyond the end of the stream. + So, NEEDBITS should not read any more bytes than are needed to + meet the request. Then no bytes need to be "returned" to the buffer + at the end of the last block. + + However, this assumption is not true for fixed blocks--the EOB code + is 7 bits, but the other literal/length codes can be 8 or 9 bits. + (The EOB code is shorter than other codes because fixed blocks are + generally short. So, while a block always has an EOB, many other + literal/length codes have a significantly lower probability of + showing up at all.) However, by making the first table have a + lookup of seven bits, the EOB code will be found in that first + lookup, and so will not require that too many bits be pulled from + the stream. + */ + +ulg bb; /* bit buffer */ +unsigned bk; /* bits in bit buffer */ + +ush mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +#ifdef CRYPT + uch cc; +# define NEXTBYTE() \ + (decrypt ? (cc = get_byte(), cc) : get_byte()) +#else +# define NEXTBYTE() (uch)get_byte() +#endif +#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<>=(n);k-=(n);} + + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +int lbits = 9; /* bits in base literal/length lookup table */ +int dbits = 6; /* bits in base distance lookup table */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + + +unsigned hufts; /* track memory usage */ + + +int huft_build(b, n, s, d, e, t, m) +unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ +unsigned n; /* number of codes (assumed <= N_MAX) */ +unsigned s; /* number of simple-valued codes (0..s-1) */ +ush *d; /* list of base values for non-simple codes */ +ush *e; /* list of extra bits for non-simple codes */ +struct huft **t; /* result: starting table */ +int *m; /* maximum lookup bits, returns actual */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + memzero(c, sizeof(c)); + p = b; i = n; + do { + Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), + n-i, *p)); + c[*p]++; /* assume all entries <= BMAX */ + p++; /* Can't combine with above line (Solaris bug) */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? (unsigned)l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == + (struct huft *)NULL) + { + if (h) + huft_free(u[0]); + return 3; /* not enough memory */ + } + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (uch)l; /* bits to dump before this table */ + r.e = (uch)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (uch)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = (ush)(*p); /* simple code is just the value */ + p++; /* one compiler does not like *p++ */ + } + else + { + r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } + } + } + + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + + +int huft_free(t) +struct huft *t; /* table to free */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free((char*)p); + p = q; + } + return 0; +} + + +int inflate_codes(tl, td, bl, bd) +struct huft *tl, *td; /* literal/length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) /* do until end of block */ + { + NEEDBITS((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + slide[w++] = (uch)t->v.n; + Tracevv((stderr, "%c", slide[w-1])); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy */ + NEEDBITS((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + Tracevv((stderr,"\\[%d,%d]", w-d, n)); + + /* do the copy */ + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); +#if !defined(NOMEMCPY) && !defined(DEBUG) + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + Tracevv((stderr, "%c", slide[w-1])); + } while (--e); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + /* done */ + return 0; +} + + + +int inflate_stored() +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + + /* go to byte boundary */ + n = k & 7; + DUMPBITS(n); + + + /* get the length and its complement */ + NEEDBITS(16) + n = ((unsigned)b & 0xffff); + DUMPBITS(16) + NEEDBITS(16) + if (n != (unsigned)((~b) & 0xffff)) + return 1; /* error in compressed data */ + DUMPBITS(16) + + + /* read and output the compressed data */ + while (n--) + { + NEEDBITS(8) + slide[w++] = (uch)b; + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + DUMPBITS(8) + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + return 0; +} + + + +int inflate_fixed() +/* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ +{ + int i; /* temporary variable */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned l[288]; /* length list for huft_build */ + + + /* set up literal table */ + for (i = 0; i < 144; i++) + l[i] = 8; + for (; i < 256; i++) + l[i] = 9; + for (; i < 280; i++) + l[i] = 7; + for (; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + bl = 7; + if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) + return i; + + + /* set up distance table */ + for (i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + bd = 5; + if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) + { + huft_free(tl); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +int inflate_dynamic() +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local bit buffer */ + b = bb; + k = bk; + + + /* read in table lengths */ + NEEDBITS(5) + nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ + DUMPBITS(5) + NEEDBITS(5) + nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ + DUMPBITS(5) + NEEDBITS(4) + nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ + DUMPBITS(4) +#ifdef PKZIP_BUG_WORKAROUND + if (nl > 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + return 1; /* bad lengths */ + + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + + + /* free decoding table for trees */ + huft_free(tl); + + + /* restore the global bit buffer */ + bb = b; + bk = k; + + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) + { + if (i == 1) { + fprintf(stderr, " incomplete literal tree\n"); + huft_free(tl); + } + return i; /* incomplete code set */ + } + bd = dbits; + if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) + { + if (i == 1) { + fprintf(stderr, " incomplete distance tree\n"); +#ifdef PKZIP_BUG_WORKAROUND + i = 0; + } +#else + huft_free(td); + } + huft_free(tl); + return i; /* incomplete code set */ +#endif + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +int inflate_block(e) +int *e; /* last block flag */ +/* decompress an inflated block */ +{ + unsigned t; /* block type */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local bit buffer */ + b = bb; + k = bk; + + + /* read in last block bit */ + NEEDBITS(1) + *e = (int)b & 1; + DUMPBITS(1) + + + /* read in block type */ + NEEDBITS(2) + t = (unsigned)b & 3; + DUMPBITS(2) + + + /* restore the global bit buffer */ + bb = b; + bk = k; + + + /* inflate that block type */ + if (t == 2) + return inflate_dynamic(); + if (t == 0) + return inflate_stored(); + if (t == 1) + return inflate_fixed(); + + + /* bad block type */ + return 2; +} + + + +int inflate() +/* decompress an inflated entry */ +{ + int e; /* last block flag */ + int r; /* result code */ + unsigned h; /* maximum struct huft's malloc'ed */ + + + /* initialize window, bit buffer */ + wp = 0; + bk = 0; + bb = 0; + + + /* decompress until the last block */ + h = 0; + do { + hufts = 0; + if ((r = inflate_block(&e)) != 0) + return r; + if (hufts > h) + h = hufts; + } while (!e); + + /* Undo too much lookahead. The next read will be byte aligned so we + * can discard unused bits in the last meaningful byte. + */ + while (bk >= 8) { + bk -= 8; + inptr--; + } + + /* flush out slide */ + flush_output(wp); + + + /* return success */ +#ifdef DEBUG + fprintf(stderr, "<%u> ", h); +#endif /* DEBUG */ + return 0; +} diff -puN /dev/null usr/gzip/Kbuild --- /dev/null +++ a/usr/gzip/Kbuild @@ -0,0 +1,25 @@ +# +# Kbuild file for gzip +# + +# The gzip executable +static-y := gzip +gzip-y := gzip.o util.o unzip.o inflate.o + +# Additional targets +always := gunzip zcat + +# Optional ZIP support +gzip-$(CONFIG_KLIB_ZIP) += zip.o deflate.o trees.o bits.o +cflags-$(CONFIG_KLIB_ZIP) += -DSUPPORT_ZIP +EXTRA_KLIBCCFLAGS := $(cflags-y) + +# Additionally linked targets +$(obj)/gunzip $(obj)/zcat: $(obj)/gzip + $(call cmd,ln) + +# Cleaning +targets := gzip gzip.g gunzip zcat + +# Targets to install +install-y := gzip gunzip zcat diff -puN /dev/null usr/gzip/README --- /dev/null +++ a/usr/gzip/README @@ -0,0 +1,144 @@ +This is the file README for the gzip distribution, version 1.2.4. + +gzip (GNU zip) is a compression utility designed to be a replacement +for 'compress'. Its main advantages over compress are much better +compression and freedom from patented algorithms. The GNU Project +uses it as the standard compression program for its system. + +gzip currently uses by default the LZ77 algorithm used in zip 1.9 (the +portable pkzip compatible archiver). The gzip format was however +designed to accommodate several compression algorithms. See below +for a comparison of zip and gzip. + +gunzip can currently decompress files created by gzip, compress or +pack. The detection of the input format is automatic. For the +gzip format, gunzip checks a 32 bit CRC. For pack, gunzip checks the +uncompressed length. The 'compress' format was not designed to allow +consistency checks. However gunzip is sometimes able to detect a bad +.Z file because there is some redundancy in the .Z compression format. +If you get an error when uncompressing a .Z file, do not assume that +the .Z file is correct simply because the standard uncompress does not +complain. This generally means that the standard uncompress does not +check its input, and happily generates garbage output. + +gzip produces files with a .gz extension. Previous versions of gzip +used the .z extension, which was already used by the 'pack' +Huffman encoder. gunzip is able to decompress .z files (packed +or gzip'ed). + +Several planned features are not yet supported (see the file TODO). +See the file NEWS for a summary of changes since 0.5. See the file +INSTALL for installation instructions. Some answers to frequently +asked questions are given in the file INSTALL, please read it. (In +particular, please don't ask me once more for an /etc/magic entry.) + +WARNING: on several systems, compiler bugs cause gzip to fail, in +particular when optimization options are on. See the section "Special +targets" at the end of the INSTALL file for a list of known problems. +For all machines, use "make check" to check that gzip was compiled +correctly. Try compiling gzip without any optimization if you have a +problem. + +Please send all comments and bug reports by electronic mail to: + Jean-loup Gailly + +or, if this fails, to bug-gnu-utils@prep.ai.mit.edu. +Bug reports should ideally include: + + * The complete output of "gzip -V" (or the contents of revision.h + if you can't get gzip to compile) + * The hardware and operating system (try "uname -a") + * The compiler used to compile (if it is gcc, use "gcc -v") + * A description of the bug behavior + * The input to gzip, that triggered the bug + +If you send me patches for machines I don't have access to, please test them +very carefully. gzip is used for backups, it must be extremely reliable. + +The package crypt++.el is highly recommended to manipulate gzip'ed +file from emacs. It recognizes automatically encrypted and compressed +files when they are first visited or written. It is available via +anonymous ftp to roebling.poly.edu [128.238.5.31] in /pub/crypt++.el. +The same directory contains also patches to dired, ange-ftp and info. +GNU tar 1.11.2 has a -z option to invoke directly gzip, so you don't have to +patch it. The package ftp.uu.net:/languages/emacs-lisp/misc/jka-compr19.el.Z +also supports gzip'ed files. + +The znew and gzexe shell scripts provided with gzip benefit from +(but do not require) the cpmod utility to transfer file attributes. +It is available by anonymous ftp on gatekeeper.dec.com in +/.0/usenet/comp.sources.unix/volume11/cpmod.Z. + +The sample programs zread.c, sub.c and add.c in subdirectory sample +are provided as examples of useful complements to gzip. Read the +comments inside each source file. The perl script ztouch is also +provided as example (not installed by default since it relies on perl). + + +gzip is free software, you can redistribute it and/or modify it under +the terms of the GNU General Public License, a copy of which is +provided under the name COPYING. The latest version of gzip are always +available by ftp in prep.ai.mit.edu:/pub/gnu, or in any of the prep +mirror sites: + +- sources in gzip-*.tar (or .shar or .tar.gz). +- Solaris 2 executables in sparc-sun-solaris2/gzip-binaries-*.tar +- MSDOS lha self-extracting exe in gzip-msdos-*.exe. Once extracted, + copy gzip.exe to gunzip.exe and zcat.exe, or use "gzip -d" to decompress. + gzip386.exe runs much faster but only on 386 and above; it is compiled with + djgpp 1.10 available in directory omnigate.clarkson.edu:/pub/msdos/djgpp. + +A VMS executable is available in ftp.spc.edu:[.macro32.savesets]gzip-1-*.zip +(use [.macro32]unzip.exe to extract). A PRIMOS executable is available +in ftp.lysator.liu.se:/pub/primos/run/gzip.run. +OS/2 executables (16 and 32 bits versions) are available in +ftp.tu-muenchen.de:/pub/comp/os/os2/archiver/gz*-[16,32].zip + +Some ftp servers can automatically make a tar.Z from a tar file. If +you are getting gzip for the first time, you can ask for a tar.Z file +instead of the much larger tar file. + +Many thanks to those who provided me with bug reports and feedback. +See the files THANKS and ChangeLog for more details. + + + Note about zip vs. gzip: + +The name 'gzip' was a very unfortunate choice, because zip and gzip +are two really different programs, although the actual compression and +decompression sources were written by the same persons. A different +name should have been used for gzip, but it is too late to change now. + +zip is an archiver: it compresses several files into a single archive +file. gzip is a simple compressor: each file is compressed separately. +Both share the same compression and decompression code for the +'deflate' method. unzip can also decompress old zip archives +(implode, shrink and reduce methods). gunzip can also decompress files +created by compress and pack. zip 1.9 and gzip do not support +compression methods other than deflation. (zip 1.0 supports shrink and +implode). Better compression methods may be added in future versions +of gzip. zip will always stick to absolute compatibility with pkzip, +it is thus constrained by PKWare, which is a commercial company. The +gzip header format is deliberately different from that of pkzip to +avoid such a constraint. + +On Unix, gzip is mostly useful in combination with tar. GNU tar +1.11.2 has a -z option to invoke gzip automatically. "tar -z" +compresses better than zip, since gzip can then take advantage of +redundancy between distinct files. The drawback is that you must +scan the whole tar.gz file in order to extract a single file near +the end; unzip can directly seek to the end of the zip file. There +is no overhead when you extract the whole archive anyway. +If a member of a .zip archive is damaged, other files can still +be recovered. If a .tar.gz file is damaged, files beyond the failure +point cannot be recovered. (Future versions of gzip will have +error recovery features.) + +gzip and gunzip are distributed as a single program. zip and unzip +are, for historical reasons, two separate programs, although the +authors of these two programs work closely together in the info-zip +team. zip and unzip are not associated with the GNU project. +The sources are available by ftp in + + oak.oakland.edu:/pub/misc/unix/zip19p1.zip + oak.oakland.edu:/pub/misc/unix/unz50p1.tar-z diff -puN /dev/null usr/gzip/revision.h --- /dev/null +++ a/usr/gzip/revision.h @@ -0,0 +1,11 @@ +/* revision.h -- define the version number + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +#define VERSION "1.2.4" +#define PATCHLEVEL 0 +#define REVDATE "18 Aug 93" + +/* $Id: revision.h,v 1.1 2002/08/18 00:59:21 hpa Exp $ */ diff -puN /dev/null usr/gzip/tailor.h --- /dev/null +++ a/usr/gzip/tailor.h @@ -0,0 +1,50 @@ +/* tailor.h -- target dependent definitions + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +/* The target dependent definitions should be defined here only. + * The target dependent functions should be defined in tailor.c. + */ + +/* $Id: tailor.h,v 1.1 2002/08/18 00:59:21 hpa Exp $ */ + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#define PATH_SEP '/' + +#ifndef casemap +# define casemap(c) (c) +#endif + +#ifndef OPTIONS_VAR +# define OPTIONS_VAR "GZIP" +#endif + +#ifndef Z_SUFFIX +# define Z_SUFFIX ".gz" +#endif + +#define MAX_SUFFIX 30 + +#ifndef MIN_PART +# define MIN_PART 3 + /* keep at least MIN_PART chars between dots in a file name. */ +#endif + +#ifndef RECORD_IO +# define RECORD_IO 0 +#endif + +#ifndef get_char +# define get_char() get_byte() +#endif + +#ifndef put_char +# define put_char(c) put_byte(c) +#endif diff -puN /dev/null usr/gzip/trees.c --- /dev/null +++ a/usr/gzip/trees.c @@ -0,0 +1,1075 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1992-1993 Jean-loup Gailly + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +/* + * PURPOSE + * + * Encode various sets of source values using variable-length + * binary code trees. + * + * DISCUSSION + * + * The PKZIP "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in the ZIP file in a compressed form + * which is itself a Huffman encoding of the lengths of + * all the code strings (in ascending order by source values). + * The actual code strings are reconstructed from the lengths in + * the UNZIP process, as described in the "application note" + * (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program. + * + * REFERENCES + * + * Lynch, Thomas J. + * Data Compression: Techniques and Applications, pp. 53-55. + * Lifetime Learning Publications, 1985. ISBN 0-534-03418-7. + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + * + * INTERFACE + * + * void ct_init (ush *attr, int *methodp) + * Allocate the match buffer, initialize the various tables and save + * the location of the internal file attribute (ascii/binary) and + * method (DEFLATE/STORE) + * + * void ct_tally (int dist, int lc); + * Save the match info and tally the frequency counts. + * + * long flush_block (char *buf, ulg stored_len, int eof) + * Determine the best encoding for the current block: dynamic trees, + * static trees or store, and output the encoded block to the zip + * file. Returns the total compressed length for the file so far. + * + */ + +#include + +#include "tailor.h" +#include "gzip.h" + +#ifdef RCSID +static char rcsid[] = "$Id: trees.c,v 1.1 2002/08/18 00:59:21 hpa Exp $"; +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + + +local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#ifndef LIT_BUFSIZE +# ifdef SMALL_MEM +# define LIT_BUFSIZE 0x2000 +# else +# ifdef MEDIUM_MEM +# define LIT_BUFSIZE 0x4000 +# else +# define LIT_BUFSIZE 0x8000 +# endif +# endif +#endif +#ifndef DIST_BUFSIZE +# define DIST_BUFSIZE LIT_BUFSIZE +#endif +/* Sizes of match buffers for literals/lengths and distances. There are + * 4 reasons for limiting LIT_BUFSIZE to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input data is + * still in the window so we can still emit a stored block even when input + * comes from standard input. (This can also be done for all blocks if + * LIT_BUFSIZE is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting trees + * more frequently. + * - I can't count above 4 + * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save + * memory at the expense of compression). Some optimizations would be possible + * if we rely on DIST_BUFSIZE == LIT_BUFSIZE. + */ +#if LIT_BUFSIZE > INBUFSIZ + error cannot overlay l_buf and inbuf +#endif + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +/* =========================================================================== + * Local data + */ + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +local ct_data dyn_ltree[HEAP_SIZE]; /* literal and length tree */ +local ct_data dyn_dtree[2*D_CODES+1]; /* distance tree */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see ct_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +local ct_data bl_tree[2*BL_CODES+1]; +/* Huffman tree for the bit lengths */ + +typedef struct tree_desc { + ct_data *dyn_tree; /* the dynamic tree */ + ct_data *static_tree; /* corresponding static tree or NULL */ + int *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ + int max_code; /* largest code with non zero frequency */ +} tree_desc; + +local tree_desc l_desc = +{dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0}; + +local tree_desc d_desc = +{dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0}; + +local tree_desc bl_desc = +{bl_tree, (ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0}; + + +local ush bl_count[MAX_BITS+1]; +/* number of codes at each bit length for an optimal tree */ + +local uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +local int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ +local int heap_len; /* number of elements in the heap */ +local int heap_max; /* element of largest frequency */ +/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + +local uch depth[2*L_CODES+1]; +/* Depth of each subtree used as tie breaker for trees of equal frequency */ + +local uch length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local uch dist_code[512]; +/* distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#define l_buf inbuf +/* DECLARE(uch, l_buf, LIT_BUFSIZE); buffer for literals or lengths */ + +/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */ + +local uch flag_buf[(LIT_BUFSIZE/8)]; +/* flag_buf is a bit array distinguishing literals from lengths in + * l_buf, thus indicating the presence or absence of a distance. + */ + +local unsigned last_lit; /* running index in l_buf */ +local unsigned last_dist; /* running index in d_buf */ +local unsigned last_flags; /* running index in flag_buf */ +local uch flags; /* current flags not yet saved in flag_buf */ +local uch flag_bit; /* current bit used in flags */ +/* bits are filled in flags starting at bit 0 (least significant). + * Note: these flags are overkill in the current code since we don't + * take advantage of DIST_BUFSIZE == LIT_BUFSIZE. + */ + +local ulg opt_len; /* bit length of current block with optimal trees */ +local ulg static_len; /* bit length of current block with static trees */ + +local ulg compressed_len; /* total bit length of compressed file */ + +local ulg input_len; /* total byte length of input file */ +/* input_len is for debugging only since we can get it by other means. */ + +ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */ +int *file_method; /* pointer to DEFLATE or STORE */ + +#ifdef DEBUG +extern ulg bits_sent; /* bit length of the compressed data */ +extern long isize; /* byte length of input file */ +#endif + +extern long block_start; /* window offset of current block */ +extern unsigned strstart; /* window offset of current string */ + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void init_block OF((void)); +local void pqdownheap OF((ct_data *tree, int k)); +local void gen_bitlen OF((tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code)); +local void build_tree OF((tree_desc *desc)); +local void scan_tree OF((ct_data *tree, int max_code)); +local void send_tree OF((ct_data *tree, int max_code)); +local int build_bl_tree OF((void)); +local void send_all_trees OF((int lcodes, int dcodes, int blcodes)); +local void compress_block OF((ct_data *ltree, ct_data *dtree)); +local void set_file_type OF((void)); + + +#ifndef DEBUG +# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(c, tree) \ + { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(tree[c].Code, tree[c].Len); } +#endif + +#define d_code(dist) \ + ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. dist_code[256] and dist_code[257] are never + * used. + */ + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Allocate the match buffer, initialize the various tables and save the + * location of the internal file attribute (ascii/binary) and method + * (DEFLATE/STORE). + */ +void ct_init(attr, methodp) + ush *attr; /* pointer to internal file attribute */ + int *methodp; /* pointer to compression method */ +{ + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + + file_type = attr; + file_method = methodp; + compressed_len = input_len = 0L; + + if (static_dtree[0].Len != 0) return; /* ct_init already called */ + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "ct_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse(n, 5); + } + + /* Initialize the first block of the first file: */ + init_block(); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block() +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0; + + dyn_ltree[END_BLOCK].Freq = 1; + opt_len = static_len = 0L; + last_lit = last_dist = last_flags = 0; + flags = 0; flag_bit = 1; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(tree, top) \ +{\ + top = heap[SMALLEST]; \ + heap[SMALLEST] = heap[heap_len--]; \ + pqdownheap(tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(tree, k) + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = heap[k]; + int j = k << 1; /* left son of k */ + while (j <= heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < heap_len && smaller(tree, heap[j+1], heap[j])) j++; + + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, heap[j])) break; + + /* Exchange v with the smallest son */ + heap[k] = heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(desc) + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int *extra = desc->extra_bits; + int base = desc->extra_base; + int max_code = desc->max_code; + int max_length = desc->max_length; + ct_data *stree = desc->static_tree; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[heap[heap_max]].Len = 0; /* root of the heap */ + + for (h = heap_max+1; h < HEAP_SIZE; h++) { + n = heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + opt_len += (ulg)f * (bits + xbits); + if (stree) static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (bl_count[bits] == 0) bits--; + bl_count[bits]--; /* move one leaf down the tree */ + bl_count[bits+1] += 2; /* move one overflow item as its brother */ + bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = bl_count[bits]; + while (n != 0) { + m = heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + ct_data *stree = desc->static_tree; + int elems = desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node = elems; /* next internal node of the tree */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + heap_len = 0, heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + heap[++heap_len] = max_code = n; + depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (heap_len < 2) { + int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0); + tree[new].Freq = 1; + depth[new] = 0; + opt_len--; if (stree) static_len -= stree[new].Len; + /* new is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + pqremove(tree, n); /* n = node of least frequency */ + m = heap[SMALLEST]; /* m = node of next least frequency */ + + heap[--heap_max] = n; /* keep the nodes sorted by frequency */ + heap[--heap_max] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + depth[node] = (uch) (MAX(depth[n], depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + heap[SMALLEST] = node++; + pqdownheap(tree, SMALLEST); + + } while (heap_len >= 2); + + heap[--heap_max] = heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen((tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. Updates opt_len to take into account the repeat + * counts. (The contribution of the bit length codes will be added later + * during the construction of bl_tree.) + */ +local void scan_tree (tree, max_code) + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) bl_tree[curlen].Freq++; + bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + bl_tree[REPZ_3_10].Freq++; + } else { + bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (tree, max_code) + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(curlen, bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(curlen, bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(REP_3_6, bl_tree); send_bits(count-3, 2); + + } else if (count <= 10) { + send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3); + + } else { + send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree() +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree((ct_data *)dyn_ltree, l_desc.max_code); + scan_tree((ct_data *)dyn_dtree, d_desc.max_code); + + /* Build the bit length tree: */ + build_tree((tree_desc *)(&bl_desc)); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(lcodes, dcodes, blcodes) + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(dcodes-1, 5); + send_bits(blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", bits_sent)); + + send_tree((ct_data *)dyn_ltree, lcodes-1); /* send the literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", bits_sent)); + + send_tree((ct_data *)dyn_dtree, dcodes-1); /* send the distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", bits_sent)); +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. This function + * returns the total compressed length for the file so far. + */ +ulg flush_block(buf, stored_len, eof) + char *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex; /* index of last bit length code of non zero freq */ + + flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */ + + /* Check if the file is ascii or binary */ + if (*file_type == (ush)UNKNOWN) set_file_type(); + + /* Construct the literal and distance trees */ + build_tree((tree_desc *)(&l_desc)); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len)); + + build_tree((tree_desc *)(&d_desc)); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(); + + /* Determine the best encoding. Compute first the block length in bytes */ + opt_lenb = (opt_len+3+7)>>3; + static_lenb = (static_len+3+7)>>3; + input_len += stored_len; /* for debugging only */ + + Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", + opt_lenb, opt_len, static_lenb, static_len, stored_len, + last_lit, last_dist)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + /* If compression failed and this is the first and last block, + * and if the zip file can be seeked (to rewrite the local header), + * the whole file is transformed into a stored file: + */ +#ifdef FORCE_METHOD + if (level == 1 && eof && compressed_len == 0L) { /* force stored file */ +#else + if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) { +#endif + /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ + if (buf == (char*)0) error ("block vanished"); + + copy_block(buf, (unsigned)stored_len, 0); /* without header */ + compressed_len = stored_len << 3; + *file_method = STORED; + +#ifdef FORCE_METHOD + } else if (level == 2 && buf != (char*)0) { /* force stored block */ +#else + } else if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + send_bits((STORED_BLOCK<<1)+eof, 3); /* send block type */ + compressed_len = (compressed_len + 3 + 7) & ~7L; + compressed_len += (stored_len + 4) << 3; + + copy_block(buf, (unsigned)stored_len, 1); /* with header */ + +#ifdef FORCE_METHOD + } else if (level == 3) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits((STATIC_TREES<<1)+eof, 3); + compress_block((ct_data *)static_ltree, (ct_data *)static_dtree); + compressed_len += 3 + static_len; + } else { + send_bits((DYN_TREES<<1)+eof, 3); + send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); + compress_block((ct_data *)dyn_ltree, (ct_data *)dyn_dtree); + compressed_len += 3 + opt_len; + } + Assert (compressed_len == bits_sent, "bad compressed size"); + init_block(); + + if (eof) { + Assert (input_len == isize, "bad input size"); + bi_windup(); + compressed_len += 7; /* align on byte boundary */ + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", compressed_len>>3, + compressed_len-7*eof)); + + return compressed_len >> 3; +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ct_tally (dist, lc) + int dist; /* distance of matched string */ + int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + l_buf[last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + dyn_ltree[lc].Freq++; + } else { + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match"); + + dyn_ltree[length_code[lc]+LITERALS+1].Freq++; + dyn_dtree[d_code(dist)].Freq++; + + d_buf[last_dist++] = (ush)dist; + flags |= flag_bit; + } + flag_bit <<= 1; + + /* Output the flags if they fill a byte: */ + if ((last_lit & 7) == 0) { + flag_buf[last_flags++] = flags; + flags = 0, flag_bit = 1; + } + /* Try to guess if it is profitable to stop the current block here */ + if (level > 2 && (last_lit & 0xfff) == 0) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)last_lit*8L; + ulg in_length = (ulg)strstart-block_start; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]); + } + out_length >>= 3; + Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", + last_lit, last_dist, in_length, out_length, + 100L - out_length*100L/in_length)); + if (last_dist < last_lit/2 && out_length < in_length/2) return 1; + } + return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE); + /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(ltree, dtree) + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned dx = 0; /* running index in d_buf */ + unsigned fx = 0; /* running index in flag_buf */ + uch flag = 0; /* current flags */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (last_lit != 0) do { + if ((lx & 7) == 0) flag = flag_buf[fx++]; + lc = l_buf[lx++]; + if ((flag & 1) == 0) { + send_code(lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = length_code[lc]; + send_code(code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(lc, extra); /* send the extra length bits */ + } + dist = d_buf[dx++]; + /* Here, dist is the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + flag >>= 1; + } while (lx < last_lit); + + send_code(END_BLOCK, ltree); +} + +/* =========================================================================== + * Set the file type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_file_type() +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += dyn_ltree[n++].Freq; + *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII; + if (*file_type == BINARY && translate_eol) { + warn("-l used on binary file", ""); + } +} diff -puN /dev/null usr/gzip/unzip.c --- /dev/null +++ a/usr/gzip/unzip.c @@ -0,0 +1,77 @@ +/* unzip.c -- decompress files in gzip or pkzip format. + * Copyright (C) 1992-1993 Jean-loup Gailly + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + * + * The code in this file is derived from the file funzip.c written + * and put in the public domain by Mark Adler. + */ + +/* + This version can extract files in gzip format. + Only the first entry is extracted, and it has to be + either deflated or stored. + */ + +#ifdef RCSID +static char rcsid[] = "$Id: unzip.c,v 1.1 2002/08/18 00:59:21 hpa Exp $"; +#endif + +#include "tailor.h" +#include "gzip.h" + +/* =========================================================================== + * Unzip in to out. This routine works on gzip files only. + * + * IN assertions: the buffer inbuf contains already the beginning of + * the compressed data, from offsets inptr to insize-1 included. + * The magic header has already been checked. The output buffer is cleared. + */ +int unzip(in, out) + int in, out; /* input and output file descriptors */ +{ + ulg orig_crc = 0; /* original crc */ + ulg orig_len = 0; /* original uncompressed length */ + int n; + uch buf[8]; /* extended local header */ + + ifd = in; + ofd = out; + + updcrc(NULL, 0); /* initialize crc */ + + /* Decompress */ + if (method == DEFLATED) { + + int res = inflate(); + + if (res == 3) { + error("out of memory"); + } else if (res != 0) { + error("invalid compressed data--format violated"); + } + + } else { + error("internal error, invalid method"); + } + + /* Get the crc and original length */ + /* crc32 (see algorithm.doc) + * uncompressed input size modulo 2^32 + */ + for (n = 0; n < 8; n++) { + buf[n] = (uch)get_byte(); /* may cause an error if EOF */ + } + orig_crc = LG(buf); + orig_len = LG(buf+4); + + /* Validate decompression */ + if (orig_crc != updcrc(outbuf, 0)) { + error("invalid compressed data--crc error"); + } + if (orig_len != (ulg)bytes_out) { + error("invalid compressed data--length error"); + } + + return OK; +} diff -puN /dev/null usr/gzip/util.c --- /dev/null +++ a/usr/gzip/util.c @@ -0,0 +1,372 @@ +/* util.c -- utility functions for gzip support + * Copyright (C) 1992-1993 Jean-loup Gailly + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +#ifdef RCSID +static char rcsid[] = "$Id: util.c,v 1.1 2002/08/18 00:59:21 hpa Exp $"; +#endif + +#include +#include +#include + +#include "tailor.h" + +#include +#include +#include + +#include "gzip.h" + +extern ulg crc_32_tab[]; /* crc table, defined below */ + +/* =========================================================================== + * Copy input to output unchanged: zcat == cat with --force. + * IN assertion: insize bytes have already been read in inbuf. + */ +int copy(in, out) + int in, out; /* input and output file descriptors */ +{ + errno = 0; + while (insize != 0 && (int)insize != EOF) { + write_buf(out, (char*)inbuf, insize); + bytes_out += insize; + insize = read(in, (char*)inbuf, INBUFSIZ); + } + if ((int)insize == EOF && errno != 0) { + read_error(); + } + bytes_in = bytes_out; + return OK; +} + +/* =========================================================================== + * Run a set of bytes through the crc shift register. If s is a NULL + * pointer, then initialize the crc shift register contents instead. + * Return the current crc in either case. + */ +ulg updcrc(s, n) + uch *s; /* pointer to bytes to pump through */ + unsigned n; /* number of bytes in s[] */ +{ + register ulg c; /* temporary variable */ + + static ulg crc = (ulg)0xffffffffL; /* shift register contents */ + + if (s == NULL) { + c = 0xffffffffL; + } else { + c = crc; + if (n) do { + c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); + } while (--n); + } + crc = c; + return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ +} + +/* =========================================================================== + * Clear input and output buffers + */ +void clear_bufs() +{ + outcnt = 0; + insize = inptr = 0; + bytes_in = bytes_out = 0L; +} + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty. + */ +int fill_inbuf(eof_ok) + int eof_ok; /* set if EOF acceptable as a result */ +{ + int len; + + /* Read as much as possible */ + insize = 0; + errno = 0; + do { + len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize); + if (len == 0 || len == EOF) break; + insize += len; + } while (insize < INBUFSIZ); + + if (insize == 0) { + if (eof_ok) return EOF; + read_error(); + } + bytes_in += (ulg)insize; + inptr = 1; + return inbuf[0]; +} + +/* =========================================================================== + * Write the output buffer outbuf[0..outcnt-1] and update bytes_out. + * (used for the compressed data only) + */ +void flush_outbuf() +{ + if (outcnt == 0) return; + + write_buf(ofd, (char *)outbuf, outcnt); + bytes_out += (ulg)outcnt; + outcnt = 0; +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +void flush_window() +{ + if (outcnt == 0) return; + updcrc(window, outcnt); + + if (!test) { + write_buf(ofd, (char *)window, outcnt); + } + bytes_out += (ulg)outcnt; + outcnt = 0; +} + +/* =========================================================================== + * Does the same as write(), but also handles partial pipe writes and checks + * for error return. + */ +void write_buf(fd, buf, cnt) + int fd; + voidp buf; + unsigned cnt; +{ + unsigned n; + + while ((n = write(fd, buf, cnt)) != cnt) { + if (n == (unsigned)(-1)) { + write_error(); + } + cnt -= n; + buf = (voidp)((char*)buf+n); + } +} + +/* ======================================================================== + * Put string s in lower case, return s. + */ +char *strlwr(s) + char *s; +{ + char *t; + for (t = s; *t; t++) *t = tolow(*t); + return s; +} + +/* ======================================================================== + * Return the base name of a file (remove any directory prefix and + * any version suffix). For systems with file names that are not + * case sensitive, force the base name to lower case. + */ +char *basename(fname) + char *fname; +{ + char *p; + + if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1; + if (casemap('A') == 'a') strlwr(fname); + return fname; +} + +/* ======================================================================== + * Add an environment variable (if any) before argv, and update argc. + * Return the expanded environment variable to be freed later, or NULL + * if no options were added to argv. + */ +#define SEPARATOR " \t" /* separators in env variable */ + +char *add_envopt(argcp, argvp, env) + int *argcp; /* pointer to argc */ + char ***argvp; /* pointer to argv */ + char *env; /* name of environment variable */ +{ + char *p; /* running pointer through env variable */ + char **oargv; /* runs through old argv array */ + char **nargv; /* runs through new argv array */ + int oargc = *argcp; /* old argc */ + int nargc = 0; /* number of arguments in env variable */ + + env = (char*)getenv(env); + if (env == NULL) return NULL; + + p = (char*)xmalloc(strlen(env)+1); + env = strcpy(p, env); /* keep env variable intact */ + + for (p = env; *p; nargc++ ) { /* move through env */ + p += strspn(p, SEPARATOR); /* skip leading separators */ + if (*p == '\0') break; + + p += strcspn(p, SEPARATOR); /* find end of word */ + if (*p) *p++ = '\0'; /* mark it */ + } + if (nargc == 0) { + free(env); + return NULL; + } + *argcp += nargc; + /* Allocate the new argv array, with an extra element just in case + * the original arg list did not end with a NULL. + */ + nargv = (char**)calloc(*argcp+1, sizeof(char *)); + if (nargv == NULL) error("out of memory"); + oargv = *argvp; + *argvp = nargv; + + /* Copy the program name first */ + if (oargc-- < 0) error("argc<=0"); + *(nargv++) = *(oargv++); + + /* Then copy the environment args */ + for (p = env; nargc > 0; nargc--) { + p += strspn(p, SEPARATOR); /* skip separators */ + *(nargv++) = p; /* store start */ + while (*p++) ; /* skip over word */ + } + + /* Finally copy the old args and add a NULL (usual convention) */ + while (oargc--) *(nargv++) = *(oargv++); + *nargv = NULL; + return env; +} + +/* ======================================================================== + * Error handlers. + */ +void error(m) + char *m; +{ + fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m); + abort_gzip(); +} + +void warn(a, b) + char *a, *b; /* message strings juxtaposed in output */ +{ + WARN((stderr, "%s: %s: warning: %s%s\n", progname, ifname, a, b)); +} + +void read_error() +{ + fprintf(stderr, "\n%s: ", progname); + if (errno != 0) { + perror(ifname); + } else { + fprintf(stderr, "%s: unexpected end of file\n", ifname); + } + abort_gzip(); +} + +void write_error() +{ + fprintf(stderr, "\n%s: ", progname); + perror(ofname); + abort_gzip(); +} + +/* ======================================================================== + * Display compression ratio on the given stream on 6 characters. + */ +void display_ratio(num, den, file) + long num; + long den; + FILE *file; +{ + long ratio; /* 1000 times the compression ratio */ + char sign; + + if (den == 0) { + ratio = 0; /* no compression */ + } else if (den < 2147483L) { /* (2**31 -1)/1000 */ + ratio = 1000L*num/den; + } else { + ratio = num/(den/1000L); + } + if (ratio < 0) { + sign = '-'; + ratio = -ratio; + } else { + sign = ' '; + } + fprintf(file, "%c%2ld.%1ld%%", sign, ratio / 10L, ratio % 10L); +} + + +/* ======================================================================== + * Semi-safe malloc -- never returns NULL. + */ +voidp xmalloc (size) + unsigned size; +{ + voidp cp = (voidp)malloc (size); + + if (cp == NULL) error("out of memory"); + return cp; +} + +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by makecrc.c) + */ +ulg crc_32_tab[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; diff -puN /dev/null usr/gzip/zip.c --- /dev/null +++ a/usr/gzip/zip.c @@ -0,0 +1,110 @@ +/* zip.c -- compress files to the gzip or pkzip format + * Copyright (C) 1992-1993 Jean-loup Gailly + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ + +#ifdef RCSID +static char rcsid[] = "$Id: zip.c,v 1.1 2002/08/18 00:59:21 hpa Exp $"; +#endif + +#include +#include +#include +#include + +#include "tailor.h" +#include "gzip.h" + +local ulg crc; /* crc on uncompressed file data */ + +/* =========================================================================== + * Deflate in to out. + * IN assertions: the input and output buffers are cleared. + * The variables time_stamp and save_orig_name are initialized. + */ +int zip(in, out) + int in, out; /* input and output file descriptors */ +{ + uch flags = 0; /* general purpose bit flags */ + ush attr = 0; /* ascii/binary flag */ + ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */ + + ifd = in; + ofd = out; + outcnt = 0; + + /* Write the header to the gzip file. See algorithm.doc for the format */ + + method = DEFLATED; + put_byte(GZIP_MAGIC[0]); /* magic header */ + put_byte(GZIP_MAGIC[1]); + put_byte(DEFLATED); /* compression method */ + + if (save_orig_name) { + flags |= ORIG_NAME; + } + put_byte(flags); /* general flags */ + put_long(time_stamp); + + /* Write deflated file to zip file */ + crc = updcrc(0, 0); + + bi_init(out); + ct_init(&attr, &method); + lm_init(level, &deflate_flags); + + put_byte((uch)deflate_flags); /* extra flags */ + put_byte(OS_CODE); /* OS identifier */ + + if (save_orig_name) { + char *p = basename(ifname); /* Don't save the directory part. */ + do { + put_char(*p); + } while (*p++); + } + header_bytes = (long)outcnt; + + (void)deflate(); + +#if !defined(NO_SIZE_CHECK) && !defined(RECORD_IO) + /* Check input size (but not in VMS -- variable record lengths mess it up) + * and not on MSDOS -- diet in TSR mode reports an incorrect file size) + */ + if (ifile_size != -1L && isize != (ulg)ifile_size) { + Trace((stderr, " actual=%ld, read=%ld ", ifile_size, isize)); + fprintf(stderr, "%s: %s: file size changed while zipping\n", + progname, ifname); + } +#endif + + /* Write the crc and uncompressed size */ + put_long(crc); + put_long(isize); + header_bytes += 2*sizeof(long); + + flush_outbuf(); + return OK; +} + + +/* =========================================================================== + * Read a new buffer from the current input file, perform end-of-line + * translation, and update the crc and input file size. + * IN assertion: size >= 2 (for end-of-line translation) + */ +int file_read(buf, size) + char *buf; + unsigned size; +{ + unsigned len; + + Assert(insize == 0, "inbuf not empty"); + + len = read(ifd, buf, size); + if (len == (unsigned)(-1) || len == 0) return (int)len; + + crc = updcrc((uch*)buf, len); + isize += (ulg)len; + return (int)len; +} diff -puN /dev/null usr/include/alloca.h --- /dev/null +++ a/usr/include/alloca.h @@ -0,0 +1,12 @@ +/* + * alloca.h + * + * Just call the builtin alloca() function + */ + +#ifndef _ALLOCA_H +#define _ALLOCA_H + +#define alloca(size) __builtin_alloca(size) + +#endif /* _ALLOCA_H */ diff -puN /dev/null usr/include/arch/alpha/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/alpha/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/alpha/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +#define _KLIBC_USE_RT_SIG 1 +#define _KLIBC_STATFS_F_TYPE_64 0 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/alpha/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/alpha/klibc/archsetjmp.h @@ -0,0 +1,33 @@ +/* + * arch/alpha/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __s0; + unsigned long __s1; + unsigned long __s2; + unsigned long __s3; + unsigned long __s4; + unsigned long __s5; + unsigned long __fp; + unsigned long __ra; + unsigned long __gp; + unsigned long __sp; + + unsigned long __f2; + unsigned long __f3; + unsigned long __f4; + unsigned long __f5; + unsigned long __f6; + unsigned long __f7; + unsigned long __f8; + unsigned long __f9; +}; + +/* Must be an array so it will decay to a pointer when a function is called */ +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff -puN /dev/null usr/include/arch/alpha/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/alpha/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/alpha/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/alpha/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/alpha/klibc/archstat.h @@ -0,0 +1,28 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); + unsigned long st_ino; + __stdev64 (st_rdev); + long st_size; + unsigned long st_blocks; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_blksize; + unsigned int st_nlink; + unsigned int __pad0; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long __unused[3]; +}; + +#endif diff -puN /dev/null usr/include/arch/alpha/machine/asm.h --- /dev/null +++ a/usr/include/arch/alpha/machine/asm.h @@ -0,0 +1,44 @@ +/* + * machine/asm.h + */ + +#ifndef _MACHINE_ASM_H +#define _MACHINE_ASM_H + +/* Standard aliases for Alpha register names */ + +#define v0 $0 +#define t0 $1 +#define t1 $2 +#define t2 $3 +#define t3 $4 +#define t4 $5 +#define t5 $6 +#define t6 $7 +#define t7 $8 +#define s0 $9 +#define s1 $10 +#define s2 $11 +#define s3 $12 +#define s4 $13 +#define s5 $14 +#define fp $15 +#define a0 $16 +#define a1 $17 +#define a2 $18 +#define a3 $19 +#define a4 $20 +#define a5 $21 +#define t8 $22 +#define t9 $23 +#define t10 $24 +#define t11 $25 +#define ra $26 +#define t12 $27 /* t12 and pv are both used for $27 */ +#define pv $27 /* t12 and pv are both used for $27 */ +#define at $28 +#define gp $29 +#define sp $30 +#define zero $31 + +#endif /* _MACHINE_ASM_H */ diff -puN /dev/null usr/include/arch/arm/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/arm/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/arm/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* All defaults */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/arm/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/arm/klibc/archsetjmp.h @@ -0,0 +1,14 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int regs[10]; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/arm/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/arm/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/arm/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/arm/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/arm/klibc/archstat.h @@ -0,0 +1,40 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + * Note: The kernel zero's the padded region because glibc might read them + * in the hope that the kernel has stretched to using larger sizes. + */ + +struct stat { + __stdev64 (st_dev); + unsigned char __pad0[4]; + + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + __stdev64 (st_rdev); + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long st_ino; +}; + +#endif diff -puN /dev/null usr/include/arch/arm/klibc/asmmacros.h --- /dev/null +++ a/usr/include/arch/arm/klibc/asmmacros.h @@ -0,0 +1,30 @@ +/* + * usr/include/arch/arm/klibc/asmmacros.h + * + * Assembly macros used by ARM system call stubs + */ + +#ifndef _KLIBC_ASMMACROS_H +#define _KLIBC_ASMMACROS_H + +/* An immediate in ARM can be any 8-bit value rotated by an even number of bits */ + +#define ARM_VALID_IMM(x) \ + ((((x) & ~0x000000ff) == 0) || \ + (((x) & ~0x000003fc) == 0) || \ + (((x) & ~0x00000ff0) == 0) || \ + (((x) & ~0x00003fc0) == 0) || \ + (((x) & ~0x0000ff00) == 0) || \ + (((x) & ~0x0003fc00) == 0) || \ + (((x) & ~0x000ff000) == 0) || \ + (((x) & ~0x003fc000) == 0) || \ + (((x) & ~0x00ff0000) == 0) || \ + (((x) & ~0x03fc0000) == 0) || \ + (((x) & ~0x0ff00000) == 0) || \ + (((x) & ~0x3fc00000) == 0) || \ + (((x) & ~0xff000000) == 0) || \ + (((x) & ~0xfc000003) == 0) || \ + (((x) & ~0xf000000f) == 0) || \ + (((x) & ~0xc000003f) == 0)) + +#endif /* _KLIBC_ASMMACROS_H */ diff -puN /dev/null usr/include/arch/cris/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/cris/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/cris/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* cris uses 13 as the page shift factor for sys_mmap2 */ +#define _KLIBC_MMAP2_SHIFT 13 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/cris/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/cris/klibc/archsetjmp.h @@ -0,0 +1,24 @@ +/* + * arch/cris/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __r0; + unsigned long __r1; + unsigned long __r2; + unsigned long __r3; + unsigned long __r4; + unsigned long __r5; + unsigned long __r6; + unsigned long __r7; + unsigned long __r8; + unsigned long __sp; + unsigned long __srp; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff -puN /dev/null usr/include/arch/cris/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/cris/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/cris/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/cris/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/cris/klibc/archstat.h @@ -0,0 +1,39 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat { + __stdev64 (st_dev); + unsigned char __pad0[4]; + + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + __stdev64 (st_rdev); + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long st_ino; +}; + +#endif diff -puN /dev/null usr/include/arch/i386/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/i386/klibc/archconfig.h @@ -0,0 +1,19 @@ +/* + * include/arch/i386/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* On i386, only half the signals are accessible using the legacy calls. */ +#define _KLIBC_USE_RT_SIG 1 + +/* The stock i386 kernel is fine, but a whole string of Fedora kernels + had a broken default restorer. It's easier to enable this here. */ +#define _KLIBC_NEEDS_SA_RESTORER 1 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/i386/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/i386/klibc/archsetjmp.h @@ -0,0 +1,19 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int __ebx; + unsigned int __esp; + unsigned int __ebp; + unsigned int __esi; + unsigned int __edi; + unsigned int __eip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/i386/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/i386/klibc/archsignal.h @@ -0,0 +1,114 @@ +/* + * arch/i386/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +/* The in-kernel headers for i386 still have libc5 + crap in them. Reconsider using + when/if it gets cleaned up; for now, duplicate + the definitions here. */ + +#define _NSIG 64 +#define _NSIG_BPW 32 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +#define SIGRTMIN 32 +#define SIGRTMAX (_NSIG-1) + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001u +#define SA_NOCLDWAIT 0x00000002u +#define SA_SIGINFO 0x00000004u +#define SA_ONSTACK 0x08000000u +#define SA_RESTART 0x10000000u +#define SA_NODEFER 0x40000000u +#define SA_RESETHAND 0x80000000u + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ + +#define SA_RESTORER 0x04000000 + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +#include + +/* This uses gcc anonymous union support... */ +struct siginfo; + +struct sigaction { + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, struct siginfo *, void *); + }; + unsigned long sa_flags; + __sigrestore_t sa_restorer; + sigset_t sa_mask; +}; + +#endif diff -puN /dev/null usr/include/arch/i386/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/i386/klibc/archstat.h @@ -0,0 +1,38 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat { + __stdev64 (st_dev); + unsigned char __pad0[4]; + + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + __stdev64 (st_rdev); + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long st_ino; +}; + +#endif diff -puN /dev/null usr/include/arch/i386/klibc/diverr.h --- /dev/null +++ a/usr/include/arch/i386/klibc/diverr.h @@ -0,0 +1,15 @@ +/* + * arch/i386/include/klibc/diverr.h + */ + +#ifndef _KLIBC_DIVERR_H +#define _KLIBC_DIVERR_H + +#include + +static __inline__ void __divide_error(void) +{ + asm volatile ("int $0"); +} + +#endif /* _KLIBC_DIVERR_H */ diff -puN /dev/null usr/include/arch/i386/sys/io.h --- /dev/null +++ a/usr/include/arch/i386/sys/io.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/io.h for the i386 architecture + * + * Basic I/O macros + */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +/* I/O-related system calls */ + +int iopl(int); +int ioperm(unsigned long, unsigned long, int); + +/* Basic I/O macros */ + +static __inline__ void outb(unsigned char __v, unsigned short __p) +{ + asm volatile ("outb %0,%1" : : "a" (__v), "dN" (__p)); +} + +static __inline__ void outw(unsigned short __v, unsigned short __p) +{ + asm volatile ("outw %0,%1" : : "a" (__v), "dN" (__p)); +} + +static __inline__ void outl(unsigned int __v, unsigned short __p) +{ + asm volatile ("outl %0,%1" : : "a" (__v), "dN" (__p)); +} + +static __inline__ unsigned char inb(unsigned short __p) +{ + unsigned char __v; + asm volatile ("inb %1,%0" : "=a" (__v) : "dN" (__p)); + return __v; +} + +static __inline__ unsigned short inw(unsigned short __p) +{ + unsigned short __v; + asm volatile ("inw %1,%0" : "=a" (__v) : "dN" (__p)); + return __v; +} + +static __inline__ unsigned int inl(unsigned short __p) +{ + unsigned int __v; + asm volatile ("inl %1,%0" : "=a" (__v) : "dN" (__p)); + return __v; +} + +/* String I/O macros */ + +static __inline__ void +outsb(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsb" + : "+S" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void +outsw(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsw" + : "+S" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void +outsl(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsl" + : "+S" (__d), "+c"(__n) + : "d" (__p)); +} + +static __inline__ void insb(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insb" + : "+D" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void insw(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insw" + : "+D" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void insl(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insl" + : "+D" (__d), "+c" (__n) + : "d" (__p)); +} + +#endif /* _SYS_IO_H */ diff -puN /dev/null usr/include/arch/i386/sys/vm86.h --- /dev/null +++ a/usr/include/arch/i386/sys/vm86.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/vm86.h for i386 + */ + +#ifndef _SYS_VM86_H +#define _SYS_VM86_H 1 + +#include + +/* Actual system call */ +int vm86(struct vm86_struct *); + +#endif diff -puN /dev/null usr/include/arch/ia64/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/ia64/klibc/archconfig.h @@ -0,0 +1,17 @@ +/* + * include/arch/ia64/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* IA64 doesn't have sys_fork, but it does have an MMU */ +#define _KLIBC_NO_MMU 0 +/* IA64 doesn't have sys_vfork, it has architecture-specific code */ +#define _KLIBC_REAL_VFORK 1 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/ia64/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/ia64/klibc/archsetjmp.h @@ -0,0 +1,17 @@ +/* + * arch/ia64/include/klibc/archsetjmp.h + * + * Code borrowed from the FreeBSD kernel. + * + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +/* User code must not depend on the internal representation of jmp_buf. */ +#define _JBLEN 0x200 + +/* guaranteed 128-bit alignment! */ +typedef char jmp_buf[_JBLEN] __attribute__ ((aligned(16))); + +#endif diff -puN /dev/null usr/include/arch/ia64/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/ia64/klibc/archsignal.h @@ -0,0 +1,32 @@ +/* + * arch/ia64/include/klibc/archsignal.h + * + * Architecture-specific signal definitions. + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +#define _NSIG 64 +#define _NSIG_BPW 64 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +struct sigaction { + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction) (int, struct siginfo *, void *); + } _u; + sigset_t sa_mask; + int sa_flags; +}; + +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + +#endif diff -puN /dev/null usr/include/arch/ia64/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/ia64/klibc/archstat.h @@ -0,0 +1,26 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); + unsigned long st_ino; + unsigned long st_nlink; + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + __stdev64 (st_rdev); + unsigned long st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long st_blksize; + long st_blocks; + unsigned long __unused[3]; +}; + +#endif diff -puN /dev/null usr/include/arch/ia64/klibc/archsys.h --- /dev/null +++ a/usr/include/arch/ia64/klibc/archsys.h @@ -0,0 +1,217 @@ +/* + * arch/ia64/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +#define __IA64_BREAK "break 0x100000;;\n\t" + +#define _syscall0(type,name) \ +type \ +name (void) \ +{ \ + register long _r8 asm ("r8"); \ + register long _r10 asm ("r10"); \ + register long _r15 asm ("r15") = __NR_##name; \ + long _retval; \ + __asm __volatile (__IA64_BREAK \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15) \ + : "2" (_r15) ASM_ARGS_0 \ + : "memory" ASM_CLOBBERS_0); \ + _retval = _r8; \ + if (_r10 == -1) { \ + errno = (_retval); \ + _retval = -1; \ + } \ + return (type)_retval; \ +} + +#define _syscall1(type,name,type1,arg1) \ +type \ +name (type1 arg1) \ +{ \ + register long _r8 asm ("r8"); \ + register long _r10 asm ("r10"); \ + register long _r15 asm ("r15") = __NR_##name; \ + long _retval; \ + LOAD_ARGS_1(arg1); \ + __asm __volatile (__IA64_BREAK \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15), \ + ASM_OUTARGS_1 \ + : "2" (_r15) ASM_ARGS_1 \ + : "memory" ASM_CLOBBERS_1); \ + _retval = _r8; \ + if (_r10 == -1) { \ + errno = (_retval); \ + _retval = -1; \ + } \ + return (type)_retval; \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type \ +name (type1 arg1, type2 arg2) \ +{ \ + register long _r8 asm ("r8"); \ + register long _r10 asm ("r10"); \ + register long _r15 asm ("r15") = __NR_##name; \ + long _retval; \ + LOAD_ARGS_2(arg1, arg2); \ + __asm __volatile (__IA64_BREAK \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15), \ + ASM_OUTARGS_2 \ + : "2" (_r15) ASM_ARGS_2 \ + : "memory" ASM_CLOBBERS_2); \ + _retval = _r8; \ + if (_r10 == -1) { \ + errno = (_retval); \ + _retval = -1; \ + } \ + return (type)_retval; \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type \ +name (type1 arg1, type2 arg2, type3 arg3) \ +{ \ + register long _r8 asm ("r8"); \ + register long _r10 asm ("r10"); \ + register long _r15 asm ("r15") = __NR_##name; \ + long _retval; \ + LOAD_ARGS_3(arg1, arg2, arg3); \ + __asm __volatile (__IA64_BREAK \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15), \ + ASM_OUTARGS_3 \ + : "2" (_r15) ASM_ARGS_3 \ + : "memory" ASM_CLOBBERS_3); \ + _retval = _r8; \ + if (_r10 == -1) { \ + errno = (_retval); \ + _retval = -1; \ + } \ + return (type)_retval; \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type \ +name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + register long _r8 asm ("r8"); \ + register long _r10 asm ("r10"); \ + register long _r15 asm ("r15") = __NR_##name; \ + long _retval; \ + LOAD_ARGS_4(arg1, arg2, arg3, arg4); \ + __asm __volatile (__IA64_BREAK \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15), \ + ASM_OUTARGS_4 \ + : "2" (_r15) ASM_ARGS_4 \ + : "memory" ASM_CLOBBERS_4); \ + _retval = _r8; \ + if (_r10 == -1) { \ + errno = (_retval); \ + _retval = -1; \ + } \ + return (type)_retval; \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type \ +name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ + register long _r8 asm ("r8"); \ + register long _r10 asm ("r10"); \ + register long _r15 asm ("r15") = __NR_##name; \ + long _retval; \ + LOAD_ARGS_5(arg1, arg2, arg3, arg4, arg5); \ + __asm __volatile (__IA64_BREAK \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15), \ + ASM_OUTARGS_5 \ + : "2" (_r15) ASM_ARGS_5 \ + : "memory" ASM_CLOBBERS_5); \ + _retval = _r8; \ + if (_r10 == -1) { \ + errno = (_retval); \ + _retval = -1; \ + } \ + return (type)_retval; \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type \ +name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ + register long _r8 asm ("r8"); \ + register long _r10 asm ("r10"); \ + register long _r15 asm ("r15") = __NR_##name; \ + long _retval; \ + LOAD_ARGS_6(arg1, arg2, arg3, arg4, arg5, arg6); \ + __asm __volatile (__IA64_BREAK \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15), \ + ASM_OUTARGS_6 \ + : "2" (_r15) ASM_ARGS_6 \ + : "memory" ASM_CLOBBERS_6); \ + _retval = _r8; \ + if (_r10 == -1) { \ + errno = (_retval); \ + _retval = -1; \ + } \ + return (type)_retval; \ +} + +#define LOAD_ARGS_0() do { } while (0) +#define LOAD_ARGS_1(out0) \ + register long _out0 asm ("out0") = (long) (out0); \ + LOAD_ARGS_0 () +#define LOAD_ARGS_2(out0, out1) \ + register long _out1 asm ("out1") = (long) (out1); \ + LOAD_ARGS_1 (out0) +#define LOAD_ARGS_3(out0, out1, out2) \ + register long _out2 asm ("out2") = (long) (out2); \ + LOAD_ARGS_2 (out0, out1) +#define LOAD_ARGS_4(out0, out1, out2, out3) \ + register long _out3 asm ("out3") = (long) (out3); \ + LOAD_ARGS_3 (out0, out1, out2) +#define LOAD_ARGS_5(out0, out1, out2, out3, out4) \ + register long _out4 asm ("out4") = (long) (out4); \ + LOAD_ARGS_4 (out0, out1, out2, out3) +#define LOAD_ARGS_6(out0, out1, out2, out3, out4, out5) \ + register long _out5 asm ("out5") = (long) (out5); \ + LOAD_ARGS_5 (out0, out1, out2, out3, out4) + +#define ASM_OUTARGS_1 "=r" (_out0) +#define ASM_OUTARGS_2 ASM_OUTARGS_1, "=r" (_out1) +#define ASM_OUTARGS_3 ASM_OUTARGS_2, "=r" (_out2) +#define ASM_OUTARGS_4 ASM_OUTARGS_3, "=r" (_out3) +#define ASM_OUTARGS_5 ASM_OUTARGS_4, "=r" (_out4) +#define ASM_OUTARGS_6 ASM_OUTARGS_5, "=r" (_out5) + +#define ASM_ARGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "3" (_out0) +#define ASM_ARGS_2 ASM_ARGS_1, "4" (_out1) +#define ASM_ARGS_3 ASM_ARGS_2, "5" (_out2) +#define ASM_ARGS_4 ASM_ARGS_3, "6" (_out3) +#define ASM_ARGS_5 ASM_ARGS_4, "7" (_out4) +#define ASM_ARGS_6 ASM_ARGS_5, "8" (_out5) + +#define ASM_CLOBBERS_0 ASM_CLOBBERS_1, "out0" +#define ASM_CLOBBERS_1 ASM_CLOBBERS_2, "out1" +#define ASM_CLOBBERS_2 ASM_CLOBBERS_3, "out2" +#define ASM_CLOBBERS_3 ASM_CLOBBERS_4, "out3" +#define ASM_CLOBBERS_4 ASM_CLOBBERS_5, "out4" +#define ASM_CLOBBERS_5 ASM_CLOBBERS_6, "out5" +#define ASM_CLOBBERS_6 , "out6", "out7", \ + /* Non-stacked integer registers, minus r8, r10, r15. */ \ + "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \ + "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \ + "r28", "r29", "r30", "r31", \ + /* Predicate registers. */ \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + /* Non-rotating fp registers. */ \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + /* Branch registers. */ \ + "b6", "b7" + +#endif /* _KLIBC_ARCHSYS_H */ diff -puN /dev/null usr/include/arch/m32r/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/m32r/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/m32r/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* All defaults */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/m32r/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/m32r/klibc/archsetjmp.h @@ -0,0 +1,21 @@ +/* + * arch/m32r/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __r8; + unsigned long __r9; + unsigned long __r10; + unsigned long __r11; + unsigned long __r12; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff -puN /dev/null usr/include/arch/m32r/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/m32r/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/m32r/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/m32r/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/m32r/klibc/archstat.h @@ -0,0 +1,39 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat { + __stdev64 (st_dev); + unsigned char __pad0[4]; + + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + __stdev64 (st_rdev); + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long st_ino; +}; + +#endif diff -puN /dev/null usr/include/arch/m68k/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/m68k/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/m68k/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* On m68k, sys_mmap2 uses the current page size as the shift factor */ +#define _KLIBC_MMAP2_SHIFT __getpageshift() + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/m68k/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/m68k/klibc/archsetjmp.h @@ -0,0 +1,26 @@ +/* + * usr/include/arch/m68k/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int __d2; + unsigned int __d3; + unsigned int __d4; + unsigned int __d5; + unsigned int __d6; + unsigned int __d7; + unsigned int __a2; + unsigned int __a3; + unsigned int __a4; + unsigned int __a5; + unsigned int __fp; /* a6 */ + unsigned int __sp; /* a7 */ + unsigned int __retaddr; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLBIC_ARCHSETJMP_H */ diff -puN /dev/null usr/include/arch/m68k/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/m68k/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/m68k/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/m68k/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/m68k/klibc/archstat.h @@ -0,0 +1,38 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane padding around dev_t's. + */ +struct stat { + __stdev64 (st_dev); + unsigned char __pad1[2]; + + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + __stdev64 (st_rdev); + unsigned char __pad3[2]; + + long long st_size; + unsigned long st_blksize; + + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long st_ino; +}; + +#endif diff -puN /dev/null usr/include/arch/mips64/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/mips64/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/mips64/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* All defaults */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/mips64/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/mips64/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/mips64/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/mips64/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/mips64/klibc/archstat.h @@ -0,0 +1,33 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#define _STATBUF_ST_NSEC + +struct stat { + unsigned int st_dev; + unsigned int st_pad0[3]; /* Reserved for st_dev expansion */ + + unsigned long st_ino; + + mode_t st_mode; + nlink_t st_nlink; + + uid_t st_uid; + gid_t st_gid; + + unsigned int st_rdev; + unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */ + + off_t st_size; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned int st_blksize; + unsigned int st_pad2; + + unsigned long st_blocks; +}; + +#endif diff -puN /dev/null usr/include/arch/mips/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/mips/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/mips/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* MIPS has architecture-specific code for vfork() */ +#define _KLIBC_REAL_VFORK 1 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/mips/klibc/archfcntl.h --- /dev/null +++ a/usr/include/arch/mips/klibc/archfcntl.h @@ -0,0 +1,86 @@ +/* + * arch/mips/include/klibc/archfcntl.h + * + * On MIPS, isn't usable (compiling struct stat with + * the correct definitions doesn't "just work"), so we need to provide + * our own definitions. + */ + +#ifndef _KLIBC_ARCHFCNTL_H +#define _KLIBC_ARCHFCNTL_H + +#ifdef _ASM_FCNTL_H /* We were too late! */ +# error " included before " +#endif +#define _ASM_FCNTL_H /* Keep from getting included */ + +#define O_ACCMODE 0x0003 +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_APPEND 0x0008 +#define O_SYNC 0x0010 +#define O_NONBLOCK 0x0080 +#define O_CREAT 0x0100 +#define O_TRUNC 0x0200 +#define O_EXCL 0x0400 +#define O_NOCTTY 0x0800 +#define FASYNC 0x1000 +#define O_LARGEFILE 0x2000 +#define O_DIRECT 0x8000 +#define O_DIRECTORY 0x10000 +#define O_NOFOLLOW 0x20000 +#define O_NOATIME 0x40000 + +#define O_NDELAY O_NONBLOCK + +#define F_DUPFD 0 +#define F_GETFD 1 +#define F_SETFD 2 +#define F_GETFL 3 +#define F_SETFL 4 +#define F_GETLK 14 +#define F_SETLK 6 +#define F_SETLKW 7 + +#define F_SETOWN 24 +#define F_GETOWN 23 +#define F_SETSIG 10 +#define F_GETSIG 11 + +#define F_GETLK64 33 +#define F_SETLK64 34 +#define F_SETLKW64 35 + +#define FD_CLOEXEC 1 + +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +#define F_EXLCK 4 +#define F_SHLCK 8 + +#define F_INPROGRESS 16 + +#define LOCK_SH 1 +#define LOCK_EX 2 +#define LOCK_NB 4 +#define LOCK_UN 8 + +#define LOCK_MAND 32 +#define LOCK_READ 64 +#define LOCK_WRITE 128 +#define LOCK_RW 192 + +typedef struct flock { + short l_type; + short l_whence; + loff_t l_start; + loff_t l_len; + pid_t l_pid; +} flock_t; + +#define F_LINUX_SPECIFIC_BASE 1024 + +#endif /* _KLIBC_ARCHFCNTL_H */ diff -puN /dev/null usr/include/arch/mips/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/mips/klibc/archsetjmp.h @@ -0,0 +1,39 @@ +/* + * arch/mips/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __s0; + unsigned long __s1; + unsigned long __s2; + unsigned long __s3; + unsigned long __s4; + unsigned long __s5; + unsigned long __s6; + unsigned long __s7; + unsigned long __gp; + unsigned long __sp; + unsigned long __s8; + unsigned long __ra; + unsigned long __f20; + unsigned long __f21; + unsigned long __f22; + unsigned long __f23; + unsigned long __f24; + unsigned long __f25; + unsigned long __f26; + unsigned long __f27; + unsigned long __f28; + unsigned long __f29; + unsigned long __f30; + unsigned long __f31; + unsigned long __fcr31; + unsigned long __unused; +} __attribute__ ((aligned(8))); + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff -puN /dev/null usr/include/arch/mips/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/mips/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/mips/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/mips/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/mips/klibc/archstat.h @@ -0,0 +1,40 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#define _STATBUF_ST_NSEC + +/* + * This matches struct stat64 in glibc2.1, hence the absolutely insane + * amounts of padding around dev_t's. The memory layout is the same as of + * struct stat of the 64-bit kernel, which makes this one of the sanest + * 32-bit struct stats. + */ + +struct stat { + unsigned int st_dev; + unsigned long st_pad0[3]; /* Reserved for st_dev expansion */ + + unsigned long long st_ino; + + mode_t st_mode; + nlink_t st_nlink; + + uid_t st_uid; + gid_t st_gid; + + unsigned int st_rdev; + unsigned long st_pad1[3]; /* Reserved for st_rdev expansion */ + + long long st_size; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long st_blksize; + unsigned long st_pad2; + + long long st_blocks; +}; + +#endif diff -puN /dev/null usr/include/arch/mips/machine/asm.h --- /dev/null +++ a/usr/include/arch/mips/machine/asm.h @@ -0,0 +1,11 @@ +/* + * arch/mips/include/machine/asm.h + */ + +#ifndef _MACHINE_ASM_H +#define _MACHINE_ASM_H + +#include +#include + +#endif /* _MACHINE_ASM_H */ diff -puN /dev/null usr/include/arch/mips/sgidefs.h --- /dev/null +++ a/usr/include/arch/mips/sgidefs.h @@ -0,0 +1,20 @@ +/* + * arch/mips/include/sgidefs.h + */ + +/* Some ABI constants */ + +#ifndef _SGIDEFS_H +#define _SGIDEFS_H + +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 + +#define _MIPS_SIM_ABI32 1 +#define _MIPS_SIM_NABI32 2 +#define _MIPS_SIM_ABI64 3 + +#endif /* _SGIDEFS_H */ diff -puN /dev/null usr/include/arch/mips/spaces.h --- /dev/null +++ a/usr/include/arch/mips/spaces.h @@ -0,0 +1 @@ +/* Included by but not actually needed */ diff -puN /dev/null usr/include/arch/parisc/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/parisc/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/parisc/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* All defaults */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/parisc/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/parisc/klibc/archsetjmp.h @@ -0,0 +1,14 @@ +/* + * arch/parisc/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + double regs[21]; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/parisc/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/parisc/klibc/archsignal.h @@ -0,0 +1,25 @@ +/* + * arch/parisc/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +#define _NSIG 64 +#define _NSIG_SZ (_NSIG / LONG_BIT) + +typedef struct { + unsigned long sig[_NSIG_SZ]; +} sigset_t; + +struct sigaction { + __sighandler_t sa_handler; + unsigned long sa_flags; + sigset_t sa_mask; +}; + +#endif diff -puN /dev/null usr/include/arch/parisc/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/parisc/klibc/archstat.h @@ -0,0 +1,29 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); + unsigned int __pad1; + + unsigned int __st_ino; /* Not actually filled in */ + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + __stdev64 (st_rdev); + unsigned int __pad2; + signed long long st_size; + signed int st_blksize; + + signed long long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif diff -puN /dev/null usr/include/arch/ppc64/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/ppc64/klibc/archconfig.h @@ -0,0 +1,12 @@ +/* + * include/arch/ppc64/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in this file. + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +#define _KLIBC_USE_RT_SIG 1 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/ppc64/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/ppc64/klibc/archsetjmp.h @@ -0,0 +1,36 @@ +/* + * arch/ppc64/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __r2; + unsigned long __sp; + unsigned long __lr; + unsigned long __cr; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __r16; + unsigned long __r17; + unsigned long __r18; + unsigned long __r19; + unsigned long __r20; + unsigned long __r21; + unsigned long __r22; + unsigned long __r23; + unsigned long __r24; + unsigned long __r25; + unsigned long __r26; + unsigned long __r27; + unsigned long __r28; + unsigned long __r29; + unsigned long __r30; + unsigned long __r31; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/ppc64/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/ppc64/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/ppc64/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/ppc64/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/ppc64/klibc/archstat.h @@ -0,0 +1,27 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); + ino_t st_ino; + nlink_t st_nlink; + mode_t st_mode; + uid_t st_uid; + gid_t st_gid; + __stdev64 (st_rdev); + off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ + unsigned long __unused4; + unsigned long __unused5; + unsigned long __unused6; +}; + +#endif diff -puN /dev/null usr/include/arch/ppc/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/ppc/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/ppc/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* All defaults */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/ppc/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/ppc/klibc/archsetjmp.h @@ -0,0 +1,36 @@ +/* + * arch/ppc/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __r2; + unsigned long __sp; + unsigned long __lr; + unsigned long __cr; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __r16; + unsigned long __r17; + unsigned long __r18; + unsigned long __r19; + unsigned long __r20; + unsigned long __r21; + unsigned long __r22; + unsigned long __r23; + unsigned long __r24; + unsigned long __r25; + unsigned long __r26; + unsigned long __r27; + unsigned long __r28; + unsigned long __r29; + unsigned long __r30; + unsigned long __r31; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/ppc/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/ppc/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/ppc/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/ppc/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/ppc/klibc/archstat.h @@ -0,0 +1,30 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1. + */ +struct stat { + __stdev64 (st_dev); /* Device. */ + unsigned long long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + __stdev64 (st_rdev); /* Device number, if device. */ + unsigned short int __pad2; + long long st_size; /* Size of file, in bytes. */ + long st_blksize; /* Optimal block size for I/O. */ + + long long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#endif diff -puN /dev/null usr/include/arch/s390/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/s390/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/s390/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* Both s390 and s390x use the "32-bit" version of this structure */ +#define _KLIBC_STATFS_F_TYPE_64 0 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/s390/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/s390/klibc/archsetjmp.h @@ -0,0 +1,26 @@ +/* + * arch/s390/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +#ifndef __s390x__ + +struct __jmp_buf { + uint32_t __gregs[10]; /* general registers r6-r15 */ + uint64_t __fpregs[2]; /* fp registers f4 and f6 */ +}; + +#else /* __s390x__ */ + +struct __jmp_buf { + uint64_t __gregs[10]; /* general registers r6-r15 */ + uint64_t __fpregs[4]; /* fp registers f1, f3, f5, f7 */ +}; + +#endif /* __s390x__ */ + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/s390/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/s390/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/s390/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/s390/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/s390/klibc/archstat.h @@ -0,0 +1,56 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +#ifndef __s390x__ + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat { + __stdev64 (st_dev); + unsigned int __pad1; +#define STAT64_HAS_BROKEN_ST_INO 1 + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + __stdev64 (st_rdev); + unsigned int __pad3; + long long st_size; + unsigned long st_blksize; + unsigned char __pad4[4]; + unsigned long __pad5; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#else /* __s390x__ */ + +struct stat { + __stdev64 (st_dev); + unsigned long st_ino; + unsigned long st_nlink; + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad1; + __stdev64 (st_rdev); + unsigned long st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long st_blksize; + long st_blocks; + unsigned long __unused[3]; +}; + +#endif /* __s390x__ */ +#endif diff -puN /dev/null usr/include/arch/sh/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/sh/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/sh/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* All defaults */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/sh/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/sh/klibc/archsetjmp.h @@ -0,0 +1,22 @@ +/* + * arch/sh/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __r8; + unsigned long __r9; + unsigned long __r10; + unsigned long __r11; + unsigned long __r12; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __pr; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _KLIBC_ARCHSETJMP_H */ diff -puN /dev/null usr/include/arch/sh/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/sh/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/sh/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* No special stuff for this architecture */ + +#endif diff -puN /dev/null usr/include/arch/sh/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/sh/klibc/archstat.h @@ -0,0 +1,38 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat64 { + __stdev64 (st_dev); + unsigned char __pad0[4]; + + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + __stdev64 (st_rdev); + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + + unsigned long long st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif diff -puN /dev/null usr/include/arch/sparc64/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/sparc64/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/sparc64/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +#define _KLIBC_USE_RT_SIG 1 /* Use rt_* signals */ +#define _KLIBC_NEEDS_SA_RESTORER 1 /* Need a restorer function */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/sparc64/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/sparc64/klibc/archsetjmp.h @@ -0,0 +1,16 @@ +/* + * arch/sparc64/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __sp; + unsigned long __fp; + unsigned long __pc; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/sparc64/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/sparc64/klibc/archsignal.h @@ -0,0 +1,17 @@ +/* + * arch/sparc64/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#define __WANT_POSIX1B_SIGNALS__ +#include + +/* Not actually used by the kernel... */ +#define SA_RESTORER 0x80000000 + +#endif diff -puN /dev/null usr/include/arch/sparc64/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/sparc64/klibc/archstat.h @@ -0,0 +1,30 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); + unsigned long st_ino; + unsigned long st_nlink; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + + __stdev64 (st_rdev); + long st_size; + long st_blksize; + long st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long __unused[3]; +}; + +#endif diff -puN /dev/null usr/include/arch/sparc/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/sparc/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/sparc/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +#define _KLIBC_USE_RT_SIG 1 /* Use rt_* signals */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/sparc/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/sparc/klibc/archsetjmp.h @@ -0,0 +1,16 @@ +/* + * arch/sparc/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __sp; + unsigned long __fp; + unsigned long __pc; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/sparc/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/sparc/klibc/archsignal.h @@ -0,0 +1,24 @@ +/* + * arch/sparc/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#define __WANT_POSIX1B_SIGNALS__ +#include + +struct sigaction { + __sighandler_t sa_handler; + unsigned long sa_flags; + void (*sa_restorer)(void); /* Not used by Linux/SPARC */ + sigset_t sa_mask; +}; + +/* Not actually used by the kernel... */ +#define SA_RESTORER 0x80000000 + +#endif diff -puN /dev/null usr/include/arch/sparc/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/sparc/klibc/archstat.h @@ -0,0 +1,37 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned int st_uid; + unsigned int st_gid; + + __stdev64 (st_rdev); + + unsigned char __pad3[8]; + + long long st_size; + unsigned int st_blksize; + + unsigned char __pad4[8]; + unsigned int st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned int __unused4; + unsigned int __unused5; +}; + +#endif diff -puN /dev/null usr/include/arch/sparc/machine/asm.h --- /dev/null +++ a/usr/include/arch/sparc/machine/asm.h @@ -0,0 +1,191 @@ +/* $NetBSD: asm.h,v 1.14 2002/07/20 08:37:30 mrg Exp $ */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ASM_H_ +#define _ASM_H_ + +/* Pull in CCFSZ, CC64FSZ, and BIAS from frame.h */ +#ifndef _LOCORE +#define _LOCORE +#endif +#include + +#ifdef __ELF__ +#define _C_LABEL(name) name +#else +#ifdef __STDC__ +#define _C_LABEL(name) _ ## name +#else +#define _C_LABEL(name) _/**/name +#endif +#endif +#define _ASM_LABEL(name) name + +#ifdef PIC +/* + * PIC_PROLOGUE() is akin to the compiler generated function prologue for + * PIC code. It leaves the address of the Global Offset Table in DEST, + * clobbering register TMP in the process. + * + * We can use two code sequences. We can read the %pc or use the call + * instruction that saves the pc in %o7. Call requires the branch unit and + * IEU1, and clobbers %o7 which needs to be restored. This instruction + * sequence takes about 4 cycles due to instruction interdependence. Reading + * the pc takes 4 cycles to dispatch and is always dispatched alone. That + * sequence takes 7 cycles. + */ +#ifdef __arch64__ +#define PIC_PROLOGUE(dest,tmp) \ + mov %o7, tmp; \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4),dest; \ + call 0f; \ + or dest,%lo(_GLOBAL_OFFSET_TABLE_+4),dest; \ +0: \ + add dest,%o7,dest; \ + mov tmp, %o7 +#else +#define PIC_PROLOGUE(dest,tmp) \ + mov %o7,tmp; 3: call 4f; nop; 4: \ + sethi %hi(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \ + or dest,%lo(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \ + add dest,%o7,dest; mov tmp,%o7 +#endif + +/* + * PICCY_SET() does the equivalent of a `set var, %dest' instruction in + * a PIC-like way, but without involving the Global Offset Table. This + * only works for VARs defined in the same file *and* in the text segment. + */ +#ifdef __arch64__ +#define PICCY_SET(var,dest,tmp) \ + 3: rd %pc, tmp; add tmp,(var-3b),dest +#else +#define PICCY_SET(var,dest,tmp) \ + mov %o7,tmp; 3: call 4f; nop; 4: \ + add %o7,(var-3b),dest; mov tmp,%o7 +#endif +#else +#define PIC_PROLOGUE(dest,tmp) +#define PICCY_OFFSET(var,dest,tmp) +#endif + +#define FTYPE(x) .type x,@function +#define OTYPE(x) .type x,@object + +#define _ENTRY(name) \ + .align 4; .globl name; .proc 1; FTYPE(name); name: + +#ifdef GPROF +/* see _MCOUNT_ENTRY in profile.h */ +#ifdef __ELF__ +#ifdef __arch64__ +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE \ + .data; .align 4; 1: .long 0; \ + .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#endif +#else +#ifdef __arch64__ +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE \ + .data; .align 4; 1: .long 0; \ + .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call mcount; \ + or %o0,%lo(1b),%o0; restore +#endif +#endif +#else +#define _PROF_PROLOGUE +#endif + +#define ENTRY(name) _ENTRY(_C_LABEL(name)); _PROF_PROLOGUE +#define ENTRY_NOPROFILE(name) _ENTRY(_C_LABEL(name)) +#define ASENTRY(name) _ENTRY(_ASM_LABEL(name)); _PROF_PROLOGUE +#define FUNC(name) ASENTRY(name) +#define RODATA(name) .align 4; .text; .globl _C_LABEL(name); \ + OTYPE(_C_LABEL(name)); _C_LABEL(name): + +#define ASMSTR .asciz + +#define RCSID(name) .asciz name + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif + +/* + * WARN_REFERENCES: create a warning if the specified symbol is referenced. + */ +#ifdef __ELF__ +#ifdef __STDC__ +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning. ## _sym ; .ascii _msg ; .text +#else +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning./**/_sym ; .ascii _msg ; .text +#endif /* __STDC__ */ +#else +#ifdef __STDC__ +#define __STRING(x) #x +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_ ## sym) ## ,1,0,0,0 +#else +#define __STRING(x) "x" +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ +#endif /* __ELF__ */ + +#endif /* _ASM_H_ */ diff -puN /dev/null usr/include/arch/sparc/machine/frame.h --- /dev/null +++ a/usr/include/arch/sparc/machine/frame.h @@ -0,0 +1,146 @@ +/* $NetBSD: frame.h,v 1.4 2001/12/04 00:05:05 darrenr Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)frame.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _MACHINE_FRAME_H +#define _MACHINE_FRAME_H + +#ifdef __ASSEMBLY__ +# define _LOCORE +#endif + +#ifndef _LOCORE +# include +#endif + +/* + * Sparc stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + */ +#ifndef _LOCORE +#ifndef SUN4U +struct frame { + int32_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int32_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + struct frame *fr_fp; /* space to save frame pointer (%i6) */ + int32_t fr_pc; /* space to save return pc (%i7) */ + /* + * SunOS reserves another 8 words here; this is pointless + * but we do it for compatibility. + */ + int32_t fr_xxx; /* `structure return pointer' (unused) */ + int32_t fr_argd[6]; /* `arg dump area' (lunacy) */ + int32_t fr_argx[1]; /* arg extension (args 7..n; variable size) */ +}; +#else +struct frame32 { + int32_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int32_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + uint32_t fr_fp; /* space to save frame pointer (%i6) */ + uint32_t fr_pc; /* space to save return pc (%i7) */ + /* + * SunOS reserves another 8 words here; this is pointless + * but we do it for compatibility. + */ + int32_t fr_xxx; /* `structure return pointer' (unused) */ + int32_t fr_argd[6]; /* `arg dump area' (lunacy) */ + int32_t fr_argx[1]; /* arg extension (args 7..n; variable size) */ +}; +#endif +#endif + +/* + * CCFSZ (C Compiler Frame SiZe) is the size of a stack frame required if + * a function is to call C code. It should be just 64, but Sun defined + * their frame with space to hold arguments 0 through 5 (plus some junk), + * and varargs routines (such as kprintf) demand this, and gcc uses this + * area at times anyway. + */ +#define CCFSZ 96 + +/* + * Sparc v9 stack frame format. + * + * Note that the contents of each stack frame may be held only in + * machine register windows. In order to get an accurate picture + * of the frame, you must first force the kernel to write any such + * windows to the stack. + * + * V9 frames have an odd bias, so you can tall a v9 frame from + * a v8 frame by testing the stack pointer's lsb. + */ +#if !defined(_LOCORE) && !defined(_LIBC) +struct frame64 { + int64_t fr_local[8]; /* space to save locals (%l0..%l7) */ + int64_t fr_arg[6]; /* space to save arguments (%i0..%i5) */ + uint64_t fr_fp; /* space to save frame pointer (%i6) */ + uint64_t fr_pc; /* space to save return pc (%i7) */ + /* + * SVR4 reserves a bunch of extra stuff. + */ + int64_t fr_argd[6]; /* `register save area' (lunacy) */ + int64_t fr_argx[0]; /* arg extension (args 7..n; variable size) */ +}; + +#define v9next_frame(f) ((struct frame64*)(f->fr_fp+BIAS)) +#endif + +/* + * CC64FSZ (C Compiler 64-bit Frame SiZe) is the size of a stack frame used + * by the compiler in 64-bit mode. It is (16)*8; space for 8 ins, 8 outs. + */ +#define CC64FSZ 176 + +/* + * v9 stacks all have a bias of 2047 added to the %sp and %fp, so you can easily + * detect it by testing the register for an odd value. Why 2K-1 I don't know. + */ +#define BIAS (2048-1) + +#endif /* _MACHINE_FRAME_H */ diff -puN /dev/null usr/include/arch/sparc/machine/trap.h --- /dev/null +++ a/usr/include/arch/sparc/machine/trap.h @@ -0,0 +1,140 @@ +/* $NetBSD: trap.h,v 1.11 1999/01/20 00:15:08 pk Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)trap.h 8.1 (Berkeley) 6/11/93 + */ +/* + * Sun4m support by Aaron Brown, Harvard University. + * Changes Copyright (c) 1995 The President and Fellows of Harvard College. + * All rights reserved. + */ + +#ifndef _MACHINE_TRAP_H +#define _MACHINE_TRAP_H + +/* trap vec (pri) description */ +#define T_RESET 0x00 /* (1) not actually vectored; jumps to 0 */ +#define T_TEXTFAULT 0x01 /* (2) address fault during instr fetch */ +#define T_ILLINST 0x02 /* (3) illegal instruction */ +#define T_PRIVINST 0x03 /* (4) privileged instruction */ +#define T_FPDISABLED 0x04 /* (5) fp instr while fp disabled */ +#define T_WINOF 0x05 /* (6) register window overflow */ +#define T_WINUF 0x06 /* (7) register window underflow */ +#define T_ALIGN 0x07 /* (8) address not properly aligned */ +#define T_FPE 0x08 /* (9) floating point exception */ +#define T_DATAFAULT 0x09 /* (10) address fault during data fetch */ +#define T_TAGOF 0x0a /* (11) tag overflow */ +/* 0x0b unused */ +/* 0x0c unused */ +/* 0x0d unused */ +/* 0x0e unused */ +/* 0x0f unused */ +/* 0x10 unused */ +#define T_L1INT 0x11 /* (27) level 1 interrupt */ +#define T_L2INT 0x12 /* (26) level 2 interrupt */ +#define T_L3INT 0x13 /* (25) level 3 interrupt */ +#define T_L4INT 0x14 /* (24) level 4 interrupt */ +#define T_L5INT 0x15 /* (23) level 5 interrupt */ +#define T_L6INT 0x16 /* (22) level 6 interrupt */ +#define T_L7INT 0x17 /* (21) level 7 interrupt */ +#define T_L8INT 0x18 /* (20) level 8 interrupt */ +#define T_L9INT 0x19 /* (19) level 9 interrupt */ +#define T_L10INT 0x1a /* (18) level 10 interrupt */ +#define T_L11INT 0x1b /* (17) level 11 interrupt */ +#define T_L12INT 0x1c /* (16) level 12 interrupt */ +#define T_L13INT 0x1d /* (15) level 13 interrupt */ +#define T_L14INT 0x1e /* (14) level 14 interrupt */ +#define T_L15INT 0x1f /* (13) level 15 interrupt */ +/* 0x20 unused */ +/* through 0x23 unused */ +#define T_CPDISABLED 0x24 /* (5) coprocessor instr while disabled */ +#define T_UNIMPLFLUSH 0x25 /* Unimplemented FLUSH */ +/* through 0x27 unused */ +#define T_CPEXCEPTION 0x28 /* (9) coprocessor exception */ +/* 0x29 unused */ +#define T_IDIV0 0x2a /* divide by zero (from hw [su]div instr) */ +#define T_STOREBUFFAULT 0x2b /* SuperSPARC: Store buffer copy-back fault */ +/* 0x2c unused */ +/* through 0x7f unused */ + +/* beginning of `user' vectors (from trap instructions) - all priority 12 */ +#define T_SUN_SYSCALL 0x80 /* system call */ +#define T_BREAKPOINT 0x81 /* breakpoint `instruction' */ +#define T_DIV0 0x82 /* division routine was handed 0 */ +#define T_FLUSHWIN 0x83 /* flush windows */ +#define T_CLEANWIN 0x84 /* provide clean windows */ +#define T_RANGECHECK 0x85 /* ? */ +#define T_FIXALIGN 0x86 /* fix up unaligned accesses */ +#define T_INTOF 0x87 /* integer overflow ? */ +#define T_SVR4_SYSCALL 0x88 /* SVR4 system call */ +#define T_BSD_SYSCALL 0x89 /* BSD system call */ +#define T_KGDB_EXEC 0x8a /* for kernel gdb */ + +/* 0x8b..0xff are currently unallocated, except the following */ +#define T_SVR4_GETCC 0xa0 +#define T_SVR4_SETCC 0xa1 +#define T_SVR4_GETPSR 0xa2 +#define T_SVR4_SETPSR 0xa3 +#define T_SVR4_GETHRTIME 0xa4 +#define T_SVR4_GETHRVTIME 0xa5 +#define T_SVR4_GETHRESTIME 0xa7 + +#ifdef _KERNEL /* pseudo traps for locore.s */ +#define T_RWRET -1 /* need first user window for trap return */ +#define T_AST -2 /* no-op, just needed reschedule or profile */ +#endif + +/* flags to system call (flags in %g1 along with syscall number) */ +#define SYSCALL_G2RFLAG 0x400 /* on success, return to %g2 rather than npc */ +#define SYSCALL_G7RFLAG 0x800 /* use %g7 as above (deprecated) */ + +/* + * `software trap' macros to keep people happy (sparc v8 manual says not + * to set the upper bits). + */ +#define ST_BREAKPOINT (T_BREAKPOINT & 0x7f) +#define ST_DIV0 (T_DIV0 & 0x7f) +#define ST_FLUSHWIN (T_FLUSHWIN & 0x7f) +#define ST_SYSCALL (T_SUN_SYSCALL & 0x7f) + +#endif /* _MACHINE_TRAP_H_ */ diff -puN /dev/null usr/include/arch/x86_64/klibc/archconfig.h --- /dev/null +++ a/usr/include/arch/x86_64/klibc/archconfig.h @@ -0,0 +1,15 @@ +/* + * include/arch/x86_64/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* x86-64 doesn't provide a default sigreturn. */ +#define _KLIBC_NEEDS_SA_RESTORER 1 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff -puN /dev/null usr/include/arch/x86_64/klibc/archsetjmp.h --- /dev/null +++ a/usr/include/arch/x86_64/klibc/archsetjmp.h @@ -0,0 +1,21 @@ +/* + * arch/x86_64/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __rbx; + unsigned long __rsp; + unsigned long __rbp; + unsigned long __r12; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __rip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/arch/x86_64/klibc/archsignal.h --- /dev/null +++ a/usr/include/arch/x86_64/klibc/archsignal.h @@ -0,0 +1,18 @@ +/* + * arch/x86_64/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include +/* The x86-64 headers defines NSIG 32, but it's actually 64 */ +#undef _NSIG +#undef NSIG +#define _NSIG 64 +#define NSIG _NSIG + +#endif diff -puN /dev/null usr/include/arch/x86_64/klibc/archstat.h --- /dev/null +++ a/usr/include/arch/x86_64/klibc/archstat.h @@ -0,0 +1,28 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +struct stat { + __stdev64 (st_dev); + unsigned long st_ino; + unsigned long st_nlink; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + __stdev64 (st_rdev); + long st_size; + long st_blksize; + long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long __unused[3]; +}; + +#endif diff -puN /dev/null usr/include/arch/x86_64/sys/io.h --- /dev/null +++ a/usr/include/arch/x86_64/sys/io.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/io.h for the i386 architecture + * + * Basic I/O macros + */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +/* I/O-related system calls */ + +int iopl(int); +int ioperm(unsigned long, unsigned long, int); + +/* Basic I/O macros */ + +static __inline__ void outb(unsigned char __v, unsigned short __p) +{ + asm volatile ("outb %0,%1" : : "a" (__v), "dN"(__p)); +} + +static __inline__ void outw(unsigned short __v, unsigned short __p) +{ + asm volatile ("outw %0,%1" : : "a" (__v), "dN"(__p)); +} + +static __inline__ void outl(unsigned int __v, unsigned short __p) +{ + asm volatile ("outl %0,%1" : : "a" (__v), "dN"(__p)); +} + +static __inline__ unsigned char inb(unsigned short __p) +{ + unsigned char __v; + asm volatile ("inb %1,%0" : "=a" (__v) : "dN"(__p)); + return v; +} + +static __inline__ unsigned short inw(unsigned short __p) +{ + unsigned short __v; + asm volatile ("inw %1,%0" : "=a" (__v) : "dN"(__p)); + return v; +} + +static __inline__ unsigned int inl(unsigned short __p) +{ + unsigned int __v; + asm volatile ("inl %1,%0" : "=a" (__v) : "dN"(__p)); + return v; +} + +/* String I/O macros */ + +static __inline__ void +outsb(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsb" + : "+S" (__d), "+c"(__n) + : "d"(__p)); +} + +static __inline__ void +outsw(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsw" + : "+S" (__d), "+c"(__n) + : "d"(__p)); +} + +static __inline__ void +outsl(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsl" + : "+S" (__d), "+c"(__n) + : "d"(__p)); +} + +static __inline__ void insb(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insb" + : "+D" (__d), "+c"(__n) + : "d"(__p)); +} + +static __inline__ void insw(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insw" + : "+D" (__d), "+c"(__n) + : "d"(__p)); +} + +static __inline__ void insl(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insl" + : "+D" (__d), "+c"(__n) + : "d"(__p)); +} + +#endif /* _SYS_IO_H */ diff -puN /dev/null usr/include/arpa/inet.h --- /dev/null +++ a/usr/include/arpa/inet.h @@ -0,0 +1,22 @@ +/* + * arpa/inet.h + */ + +#ifndef _ARPA_INET_H +#define _ARPA_INET_H + +#include +#include +#include +#include +#include + +__extern uint32_t inet_addr(const char *); +__extern int inet_aton(const char *, struct in_addr *); +__extern char *inet_ntoa(struct in_addr); +__extern int inet_pton(int, const char *, void *); +__extern const char *inet_ntop(int, const void *, char *, size_t); +__extern unsigned int inet_nsap_addr(const char *, unsigned char *, int); +__extern char *inet_nsap_ntoa(int, const unsigned char *, char *); + +#endif /* _ARPA_INET_H */ diff -puN /dev/null usr/include/assert.h --- /dev/null +++ a/usr/include/assert.h @@ -0,0 +1,22 @@ +/* + * assert.h + */ + +#ifndef _ASSERT_H +#define _ASSERT_H + +#include + +#ifdef NDEBUG + +#define assert(x) ((void)(x)) + +#else + +extern __noreturn __assert_fail(const char *, const char *, unsigned int); + +#define assert(x) ((x) ? (void)0 : __assert_fail(#x, __FILE__, __LINE__)) + +#endif + +#endif /* _ASSERT_H */ diff -puN /dev/null usr/include/bits32/bitsize.h --- /dev/null +++ a/usr/include/bits32/bitsize.h @@ -0,0 +1,3 @@ +#ifndef _BITSIZE +#define _BITSIZE 32 +#endif diff -puN /dev/null usr/include/bits32/bitsize/limits.h --- /dev/null +++ a/usr/include/bits32/bitsize/limits.h @@ -0,0 +1,14 @@ +/* + * bits32/limits.h + */ + +#ifndef _BITSIZE_LIMITS_H +#define _BITSIZE_LIMITS_H + +#define LONG_BIT 32 + +#define LONG_MIN (-2147483647L-1) +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL + +#endif /* _BITSIZE_LIMITS_H */ diff -puN /dev/null usr/include/bits32/bitsize/stddef.h --- /dev/null +++ a/usr/include/bits32/bitsize/stddef.h @@ -0,0 +1,18 @@ +/* + * bits32/stddef.h + */ + +#ifndef _BITSIZE_STDDEF_H +#define _BITSIZE_STDDEF_H + +#define _SIZE_T +#if defined(__s390__) || defined(__cris__) +typedef unsigned long size_t; +#else +typedef unsigned int size_t; +#endif + +#define _PTRDIFF_T +typedef signed int ptrdiff_t; + +#endif /* _BITSIZE_STDDEF_H */ diff -puN /dev/null usr/include/bits32/bitsize/stdintconst.h --- /dev/null +++ a/usr/include/bits32/bitsize/stdintconst.h @@ -0,0 +1,18 @@ +/* + * bits32/stdintconst.h + */ + +#ifndef _BITSIZE_STDINTCONST_H +#define _BITSIZE_STDINTCONST_H + +#define INT_FAST16_C(c) INT32_C(c) +#define INT_FAST32_C(c) INT32_C(c) + +#define UINT_FAST16_C(c) UINT32_C(c) +#define UINT_FAST32_C(c) UINT32_C(c) + +#define INTPTR_C(c) INT32_C(c) +#define UINTPTR_C(c) UINT32_C(c) +#define PTRDIFF_C(c) INT32_C(c) + +#endif /* _BITSIZE_STDINTCONST_H */ diff -puN /dev/null usr/include/bits32/bitsize/stdint.h --- /dev/null +++ a/usr/include/bits32/bitsize/stdint.h @@ -0,0 +1,34 @@ +/* + * bits32/stdint.h + */ + +#ifndef _BITSIZE_STDINT_H +#define _BITSIZE_STDINT_H + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long long int int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; + +typedef int int_fast16_t; +typedef int int_fast32_t; + +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; + +typedef int intptr_t; +typedef unsigned int uintptr_t; + +#define __INT64_C(c) c ## LL +#define __UINT64_C(c) c ## ULL + +#define __PRI64_RANK "ll" +#define __PRIFAST_RANK "" +#define __PRIPTR_RANK "" + +#endif /* _BITSIZE_STDINT_H */ diff -puN /dev/null usr/include/bits32/bitsize/stdintlimits.h --- /dev/null +++ a/usr/include/bits32/bitsize/stdintlimits.h @@ -0,0 +1,22 @@ +/* + * bits32/stdintlimits.h + */ + +#ifndef _BITSIZE_STDINTLIMITS_H +#define _BITSIZE_STDINTLIMITS_H + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +#endif /* _BITSIZE_STDINTLIMITS_H */ diff -puN /dev/null usr/include/bits64/bitsize.h --- /dev/null +++ a/usr/include/bits64/bitsize.h @@ -0,0 +1,3 @@ +#ifndef _BITSIZE +#define _BITSIZE 64 +#endif diff -puN /dev/null usr/include/bits64/bitsize/limits.h --- /dev/null +++ a/usr/include/bits64/bitsize/limits.h @@ -0,0 +1,14 @@ +/* + * bits64/limits.h + */ + +#ifndef _BITSIZE_LIMITS_H +#define _BITSIZE_LIMITS_H + +#define LONG_BIT 64 + +#define LONG_MIN (-9223372036854775807L-1) +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL + +#endif /* _BITSIZE_LIMITS_H */ diff -puN /dev/null usr/include/bits64/bitsize/stddef.h --- /dev/null +++ a/usr/include/bits64/bitsize/stddef.h @@ -0,0 +1,13 @@ +/* + * bits64/stddef.h + */ + +#ifndef _BITSIZE_STDDEF_H +#define _BITSIZE_STDDEF_H + +#define _SIZE_T +typedef unsigned long size_t; +#define _PTRDIFF_T +typedef signed long ptrdiff_t; + +#endif /* _BITSIZE_STDDEF_H */ diff -puN /dev/null usr/include/bits64/bitsize/stdintconst.h --- /dev/null +++ a/usr/include/bits64/bitsize/stdintconst.h @@ -0,0 +1,18 @@ +/* + * bits64/stdintconst.h + */ + +#ifndef _BITSIZE_STDINTCONST_H +#define _BITSIZE_STDINTCONST_H + +#define INT_FAST16_C(c) INT64_C(c) +#define INT_FAST32_C(c) INT64_C(c) + +#define UINT_FAST16_C(c) UINT64_C(c) +#define UINT_FAST32_C(c) UINT64_C(c) + +#define INTPTR_C(c) INT64_C(c) +#define UINTPTR_C(c) UINT64_C(c) +#define PTRDIFF_C(c) INT64_C(c) + +#endif /* _BITSIZE_STDINTCONST_H */ diff -puN /dev/null usr/include/bits64/bitsize/stdint.h --- /dev/null +++ a/usr/include/bits64/bitsize/stdint.h @@ -0,0 +1,34 @@ +/* + * bits64/stdint.h + */ + +#ifndef _BITSIZE_STDINT_H +#define _BITSIZE_STDINT_H + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long int int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; + +typedef long int int_fast16_t; +typedef long int int_fast32_t; + +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; + +typedef long int intptr_t; +typedef unsigned long int uintptr_t; + +#define __INT64_C(c) c ## L +#define __UINT64_C(c) c ## UL + +#define __PRI64_RANK "l" +#define __PRIFAST_RANK "l" +#define __PRIPTR_RANK "l" + +#endif /* _BITSIZE_STDINT_H */ diff -puN /dev/null usr/include/bits64/bitsize/stdintlimits.h --- /dev/null +++ a/usr/include/bits64/bitsize/stdintlimits.h @@ -0,0 +1,22 @@ +/* + * bits64/stdintlimits.h + */ + +#ifndef _BITSIZE_STDINTLIMITS_H +#define _BITSIZE_STDINTLIMITS_H + +#define INT_FAST16_MIN INT64_MIN +#define INT_FAST32_MIN INT64_MIN +#define INT_FAST16_MAX INT64_MAX +#define INT_FAST32_MAX INT64_MAX +#define UINT_FAST16_MAX UINT64_MAX +#define UINT_FAST32_MAX UINT64_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +#endif /* _BITSIZE_STDINTLIMITS_H */ diff -puN /dev/null usr/include/byteswap.h --- /dev/null +++ a/usr/include/byteswap.h @@ -0,0 +1,15 @@ +/* + * byteswap.h + */ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H + +#include +#include + +#define bswap_16(x) __swab16(x) +#define bswap_32(x) __swab32(x) +#define bswap_64(x) __swab64(x) + +#endif /* _BYTESWAP_H */ diff -puN /dev/null usr/include/ctype.h --- /dev/null +++ a/usr/include/ctype.h @@ -0,0 +1,140 @@ +/* + * ctype.h + * + * This assumes ISO 8859-1, being a reasonable superset of ASCII. + */ + +#ifndef _CTYPE_H +#define _CTYPE_H + +#include + +/* + * This relies on the following definitions: + * + * cntrl = !print + * alpha = upper|lower + * graph = punct|alpha|digit + * blank = '\t' || ' ' (per POSIX requirement) + */ +enum { + __ctype_upper = (1 << 0), + __ctype_lower = (1 << 1), + __ctype_digit = (1 << 2), + __ctype_xdigit = (1 << 3), + __ctype_space = (1 << 4), + __ctype_print = (1 << 5), + __ctype_punct = (1 << 6), + __ctype_cntrl = (1 << 7), +}; + +extern const unsigned char __ctypes[]; + +static inline int __ctype_isalnum(int __c) +{ + return __ctypes[__c + 1] & + (__ctype_upper | __ctype_lower | __ctype_digit); +} + +static inline int __ctype_isalpha(int __c) +{ + return __ctypes[__c + 1] & (__ctype_upper | __ctype_lower); +} + +static inline int __ctype_isascii(int __c) +{ + return !(__c & ~0x7f); +} + +static inline int __ctype_isblank(int __c) +{ + return (__c == '\t') || (__c == ' '); +} + +static inline int __ctype_iscntrl(int __c) +{ + return __ctypes[__c + 1] & __ctype_cntrl; +} + +static inline int __ctype_isdigit(int __c) +{ + return ((unsigned)__c - '0') <= 9; +} + +static inline int __ctype_isgraph(int __c) +{ + return __ctypes[__c + 1] & + (__ctype_upper | __ctype_lower | __ctype_digit | __ctype_punct); +} + +static inline int __ctype_islower(int __c) +{ + return __ctypes[__c + 1] & __ctype_lower; +} + +static inline int __ctype_isprint(int __c) +{ + return __ctypes[__c + 1] & __ctype_print; +} + +static inline int __ctype_ispunct(int __c) +{ + return __ctypes[__c + 1] & __ctype_punct; +} + +static inline int __ctype_isspace(int __c) +{ + return __ctypes[__c + 1] & __ctype_space; +} + +static inline int __ctype_isupper(int __c) +{ + return __ctypes[__c + 1] & __ctype_upper; +} + +static inline int __ctype_isxdigit(int __c) +{ + return __ctypes[__c + 1] & __ctype_xdigit; +} + +/* Note: this is decimal, not hex, to avoid accidental promotion to unsigned */ +#define _toupper(__c) ((__c) & ~32) +#define _tolower(__c) ((__c) | 32) + +static inline int __ctype_toupper(int __c) +{ + return __ctype_islower(__c) ? _toupper(__c) : __c; +} + +static inline int __ctype_tolower(int __c) +{ + return __ctype_isupper(__c) ? _tolower(__c) : __c; +} + +#ifdef __CTYPE_NO_INLINE +# define __CTYPEFUNC(X) \ + __extern int X(int); +#else +#define __CTYPEFUNC(X) \ + __extern inline int X(int __c) \ + { \ + return __ctype_##X(__c); \ + } +#endif + +__CTYPEFUNC(isalnum) + __CTYPEFUNC(isalpha) + __CTYPEFUNC(isascii) + __CTYPEFUNC(isblank) + __CTYPEFUNC(iscntrl) + __CTYPEFUNC(isdigit) + __CTYPEFUNC(isgraph) + __CTYPEFUNC(islower) + __CTYPEFUNC(isprint) + __CTYPEFUNC(ispunct) + __CTYPEFUNC(isspace) + __CTYPEFUNC(isupper) + __CTYPEFUNC(isxdigit) + __CTYPEFUNC(toupper) + __CTYPEFUNC(tolower) +#endif /* _CTYPE_H */ diff -puN /dev/null usr/include/dirent.h --- /dev/null +++ a/usr/include/dirent.h @@ -0,0 +1,33 @@ +/* + * dirent.h + */ + +#ifndef _DIRENT_H +#define _DIRENT_H + +#include +#include + +struct _IO_dir { + int __fd; + +#ifdef __KLIBC_DIRENT_INTERNALS + /* These fields for internal use only */ + + size_t bytes_left; + struct dirent *next; + /* Declaring this as an array of struct enforces correct alignment */ + struct dirent buffer[15]; /* 15 times max dirent size =~ 4K */ +#endif +}; +typedef struct _IO_dir DIR; + +__extern DIR *opendir(const char *); +__extern struct dirent *readdir(DIR *); +__extern int closedir(DIR *); +static __inline__ int dirfd(DIR * __d) +{ + return __d->__fd; +} + +#endif /* _DIRENT_H */ diff -puN /dev/null usr/include/elf.h --- /dev/null +++ a/usr/include/elf.h @@ -0,0 +1,11 @@ +/* + * elf.h + */ + +#ifndef _ELF_H +#define _ELF_H + +#include +#include + +#endif /* _ELF_H */ diff -puN /dev/null usr/include/endian.h --- /dev/null +++ a/usr/include/endian.h @@ -0,0 +1,15 @@ +/* + * endian.h + */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include + +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define BIG_ENDIAN __BIG_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +#endif /* _ENDIAN_H */ diff -puN /dev/null usr/include/errno.h --- /dev/null +++ a/usr/include/errno.h @@ -0,0 +1,13 @@ +/* + * errno.h + */ + +#ifndef _ERRNO_H +#define _ERRNO_H + +#include +#include + +__extern int errno; + +#endif /* _ERRNO_H */ diff -puN /dev/null usr/include/fcntl.h --- /dev/null +++ a/usr/include/fcntl.h @@ -0,0 +1,47 @@ +/* + * fcntl.h + */ + +#ifndef _FCNTL_H +#define _FCNTL_H + +#include +#include +#include +#if defined(__mips__) && !defined(__mips64__) +# include +#endif +#include + +/* This is ugly, but "struct flock" has actually been defined with + a long off_t, so it's really "struct flock64". It just happens + to work. Gag. Barf. + + This happens to work on all 32-bit architectures except MIPS. */ + +#ifdef F_GETLK64 +# undef F_GETLK +# define F_GETLK F_GETLK64 +#endif + +#ifdef F_SETLK64 +# undef F_SETLK +# define F_SETLK F_SETLK64 +#endif + +#ifdef F_SETLKW64 +# undef F_SETLKW +# define F_SETLKW F_SETLKW64 +#endif + +/* This is defined here as well as in since old-style code + would still include when using open(), and open() being + a varadic function changes its calling convention on some architectures. */ +#ifndef _KLIBC_IN_OPEN_C +__extern int open(const char *, int, ...); +__extern int openat(int, const char *, int, ...); +#endif + +__extern int fcntl(int, int, ...); + +#endif /* _FCNTL_H */ diff -puN /dev/null usr/include/grp.h --- /dev/null +++ a/usr/include/grp.h @@ -0,0 +1,13 @@ +/* + * grp.h + */ + +#ifndef _GRP_H +#define _GRP_H + +#include +#include + +__extern int setgroups(size_t, const gid_t *); + +#endif /* _GRP_H */ diff -puN /dev/null usr/include/inttypes.h --- /dev/null +++ a/usr/include/inttypes.h @@ -0,0 +1,226 @@ +/* + * inttypes.h + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#include +#include +#include + +static __inline__ intmax_t imaxabs(intmax_t __n) +{ + return (__n < (intmax_t) 0) ? -__n : __n; +} + +__extern intmax_t strtoimax(const char *, char **, int); +__extern uintmax_t strtoumax(const char *, char **, int); + +/* extensions */ +__extern intmax_t strntoimax(const char *, char **, int, size_t); +__extern uintmax_t strntoumax(const char *, char **, int, size_t); + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 __PRI64_RANK "d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 __PRI64_RANK "d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 __PRIFAST_RANK "d" +#define PRIdFAST32 __PRIFAST_RANK "d" +#define PRIdFAST64 __PRI64_RANK "d" + +#define PRIdMAX __PRI64_RANK "d" +#define PRIdPTR __PRIPTR_RANK "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 __PRI64_RANK "i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 __PRI64_RANK "i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 __PRIFAST_RANK "i" +#define PRIiFAST32 __PRIFAST_RANK "i" +#define PRIiFAST64 __PRI64_RANK "i" + +#define PRIiMAX __PRI64_RANK "i" +#define PRIiPTR __PRIPTR_RANK "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 __PRI64_RANK "o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 __PRI64_RANK "o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 __PRIFAST_RANK "o" +#define PRIoFAST32 __PRIFAST_RANK "o" +#define PRIoFAST64 __PRI64_RANK "o" + +#define PRIoMAX __PRI64_RANK "o" +#define PRIoPTR __PRIPTR_RANK "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 __PRI64_RANK "u" + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 __PRI64_RANK "u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 __PRIFAST_RANK "u" +#define PRIuFAST32 __PRIFAST_RANK "u" +#define PRIuFAST64 __PRI64_RANK "u" + +#define PRIuMAX __PRI64_RANK "u" +#define PRIuPTR __PRIPTR_RANK "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 __PRI64_RANK "x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 __PRI64_RANK "x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 __PRIFAST_RANK "x" +#define PRIxFAST32 __PRIFAST_RANK "x" +#define PRIxFAST64 __PRI64_RANK "x" + +#define PRIxMAX __PRI64_RANK "x" +#define PRIxPTR __PRIPTR_RANK "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 __PRI64_RANK "X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 __PRI64_RANK "X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 __PRIFAST_RANK "X" +#define PRIXFAST32 __PRIFAST_RANK "X" +#define PRIXFAST64 __PRI64_RANK "X" + +#define PRIXMAX __PRI64_RANK "X" +#define PRIXPTR __PRIPTR_RANK "X" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 __PRI64_RANK "d" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 __PRI64_RANK "d" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 __PRIFAST_RANK "d" +#define SCNdFAST32 __PRIFAST_RANK "d" +#define SCNdFAST64 __PRI64_RANK "d" + +#define SCNdMAX __PRI64_RANK "d" +#define SCNdPTR __PRIPTR_RANK "d" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 __PRI64_RANK "i" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 __PRI64_RANK "i" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 __PRIFAST_RANK "i" +#define SCNiFAST32 __PRIFAST_RANK "i" +#define SCNiFAST64 __PRI64_RANK "i" + +#define SCNiMAX __PRI64_RANK "i" +#define SCNiPTR __PRIPTR_RANK "i" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 __PRI64_RANK "o" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 __PRI64_RANK "o" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 __PRIFAST_RANK "o" +#define SCNoFAST32 __PRIFAST_RANK "o" +#define SCNoFAST64 __PRI64_RANK "o" + +#define SCNoMAX __PRI64_RANK "o" +#define SCNoPTR __PRIPTR_RANK "o" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 __PRI64_RANK "u" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 __PRI64_RANK "u" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 __PRIFAST_RANK "u" +#define SCNuFAST32 __PRIFAST_RANK "u" +#define SCNuFAST64 __PRI64_RANK "u" + +#define SCNuMAX __PRI64_RANK "u" +#define SCNuPTR __PRIPTR_RANK "u" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 __PRI64_RANK "x" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 __PRI64_RANK "x" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 __PRIFAST_RANK "x" +#define SCNxFAST32 __PRIFAST_RANK "x" +#define SCNxFAST64 __PRI64_RANK "x" + +#define SCNxMAX __PRI64_RANK "x" +#define SCNxPTR __PRIPTR_RANK "x" + +#endif + +#endif /* _INTTYPES_H */ diff -puN /dev/null usr/include/Kbuild --- /dev/null +++ a/usr/include/Kbuild @@ -0,0 +1,11 @@ +always := asm + +$(obj)/asm: + @echo ' SYMLINK $@ -> include/asm-$(KLIBCASMARCH)' + $(Q)if [ '$(KLIBCKERNELSRC).' -ef '$(obj)/../..' ]; then \ + ln -fsn ../../include/asm-$(KLIBCASMARCH) $@; \ + else \ + ln -fsn $(KLIBCKERNELSRC)./include/asm-$(KLIBCASMARCH) $@; \ + fi + +clean-files := asm diff -puN /dev/null usr/include/klibc/compiler.h --- /dev/null +++ a/usr/include/klibc/compiler.h @@ -0,0 +1,123 @@ +/* + * klibc/compiler.h + * + * Various compiler features + */ + +#ifndef _KLIBC_COMPILER_H +#define _KLIBC_COMPILER_H + +/* Specific calling conventions */ +/* __cdecl is used when we want varadic and non-varadic functions to have + the same binary calling convention. */ +#ifdef __i386__ +# ifdef __GNUC__ +# define __cdecl __attribute__((cdecl,regparm(0))) +# else + /* Most other C compilers have __cdecl as a keyword */ +# endif +#else +# define __cdecl /* Meaningless on non-i386 */ +#endif + +/* How to declare a function that *must* be inlined */ +#ifdef __GNUC__ +# if __GNUC__ >= 3 +# define __must_inline static __inline__ __attribute__((always_inline)) +# else +# define __must_inline extern __inline__ +# endif +#else +# define __must_inline inline /* Just hope this works... */ +#endif + +/* How to declare a function that does not return */ +#ifdef __GNUC__ +# define __noreturn void __attribute__((noreturn)) +#else +# define __noreturn void +#endif + +/* "const" function: + + Many functions do not examine any values except their arguments, + and have no effects except the return value. Basically this is + just slightly more strict class than the `pure' attribute above, + since function is not allowed to read global memory. + + Note that a function that has pointer arguments and examines the + data pointed to must _not_ be declared `const'. Likewise, a + function that calls a non-`const' function usually must not be + `const'. It does not make sense for a `const' function to return + `void'. +*/ +#ifdef __GNUC__ +# define __constfunc __attribute__((const)) +#else +# define __constfunc +#endif +#undef __attribute_const__ +#define __attribute_const__ __constfunc + +/* "pure" function: + + Many functions have no effects except the return value and their + return value depends only on the parameters and/or global + variables. Such a function can be subject to common subexpression + elimination and loop optimization just as an arithmetic operator + would be. These functions should be declared with the attribute + `pure'. +*/ +#ifdef __GNUC__ +# define __purefunc __attribute__((pure)) +#else +# define __purefunc +#endif +#undef __attribute_pure__ +#define __attribute_pure__ __purefunc + +/* Format attribute */ +#ifdef __GNUC__ +# define __formatfunc(t,f,a) __attribute__((format(t,f,a))) +#else +# define __formatfunc(t,f,a) +#endif + +/* malloc() function (returns unaliased pointer) */ +#if defined(__GNUC__) && (__GNUC__ >= 3) +# define __mallocfunc __attribute__((malloc)) +#else +# define __mallocfunc +#endif + +/* likely/unlikely */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) +# define __likely(x) __builtin_expect((x), 1) +# define __unlikely(x) __builtin_expect((x), 0) +#else +# define __likely(x) (x) +# define __unlikely(x) (x) +#endif + +/* Possibly unused function */ +#ifdef __GNUC__ +# define __unusedfunc __attribute__((unused)) +#else +# define __unusedfunc +#endif + +/* It's all user space... */ +#define __user + +/* The bitwise attribute: disallow arithmetric operations */ +#ifdef __CHECKER__ /* sparse only */ +# define __bitwise __attribute__((bitwise)) +#else +# define __bitwise +#endif + +/* Compiler pragma to make an alias symbol */ +#define __ALIAS(__t, __f, __p, __a) \ + __t __f __p __attribute__((weak, alias(#__a))); + +#endif diff -puN /dev/null usr/include/klibc/diverr.h --- /dev/null +++ a/usr/include/klibc/diverr.h @@ -0,0 +1,15 @@ +/* + * klibc/diverr.h + */ + +#ifndef _KLIBC_DIVERR_H +#define _KLIBC_DIVERR_H + +#include + +static __inline__ void __divide_error(void) +{ + raise(SIGFPE); +} + +#endif /* _KLIBC_DIVERR_H */ diff -puN /dev/null usr/include/klibc/endian.h --- /dev/null +++ a/usr/include/klibc/endian.h @@ -0,0 +1,39 @@ +/* + * klibc/endian.h + * + * Like , but export only double-underscore symbols + */ + +#ifndef _KLIBC_ENDIAN_H +#define _KLIBC_ENDIAN_H + +#include +#include + +/* Linux' asm/byteorder.h defines either __LITTLE_ENDIAN or + __BIG_ENDIAN, but the glibc/BSD-ish macros expect both to be + defined with __BYTE_ORDER defining which is actually used... */ + +#if defined(__LITTLE_ENDIAN) +# undef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __LITTLE_ENDIAN +#elif defined(__BIG_ENDIAN) +# undef __BIG_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __BIG_ENDIAN +#elif defined(__PDP_ENDIAN) +# undef __PDP_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __PDP_ENDIAN +#else +# error "Unknown byte order!" +#endif + +#endif /* _KLIBC_ENDIAN_H */ diff -puN /dev/null usr/include/klibc/extern.h --- /dev/null +++ a/usr/include/klibc/extern.h @@ -0,0 +1,16 @@ +/* + * klibc/extern.h + */ + +#ifndef _KLIBC_EXTERN_H +#define _KLIBC_EXTERN_H + +#ifdef __cplusplus +#define __extern extern "C" +#else +#define __extern extern +#endif + +#define __alias(x) __attribute__((weak, alias(x))) + +#endif /* _KLIBC_EXTERN_H */ diff -puN /dev/null usr/include/klibc/stathelp.h --- /dev/null +++ a/usr/include/klibc/stathelp.h @@ -0,0 +1,24 @@ +/* + * stathelp.h + * + * Helper macros for + */ + +#ifndef _KLIBC_STATHELP_H +#define _KLIBC_STATHELP_H + +#include + +/* + * Most architectures have a 64-bit field for st_dev and st_rdev, + * but dev_t is 32 bits (uint32_t == unsigned int), so make a + * macro we can use across all architectures. + */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define __stdev64(x) unsigned int __##x, x; +#else +# define __stdev64(x) unsigned int x, __##x; +#endif + +#endif /* _KLIBC_STATHELP_H */ diff -puN /dev/null usr/include/klibc/sysconfig.h --- /dev/null +++ a/usr/include/klibc/sysconfig.h @@ -0,0 +1,166 @@ +/* + * klibc/sysconfig.h + * + * Allows for definitions of some things which may be system-dependent + * NOTE: this file must not result in any output from the preprocessor. + */ + +#ifndef _KLIBC_SYSCONFIG_H +#define _KLIBC_SYSCONFIG_H + +#include +#include + +/* + * These are the variables that can be defined in . + * For boolean options, #define to 0 to disable, #define to 1 to enable. + * + * If undefined, they will be given defaults here. + */ + + +/* + * _KLIBC_NO_MMU: + * + * Indicates this architecture doesn't have an MMU, and therefore + * does not have the sys_fork and sys_brk system calls. + */ +/* Default to having an MMU if we can find the fork system call */ +#ifndef _KLIBC_NO_MMU +# if defined(__NR_fork) +# define _KLIBC_NO_MMU 0 +# else +# define _KLIBC_NO_MMU 1 +# endif +#endif + + +/* + * _KLIBC_REAL_VFORK: + * + * Indicates that this architecture has a real vfork() system call. + * This is the default if sys_vfork exists; if there is an + * architecture-dependent implementation of vfork(), define this + * symbol. + */ +#ifndef _KLIBC_REAL_VFORK +# if defined(__NR_vfork) +# define _KLIBC_REAL_VFORK 1 +# else +# define _KLIBC_REAL_VFORK 0 +# endif +#endif + + +/* + * _KLIBC_USE_MMAP2: + * + * Indicates that this architecture should use sys_mmap2 instead + * of sys_mmap. This is the default on 32-bit architectures, assuming + * sys_mmap2 exists. + */ +#ifndef _KLIBC_USE_MMAP2 +# if (_BITSIZE == 32 && defined(__NR_mmap2)) || \ + (_BITSIZE == 64 && !defined(__NR_mmap)) +# define _KLIBC_USE_MMAP2 1 +# else +# define _KLIBC_USE_MMAP2 0 +# endif +#endif + + +/* + * _KLIBC_MMAP2_SHIFT: + * + * Indicate the shift of the offset parameter in sys_mmap2. + * On most architectures, this is always 12, but on some + * architectures it can be a different number, or the current + * page size. If this is dependent on the page size, define + * this to an expression which includes __getpageshift(). + */ +#ifndef _KLIBC_MMAP2_SHIFT +# define _KLIBC_MMAP2_SHIFT 12 +#endif + + +/* + * _KLIBC_MALLOC_USES_SBRK: + * + * Indicates that malloc() should use sbrk() to obtain raw memory + * from the system, rather than mmap(). + */ +/* Default to get memory using mmap() */ +#ifndef _KLIBC_MALLOC_USES_SBRK +# define _KLIBC_MALLOC_USES_SBRK 0 +#endif + + +/* + * _KLIBC_MALLOC_CHUNK_SIZE: + * This is the minimum chunk size we will ask the kernel for using + * malloc(); this should be a multiple of the page size and must + * be a power of 2. + */ +#ifndef _KLIBC_MALLOC_CHUNK_SIZE +# define _KLIBC_MALLOC_CHUNK_SIZE 65536 +#endif + + +/* + * _KLIBC_SBRK_ALIGNMENT: + * + * This is the minimum alignment for the memory returned by + * sbrk(). It must be a power of 2. If _KLIBC_MALLOC_USES_SBRK + * is set it should be no smaller than the size of struct + * arena_header in malloc.h (== 4 pointers.) + */ +#ifndef _KLIBC_SBRK_ALIGNMENT +# define _KLIBC_SBRK_ALIGNMENT 32 +#endif + + +/* + * _KLIBC_USE_RT_SIG: + * + * Indicates that this architecture should use the rt_sig*() + * family of system calls, even if the older system calls are + * provided. This requires that is correct for + * using with the rt_sig*() system calls. This is the default if + * the older system calls are undefined in . + * + */ +#ifndef _KLIBC_USE_RT_SIG +# ifdef __NR_sigaction +# define _KLIBC_USE_RT_SIG 0 +# else +# define _KLIBC_USE_RT_SIG 1 +# endif +#endif + + +/* + * _KLIBC_NEEDS_SA_RESTORER: + * + * Some architectures, like x86-64 and some i386 Fedora kernels, + * do not provide a default sigreturn, and therefore must have + * SA_RESTORER set. + */ +#ifndef _KLIBC_NEEDS_SA_RESTORER +# define _KLIBC_NEEDS_SA_RESTORER 0 +#endif + + +/* + * _KLIBC_STATFS_F_TYPE_64: + * + * This indicates that the f_type, f_bsize, f_namelen, + * f_frsize, and f_spare fields of struct statfs are + * 64 bits long. This is normally the case for 64-bit + * platforms, and so is the default for those. See + * usr/include/sys/vfs.h for the exact details. + */ +#ifndef _KLIBC_STATFS_F_TYPE_64 +# define _KLIBC_STATFS_F_TYPE_64 (_BITSIZE == 64) +#endif + +#endif /* _KLIBC_SYSCONFIG_H */ diff -puN /dev/null usr/include/limits.h --- /dev/null +++ a/usr/include/limits.h @@ -0,0 +1,40 @@ +/* + * limits.h + */ + +#ifndef _LIMITS_H +#define _LIMITS_H + +#define CHAR_BIT 8 +#define SHRT_BIT 16 +#define INT_BIT 32 +#define LONGLONG_BIT 64 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 + +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +#else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +#endif + +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535 + +#define INT_MIN (-2147483647-1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U + +#define LONGLONG_MIN (-9223372036854775807LL-1) +#define LONGLONG_MAX 9223372036854775807LL +#define ULONGLONG_MAX 18446744073709551615ULL + +#include +#include + +#endif /* _LIMITS_H */ diff -puN /dev/null usr/include/malloc.h --- /dev/null +++ a/usr/include/malloc.h @@ -0,0 +1,21 @@ +/* + * malloc.h + * + * Apparently people haven't caught on to use , which is the + * standard place for this crap since the 1980's... + */ + +#ifndef _MALLOC_H +#define _MALLOC_H + +#include +#include +#include + +__extern void free(void *); + +__extern __mallocfunc void *malloc(size_t); +__extern __mallocfunc void *calloc(size_t, size_t); +__extern __mallocfunc void *realloc(void *, size_t); + +#endif /* _MALLOC_H */ diff -puN /dev/null usr/include/net/if_arp.h --- /dev/null +++ a/usr/include/net/if_arp.h @@ -0,0 +1 @@ +#include diff -puN /dev/null usr/include/net/if.h --- /dev/null +++ a/usr/include/net/if.h @@ -0,0 +1,7 @@ +#ifndef _NET_IF_H +#define _NET_IF_H + +#include +#include + +#endif /* _NET_IF_H */ diff -puN /dev/null usr/include/net/if_packet.h --- /dev/null +++ a/usr/include/net/if_packet.h @@ -0,0 +1 @@ +#include diff -puN /dev/null usr/include/netinet/if_ether.h --- /dev/null +++ a/usr/include/netinet/if_ether.h @@ -0,0 +1 @@ +#include diff -puN /dev/null usr/include/netinet/in6.h --- /dev/null +++ a/usr/include/netinet/in6.h @@ -0,0 +1,10 @@ +/* + * netinet/in6.h + */ + +#ifndef _NETINET_IN6_H +#define _NETINET_IN6_H + +#include + +#endif /* _NETINET_IN6_H */ diff -puN /dev/null usr/include/netinet/in.h --- /dev/null +++ a/usr/include/netinet/in.h @@ -0,0 +1,39 @@ +/* + * netinet/in.h + */ + +#ifndef _NETINET_IN_H +#define _NETINET_IN_H + +/* added this include by Mats Petersson */ +#include + +#include +#include +#include /* Must be included *before* */ +#include + +#ifndef htons +# define htons(x) __cpu_to_be16(x) +#endif +#ifndef ntohs +# define ntohs(x) __be16_to_cpu(x) +#endif +#ifndef htonl +# define htonl(x) __cpu_to_be32(x) +#endif +#ifndef ntohl +# define ntohl(x) __be32_to_cpu(x) +#endif +#ifndef htonq +# define htonq(x) __cpu_to_be64(x) +#endif +#ifndef ntohq +# define ntohq(x) __be64_to_cpu(x) +#endif + +#define IPPORT_RESERVED 1024 + +__extern int bindresvport(int sd, struct sockaddr_in *sin); + +#endif /* _NETINET_IN_H */ diff -puN /dev/null usr/include/netinet/ip.h --- /dev/null +++ a/usr/include/netinet/ip.h @@ -0,0 +1,13 @@ +/* + * netinet/ip.h + */ + +#ifndef _NETINET_IP_H +#define _NETINET_IP_H + +#include +#include + +#define IP_DF 0x4000 /* Flag: "Don't Fragment" */ + +#endif /* _NETINET_IP_H */ diff -puN /dev/null usr/include/netinet/tcp.h --- /dev/null +++ a/usr/include/netinet/tcp.h @@ -0,0 +1,11 @@ +/* + * netinet/tcp.h + */ + +#ifndef _NETINET_TCP_H +#define _NETINET_TCP_H + +#include /* Include *before* linux/tcp.h */ +#include + +#endif /* _NETINET_TCP_H */ diff -puN /dev/null usr/include/netinet/udp.h --- /dev/null +++ a/usr/include/netinet/udp.h @@ -0,0 +1,19 @@ +/* + * netinet/udp.h + */ + +#ifndef _NETINET_UDP_H +#define _NETINET_UDP_H + +/* + * We would include linux/udp.h, but it brings in too much other stuff + */ + +struct udphdr { + __u16 source; + __u16 dest; + __u16 len; + __u16 check; +}; + +#endif /* _NETINET_UDP_H */ diff -puN /dev/null usr/include/netpacket/packet.h --- /dev/null +++ a/usr/include/netpacket/packet.h @@ -0,0 +1 @@ +#include diff -puN /dev/null usr/include/net/route.h --- /dev/null +++ a/usr/include/net/route.h @@ -0,0 +1 @@ +#include diff -puN /dev/null usr/include/paths.h --- /dev/null +++ a/usr/include/paths.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)paths.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PATHS_H_ +#define _PATHS_H_ + +/* Default search path. */ +#define _PATH_DEFPATH "/usr/bin:/bin" +/* All standard utilities path. */ +#define _PATH_STDPATH \ + "/usr/bin:/bin:/usr/sbin:/sbin" + +#define _PATH_BSHELL "/bin/sh" +#define _PATH_CONSOLE "/dev/console" +#define _PATH_CSHELL "/bin/csh" +#define _PATH_DEVDB "/var/run/dev.db" +#define _PATH_DEVNULL "/dev/null" +#define _PATH_DRUM "/dev/drum" +#define _PATH_KLOG "/proc/kmsg" +#define _PATH_KMEM "/dev/kmem" +#define _PATH_LASTLOG "/var/log/lastlog" +#define _PATH_MAILDIR "/var/mail" +#define _PATH_MAN "/usr/share/man" +#define _PATH_MEM "/dev/mem" +#define _PATH_MNTTAB "/etc/fstab" +#define _PATH_MOUNTED "/etc/mtab" +#define _PATH_NOLOGIN "/etc/nologin" +#define _PATH_PRESERVE "/var/lib" +#define _PATH_RWHODIR "/var/spool/rwho" +#define _PATH_SENDMAIL "/usr/sbin/sendmail" +#define _PATH_SHADOW "/etc/shadow" +#define _PATH_SHELLS "/etc/shells" +#define _PATH_TTY "/dev/tty" +#define _PATH_UNIX "/boot/vmlinux" +#define _PATH_UTMP "/var/run/utmp" +#define _PATH_VI "/bin/vi" +#define _PATH_WTMP "/var/log/wtmp" + +/* Provide trailing slash, since mostly used for building pathnames. */ +#define _PATH_DEV "/dev/" +#define _PATH_TMP "/tmp/" +#define _PATH_VARDB "/var/db/" +#define _PATH_VARRUN "/var/run/" +#define _PATH_VARTMP "/var/tmp/" + +#endif /* !_PATHS_H_ */ diff -puN /dev/null usr/include/poll.h --- /dev/null +++ a/usr/include/poll.h @@ -0,0 +1 @@ +#include diff -puN /dev/null usr/include/sched.h --- /dev/null +++ a/usr/include/sched.h @@ -0,0 +1,36 @@ +/* + * sched.h + */ + +#ifndef _SCHED_H +#define _SCHED_H + +#include + +/* linux/sched.h is unusable; put the declarations we need here... */ + +#define SCHED_NORMAL 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 + +struct sched_param { + int sched_priority; +}; + +__extern int sched_setscheduler(pid_t, int, const struct sched_param *); +__extern int sched_yield(void); + +/* Raw interfaces to clone(2); only actually usable for non-VM-cloning */ +#ifdef __ia64__ +__extern pid_t __clone2(int, void *, void *); +static __inline__ pid_t __clone(int _f, void *_sp) +{ + /* If this is used with _sp != 0 it will have the effect of the sp + and rsp growing away from a single point in opposite directions. */ + return __clone2(_f, _sp, _sp); +} +#else +__extern pid_t __clone(int, void *); +#endif + +#endif /* _SCHED_H */ diff -puN /dev/null usr/include/setjmp.h --- /dev/null +++ a/usr/include/setjmp.h @@ -0,0 +1,43 @@ +/* + * setjmp.h + */ + +#ifndef _SETJMP_H +#define _SETJMP_H + +#include +#include +#include +#include + +#include + +__extern int setjmp(jmp_buf); +__extern __noreturn longjmp(jmp_buf, int); + +/* + Whose bright idea was it to add unrelated functionality to just about + the only function in the standard C library (setjmp) which cannot be + wrapped by an ordinary function wrapper? Anyway, the damage is done, + and therefore, this wrapper *must* be inline. However, gcc will + complain if this is an inline function for unknown reason, and + therefore sigsetjmp() needs to be a macro. +*/ + +struct __sigjmp_buf { + jmp_buf __jmpbuf; + sigset_t __sigs; +}; + +typedef struct __sigjmp_buf sigjmp_buf[1]; + +#define sigsetjmp(__env, __save) \ +({ \ + struct __sigjmp_buf *__e = (__env); \ + sigprocmask(0, NULL, &__e->__sigs); \ + setjmp(__e->__jmpbuf); \ +}) + +__extern __noreturn siglongjmp(sigjmp_buf, int); + +#endif /* _SETJMP_H */ diff -puN /dev/null usr/include/signal.h --- /dev/null +++ a/usr/include/signal.h @@ -0,0 +1,97 @@ +/* + * signal.h + */ + +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include +#include +#include /* For memset() */ +#include /* For LONG_BIT */ +#include + +#include /* Includes if appropriate */ + +/* glibc seems to use sig_atomic_t as "int" pretty much on all architectures. + Do the same, but allow the architecture to override. */ +#ifndef _KLIBC_HAS_ARCH_SIG_ATOMIC_T +typedef int sig_atomic_t; +#endif + +/* Some architectures don't define these */ +#ifndef SA_RESETHAND +# define SA_RESETHAND SA_ONESHOT +#endif +#ifndef SA_NODEFER +# define SA_NODEFER SA_NOMASK +#endif +/* Some architectures define NSIG and not _NSIG or vice versa */ +#ifndef NSIG +# define NSIG _NSIG +#endif +#ifndef _NSIG +# define _NSIG NSIG +#endif + +/* If we don't have any real-time signals available to userspace, + hide them all */ +#if SIGRTMAX <= SIGRTMIN +# undef SIGRTMIN +# undef SIGRTMAX +#endif + +/* The kernel header files are inconsistent whether or not + SIGRTMAX is inclusive or exclusive. POSIX seems to state that + it's inclusive, however. */ +#if SIGRTMAX >= _NSIG +# undef SIGRTMAX +# define SIGRTMAX (_NSIG-1) +#endif + +__extern const char *const sys_siglist[_NSIG]; +__extern const char *const sys_sigabbrev[_NSIG]; + +/* This assumes sigset_t is either an unsigned long or an array of such, + and that _NSIG_BPW in the kernel is always LONG_BIT */ + +static __inline__ int sigemptyset(sigset_t * __set) +{ + memset(__set, 0, sizeof *__set); + return 0; +} +static __inline__ int sigfillset(sigset_t * __set) +{ + memset(__set, ~0, sizeof *__set); + return 0; +} +static __inline__ int sigaddset(sigset_t * __set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + __lset[__signum / LONG_BIT] |= 1UL << (__signum % LONG_BIT); + return 0; +} +static __inline__ int sigdelset(sigset_t * __set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + __lset[__signum / LONG_BIT] &= ~(1UL << (__signum % LONG_BIT)); + return 0; +} +static __inline__ int sigismember(sigset_t * __set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + return (int)((__lset[__signum / LONG_BIT] >> (__signum % LONG_BIT)) & + 1); +} + +__extern __sighandler_t __signal(int, __sighandler_t, int); +__extern __sighandler_t sysv_signal(int, __sighandler_t); +__extern __sighandler_t bsd_signal(int, __sighandler_t); +__extern int sigaction(int, const struct sigaction *, struct sigaction *); +__extern int sigprocmask(int, const sigset_t *, sigset_t *); +__extern int sigpending(sigset_t *); +__extern int sigsuspend(const sigset_t *); +__extern int raise(int); +__extern int kill(pid_t, int); + +#endif /* _SIGNAL_H */ diff -puN /dev/null usr/include/stdarg.h --- /dev/null +++ a/usr/include/stdarg.h @@ -0,0 +1,14 @@ +/* + * stdarg.h + * + * This is just a wrapper for the gcc one, but defines va_copy() + * even if gcc doesn't. + */ + +/* Note: the _STDARG_H macro belongs to the gcc header... */ +#include_next + +/* Older gcc considers this an extension, so it's double underbar only */ +#ifndef va_copy +#define va_copy(d,s) __va_copy(d,s) +#endif diff -puN /dev/null usr/include/stddef.h --- /dev/null +++ a/usr/include/stddef.h @@ -0,0 +1,24 @@ +/* + * stddef.h + */ + +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef __KLIBC__ +# error "__KLIBC__ not defined, compiler invocation error!" +#endif + +#include + +#undef NULL +#ifdef __cplusplus +# define NULL 0 +#else +# define NULL ((void *)0) +#endif + +#undef offsetof +#define offsetof(t,m) ((size_t)&((t *)0)->m) + +#endif /* _STDDEF_H */ diff -puN /dev/null usr/include/stdint.h --- /dev/null +++ a/usr/include/stdint.h @@ -0,0 +1,116 @@ +/* + * stdint.h + */ + +#ifndef _STDINT_H +#define _STDINT_H + +#include + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +typedef int8_t int_fast8_t; +typedef int64_t int_fast64_t; + +typedef uint8_t uint_fast8_t; +typedef uint64_t uint_fast64_t; + +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647-1) +#define INT64_MIN (__INT64_C(-9223372036854775807)-1) + +#define INT8_MAX (127) +#define INT16_MAX (32767) +#define INT32_MAX (2147483647) +#define INT64_MAX (__INT64_C(9223372036854775807)) + +#define UINT8_MAX (255U) +#define UINT16_MAX (65535U) +#define UINT32_MAX (4294967295U) +#define UINT64_MAX (__UINT64_C(18446744073709551615)) + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#include + +#endif + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(c) c +#define INT16_C(c) c +#define INT32_C(c) c +#define INT64_C(c) __INT64_C(c) + +#define UINT8_C(c) c ## U +#define UINT16_C(c) c ## U +#define UINT32_C(c) c ## U +#define UINT64_C(c) __UINT64_C(c) + +#define INT_LEAST8_C(c) INT8_C(c) +#define INT_LEAST16_C(c) INT16_C(c) +#define INT_LEAST32_C(c) INT32_C(c) +#define INT_LEAST64_C(c) INT64_C(c) + +#define UINT_LEAST8_C(c) UINT8_C(c) +#define UINT_LEAST16_C(c) UINT16_C(c) +#define UINT_LEAST32_C(c) UINT32_C(c) +#define UINT_LEAST64_C(c) UINT64_C(c) + +#define INT_FAST8_C(c) INT8_C(c) +#define INT_FAST64_C(c) INT64_C(c) + +#define UINT_FAST8_C(c) UINT8_C(c) +#define UINT_FAST64_C(c) UINT64_C(c) + +#define INTMAX_C(c) INT64_C(c) +#define UINTMAX_C(c) UINT64_C(c) + +#include + +#endif + +/* Keep the kernel from trying to define these types... */ +#define __BIT_TYPES_DEFINED__ + +#endif /* _STDINT_H */ diff -puN /dev/null usr/include/stdio.h --- /dev/null +++ a/usr/include/stdio.h @@ -0,0 +1,128 @@ +/* + * stdio.h + */ + +#ifndef _STDIO_H +#define _STDIO_H + +#include +#include +#include +#include + +/* This structure doesn't really exist, but it gives us something + to define FILE * with */ +struct _IO_file; +typedef struct _IO_file FILE; + +#ifndef EOF +# define EOF (-1) +#endif + +#ifndef BUFSIZ +# define BUFSIZ 4096 +#endif + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +/* + * Convert between a FILE * and a file descriptor. We don't actually + * have any in-memory data, so we just abuse the pointer itself to + * hold the data. Note, however, that for file descriptors, -1 is + * error and 0 is a valid value; for FILE *, NULL (0) is error and + * non-NULL are valid. + */ +static __inline__ int fileno(FILE * __f) +{ + /* This should really be intptr_t, but size_t should be the same size */ + return (int)(size_t) __f - 1; +} + +/* This is a macro so it can be used as initializer */ +#define __create_file(__fd) ((FILE *)(size_t)((__fd) + 1)) + +#define stdin __create_file(0) +#define stdout __create_file(1) +#define stderr __create_file(2) + +__extern FILE *fopen(const char *, const char *); + +static __inline__ FILE *fdopen(int __fd, const char *__m) +{ + (void)__m; + return __create_file(__fd); +} +static __inline__ int fclose(FILE * __f) +{ + extern int close(int); + return close(fileno(__f)); +} +static __inline__ int fseek(FILE * __f, off_t __o, int __w) +{ + extern off_t lseek(int, off_t, int); + return (lseek(fileno(__f), __o, __w) == (off_t) - 1) ? -1 : 0; +} +static __inline__ off_t ftell(FILE * __f) +{ + extern off_t lseek(int, off_t, int); + return lseek(fileno(__f), 0, SEEK_CUR); +} + +__extern int fputs(const char *, FILE *); +__extern int puts(const char *); +__extern int fputc(int, FILE *); +#define putc(c,f) fputc((c),(f)) +#define putchar(c) fputc((c),stdout) + +__extern int fgetc(FILE *); +__extern char *fgets(char *, int, FILE *); +#define getc(f) fgetc(f) +#define getchar() fgetc(stdin) + +__extern size_t _fread(void *, size_t, FILE *); +__extern size_t _fwrite(const void *, size_t, FILE *); + +#ifndef __NO_FREAD_FWRITE_INLINES +extern __inline__ size_t fread(void *__p, size_t __s, size_t __n, FILE * __f) +{ + return _fread(__p, __s * __n, __f) / __s; +} + +extern __inline__ size_t +fwrite(const void *__p, size_t __s, size_t __n, FILE * __f) +{ + return _fwrite(__p, __s * __n, __f) / __s; +} +#endif + +__extern int printf(const char *, ...); +__extern int vprintf(const char *, va_list); +__extern int fprintf(FILE *, const char *, ...); +__extern int vfprintf(FILE *, const char *, va_list); +__extern int sprintf(char *, const char *, ...); +__extern int vsprintf(char *, const char *, va_list); +__extern int snprintf(char *, size_t n, const char *, ...); +__extern int vsnprintf(char *, size_t n, const char *, va_list); +__extern int asprintf(char **, const char *, ...); +__extern int vasprintf(char **, const char *, va_list); + +/* No buffering, so no flushing needed */ +extern __inline__ int fflush(FILE * __f) +{ + (void)__f; + return 0; +} + +__extern int sscanf(const char *, const char *, ...); +__extern int vsscanf(const char *, const char *, va_list); + +__extern void perror(const char *); + +__extern int rename(const char *, const char *); +__extern int renameat(int, const char *, int, const char *); + +__extern int remove(const char *); + +#endif /* _STDIO_H */ diff -puN /dev/null usr/include/stdlib.h --- /dev/null +++ a/usr/include/stdlib.h @@ -0,0 +1,94 @@ +/* + * stdlib.h + */ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#include +#include +#include + +#include + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +__extern __noreturn abort(void); +static __inline__ int abs(int __n) +{ + return (__n < 0) ? -__n : __n; +} +__extern int system(const char *string); +__extern int atexit(void (*)(void)); +__extern int on_exit(void (*)(int, void *), void *); +__extern int atoi(const char *); +__extern long atol(const char *); +__extern long long atoll(const char *); +__extern __noreturn exit(int); +__extern __noreturn _exit(int); +#define _Exit _exit +static __inline__ long labs(long __n) +{ + return (__n < 0L) ? -__n : __n; +} + +static __inline__ long long llabs(long long __n) +{ + return (__n < 0LL) ? -__n : __n; +} + +__extern long strtol(const char *, char **, int); +__extern long long strtoll(const char *, char **, int); +__extern unsigned long strtoul(const char *, char **, int); +__extern unsigned long long strtoull(const char *, char **, int); + +__extern char *getenv(const char *); +__extern int putenv(const char *); +__extern int setenv(const char *, const char *, int); +__extern int unsetenv(const char *); +__extern int clearenv(void); + +typedef int (*__comparefunc_t) (const void *, const void *); +__extern void *bsearch(const void *, const void *, size_t, size_t, + __comparefunc_t); +__extern void qsort(void *, size_t, size_t, __comparefunc_t); + +__extern long jrand48(unsigned short *); +__extern long mrand48(void); +__extern long nrand48(unsigned short *); +__extern long lrand48(void); +__extern unsigned short *seed48(const unsigned short *); +__extern void srand48(long); + +#define RAND_MAX 0x7fffffff +static __inline__ int rand(void) +{ + return (int)lrand48(); +} +static __inline__ void srand(unsigned int __s) +{ + srand48(__s); +} +static __inline__ long random(void) +{ + return lrand48(); +} +static __inline__ void srandom(unsigned int __s) +{ + srand48(__s); +} + +/* Basic PTY functions. These only work if devpts is mounted! */ + +__extern int unlockpt(int); +__extern char *ptsname(int); +__extern int getpt(void); + +static __inline__ int grantpt(int __fd) +{ + (void)__fd; + return 0; /* devpts does this all for us! */ +} + +#endif /* _STDLIB_H */ diff -puN /dev/null usr/include/string.h --- /dev/null +++ a/usr/include/string.h @@ -0,0 +1,47 @@ +/* + * string.h + */ + +#ifndef _STRING_H +#define _STRING_H + +#include +#include + +__extern void *memccpy(void *, const void *, int, size_t); +__extern void *memchr(const void *, int, size_t); +__extern void *memrchr(const void *, int, size_t); +__extern int memcmp(const void *, const void *, size_t); +__extern void *memcpy(void *, const void *, size_t); +__extern void *memmove(void *, const void *, size_t); +__extern void *memset(void *, int, size_t); +__extern void *memmem(const void *, size_t, const void *, size_t); +__extern void memswap(void *, void *, size_t); +__extern int strcasecmp(const char *, const char *); +__extern int strncasecmp(const char *, const char *, size_t); +__extern char *strcat(char *, const char *); +__extern char *strchr(const char *, int); +__extern char *index(const char *, int); +__extern char *strrchr(const char *, int); +__extern char *rindex(const char *, int); +__extern int strcmp(const char *, const char *); +__extern char *strcpy(char *, const char *); +__extern size_t strcspn(const char *, const char *); +__extern char *strdup(const char *); +__extern char *strndup(const char *, size_t); +__extern char *strerror(int); +__extern char *strsignal(int); +__extern size_t strlen(const char *); +__extern size_t strnlen(const char *, size_t); +__extern char *strncat(char *, const char *, size_t); +__extern size_t strlcat(char *, const char *, size_t); +__extern int strncmp(const char *, const char *, size_t); +__extern char *strncpy(char *, const char *, size_t); +__extern size_t strlcpy(char *, const char *, size_t); +__extern char *strpbrk(const char *, const char *); +__extern char *strsep(char **, const char *); +__extern size_t strspn(const char *, const char *); +__extern char *strstr(const char *, const char *); +__extern char *strtok(char *, const char *); + +#endif /* _STRING_H */ diff -puN /dev/null usr/include/sys/dirent.h --- /dev/null +++ a/usr/include/sys/dirent.h @@ -0,0 +1,32 @@ +/* + * sys/dirent.h + */ + +#ifndef _SYS_DIRENT_H +#define _SYS_DIRENT_H + +#include + +/* The kernel calls this struct dirent64 */ +struct dirent { + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +/* File types to use for d_type */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +__extern int getdents(unsigned int, struct dirent *, unsigned int); + +#endif /* _SYS_DIRENT_H */ diff -puN /dev/null usr/include/sys/elf32.h --- /dev/null +++ a/usr/include/sys/elf32.h @@ -0,0 +1,113 @@ +/* + * sys/elf32.h + */ + +#ifndef _SYS_ELF32_H +#define _SYS_ELF32_H + +#include + +/* ELF standard typedefs (yet more proof that was way overdue) */ +typedef uint16_t Elf32_Half; +typedef int16_t Elf32_SHalf; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; + +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Section; + +/* Dynamic header */ + +typedef struct elf32_dyn { + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +/* Relocations */ + +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf32_rela { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Symbol */ + +typedef struct elf32_sym { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +/* Main file header */ + +typedef struct elf32_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* Program header */ + +typedef struct elf32_phdr { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* Section header */ + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* Note header */ +typedef struct elf32_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +#endif /* _SYS_ELF32_H */ diff -puN /dev/null usr/include/sys/elf64.h --- /dev/null +++ a/usr/include/sys/elf64.h @@ -0,0 +1,113 @@ +/* + * sys/elf64.h + */ + +#ifndef _SYS_ELF64_H +#define _SYS_ELF64_H + +#include + +/* ELF standard typedefs (yet more proof that was way overdue) */ +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Section; + +/* Dynamic header */ + +typedef struct elf64_dyn { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* Relocations */ + +#define ELF64_R_SYM(x) ((x) >> 32) +#define ELF64_R_TYPE(x) ((x) & 0xffffffff) + +typedef struct elf64_rel { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +/* Symbol */ + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* Main file header */ + +typedef struct elf64_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* Program header */ + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +/* Section header */ + +typedef struct elf64_shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* Note header */ +typedef struct elf64_note { + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; + +#endif /* _SYS_ELF64_H */ diff -puN /dev/null usr/include/sys/elfcommon.h --- /dev/null +++ a/usr/include/sys/elfcommon.h @@ -0,0 +1,187 @@ +/* + * sys/elfcommon.h + */ + +#ifndef _SYS_ELFCOMMON_H +#define _SYS_ELFCOMMON_H + +#include + +/* Segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 /* Extension, eh? */ + +/* ELF file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* ELF machine types */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Not used in Linux at least */ +#define EM_860 7 +#define EM_MIPS 8 /* R3k, bigendian(?) */ +#define EM_MIPS_RS4_BE 10 /* R4k BE */ +#define EM_PARISC 15 +#define EM_SPARC32PLUS 18 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 +#define EM_SH 42 +#define EM_SPARCV9 43 /* v9 = SPARC64 */ +#define EM_H8_300H 47 +#define EM_H8S 48 +#define EM_IA_64 50 /* Itanic */ +#define EM_X86_64 62 +#define EM_CRIS 76 +#define EM_V850 87 +#define EM_ALPHA 0x9026 /* Interrim Alpha that stuck around */ +#define EM_CYGNUS_V850 0x9080 /* Old v850 ID used by Cygnus */ +#define EM_S390_OLD 0xA390 /* Obsolete interrim value for S/390 */ + +/* Dynamic type values */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* Auxilliary table entries */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ +#define AT_PLATFORM 15 /* string identifying CPU for optimizations */ +#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define AT_CLKTCK 17 /* frequency at which times() increments */ +/* 18..22 = ? */ +#define AT_SECURE 23 /* secure mode boolean */ + +/* Program header permission flags */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 + +/* Section header types */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* Section header flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* Special section numbers */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +/* Lenght of magic at the start of a file */ +#define EI_NIDENT 16 + +/* Magic number constants... */ +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#endif /* _SYS_ELFCOMMON_H */ diff -puN /dev/null usr/include/sys/fsuid.h --- /dev/null +++ a/usr/include/sys/fsuid.h @@ -0,0 +1,14 @@ +/* + * sys/fsuid.h + */ + +#ifndef _SYS_FSUID_H +#define _SYS_FSUID_H + +#include +#include + +__extern int setfsuid(uid_t); +__extern int setfsgid(gid_t); + +#endif /* _SYS_FSUID_H */ diff -puN /dev/null usr/include/sys/inotify.h --- /dev/null +++ a/usr/include/sys/inotify.h @@ -0,0 +1,16 @@ +/* + * sys/inotify.h + */ + +#ifndef _SYS_INOTIFY_H +#define _SYS_INOTIFY_H + +#include +#include +#include + +__extern int inotify_init(void); +__extern int inotify_add_watch(int, const char *, __u32); +__extern int inotify_rm_watch(int, __u32); + +#endif /* _SYS_INOTIFY_H */ diff -puN /dev/null usr/include/sys/ioctl.h --- /dev/null +++ a/usr/include/sys/ioctl.h @@ -0,0 +1,14 @@ +/* + * sys/ioctl.h + */ + +#ifndef _SYS_IOCTL_H +#define _SYS_IOCTL_H + +#include +#include +#include + +__extern int ioctl(int, int, void *); + +#endif /* _SYS_IOCTL_H */ diff -puN /dev/null usr/include/sys/klog.h --- /dev/null +++ a/usr/include/sys/klog.h @@ -0,0 +1,24 @@ +/* + * sys/klog.h + */ + +#ifndef _SYS_KLOG_H +#define _SYS_KLOG_H + +#include + +#define KLOG_CLOSE 0 +#define KLOG_OPEN 1 +#define KLOG_READ 2 +#define KLOG_READ_ALL 3 +#define KLOG_READ_CLEAR 4 +#define KLOG_CLEAR 5 +#define KLOG_DISABLE 6 +#define KLOG_ENABLE 7 +#define KLOG_SETLEVEL 8 +#define KLOG_UNREADSIZE 9 +#define KLOG_WRITE 10 + +__extern int klogctl(int, char *, int); + +#endif /* _SYS_KLOG_H */ diff -puN /dev/null usr/include/syslog.h --- /dev/null +++ a/usr/include/syslog.h @@ -0,0 +1,62 @@ +/* + * syslog.h + */ + +#ifndef _SYSLOG_H +#define _SYSLOG_H + +#include +#include + +/* Alert levels */ +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#define LOG_PRIMASK 7 +#define LOG_PRI(x) ((x) & LOG_PRIMASK) + +/* Facilities; not actually used */ +#define LOG_KERN 0000 +#define LOG_USER 0010 +#define LOG_MAIL 0020 +#define LOG_DAEMON 0030 +#define LOG_AUTH 0040 +#define LOG_SYSLOG 0050 +#define LOG_LPR 0060 +#define LOG_NEWS 0070 +#define LOG_UUCP 0100 +#define LOG_CRON 0110 +#define LOG_AUTHPRIV 0120 +#define LOG_FTP 0130 +#define LOG_LOCAL0 0200 +#define LOG_LOCAL1 0210 +#define LOG_LOCAL2 0220 +#define LOG_LOCAL3 0230 +#define LOG_LOCAL4 0240 +#define LOG_LOCAL5 0250 +#define LOG_LOCAL6 0260 +#define LOG_LOCAL7 0270 + +#define LOG_FACMASK 01770 +#define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3)) + +/* openlog() flags; only LOG_PID and LOG_PERROR supported */ +#define LOG_PID 0x01 /* include pid with message */ +#define LOG_CONS 0x02 /* write to console on logger error */ +#define LOG_ODELAY 0x04 /* delay connection until syslog() */ +#define LOG_NDELAY 0x08 /* open connection immediately */ +#define LOG_NOWAIT 0x10 /* wait for child processes (unused on linux) */ +#define LOG_PERROR 0x20 /* additional logging to stderr */ + +__extern void openlog(const char *, int, int); +__extern void syslog(int, const char *, ...); +__extern void vsyslog(int, const char *, va_list); +__extern void closelog(void); + +#endif /* _SYSLOG_H */ diff -puN /dev/null usr/include/sys/md.h --- /dev/null +++ a/usr/include/sys/md.h @@ -0,0 +1,32 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006 H. Peter Anvin - All Rights Reserved + * + * 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/md.h + * + * Defines for the Linux md functionality. Some of this stuff is + * userspace-visible but lives in md_k.h, which is user-space unsafe. + * Sigh. + */ + +#ifndef _SYS_MD_H +#define _SYS_MD_H + +#define LEVEL_MULTIPATH (-4) +#define LEVEL_LINEAR (-1) +#define LEVEL_FAULTY (-5) +#define MAX_MD_DEVS 256 /* Max number of md dev */ + +#include +#include + +#endif /* _SYS_MD_H */ diff -puN /dev/null usr/include/sys/mman.h --- /dev/null +++ a/usr/include/sys/mman.h @@ -0,0 +1,24 @@ +/* + * sys/mman.h + */ + +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H + +#include +#include +#include + +#define MAP_FAILED ((void *)-1) + +__extern void *mmap(void *, size_t, int, int, int, off_t); +__extern int munmap(void *, size_t); +__extern void *mremap(void *, size_t, size_t, unsigned long); +__extern int msync(const void *, size_t, int); +__extern int mprotect(const void *, size_t, int); +__extern int mlockall(int); +__extern int munlockall(void); +__extern int mlock(const void *, size_t); +__extern int munlock(const void *, size_t); + +#endif /* _SYS_MMAN_H */ diff -puN /dev/null usr/include/sys/mount.h --- /dev/null +++ a/usr/include/sys/mount.h @@ -0,0 +1,71 @@ +/* + * sys/mount.h + */ + +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +#include +#include + +/* + * These are the fs-independent mount-flags: up to 32 flags are supported + */ +#define MS_RDONLY 0x0001 /* Mount read-only */ +#define MS_NOSUID 0x0002 /* Ignore suid and sgid bits */ +#define MS_NODEV 0x0004 /* Disallow access to device special files */ +#define MS_NOEXEC 0x0008 /* Disallow program execution */ +#define MS_SYNCHRONOUS 0x0010 /* Writes are synced at once */ +#define MS_REMOUNT 0x0020 /* Alter flags of a mounted FS */ +#define MS_MANDLOCK 0x0040 /* Allow mandatory locks on an FS */ +#define MS_DIRSYNC 0x0080 /* Directory modifications are synchronous */ +#define MS_NOATIME 0x0400 /* Do not update access times. */ +#define MS_NODIRATIME 0x0800 /* Do not update directory access times */ +#define MS_BIND 0x1000 +#define MS_MOVE 0x2000 +#define MS_REC 0x4000 +#define MS_VERBOSE 0x8000 +#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ +#define MS_ONE_SECOND (1<<17) /* fs has 1 sec a/m/ctime resolution */ +#define MS_ACTIVE (1<<30) +#define MS_NOUSER (1<<31) + +/* + * Superblock flags that can be altered by MS_REMOUNT + */ +#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME) + +/* + * Old magic mount flag and mask + */ +#define MS_MGC_VAL 0xC0ED0000 +#define MS_MGC_MSK 0xffff0000 + +/* + * umount2() flags + */ +#define MNT_FORCE 1 /* Forcibly unmount */ +#define MNT_DETACH 2 /* Detach from tree only */ +#define MNT_EXPIRE 4 /* Mark for expiry */ + +/* + * Block device ioctls + */ +#define BLKROSET _IO(0x12, 93) /* Set device read-only (0 = read-write). */ +#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */ +#define BLKRRPART _IO(0x12, 95) /* Re-read partition table. */ +#define BLKGETSIZE _IO(0x12, 96) /* Return device size. */ +#define BLKFLSBUF _IO(0x12, 97) /* Flush buffer cache. */ +#define BLKRASET _IO(0x12, 98) /* Set read ahead for block device. */ +#define BLKRAGET _IO(0x12, 99) /* Get current read ahead setting. */ + +/* + * Prototypes + */ +__extern int mount(const char *, const char *, + const char *, unsigned long, const void *); +__extern int umount(const char *); +__extern int umount2(const char *, int); +__extern int pivot_root(const char *, const char *); + +#endif /* _SYS_MOUNT_H */ diff -puN /dev/null usr/include/sys/param.h --- /dev/null +++ a/usr/include/sys/param.h @@ -0,0 +1,11 @@ +/* + * sys/param.h + */ + +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H + +#include +#include + +#endif /* _SYS_PARAM_H */ diff -puN /dev/null usr/include/sys/poll.h --- /dev/null +++ a/usr/include/sys/poll.h @@ -0,0 +1,20 @@ +/* + * poll.h + */ + +#ifndef _POLL_H +#define _POLL_H + +#include +#include +#include +#include + +/* POSIX specifies "int" for the timeout, Linux seems to use long... */ + +typedef unsigned int nfds_t; +__extern int poll(struct pollfd *, nfds_t, long); +__extern int ppoll(struct pollfd *, nfds_t, struct timespec *, + const sigset_t *); + +#endif /* _POLL_H */ diff -puN /dev/null usr/include/sys/reboot.h --- /dev/null +++ a/usr/include/sys/reboot.h @@ -0,0 +1,25 @@ +/* + * sys/reboot.h + */ + +#ifndef _SYS_REBOOT_H +#define _SYS_REBOOT_H + +#include +#include + +/* glibc names these constants differently; allow both versions */ + +#define RB_AUTOBOOT LINUX_REBOOT_CMD_RESTART +#define RB_HALT_SYSTEM LINUX_REBOOT_CMD_HALT +#define RB_ENABLE_CAD LINUX_REBOOT_CMD_CAD_ON +#define RB_DISABLE_CAD LINUX_REBOOT_CMD_CAD_OFF +#define RB_POWER_OFF LINUX_REBOOT_CMD_POWER_OFF + +/* glibc-ish one-argument version */ +__extern int reboot(int); + +/* Native four-argument system call */ +__extern int __reboot(int, int, int, void *); + +#endif /* _SYS_REBOOT_H */ diff -puN /dev/null usr/include/sys/resource.h --- /dev/null +++ a/usr/include/sys/resource.h @@ -0,0 +1,15 @@ +/* + * sys/resource.h + */ + +#ifndef _SYS_RESOURCE_H +#define _SYS_RESOURCE_H + +#include +#include /* MUST be included before linux/resource.h */ +#include + +__extern int getpriority(int, int); +__extern int setpriority(int, int, int); + +#endif /* _SYS_RESOURCE_H */ diff -puN /dev/null usr/include/sys/select.h --- /dev/null +++ a/usr/include/sys/select.h @@ -0,0 +1,17 @@ +/* + * sys/select.h + */ + +#ifndef _SYS_SELECT_H +#define _SYS_SELECT_H + +#include +#include +#include +#include + +__extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +__extern int pselect(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const sigset_t *); + +#endif /* _SYS_SELECT_H */ diff -puN /dev/null usr/include/sys/sendfile.h --- /dev/null +++ a/usr/include/sys/sendfile.h @@ -0,0 +1,14 @@ +/* + * sys/sendfile.h + */ + +#ifndef _SYS_SENDFILE_H +#define _SYS_SENDFILE_H + +#include +#include +#include + +__extern ssize_t sendfile(int, int, off_t *, size_t, off_t); + +#endif /* _SYS_SENDFILE_H */ diff -puN /dev/null usr/include/sys/socketcalls.h --- /dev/null +++ a/usr/include/sys/socketcalls.h @@ -0,0 +1,28 @@ +/* + * sys/socketcalls.h + */ + +#ifndef _SYS_SOCKETCALLS_H +#define _SYS_SOCKETCALLS_H + +/* socketcalls by number, since isn't usable for assembly */ + +#define SYS_SOCKET 1 /* sys_socket(2) */ +#define SYS_BIND 2 /* sys_bind(2) */ +#define SYS_CONNECT 3 /* sys_connect(2) */ +#define SYS_LISTEN 4 /* sys_listen(2) */ +#define SYS_ACCEPT 5 /* sys_accept(2) */ +#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ +#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ +#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ +#define SYS_SEND 9 /* sys_send(2) */ +#define SYS_RECV 10 /* sys_recv(2) */ +#define SYS_SENDTO 11 /* sys_sendto(2) */ +#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ +#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ +#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ +#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ +#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ +#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ + +#endif /* _SYS_SOCKETCALLS_H */ diff -puN /dev/null usr/include/sys/socket.h --- /dev/null +++ a/usr/include/sys/socket.h @@ -0,0 +1,44 @@ +/* + * sys/socket.h + */ + +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H + +#include +#include +#include + +/* For some reason these may be protected by __KERNEL__ in asm/socket.h */ +#ifndef SOCK_STREAM +# define SOCK_STREAM 1 +# define SOCK_DGRAM 2 +# define SOCK_RAW 3 +# define SOCK_RDM 4 +# define SOCK_SEQPACKET 5 +# define SOCK_PACKET 10 +#endif + +typedef int socklen_t; + +__extern int socket(int, int, int); +__extern int bind(int, struct sockaddr *, int); +__extern int connect(int, struct sockaddr *, socklen_t); +__extern int listen(int, int); +__extern int accept(int, struct sockaddr *, socklen_t *); +__extern int getsockname(int, struct sockaddr *, socklen_t *); +__extern int getpeername(int, struct sockaddr *, socklen_t *); +__extern int socketpair(int, int, int, int *); +__extern int send(int, const void *, size_t, unsigned int); +__extern int sendto(int, const void *, size_t, int, const struct sockaddr *, + socklen_t); +__extern int recv(int, void *, size_t, unsigned int); +__extern int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, + socklen_t *); +__extern int shutdown(int, int); +__extern int setsockopt(int, int, int, const void *, socklen_t); +__extern int getsockopt(int, int, int, void *, socklen_t *); +__extern int sendmsg(int, const struct msghdr *, unsigned int); +__extern int recvmsg(int, struct msghdr *, unsigned int); + +#endif /* _SYS_SOCKET_H */ diff -puN /dev/null usr/include/sys/splice.h --- /dev/null +++ a/usr/include/sys/splice.h @@ -0,0 +1,19 @@ +/* + * sys/splice.h + */ + +#ifndef _SYS_SPLICE_H +#define _SYS_SPLICE_H + +/* move pages instead of copying */ +#define SPLICE_F_MOVE 1 +/* don't block on the pipe splicing (but we may still block on the fd + we splice from/to, of course */ +#define SPLICE_F_NONBLOCK 2 +/* expect more data */ +#define SPLICE_F_MORE 4 + +__extern int splice(int, off_t *, int, off_t *, size_t, unsigned int); +__extern int tee(int, int, size_t, unsigned int); + +#endif /* _SYS_SPLICE_H */ diff -puN /dev/null usr/include/sys/statfs.h --- /dev/null +++ a/usr/include/sys/statfs.h @@ -0,0 +1 @@ +#include diff -puN /dev/null usr/include/sys/stat.h --- /dev/null +++ a/usr/include/sys/stat.h @@ -0,0 +1,33 @@ +/* + * sys/stat.h + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include +#include +#include /* For struct timespec */ +#include +#include + +#ifdef _STATBUF_ST_NSEC + /* struct stat has struct timespec instead of time_t */ +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#endif + +__extern int stat(const char *, struct stat *); +__extern int fstat(int, struct stat *); +__extern int fstatat(int, const char *, struct stat *, int); +__extern int lstat(const char *, struct stat *); +__extern mode_t umask(mode_t); +__extern int mknod(const char *, mode_t, dev_t); +__extern int mknodat(int, const char *, const char *, mode_t, dev_t); +static __inline__ int mkfifo(const char *__p, mode_t __m) +{ + return mknod(__p, (__m & ~S_IFMT) | S_IFIFO, (dev_t) 0); +} + +#endif /* _SYS_STAT_H */ diff -puN /dev/null usr/include/sys/syscall.h --- /dev/null +++ a/usr/include/sys/syscall.h @@ -0,0 +1,13 @@ +/* + * sys/syscall.h + * + * Generic system call interface macros + */ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include +#include +#include + +#endif /* _SYS_SYSCALL_H */ diff -puN /dev/null usr/include/sys/sysinfo.h --- /dev/null +++ a/usr/include/sys/sysinfo.h @@ -0,0 +1,12 @@ +/* + * sys/sysinfo.h + */ + +#ifndef _SYS_SYSINFO_H +#define _SYS_SYSINFO_H + +#include + +extern int sysinfo(struct sysinfo *info); + +#endif /* _SYS_SYSINFO_H */ diff -puN /dev/null usr/include/sys/sysmacros.h --- /dev/null +++ a/usr/include/sys/sysmacros.h @@ -0,0 +1,34 @@ +/* + * sys/sysmacros.h + * + * Constructs to create and pick apart dev_t. The double-underscore + * versions are macros so they can be used as constants. + */ + +#ifndef _SYS_SYSMACROS_H +#define _SYS_SYSMACROS_H + +#ifndef _SYS_TYPES_H +# include +#endif + +#define __major(__d) (((__d) >> 8) & 0xfff) +static __inline__ int major(dev_t __d) +{ + return __major(__d); +} + +#define __minor(__d) (((__d) & 0xff)|(((__d) >> 12) & 0xfff00)) +static __inline__ int minor(dev_t __d) +{ + return __minor(__d); +} + +#define __makedev(__ma, __mi) \ + ((((__ma) & 0xfff) << 8)|((__mi) & 0xff)|(((__mi) & 0xfff00) << 12)) +static __inline__ dev_t makedev(int __ma, int __mi) +{ + return __makedev(__ma, __mi); +} + +#endif /* _SYS_SYSMACROS_H */ diff -puN /dev/null usr/include/sys/time.h --- /dev/null +++ a/usr/include/sys/time.h @@ -0,0 +1,18 @@ +/* + * sys/time.h + */ + +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#include +#include +#include + +__extern int gettimeofday(struct timeval *, struct timezone *); +__extern int settimeofday(const struct timeval *, const struct timezone *); +__extern int getitimer(int, struct itimerval *); +__extern int setitimer(int, const struct itimerval *, struct itimerval *); +__extern int utimes(const char *, const struct timeval *); + +#endif /* _SYS_TIME_H */ diff -puN /dev/null usr/include/sys/times.h --- /dev/null +++ a/usr/include/sys/times.h @@ -0,0 +1,14 @@ +/* + * sys/times.h + */ + +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#include +#include +#include + +__extern clock_t times(struct tms *); + +#endif /* _SYS_TIMES_H */ diff -puN /dev/null usr/include/sys/types.h --- /dev/null +++ a/usr/include/sys/types.h @@ -0,0 +1,111 @@ +/* + * sys/types.h + */ + +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include +#include +#include + +#define _SSIZE_T +typedef ptrdiff_t ssize_t; + +#include +#include + +/* Keeps linux/types.h from getting included elsewhere */ +#define _LINUX_TYPES_H + +typedef __kernel_fd_set fd_set; +typedef uint32_t dev_t; +typedef __kernel_ino_t ino_t; +typedef __kernel_mode_t mode_t; +typedef __kernel_nlink_t nlink_t; +typedef __kernel_loff_t off_t; +typedef __kernel_loff_t loff_t; +typedef __kernel_pid_t pid_t; +typedef __kernel_daddr_t daddr_t; +typedef __kernel_key_t key_t; +typedef __kernel_suseconds_t suseconds_t; +/* typedef __kernel_timer_t timer_t; */ +typedef int timer_t; + +typedef __kernel_uid32_t uid_t; +typedef __kernel_gid32_t gid_t; + +typedef __kernel_fsid_t fsid_t; + +/* + * The following typedefs are also protected by individual ifdefs for + * historical reasons: + */ +#ifndef _SIZE_T +#define _SIZE_T +typedef __kernel_size_t size_t; +#endif + +#ifndef _SSIZE_T +#define _SSIZE_T +typedef __kernel_ssize_t ssize_t; +#endif + +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef __kernel_ptrdiff_t ptrdiff_t; +#endif + +#ifndef _TIME_T +#define _TIME_T +typedef __kernel_time_t time_t; +#endif + +#ifndef _CLOCK_T +#define _CLOCK_T +typedef __kernel_clock_t clock_t; +#endif + +#ifndef _CADDR_T +#define _CADDR_T +typedef __kernel_caddr_t caddr_t; +#endif + +/* BSD */ +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +/* SysV */ +typedef unsigned char unchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +/* More BSD */ +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; + +typedef uint16_t __bitwise __le16; +typedef uint16_t __bitwise __be16; +typedef uint32_t __bitwise __le32; +typedef uint32_t __bitwise __be32; +typedef uint64_t __bitwise __le64; +typedef uint64_t __bitwise __be64; + +/* + * Some headers seem to require this... + */ +#ifndef BITS_PER_LONG +# define BITS_PER_LONG _BITSIZE +#endif + +/* + * Some apps want this in + */ +#include + +#endif diff -puN /dev/null usr/include/sys/uio.h --- /dev/null +++ a/usr/include/sys/uio.h @@ -0,0 +1,15 @@ +/* + * sys/uio.h + */ + +#ifndef _SYS_UIO_H +#define _SYS_UIO_H + +#include +#include +#include + +__extern int readv(int, const struct iovec *, int); +__extern int writev(int, const struct iovec *, int); + +#endif /* _SYS_UIO_H */ diff -puN /dev/null usr/include/sys/un.h --- /dev/null +++ a/usr/include/sys/un.h @@ -0,0 +1,10 @@ +/* + * + */ + +#ifndef _SYS_UN_H +#define _SYS_UN_H + +#include + +#endif /* _SYS_UN_H */ diff -puN /dev/null usr/include/sys/utime.h --- /dev/null +++ a/usr/include/sys/utime.h @@ -0,0 +1,10 @@ +/* + * sys/utime.h + */ + +#ifndef _SYS_UTIME_H +#define _SYS_UTIME_H + +#include + +#endif /* _SYS_UTIME_H */ diff -puN /dev/null usr/include/sys/utsname.h --- /dev/null +++ a/usr/include/sys/utsname.h @@ -0,0 +1,23 @@ +/* + * sys/utsname.h + */ + +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H + +#include + +#define SYS_NMLN 65 + +struct utsname { + char sysname[SYS_NMLN]; + char nodename[SYS_NMLN]; + char release[SYS_NMLN]; + char version[SYS_NMLN]; + char machine[SYS_NMLN]; + char domainname[SYS_NMLN]; +}; + +__extern int uname(struct utsname *); + +#endif /* _SYS_UTSNAME_H */ diff -puN /dev/null usr/include/sys/vfs.h --- /dev/null +++ a/usr/include/sys/vfs.h @@ -0,0 +1,115 @@ +/* + * sys/vfs.h + */ + +#ifndef _SYS_VFS_H +#define _SYS_VFS_H + +#include +#include +#include +#include +#include + +/* struct statfs64 -- there seems to be two standards - + one for 32 and one for 64 bits, and they're incompatible. + Worse, some 64-bit platforms seem to use the 32-bit layout. + Of course, there is no includable header that does this well. */ + +#if _KLIBC_STATFS_F_TYPE_64 + +struct statfs { + uint64_t f_type; + uint64_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + __kernel_fsid_t f_fsid; + uint64_t f_namelen; + uint64_t f_frsize; + uint64_t f_spare[5]; +}; + +#else /* not _KLIBC_STATFS_F_TYPE_64 */ + +struct statfs { + uint32_t f_type; + uint32_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + __kernel_fsid_t f_fsid; + uint32_t f_namelen; + uint32_t f_frsize; + uint32_t f_spare[5]; +}; + +#endif /* _KLIBC_STATFS_F_TYPE_64 */ + +__extern int statfs(const char *, struct statfs *); +__extern int fstatfs(int, struct statfs *); + +/* Various filesystem types */ +#define ADFS_SUPER_MAGIC 0xadf5 +#define AFFS_SUPER_MAGIC 0xadff +#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ +#define AUTOFS_SUPER_MAGIC 0x0187 +#define BFS_MAGIC 0x1BADFACE +#define CAPIFS_SUPER_MAGIC 0x434e +#define CIFS_MAGIC_NUMBER 0xFF534D42 +#define CODA_SUPER_MAGIC 0x73757245 +#define CRAMFS_MAGIC 0x28cd3d45 +#define DEVFS_SUPER_MAGIC 0x1373 +#define DEVPTS_SUPER_MAGIC 0x1cd1 +#define EFS_SUPER_MAGIC 0x414A53 +#define EVENTPOLLFS_MAGIC 0x03111965 +#define EXT2_SUPER_MAGIC 0xEF53 +#define EXT3_SUPER_MAGIC 0xEF53 +#define GADGETFS_MAGIC 0xaee71ee7 +#define HFSPLUS_SUPER_MAGIC 0x482b +#define HFS_MFS_SUPER_MAGIC 0xD2D7 /* MFS MDB (super block) */ +#define HFS_SUPER_MAGIC 0x4244 /* "BD": HFS MDB (super block) */ +#define HPFS_SUPER_MAGIC 0xf995e849 +#define HUGETLBFS_MAGIC 0x958458f6 +#define HWGFS_MAGIC 0x12061983 +#define IBMASMFS_MAGIC 0x66726f67 +#define ISOFS_SUPER_MAGIC 0x9660 +#define JFFS2_SUPER_MAGIC 0x72b6 +#define JFFS_MAGIC_BITMASK 0x34383931 /* "1984" */ +#define JFFS_MAGIC_SB_BITMASK 0x07c0 /* 1984 */ +#define JFS_SUPER_MAGIC 0x3153464a /* "JFS1" */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ +#define NCP_SUPER_MAGIC 0x564c +#define NFS_SUPER_MAGIC 0x6969 +#define NFS_SUPER_MAGIC 0x6969 +#define OPENPROM_SUPER_MAGIC 0x9fa1 +#define OPROFILEFS_MAGIC 0x6f70726f +#define PFMFS_MAGIC 0xa0b4d889 +#define PIPEFS_MAGIC 0x50495045 +#define PROC_SUPER_MAGIC 0x9fa0 +#define QNX4_SUPER_MAGIC 0x002f /* qnx4 fs detection */ +#define RAMFS_MAGIC 0x858458f6 +#define REISERFS_SUPER_MAGIC 0x52654973 +#define ROMFS_MAGIC 0x7275 +#define SMB_SUPER_MAGIC 0x517B +#define SOCKFS_MAGIC 0x534F434B +#define SYSFS_MAGIC 0x62656572 +#define TMPFS_MAGIC 0x01021994 +#define UDF_SUPER_MAGIC 0x15013346 +#define UFS_MAGIC 0x00011954 +#define UFS_MAGIC_4GB 0x05231994 /* fs > 4 GB && fs_featurebits */ +#define UFS_MAGIC_FEA 0x00195612 /* fs_featurebits supported */ +#define UFS_MAGIC_LFN 0x00095014 /* fs supports filenames > 14 chars */ +#define UFS_MAGIC_SEC 0x00612195 /* B1 security fs */ +#define USBDEVICE_SUPER_MAGIC 0x9fa2 +#define VXFS_SUPER_MAGIC 0xa501FCF5 + +#endif /* _SYS_VFS_H */ diff -puN /dev/null usr/include/sys/wait.h --- /dev/null +++ a/usr/include/sys/wait.h @@ -0,0 +1,28 @@ +/* + * sys/wait.h + */ + +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H + +#include +#include +#include + +#include + +#define WEXITSTATUS(s) (((s) & 0xff00) >> 8) +#define WTERMSIG(s) ((s) & 0x7f) +#define WIFEXITED(s) (WTERMSIG(s) == 0) +#define WIFSTOPPED(s) (WTERMSIG(s) == 0x7f) +/* Ugly hack to avoid multiple evaluation of "s" */ +#define WIFSIGNALED(s) (WTERMSIG((s)+1) >= 2) +#define WCOREDUMP(s) ((s) & 0x80) +#define WSTOPSIG(s) WEXITSTATUS(s) + +__extern pid_t wait(int *); +__extern pid_t waitpid(pid_t, int *, int); +__extern pid_t wait3(int *, int, struct rusage *); +__extern pid_t wait4(pid_t, int *, int, struct rusage *); + +#endif /* _SYS_WAIT_H */ diff -puN /dev/null usr/include/termios.h --- /dev/null +++ a/usr/include/termios.h @@ -0,0 +1,91 @@ +/* + * termios.h + */ + +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#include +#include +#include +#include +#include + +/* Redefine these so the magic constants == the ioctl number to use. */ +#undef TCSANOW +#undef TCSADRAIN +#undef TCSAFLUSH +#define TCSANOW TCSETS +#define TCSADRAIN TCSETSW +#define TCSAFLUSH TCSETSF + +static __inline__ int tcgetattr(int __fd, struct termios *__s) +{ + return ioctl(__fd, TCGETS, __s); +} + +static __inline__ int tcsetattr(int __fd, int __opt, const struct termios *__s) +{ + return ioctl(__fd, __opt, (void *)__s); +} + +static __inline__ int tcflow(int __fd, int __action) +{ + return ioctl(__fd, TCXONC, (void *)(intptr_t) __action); +} + +static __inline__ int tcflush(int __fd, int __queue) +{ + return ioctl(__fd, TCFLSH, (void *)(intptr_t) __queue); +} + +static __inline__ int tcdrain(int __fd) +{ + return ioctl(__fd, TCSBRK, (void *)1L); +} + +static __inline__ pid_t tcgetpgrp(int __fd) +{ + pid_t __p; + return ioctl(__fd, TIOCGPGRP, &__p) ? (pid_t) - 1 : __p; +} + +static __inline__ pid_t tcgetsid(int __fd) +{ + pid_t __p; + return ioctl(__fd, TIOCGSID, &__p) ? (pid_t) - 1 : __p; +} + +static __inline__ int tcsendbreak(int __fd, int __duration) +{ + return ioctl(__fd, TCSBRKP, (void *)(uintptr_t) __duration); +} + +static __inline__ int tcsetpgrp(int __fd, pid_t __p) +{ + return ioctl(__fd, TIOCSPGRP, &__p); +} + +static __inline__ speed_t cfgetospeed(const struct termios *__s) +{ + return (speed_t) (__s->c_cflag & CBAUD); +} + +static __inline__ speed_t cfgetispeed(const struct termios *__s) +{ + return (speed_t) (__s->c_cflag & CBAUD); +} + +static __inline__ int cfsetospeed(struct termios *__s, speed_t __v) +{ + __s->c_cflag = (__s->c_cflag & ~CBAUD) | (__v & CBAUD); + return 0; +} + +static __inline__ int cfsetispeed(struct termios *__s, speed_t __v) +{ + __s->c_cflag = (__s->c_cflag & ~CBAUD) | (__v & CBAUD); + return 0; +} + +#endif /* _TERMIOS_H */ diff -puN /dev/null usr/include/time.h --- /dev/null +++ a/usr/include/time.h @@ -0,0 +1,18 @@ +/* + * time.h + */ + +#ifndef _TIME_H +#define _TIME_H + +#include +#include + +__extern time_t time(time_t *); +__extern int nanosleep(const struct timespec *, struct timespec *); + +/* klibc-specific but useful since we don't have floating point */ +__extern char *strtotimeval(const char *str, struct timeval *tv); +__extern char *strtotimespec(const char *str, struct timespec *tv); + +#endif /* _TIME_H */ diff -puN /dev/null usr/include/unistd.h --- /dev/null +++ a/usr/include/unistd.h @@ -0,0 +1,159 @@ +/* + * unistd.h + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include +#include +#include +#include +#include + +__extern char **environ; +__extern __noreturn _exit(int); + +__extern pid_t fork(void); +__extern pid_t vfork(void); +__extern pid_t getpid(void); +__extern pid_t getpgid(pid_t); +__extern int setpgid(pid_t, pid_t); +__extern pid_t getppid(void); +__extern pid_t getpgrp(void); +__extern int setpgrp(void); +__extern pid_t setsid(void); +__extern pid_t getsid(pid_t); +__extern int execv(const char *, char *const *); +__extern int execvp(const char *, char *const *); +__extern int execve(const char *, char *const *, char *const *); +__extern int execvpe(const char *, char *const *, char *const *); +__extern int execl(const char *, const char *, ...); +__extern int execlp(const char *, const char *, ...); +__extern int execle(const char *, const char *, ...); +__extern int execlpe(const char *, const char *, ...); + +__extern int setuid(uid_t); +__extern uid_t getuid(void); +__extern int seteuid(uid_t); +__extern uid_t geteuid(void); +__extern int setgid(gid_t); +__extern gid_t getgid(void); +__extern int setegid(gid_t); +__extern gid_t getegid(void); +__extern int getgroups(int, gid_t *); +__extern int setgroups(size_t, const gid_t *); +__extern int setreuid(uid_t, uid_t); +__extern int setregid(gid_t, gid_t); +__extern int setresuid(uid_t, uid_t, uid_t); +__extern int setresgid(gid_t, gid_t, gid_t); +__extern int getfsuid(uid_t); +__extern int setfsuid(uid_t); + +/* Macros for access() */ +#define R_OK 4 /* Read */ +#define W_OK 2 /* Write */ +#define X_OK 1 /* Execute */ +#define F_OK 0 /* Existence */ + +__extern int access(const char *, int); +__extern int faccessat(int, const char *, int); +__extern int link(const char *, const char *); +__extern int linkat(int, const char *, int, const char *); +__extern int unlink(const char *); +__extern int unlinkat(int, const char *); +__extern int chdir(const char *); +__extern int fchdir(int); +__extern int chmod(const char *, mode_t); +__extern int fchmod(int, mode_t); +__extern int fchmodat(int, const char *, mode_t); +__extern int mkdir(const char *, mode_t); +__extern int mkdirat(int, const char *, const char *, mode_t); +__extern int rmdir(const char *); +__extern int pipe(int *); +__extern int chroot(const char *); +__extern int symlink(const char *, const char *); +__extern int symlinkat(int, const char *, const char *); +__extern int readlink(const char *, char *, size_t); +__extern int readlinkat(int, const char *, char *, size_t); +__extern int chown(const char *, uid_t, gid_t); +__extern int fchown(int, uid_t, gid_t); +__extern int lchown(const char *, uid_t, gid_t); +__extern char *getcwd(char *, size_t); + +/* Also in */ +#ifndef _KLIBC_IN_OPEN_C +__extern int open(const char *, int, ...); +__extern int openat(int, const char *, int, ...); +#endif +__extern int close(int); +__extern off_t lseek(int, off_t, int); +/* off_t is 64 bits now even on 32-bit platforms; see llseek.c */ +static __inline__ off_t llseek(int __f, off_t __o, int __w) +{ + return lseek(__f, __o, __w); +} + +__extern ssize_t read(int, void *, size_t); +__extern ssize_t write(int, const void *, size_t); +__extern ssize_t pread(int, void *, size_t, off_t); +__extern ssize_t pwrite(int, void *, size_t, off_t); + +__extern int dup(int); +__extern int dup2(int, int); +__extern int fcntl(int, int, ...); +__extern int ioctl(int, int, void *); +__extern int flock(int, int); +__extern int ftruncate(int, off_t); + +/* + * Macros for sync_file_range() + */ +#define SYNC_FILE_RANGE_WAIT_BEFORE 1 +#define SYNC_FILE_RANGE_WRITE 2 +#define SYNC_FILE_RANGE_WAIT_AFTER 4 + +__extern int sync(void); +__extern int fsync(int); +__extern int fdatasync(int); +__extern int sync_file_range(int, off_t, off_t, unsigned int); + +__extern int pause(void); +__extern unsigned int alarm(unsigned int); +__extern unsigned int sleep(unsigned int); +__extern void usleep(unsigned long); + +__extern int gethostname(char *, size_t); +__extern int sethostname(const char *, size_t); +__extern int getdomainname(char *, size_t); +__extern int setdomainname(const char *, size_t); + +__extern void *__brk(void *); +__extern int brk(void *); +__extern void *sbrk(ptrdiff_t); + +__extern int getopt(int, char *const *, const char *); +__extern char *optarg; +__extern int optind, opterr, optopt; + +__extern int isatty(int); + +static __inline__ int getpagesize(void) +{ + extern unsigned int __page_size; + return __page_size; +} +static __inline__ int __getpageshift(void) +{ + extern unsigned int __page_shift; + return __page_shift; +} + +__extern int daemon(int, int); + +/* Standard file descriptor numbers. */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#endif /* _UNISTD_H */ diff -puN /dev/null usr/include/utime.h --- /dev/null +++ a/usr/include/utime.h @@ -0,0 +1,14 @@ +/* + * utime.h + */ + +#ifndef _UTIME_H +#define _UTIME_H + +#include +#include +#include + +__extern int utime(const char *, const struct utimbuf *); + +#endif /* _UTIME_H */ diff -puN /dev/null usr/include/zconf.h --- /dev/null +++ a/usr/include/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff -puN /dev/null usr/include/zlib.h --- /dev/null +++ a/usr/include/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff -puN /dev/null usr/initramfs.default --- /dev/null +++ a/usr/initramfs.default @@ -0,0 +1,9 @@ +##################### +# This is a very simple, default initramfs +# See gen_init_cpio for syntax + +dir dev 0755 0 0 +nod dev/console 0600 0 0 c 5 1 +dir root 0700 0 0 +file kinit usr/kinit/kinit 0755 0 0 +slink init kinit 0755 0 0 diff -puN /dev/null usr/Kbuild --- /dev/null +++ a/usr/Kbuild @@ -0,0 +1,75 @@ +# +# kbuild file for usr/ - including initramfs image and klibc +# + +CONFIG_KLIBC := 1 + +include-subdir := include +klibc-subdir := klibc +usr-subdirs := kinit utils dash gzip +subdir- := $(include-subdir) $(klibc-subdir) $(usr-subdirs) + +usr-subdirs := $(addprefix _usr_,$(usr-subdirs)) +klibc-subdir := $(addprefix _usr_,$(klibc-subdir)) + +# Klibc binaries +ifdef CONFIG_KLIBC + +# .initramfs_data.cpio.gz.d is used to identify all files included +# in initramfs and to detect if any files are added/removed. +# Removed files are identified by directory timestamp being updated +# The dependency list is generated by gen_initramfs.sh -l +ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),) + include $(obj)/.initramfs_data.cpio.gz.d +endif + +# build klibc library before the klibc programs +# build klibc programs before cpio.gz +.PHONY: initramfs $(usr-subdirs) $(klibc-subdir) $(include-subdir) +initramfs: $(usr-subdirs) $(klibc-subdir) $(include-subdir) +$(deps_initramfs): $(usr-subdirs) $(klibc-subdir) $(include-subdir) + +$(usr-subdirs): $(klibc-subdir) + $(Q)$(MAKE) $(klibc)=$(src)/$(patsubst _usr_%,%,$(@)) + +$(klibc-subdir): $(include-subdir) + $(Q)$(MAKE) $(klibc)=$(src)/$(patsubst _usr_%,%,$(@)) + +$(include-subdir): + $(Q)$(MAKE) $(klibc)=$(src)/$(patsubst _usr_%,%,$(@)) +endif + + +# Generate builtin.o based on initramfs_data.o +obj-y := initramfs_data.o + +# initramfs_data.o contains the initramfs_data.cpio.gz image. +# The image is included using .incbin, a dependency which is not +# tracked automatically. +$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE + +##### +# Generate the initramfs cpio archive + +hostprogs-y := gen_init_cpio +ginitramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh +ramfs-def := $(srctree)/$(src)/initramfs.default +ramfs-input := $(shell echo $(CONFIG_INITRAMFS_SOURCE)) +ramfs-input := $(if $(ramfs-input), $(ramfs-input), $(ramfs-def)) + +ramfs-args := \ + $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ + $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) + +quiet_cmd_initfs = GEN $@ + cmd_initfs = $(ginitramfs) -o $@ $(ramfs-args) $(ramfs-input) + +targets := initramfs_data.cpio.gz +# We rebuild initramfs_data.cpio.gz if: +# 1) Any included file is newer then initramfs_data.cpio.gz +# 2) There are changes in which files are included (added or deleted) +# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz +# 4) arguments to gen_initramfs.sh changes +$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) initramfs + $(Q)$(ginitramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d + $(call if_changed,initfs) diff -puN usr/Kconfig~git-klibc usr/Kconfig --- a/usr/Kconfig~git-klibc +++ a/usr/Kconfig @@ -44,3 +44,24 @@ config INITRAMFS_ROOT_GID owned by group root in the initial ramdisk image. If you are not sure, leave it set to "0". + +config KLIBC_ERRLIST + bool "Early userspace real error messages" if EMBEDDED + default y + help + If this is set, kinit (and other klibc-derived binaries) + will have the standard list of error messages built in, and + thus will report, for example, "No such file or directory" + instead of "Error 1". Leaving it out will save + approximately 4K from each static binary (one, unless you + have a different initramfs_source.txt) or the shared + library. + + If you are not sure, "Y" is highly recommended. + +config KLIBC_ZLIB + bool + default y + help + This builds the zlib portion of klibc. This is currently + required. diff -puN /dev/null usr/kinit/devname.c --- /dev/null +++ a/usr/kinit/devname.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * devname.c + * + * Print the name of a block device. + */ +#define BUF_SIZE 512 + +static int scansysdir(char *namebuf, char *sysdir, dev_t dev) +{ + char *dirtailptr = strchr(sysdir, '\0'); + DIR *dir; + int done = 0; + struct dirent *de; + char *systail; + FILE *sysdev; + unsigned long ma, mi; + char *ep; + ssize_t rd; + + if (!(dir = opendir(sysdir))) + return 0; + + *dirtailptr++ = '/'; + + while (!done && (de = readdir(dir))) { + /* Assume if we see a dot-name in sysfs it's special */ + if (de->d_name[0] == '.') + continue; + + if (de->d_type != DT_UNKNOWN && de->d_type != DT_DIR) + continue; + + if (strlen(de->d_name) >= + (BUF_SIZE - 64) - (dirtailptr - sysdir)) + continue; /* Badness... */ + + strcpy(dirtailptr, de->d_name); + systail = strchr(sysdir, '\0'); + + strcpy(systail, "/dev"); + if (!(sysdev = fopen(sysdir, "r"))) + continue; + + /* Abusing the namebuf as temporary storage here. */ + rd = fread(namebuf, 1, BUF_SIZE, sysdev); + namebuf[rd] = '\0'; /* Just in case... */ + + fclose(sysdev); + + ma = strtoul(namebuf, &ep, 10); + if (ma != major(dev) || *ep != ':') + continue; + + mi = strtoul(ep + 1, &ep, 10); + if (*ep != '\n') + continue; + + if (mi == minor(dev)) { + /* Found it! */ + strcpy(namebuf, de->d_name); + done = 1; + } else { + /* we have a major number match, scan for partitions */ + *systail = '\0'; + done = scansysdir(namebuf, sysdir, dev); + } + } + + closedir(dir); + return done; +} + +const char *bdevname(dev_t dev) +{ + static char buf[BUF_SIZE]; + char sysdir[BUF_SIZE]; + char *p; + + strcpy(sysdir, "/sys/block"); + + if (!scansysdir(buf, sysdir, dev)) + strcpy(buf, "dev"); /* prints e.g. dev(3,5) */ + + p = strchr(buf, '\0'); + snprintf(p, sizeof buf - (p - buf), "(%d,%d)", major(dev), minor(dev)); + + return buf; +} + +#ifdef TEST_DEVNAME /* Standalone test */ + +int main(int argc, char *argv[]) +{ + dev_t dev; + int i; + + for (i = 1; i < argc; i++) { + dev = strtoul(argv[i], NULL, 0); + + printf("0x%08x = %s\n", (unsigned int)dev, bdevname(dev)); + } + + return 0; +} + +#endif /* TEST */ diff -puN /dev/null usr/kinit/do_mounts.c --- /dev/null +++ a/usr/kinit/do_mounts.c @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "do_mounts.h" +#include "kinit.h" +#include "fstype.h" +#include "zlib.h" + +/* Create the device node "name" */ +int create_dev(const char *name, dev_t dev) +{ + unlink(name); + return mknod(name, S_IFBLK | 0600, dev); +} + +/* mount a filesystem, possibly trying a set of different types */ +const char *mount_block(const char *source, const char *target, + const char *type, unsigned long flags, + const void *data) +{ + char *fslist, *p, *ep; + const char *rp; + ssize_t fsbytes; + int fd; + + if (type) { + DEBUG(("kinit: trying to mount %s on %s with type %s\n", + source, target, type)); + int rv = mount(source, target, type, flags, data); + /* Mount readonly if necessary */ + if (rv == -1 && errno == EACCES && !(flags & MS_RDONLY)) + rv = mount(source, target, type, flags | MS_RDONLY, + data); + return rv ? NULL : type; + } + + /* If no type given, try to identify the type first; this + also takes care of specific ordering requirements, like + ext3 before ext2... */ + fd = open(source, O_RDONLY); + if (fd >= 0) { + int err = identify_fs(fd, &type, NULL, 0); + close(fd); + + if (!err && type) { + DEBUG(("kinit: %s appears to be a %s filesystem\n", + source, type)); + type = mount_block(source, target, type, flags, data); + if (type) + return type; + } + } + + DEBUG(("kinit: failed to identify filesystem %s, trying all\n", + source)); + + fsbytes = readfile("/proc/filesystems", &fslist); + + errno = EINVAL; + if (fsbytes < 0) + return NULL; + + p = fslist; + ep = fslist + fsbytes; + + rp = NULL; + + while (p < ep) { + type = p; + p = strchr(p, '\n'); + if (!p) + break; + *p++ = '\0'; + if (*type != '\t') /* We can't mount a block device as a "nodev" fs */ + continue; + + type++; + rp = mount_block(source, target, type, flags, data); + if (rp) + break; + if (errno != EINVAL) + break; + } + + free(fslist); + return rp; +} + +/* mount the root filesystem from a block device */ +static int +mount_block_root(int argc, char *argv[], dev_t root_dev, + const char *type, unsigned long flags) +{ + const char *data, *rp; + + data = get_arg(argc, argv, "rootflags="); + create_dev("/dev/root", root_dev); + + errno = 0; + + if (type) { + if ((rp = mount_block("/dev/root", "/root", type, flags, data))) + goto ok; + if (errno != EINVAL) + goto bad; + } + + if (!errno + && (rp = mount_block("/dev/root", "/root", NULL, flags, data))) + goto ok; + + bad: + if (errno != EINVAL) { + /* + * Allow the user to distinguish between failed open + * and bad superblock on root device. + */ + fprintf(stderr, "%s: Cannot open root device %s\n", + progname, bdevname(root_dev)); + return -errno; + } else { + fprintf(stderr, "%s: Unable to mount root fs on device %s\n", + progname, bdevname(root_dev)); + return -ESRCH; + } + + ok: + printf("%s: Mounted root (%s filesystem)%s.\n", + progname, rp, (flags & MS_RDONLY) ? " readonly" : ""); + return 0; +} + +int +mount_root(int argc, char *argv[], dev_t root_dev, const char *root_dev_name) +{ + unsigned long flags = MS_RDONLY | MS_VERBOSE; + int ret; + const char *type = get_arg(argc, argv, "rootfstype="); + + if (get_flag(argc, argv, "rw") > get_flag(argc, argv, "ro")) { + DEBUG(("kinit: mounting root rw\n")); + flags &= ~MS_RDONLY; + } + + if (type) { + if (!strcmp(type, "nfs")) + root_dev = Root_NFS; + else if (!strcmp(type, "jffs2") && !major(root_dev)) + root_dev = Root_MTD; + } + + switch (root_dev) { + case Root_NFS: + ret = mount_nfs_root(argc, argv, flags); + break; + case Root_MTD: + ret = mount_mtd_root(argc, argv, root_dev_name, type, flags); + break; + default: + ret = mount_block_root(argc, argv, root_dev, type, flags); + break; + } + + if (!ret) + chdir("/root"); + + return ret; +} + +int do_mounts(int argc, char *argv[]) +{ + const char *root_dev_name = get_arg(argc, argv, "root="); + const char *root_delay = get_arg(argc, argv, "rootdelay="); + const char *load_ramdisk = get_arg(argc, argv, "load_ramdisk="); + dev_t root_dev = 0; + + DEBUG(("kinit: do_mounts\n")); + + if (root_delay) { + int delay = atoi(root_delay); + fprintf(stderr, "Waiting %d s before mounting root device...\n", + delay); + sleep(delay); + } + + md_run(argc, argv); + + if (root_dev_name) { + root_dev = name_to_dev_t(root_dev_name); + } else if (get_arg(argc, argv, "nfsroot=") || + get_arg(argc, argv, "nfsaddrs=")) { + root_dev = Root_NFS; + } else { + long rootdev; + getintfile("/proc/sys/kernel/real-root-dev", &rootdev); + root_dev = (dev_t) rootdev; + } + + DEBUG(("kinit: root_dev = %s\n", bdevname(root_dev))); + + if (initrd_load(argc, argv, root_dev)) { + DEBUG(("initrd loaded\n")); + return 0; + } + + if (load_ramdisk && atoi(load_ramdisk)) { + if (ramdisk_load(argc, argv, root_dev)) + root_dev = Root_RAM0; + } + + return mount_root(argc, argv, root_dev, root_dev_name); +} diff -puN /dev/null usr/kinit/do_mounts.h --- /dev/null +++ a/usr/kinit/do_mounts.h @@ -0,0 +1,48 @@ +/* + * do_mounts.h + */ + +#ifndef DO_MOUNTS_H +#define DO_MOUNTS_H + +#include +#include +#include + +#define Root_RAM0 __makedev(1,0) + +/* These device numbers are only used internally */ +#define Root_NFS __makedev(0,255) +#define Root_MTD __makedev(0,254) + +int create_dev(const char *name, dev_t dev); + +dev_t name_to_dev_t(const char *name); + +const char *mount_block(const char *source, const char *target, + const char *type, unsigned long flags, + const void *data); + +int mount_root(int argc, char *argv[], dev_t root_dev, + const char *root_dev_name); + +int mount_mtd_root(int argc, char *argv[], const char *root_dev_name, + const char *type, unsigned long flags); + +int do_mounts(int argc, char *argv[]); + +int initrd_load(int argc, char *argv[], dev_t root_dev); + +static inline dev_t bstat(const char *name) +{ + struct stat st; + + if (stat(name, &st) || !S_ISBLK(st.st_mode)) + return 0; + return st.st_rdev; +} + +int load_ramdisk_compressed(const char *devpath, FILE * wfd, + off_t ramdisk_start); + +#endif /* DO_MOUNTS_H */ diff -puN /dev/null usr/kinit/do_mounts_md.c --- /dev/null +++ a/usr/kinit/do_mounts_md.c @@ -0,0 +1,398 @@ +/* + * usr/kinit/do_mounts_md.c + * + * Handle autoconfiguration of md devices. This is ugly, partially since + * it still relies on a sizable kernel component. + * + * This file is derived from the Linux kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "do_mounts.h" + +#define LEVEL_NONE (-1000000) + +/* + * When md (and any require personalities) are compiled into the kernel + * (not a module), arrays can be assembles are boot time using with AUTODETECT + * where specially marked partitions are registered with md_autodetect_dev(), + * and with MD_BOOT where devices to be collected are given on the boot line + * with md=..... + * The code for that is here. + */ + +static int raid_noautodetect, raid_autopart; + +static struct { + int minor; + int partitioned; + int level; + int chunk; + char *device_names; +} md_setup_args[MAX_MD_DEVS]; + +static int md_setup_ents; + +/** + * get_option - Parse integer from an option string + * @str: option string + * @pint: (output) integer value parsed from @str + * + * Read an int from an option string; if available accept a subsequent + * comma as well. + * + * Return values: + * 0 : no int in string + * 1 : int found, no subsequent comma + * 2 : int found including a subsequent comma + */ + +static int get_option(char **str, int *pint) +{ + char *cur = *str; + + if (!cur || !(*cur)) + return 0; + *pint = strtol(cur, str, 0); + if (cur == *str) + return 0; + if (**str == ',') { + (*str)++; + return 2; + } + + return 1; +} + +/* + * Find the partitioned md device major number... of course this *HAD* + * to be done dynamically instead of using a registered number. + * Sigh. Double sigh. + */ +static int mdp_major(void) +{ + static int found = 0; + FILE *f; + char line[512], *p; + int is_blk, major_no; + + if (found) + return found; + + f = fopen("/proc/devices", "r"); + is_blk = 0; + while (fgets(line, sizeof line, f)) { + if (!strcmp(line, "Block devices:\n")) + is_blk = 1; + if (is_blk) { + major_no = strtol(line, &p, 10); + while (*p && isspace(*p)) + p++; + + if (major_no == 0) /* Not a number */ + is_blk = 0; + else if (major_no > 0 && !strcmp(p, "mdp")) { + found = major_no; + break; + } + } + } + fclose(f); + + if (!found) { + fprintf(stderr, + "Error: mdp devices detected but no mdp device found!\n"); + exit(1); + } + + return found; +} + +/* + * Parse the command-line parameters given our kernel, but do not + * actually try to invoke the MD device now; that is handled by + * md_setup_drive after the low-level disk drivers have initialised. + * + * 27/11/1999: Fixed to work correctly with the 2.3 kernel (which + * assigns the task of parsing integer arguments to the + * invoked program now). Added ability to initialise all + * the MD devices (by specifying multiple "md=" lines) + * instead of just one. -- KTK + * 18May2000: Added support for persistent-superblock arrays: + * md=n,0,factor,fault,device-list uses RAID0 for device n + * md=n,-1,factor,fault,device-list uses LINEAR for device n + * md=n,device-list reads a RAID superblock from the devices + * elements in device-list are read by name_to_kdev_t so can be + * a hex number or something like /dev/hda1 /dev/sdb + * 2001-06-03: Dave Cinege + * Shifted name_to_kdev_t() and related operations to md_set_drive() + * for later execution. Rewrote section to make devfs compatible. + */ +static int md_setup(char *str) +{ + int minor, level, factor, fault, partitioned = 0; + char *pername = ""; + char *str1; + int ent; + + if (*str == 'd') { + partitioned = 1; + str++; + } + if (get_option(&str, &minor) != 2) { /* MD Number */ + fprintf(stderr, "md: Too few arguments supplied to md=.\n"); + return 0; + } + str1 = str; + if (minor >= MAX_MD_DEVS) { + fprintf(stderr, "md: md=%d, Minor device number too high.\n", + minor); + return 0; + } + for (ent = 0; ent < md_setup_ents; ent++) + if (md_setup_args[ent].minor == minor && + md_setup_args[ent].partitioned == partitioned) { + fprintf(stderr, + "md: md=%s%d, Specified more than once. " + "Replacing previous definition.\n", + partitioned ? "d" : "", minor); + break; + } + if (ent >= MAX_MD_DEVS) { + fprintf(stderr, "md: md=%s%d - too many md initialisations\n", + partitioned ? "d" : "", minor); + return 0; + } + if (ent >= md_setup_ents) + md_setup_ents++; + switch (get_option(&str, &level)) { /* RAID level */ + case 2: /* could be 0 or -1.. */ + if (level == 0 || level == LEVEL_LINEAR) { + if (get_option(&str, &factor) != 2 || /* Chunk Size */ + get_option(&str, &fault) != 2) { + fprintf(stderr, + "md: Too few arguments supplied to md=.\n"); + return 0; + } + md_setup_args[ent].level = level; + md_setup_args[ent].chunk = 1 << (factor + 12); + if (level == LEVEL_LINEAR) + pername = "linear"; + else + pername = "raid0"; + break; + } + /* FALL THROUGH */ + case 1: /* the first device is numeric */ + str = str1; + /* FALL THROUGH */ + case 0: + md_setup_args[ent].level = LEVEL_NONE; + pername = "super-block"; + } + + fprintf(stderr, "md: Will configure md%s%d (%s) from %s, below.\n", + partitioned?"_d":"", minor, pername, str); + md_setup_args[ent].device_names = str; + md_setup_args[ent].partitioned = partitioned; + md_setup_args[ent].minor = minor; + + return 1; +} + +#define MdpMinorShift 6 + +static void md_setup_drive(void) +{ + int dev_minor, i, ent, partitioned; + dev_t dev; + dev_t devices[MD_SB_DISKS + 1]; + + for (ent = 0; ent < md_setup_ents; ent++) { + int fd; + int err = 0; + char *devname; + mdu_disk_info_t dinfo; + char name[16]; + + dev_minor = md_setup_args[ent].minor; + partitioned = md_setup_args[ent].partitioned; + devname = md_setup_args[ent].device_names; + + snprintf(name, sizeof name, + "/dev/md%s%d", partitioned ? "_d" : "", dev_minor); + + if (partitioned) + dev = makedev(mdp_major(), dev_minor << MdpMinorShift); + else + dev = makedev(MD_MAJOR, dev_minor); + create_dev(name, dev); + for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { + char *p; + + p = strchr(devname, ','); + if (p) + *p++ = 0; + + dev = name_to_dev_t(devname); + if (!dev) { + fprintf(stderr, "md: Unknown device name: %s\n", + devname); + break; + } + + devices[i] = dev; + + devname = p; + } + devices[i] = 0; + + if (!i) + continue; + + fprintf(stderr, "md: Loading md%s%d: %s\n", + partitioned ? "_d" : "", dev_minor, + md_setup_args[ent].device_names); + + fd = open(name, 0, 0); + if (fd < 0) { + fprintf(stderr, "md: open failed - cannot start " + "array %s\n", name); + continue; + } + if (ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) { + fprintf(stderr, + "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n", + dev_minor); + close(fd); + continue; + } + + if (md_setup_args[ent].level != LEVEL_NONE) { + /* non-persistent */ + mdu_array_info_t ainfo; + ainfo.level = md_setup_args[ent].level; + ainfo.size = 0; + ainfo.nr_disks = 0; + ainfo.raid_disks = 0; + while (devices[ainfo.raid_disks]) + ainfo.raid_disks++; + ainfo.md_minor = dev_minor; + ainfo.not_persistent = 1; + + ainfo.state = (1 << MD_SB_CLEAN); + ainfo.layout = 0; + ainfo.chunk_size = md_setup_args[ent].chunk; + err = ioctl(fd, SET_ARRAY_INFO, &ainfo); + for (i = 0; !err && i <= MD_SB_DISKS; i++) { + dev = devices[i]; + if (!dev) + break; + dinfo.number = i; + dinfo.raid_disk = i; + dinfo.state = + (1 << MD_DISK_ACTIVE) | (1 << MD_DISK_SYNC); + dinfo.major = major(dev); + dinfo.minor = minor(dev); + err = ioctl(fd, ADD_NEW_DISK, &dinfo); + } + } else { + /* persistent */ + for (i = 0; i <= MD_SB_DISKS; i++) { + dev = devices[i]; + if (!dev) + break; + dinfo.major = major(dev); + dinfo.minor = minor(dev); + ioctl(fd, ADD_NEW_DISK, &dinfo); + } + } + if (!err) + err = ioctl(fd, RUN_ARRAY, 0); + if (err) + fprintf(stderr, "md: starting md%d failed\n", + dev_minor); + else { + /* reread the partition table. + * I (neilb) and not sure why this is needed, but I cannot + * boot a kernel with devfs compiled in from partitioned md + * array without it + */ + close(fd); + fd = open(name, 0, 0); + ioctl(fd, BLKRRPART, 0); + } + close(fd); + } +} + +static int raid_setup(char *str) +{ + int len, pos; + + len = strlen(str) + 1; + pos = 0; + + while (pos < len) { + char *comma = strchr(str + pos, ','); + int wlen; + if (comma) + wlen = (comma - str) - pos; + else + wlen = (len - 1) - pos; + + if (!strncmp(str, "noautodetect", wlen)) + raid_noautodetect = 1; + if (strncmp(str, "partitionable", wlen) == 0) + raid_autopart = 1; + if (strncmp(str, "part", wlen) == 0) + raid_autopart = 1; + pos += wlen + 1; + } + return 1; +} + +static void md_run_setup(void) +{ + create_dev("/dev/md0", makedev(MD_MAJOR, 0)); + if (raid_noautodetect) + fprintf(stderr, + "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n"); + else { + int fd = open("/dev/md0", 0, 0); + if (fd >= 0) { + ioctl(fd, RAID_AUTORUN, + (void *)(intptr_t) raid_autopart); + close(fd); + } + } + md_setup_drive(); +} + +void md_run(int argc, char *argv[]) +{ + char **pp, *p; + + for (pp = argv; (p = *pp); pp++) { + if (!strncmp(p, "raid=", 5)) + raid_setup(p + 5); + else if (!strncmp(p, "md=", 3)) + md_setup(p + 3); + } + + md_run_setup(); +} diff -puN /dev/null usr/kinit/do_mounts_mtd.c --- /dev/null +++ a/usr/kinit/do_mounts_mtd.c @@ -0,0 +1,44 @@ +/* + * usr/kinit/do_mounts_mtd.c + * + * Mount an MTD device as a character device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kinit.h" +#include "do_mounts.h" + +int mount_mtd_root(int argc, char *argv[], const char *root_dev_name, + const char *type, unsigned long flags) +{ + const char *data = get_arg(argc, argv, "rootflags="); + + if (!type) + type = "jffs2"; + + DEBUG(("Trying to mount MTD %s as root (%s filesystem)\n", + root_dev_name, type)); + + if (mount(root_dev_name, "/root", type, flags, data)) { + int err = errno; + fprintf(stderr, + "%s: Unable to mount MTD %s (%s filesystem) " + "as root: %s\n", + progname, root_dev_name, type, strerror(err)); + return -err; + } else { + fprintf(stderr, "%s: Mounted root (%s filesystem)%s.\n", + progname, type, (flags & MS_RDONLY) ? " readonly" : ""); + return 0; + } + +} diff -puN /dev/null usr/kinit/fstype/cramfs_fs.h --- /dev/null +++ a/usr/kinit/fstype/cramfs_fs.h @@ -0,0 +1,85 @@ +#ifndef __CRAMFS_H +#define __CRAMFS_H + +#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */ +#define CRAMFS_SIGNATURE "Compressed ROMFS" + +/* + * Width of various bitfields in struct cramfs_inode. + * Primarily used to generate warnings in mkcramfs. + */ +#define CRAMFS_MODE_WIDTH 16 +#define CRAMFS_UID_WIDTH 16 +#define CRAMFS_SIZE_WIDTH 24 +#define CRAMFS_GID_WIDTH 8 +#define CRAMFS_NAMELEN_WIDTH 6 +#define CRAMFS_OFFSET_WIDTH 26 + +/* + * Since inode.namelen is a unsigned 6-bit number, the maximum cramfs + * path length is 63 << 2 = 252. + */ +#define CRAMFS_MAXPATHLEN (((1 << CRAMFS_NAMELEN_WIDTH) - 1) << 2) + +/* + * Reasonably terse representation of the inode data. + */ +struct cramfs_inode { + __u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH; + /* SIZE for device files is i_rdev */ + __u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH; + /* NAMELEN is the length of the file name, divided by 4 and + rounded up. (cramfs doesn't support hard links.) */ + /* OFFSET: For symlinks and non-empty regular files, this + contains the offset (divided by 4) of the file data in + compressed form (starting with an array of block pointers; + see README). For non-empty directories it is the offset + (divided by 4) of the inode of the first file in that + directory. For anything else, offset is zero. */ + __u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH; +}; + +struct cramfs_info { + __u32 crc; + __u32 edition; + __u32 blocks; + __u32 files; +}; + +/* + * Superblock information at the beginning of the FS. + */ +struct cramfs_super { + __u32 magic; /* 0x28cd3d45 - random number */ + __u32 size; /* length in bytes */ + __u32 flags; /* feature flags */ + __u32 future; /* reserved for future use */ + __u8 signature[16]; /* "Compressed ROMFS" */ + struct cramfs_info fsid; /* unique filesystem info */ + __u8 name[16]; /* user-defined name */ + struct cramfs_inode root; /* root inode data */ +}; + +/* + * Feature flags + * + * 0x00000000 - 0x000000ff: features that work for all past kernels + * 0x00000100 - 0xffffffff: features that don't work for past kernels + */ +#define CRAMFS_FLAG_FSID_VERSION_2 0x00000001 /* fsid version #2 */ +#define CRAMFS_FLAG_SORTED_DIRS 0x00000002 /* sorted dirs */ +#define CRAMFS_FLAG_HOLES 0x00000100 /* support for holes */ +#define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200 /* reserved */ +#define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400 /* shifted root fs */ + +/* + * Valid values in super.flags. Currently we refuse to mount + * if (flags & ~CRAMFS_SUPPORTED_FLAGS). Maybe that should be + * changed to test super.future instead. + */ +#define CRAMFS_SUPPORTED_FLAGS ( 0x000000ff \ + | CRAMFS_FLAG_HOLES \ + | CRAMFS_FLAG_WRONG_SIGNATURE \ + | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) + +#endif diff -puN /dev/null usr/kinit/fstype/ext2_fs.h --- /dev/null +++ a/usr/kinit/fstype/ext2_fs.h @@ -0,0 +1,79 @@ +/* + * The second extended file system magic number + */ +#define EXT2_SUPER_MAGIC 0xEF53 + +/* + * Structure of the super block + */ +struct ext2_super_block { + __le32 s_inodes_count; /* Inodes count */ + __le32 s_blocks_count; /* Blocks count */ + __le32 s_r_blocks_count; /* Reserved blocks count */ + __le32 s_free_blocks_count; /* Free blocks count */ + __le32 s_free_inodes_count; /* Free inodes count */ + __le32 s_first_data_block; /* First Data Block */ + __le32 s_log_block_size; /* Block size */ + __le32 s_log_frag_size; /* Fragment size */ + __le32 s_blocks_per_group; /* # Blocks per group */ + __le32 s_frags_per_group; /* # Fragments per group */ + __le32 s_inodes_per_group; /* # Inodes per group */ + __le32 s_mtime; /* Mount time */ + __le32 s_wtime; /* Write time */ + __le16 s_mnt_count; /* Mount count */ + __le16 s_max_mnt_count; /* Maximal mount count */ + __le16 s_magic; /* Magic signature */ + __le16 s_state; /* File system state */ + __le16 s_errors; /* Behaviour when detecting errors */ + __le16 s_minor_rev_level; /* minor revision level */ + __le32 s_lastcheck; /* time of last check */ + __le32 s_checkinterval; /* max. time between checks */ + __le32 s_creator_os; /* OS */ + __le32 s_rev_level; /* Revision level */ + __le16 s_def_resuid; /* Default uid for reserved blocks */ + __le16 s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + __le32 s_first_ino; /* First non-reserved inode */ + __le16 s_inode_size; /* size of inode structure */ + __le16 s_block_group_nr; /* block group # of this superblock */ + __le32 s_feature_compat; /* compatible feature set */ + __le32 s_feature_incompat; /* incompatible feature set */ + __le32 s_feature_ro_compat; /* readonly-compatible feature set */ + __u8 s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + __le32 s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_COMPAT_PREALLOC flag is on. + */ + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate */ + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + __u16 s_padding1; + /* + * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set. + */ + __u8 s_journal_uuid[16]; /* uuid of journal superblock */ + __u32 s_journal_inum; /* inode number of journal file */ + __u32 s_journal_dev; /* device number of journal file */ + __u32 s_last_orphan; /* start of list of inodes to delete */ + __u32 s_hash_seed[4]; /* HTREE hash seed */ + __u8 s_def_hash_version; /* Default hash version to use */ + __u8 s_reserved_char_pad; + __u16 s_reserved_word_pad; + __le32 s_default_mount_opts; + __le32 s_first_meta_bg; /* First metablock block group */ + __u32 s_reserved[190]; /* Padding to the end of the block */ +}; diff -puN /dev/null usr/kinit/fstype/ext3_fs.h --- /dev/null +++ a/usr/kinit/fstype/ext3_fs.h @@ -0,0 +1,92 @@ +/* + * The second extended file system magic number + */ +#define EXT3_SUPER_MAGIC 0xEF53 + +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 + +/* + * Structure of the super block + */ +struct ext3_super_block { + /*00*/ __u32 s_inodes_count; + /* Inodes count */ + __u32 s_blocks_count; /* Blocks count */ + __u32 s_r_blocks_count; /* Reserved blocks count */ + __u32 s_free_blocks_count; /* Free blocks count */ + /*10*/ __u32 s_free_inodes_count; + /* Free inodes count */ + __u32 s_first_data_block; /* First Data Block */ + __u32 s_log_block_size; /* Block size */ + __s32 s_log_frag_size; /* Fragment size */ + /*20*/ __u32 s_blocks_per_group; + /* # Blocks per group */ + __u32 s_frags_per_group; /* # Fragments per group */ + __u32 s_inodes_per_group; /* # Inodes per group */ + __u32 s_mtime; /* Mount time */ + /*30*/ __u32 s_wtime; + /* Write time */ + __u16 s_mnt_count; /* Mount count */ + __s16 s_max_mnt_count; /* Maximal mount count */ + __u16 s_magic; /* Magic signature */ + __u16 s_state; /* File system state */ + __u16 s_errors; /* Behaviour when detecting errors */ + __u16 s_minor_rev_level; /* minor revision level */ + /*40*/ __u32 s_lastcheck; + /* time of last check */ + __u32 s_checkinterval; /* max. time between checks */ + __u32 s_creator_os; /* OS */ + __u32 s_rev_level; /* Revision level */ + /*50*/ __u16 s_def_resuid; + /* Default uid for reserved blocks */ + __u16 s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT3_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + __u32 s_first_ino; /* First non-reserved inode */ + __u16 s_inode_size; /* size of inode structure */ + __u16 s_block_group_nr; /* block group # of this superblock */ + __u32 s_feature_compat; /* compatible feature set */ + /*60*/ __u32 s_feature_incompat; + /* incompatible feature set */ + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ + /*68*/ __u8 s_uuid[16]; + /* 128-bit uuid for volume */ + /*78*/ char s_volume_name[16]; + /* volume name */ + /*88*/ char s_last_mounted[64]; + /* directory where last mounted */ + /*C8*/ __u32 s_algorithm_usage_bitmap; + /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT3_FEATURE_COMPAT_DIR_PREALLOC flag is on. + */ + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate */ + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + __u16 s_padding1; + /* + * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set. + */ + /*D0*/ __u8 s_journal_uuid[16]; + /* uuid of journal superblock */ + /*E0*/ __u32 s_journal_inum; + /* inode number of journal file */ + __u32 s_journal_dev; /* device number of journal file */ + __u32 s_last_orphan; /* start of list of inodes to delete */ + __u32 s_hash_seed[4]; /* HTREE hash seed */ + __u8 s_def_hash_version; /* Default hash version to use */ + __u8 s_reserved_char_pad; + __u16 s_reserved_word_pad; + __u32 s_reserved[192]; /* Padding to the end of the block */ +}; diff -puN /dev/null usr/kinit/fstype/fstype.c --- /dev/null +++ a/usr/kinit/fstype/fstype.c @@ -0,0 +1,296 @@ +/* + * fstype.c, by rmk + * + * Detect filesystem type (on stdin) and output strings for two + * environment variables: + * FSTYPE - filesystem type + * FSSIZE - filesystem size (if known) + * + * We currently detect the filesystems listed below in the struct + * "imagetype images" (in the order they are listed). + * + * MINIX, ext3 and Reiserfs bits are currently untested. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define cpu_to_be32(x) __cpu_to_be32(x) /* Needed by romfs_fs.h */ + +#include "romfs_fs.h" +#include "cramfs_fs.h" +#include "minix_fs.h" +#include "ext2_fs.h" +#include "ext3_fs.h" +#include "xfs_sb.h" +#include "luks_fs.h" +#include "lvm2_sb.h" + +/* + * Slightly cleaned up version of jfs_superblock to + * avoid pulling in other kernel header files. + */ +#include "jfs_superblock.h" + +/* + * reiserfs_fs.h is too sick to include directly. + * Use a cleaned up version. + */ +#include "reiserfs_fs.h" + +#include "fstype.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +#define BLOCK_SIZE 1024 + +/* Swap needs the definition of block size */ +#include "swap_fs.h" + +static int gzip_image(const void *buf, unsigned long long *bytes) +{ + const unsigned char *p = buf; + + if (p[0] == 037 && (p[1] == 0213 || p[1] == 0236)) { + /* The length of a gzip stream can only be determined + by processing the whole stream */ + *bytes = 0ULL; + return 1; + } + return 0; +} + +static int cramfs_image(const void *buf, unsigned long long *bytes) +{ + const struct cramfs_super *sb = (const struct cramfs_super *)buf; + + if (sb->magic == CRAMFS_MAGIC) { + if (sb->flags & CRAMFS_FLAG_FSID_VERSION_2) + *bytes = (unsigned long long)sb->fsid.blocks << 10; + else + *bytes = 0; + return 1; + } + return 0; +} + +static int romfs_image(const void *buf, unsigned long long *bytes) +{ + const struct romfs_super_block *sb = + (const struct romfs_super_block *)buf; + + if (sb->word0 == ROMSB_WORD0 && sb->word1 == ROMSB_WORD1) { + *bytes = __be32_to_cpu(sb->size); + return 1; + } + return 0; +} + +static int minix_image(const void *buf, unsigned long long *bytes) +{ + const struct minix_super_block *sb = + (const struct minix_super_block *)buf; + + if (sb->s_magic == MINIX_SUPER_MAGIC || + sb->s_magic == MINIX_SUPER_MAGIC2) { + *bytes = (unsigned long long)sb->s_nzones + << (sb->s_log_zone_size + 10); + return 1; + } + return 0; +} + +static int ext3_image(const void *buf, unsigned long long *bytes) +{ + const struct ext3_super_block *sb = + (const struct ext3_super_block *)buf; + + if (sb->s_magic == __cpu_to_le16(EXT2_SUPER_MAGIC) && + sb-> + s_feature_compat & __cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { + *bytes = (unsigned long long)__le32_to_cpu(sb->s_blocks_count) + << (10 + sb->s_log_block_size); + return 1; + } + return 0; +} + +static int ext2_image(const void *buf, unsigned long long *bytes) +{ + const struct ext2_super_block *sb = + (const struct ext2_super_block *)buf; + + if (sb->s_magic == __cpu_to_le16(EXT2_SUPER_MAGIC)) { + *bytes = (unsigned long long)__le32_to_cpu(sb->s_blocks_count) + << (10 + sb->s_log_block_size); + return 1; + } + return 0; +} + +static int reiserfs_image(const void *buf, unsigned long long *bytes) +{ + const struct reiserfs_super_block *sb = + (const struct reiserfs_super_block *)buf; + + if (memcmp(REISERFS_MAGIC(sb), REISERFS_SUPER_MAGIC_STRING, + sizeof(REISERFS_SUPER_MAGIC_STRING) - 1) == 0 || + memcmp(REISERFS_MAGIC(sb), REISER2FS_SUPER_MAGIC_STRING, + sizeof(REISER2FS_SUPER_MAGIC_STRING) - 1) == 0 || + memcmp(REISERFS_MAGIC(sb), REISER2FS_JR_SUPER_MAGIC_STRING, + sizeof(REISER2FS_JR_SUPER_MAGIC_STRING) - 1) == 0) { + *bytes = (unsigned long long)REISERFS_BLOCK_COUNT(sb) * + REISERFS_BLOCKSIZE(sb); + return 1; + } + return 0; +} + +static int xfs_image(const void *buf, unsigned long long *bytes) +{ + const struct xfs_sb *sb = (const struct xfs_sb *)buf; + + if (__be32_to_cpu(sb->sb_magicnum) == XFS_SB_MAGIC) { + *bytes = __be64_to_cpu(sb->sb_dblocks) * + __be32_to_cpu(sb->sb_blocksize); + return 1; + } + return 0; +} + +static int jfs_image(const void *buf, unsigned long long *bytes) +{ + const struct jfs_superblock *sb = (const struct jfs_superblock *)buf; + + if (!memcmp(sb->s_magic, JFS_MAGIC, 4)) { + *bytes = __le32_to_cpu(sb->s_size); + return 1; + } + return 0; +} + +static int luks_image(const void *buf, unsigned long long *blocks) +{ + const struct luks_partition_header *lph = + (const struct luks_partition_header *)buf; + + if (!memcmp(lph->magic, LUKS_MAGIC, LUKS_MAGIC_L)) { + /* FSSIZE is dictated by the underlying fs, not by LUKS */ + *blocks = 0; + return 1; + } + return 0; +} + +static int swap_image(const void *buf, unsigned long long *blocks) +{ + const struct swap_super_block *ssb = + (const struct swap_super_block *)buf; + + if (!memcmp(ssb->magic, SWAP_MAGIC_1, SWAP_MAGIC_L) || + !memcmp(ssb->magic, SWAP_MAGIC_2, SWAP_MAGIC_L)) { + *blocks = 0; + return 1; + } + return 0; +} + +static int lvm2_image(const void *buf, unsigned long long *blocks) +{ + const struct lvm2_super_block *lsb; + int i; + + /* We must check every 512 byte sector */ + for (i = 0; i < BLOCK_SIZE; i += 0x200) { + lsb = (const struct lvm2_super_block *)(buf + i); + + if (!memcmp(lsb->magic, LVM2_MAGIC, LVM2_MAGIC_L) && + !memcmp(lsb->type, LVM2_TYPE, LVM2_TYPE_L)) { + /* This is just one of possibly many PV's */ + *blocks = 0; + return 1; + } + } + + return 0; +} + +struct imagetype { + off_t block; + const char name[12]; + int (*identify) (const void *, unsigned long long *); +}; + +/* + * Note: + * + * Minix test needs to come after ext3/ext2, since it's possible for + * ext3/ext2 to look like minix by pure random chance. + * + * LVM comes after all other filesystems since it's possible + * that an old lvm signature is left on the disk if pvremove + * is not used before creating the new fs. + */ +static struct imagetype images[] = { + {0, "gzip", gzip_image}, + {0, "cramfs", cramfs_image}, + {0, "romfs", romfs_image}, + {0, "xfs", xfs_image}, + {0, "luks", luks_image}, + {1, "ext3", ext3_image}, + {1, "ext2", ext2_image}, + {1, "minix", minix_image}, + {8, "reiserfs", reiserfs_image}, + {64, "reiserfs", reiserfs_image}, + {32, "jfs", jfs_image}, + {0, "lvm2", lvm2_image}, + {1, "lvm2", lvm2_image}, + {-1, "swap", swap_image}, + {0, "", NULL} +}; + +int identify_fs(int fd, const char **fstype, + unsigned long long *bytes, off_t offset) +{ + uint64_t buf[BLOCK_SIZE >> 3]; /* 64-bit worst case alignment */ + off_t cur_block = (off_t) - 1; + struct imagetype *ip; + int ret; + unsigned long long dummy; + + if (!bytes) + bytes = &dummy; + + *fstype = NULL; + *bytes = 0; + + for (ip = images; ip->identify; ip++) { + /* Hack for swap, which apparently is dependent on page size */ + if (ip->block == -1) + ip->block = SWAP_OFFSET(); + + if (cur_block != ip->block) { + /* + * Read block. + */ + cur_block = ip->block; + ret = pread(fd, buf, BLOCK_SIZE, + offset + cur_block * BLOCK_SIZE); + if (ret != BLOCK_SIZE) + return -1; /* error */ + } + + if (ip->identify(buf, bytes)) { + *fstype = ip->name; + return 0; + } + } + + return 1; /* Unknown filesystem */ +} diff -puN /dev/null usr/kinit/fstype/fstype.h --- /dev/null +++ a/usr/kinit/fstype/fstype.h @@ -0,0 +1,23 @@ +/* + * fstype.c, by rmk + * + * Detect filesystem type (on stdin) and output strings for two + * environment variables: + * FSTYPE - filesystem type + * FSSIZE - filesystem size (if known) + * + * We currently detect (in order): + * gzip, cramfs, romfs, xfs, minix, ext3, ext2, reiserfs, jfs + * + * MINIX, ext3 and Reiserfs bits are currently untested. + */ + +#ifndef FSTYPE_H +#define FSTYPE_H + +#include + +int identify_fs(int fd, const char **fstype, + unsigned long long *bytes, off_t offset); + +#endif diff -puN /dev/null usr/kinit/fstype/jfs_superblock.h --- /dev/null +++ a/usr/kinit/fstype/jfs_superblock.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) International Business Machines Corp., 2000-2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _H_JFS_SUPERBLOCK +#define _H_JFS_SUPERBLOCK + +struct timestruc_t { + __le32 tv_sec; + __le32 tv_nsec; +}; + +/* + * make the magic number something a human could read + */ +#define JFS_MAGIC "JFS1" /* Magic word */ + +#define JFS_VERSION 2 /* Version number: Version 2 */ + +#define LV_NAME_SIZE 11 /* MUST BE 11 for OS/2 boot sector */ + +/* + * aggregate superblock + * + * The name superblock is too close to super_block, so the name has been + * changed to jfs_superblock. The utilities are still using the old name. + */ +struct jfs_superblock { + char s_magic[4]; /* 4: magic number */ + __le32 s_version; /* 4: version number */ + + __le64 s_size; /* 8: aggregate size in hardware/LVM blocks; + * VFS: number of blocks + */ + __le32 s_bsize; /* 4: aggregate block size in bytes; + * VFS: fragment size + */ + __le16 s_l2bsize; /* 2: log2 of s_bsize */ + __le16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ + __le32 s_pbsize; /* 4: hardware/LVM block size in bytes */ + __le16 s_l2pbsize; /* 2: log2 of s_pbsize */ + __le16 pad; /* 2: padding necessary for alignment */ + + __le32 s_agsize; /* 4: allocation group size in aggr. blocks */ + + __le32 s_flag; /* 4: aggregate attributes: + * see jfs_filsys.h + */ + __le32 s_state; /* 4: mount/unmount/recovery state: + * see jfs_filsys.h + */ + __le32 s_compress; /* 4: > 0 if data compression */ + + __le64 s_ait2; /* 8: first extent of secondary + * aggregate inode table + */ + + __le64 s_aim2; /* 8: first extent of secondary + * aggregate inode map + */ + __le32 s_logdev; /* 4: device address of log */ + __le32 s_logserial; /* 4: log serial number at aggregate mount */ + __le64 s_logpxd; /* 8: inline log extent */ + + __le64 s_fsckpxd; /* 8: inline fsck work space extent */ + + struct timestruc_t s_time; /* 8: time last updated */ + + __le32 s_fsckloglen; /* 4: Number of filesystem blocks reserved for + * the fsck service log. + * N.B. These blocks are divided among the + * versions kept. This is not a per + * version size. + * N.B. These blocks are included in the + * length field of s_fsckpxd. + */ + char s_fscklog; /* 1: which fsck service log is most recent + * 0 => no service log data yet + * 1 => the first one + * 2 => the 2nd one + */ + char s_fpack[11]; /* 11: file system volume name + * N.B. This must be 11 bytes to + * conform with the OS/2 BootSector + * requirements + * Only used when s_version is 1 + */ + + /* extendfs() parameter under s_state & FM_EXTENDFS */ + __le64 s_xsize; /* 8: extendfs s_size */ + __le64 s_xfsckpxd; /* 8: extendfs fsckpxd */ + __le64 s_xlogpxd; /* 8: extendfs logpxd */ + /* - 128 byte boundary - */ + + char s_uuid[16]; /* 16: 128-bit uuid for volume */ + char s_label[16]; /* 16: volume label */ + char s_loguuid[16]; /* 16: 128-bit uuid for log device */ + +}; + +#endif /*_H_JFS_SUPERBLOCK */ diff -puN /dev/null usr/kinit/fstype/Kbuild --- /dev/null +++ a/usr/kinit/fstype/Kbuild @@ -0,0 +1,25 @@ +# +# Kbuild file for fstype +# + +static-y := static/fstype +shared-y := shared/fstype + +# common .o files +objs := main.o fstype.o + +# TODO - do we want a stripped version +# TODO - do we want the static.g + shared.g directories? + +# Create built-in.o with all object files (used by kinit) +lib-y := $(objs) + +# .o files used to built executables +static/fstype-y := $(objs) +shared/fstype-y := $(objs) + +# Cleaning +clean-dirs := static shared + +# install binary +install-y := $(shared-y) diff -puN /dev/null usr/kinit/fstype/luks_fs.h --- /dev/null +++ a/usr/kinit/fstype/luks_fs.h @@ -0,0 +1,44 @@ +#ifndef __LINUX_LUKS_FS_H +#define __LINUX_LUKS_FS_H + +/* The basic structures of the luks partition header */ +#define LUKS_MAGIC_L 6 +#define LUKS_CIPHERNAME_L 32 +#define LUKS_CIPHERMODE_L 32 +#define LUKS_HASHSPEC_L 32 +#define LUKS_UUID_STRING_L 40 + +#define LUKS_MAGIC "LUKS\xBA\xBE" +#define LUKS_DIGESTSIZE 20 +#define LUKS_SALTSIZE 32 +#define LUKS_NUMKEYS 8 +#define LUKS_MKD_ITER 10 +#define LUKS_KEY_DISABLED 0x0000DEAD +#define LUKS_KEY_ENABLED 0x00AC71F3 +#define LUKS_STRIPES 4000 + +/* On-disk "super block" */ +struct luks_partition_header { + char magic[LUKS_MAGIC_L]; + __be16 version; + char cipherName[LUKS_CIPHERNAME_L]; + char cipherMode[LUKS_CIPHERMODE_L]; + char hashSpec[LUKS_HASHSPEC_L]; + __be32 payloadOffset; + __be32 keyBytes; + char mkDigest[LUKS_DIGESTSIZE]; + char mkDigestSalt[LUKS_SALTSIZE]; + __be32 mkDigestIterations; + char uuid[LUKS_UUID_STRING_L]; + + struct { + __be32 active; + /* Parameters for PBKDF2 processing */ + __be32 passwordIterations; + char passwordSalt[LUKS_SALTSIZE]; + __be32 keyMaterialOffset; + __be32 stripes; + } keyblock[LUKS_NUMKEYS]; +}; + +#endif diff -puN /dev/null usr/kinit/fstype/lvm2_sb.h --- /dev/null +++ a/usr/kinit/fstype/lvm2_sb.h @@ -0,0 +1,18 @@ +#ifndef __LVM2_SB_H +#define __LVM2_SB_H + +/* LVM2 super block definitions */ +#define LVM2_MAGIC_L 8 +#define LVM2_MAGIC "LABELONE" +#define LVM2_TYPE_L 8 +#define LVM2_TYPE "LVM2 001" + +struct lvm2_super_block { + char magic[LVM2_MAGIC_L]; + __be64 sector; + __be32 crc; + __be32 offset; + char type[LVM2_TYPE_L]; +}; + +#endif diff -puN /dev/null usr/kinit/fstype/main.c --- /dev/null +++ a/usr/kinit/fstype/main.c @@ -0,0 +1,58 @@ +/* + * fstype.c, by rmk + * + * Detect filesystem type (on stdin) and output strings for two + * environment variables: + * FSTYPE - filesystem type + * FSSIZE - filesystem size (if known) + * + * We currently detect (in order): + * gzip, cramfs, romfs, xfs, minix, ext3, ext2, reiserfs, jfs + * + * MINIX, ext3 and Reiserfs bits are currently untested. + */ + +#include +#include +#include +#include +#include +#include +#include "fstype.h" + +char *progname; + +int main(int argc, char *argv[]) +{ + int fd = 0; + int rv; + const char *fstype; + const char *file = "stdin"; + unsigned long long bytes; + + progname = argv[0]; + + if (argc > 2) { + fprintf(stderr, "Usage: %s [file]\n", progname); + return 1; + } + + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '\0') { + fd = open(file = argv[1], O_RDONLY); + if (fd < 0) { + perror(argv[1]); + return 2; + } + } + + rv = identify_fs(fd, &fstype, &bytes, 0); + if (rv == -1) { + perror(file); + return 2; + } + + fstype = fstype ? fstype : "unknown"; + + fprintf(stdout, "FSTYPE=%s\nFSSIZE=%llu\n", fstype, bytes); + return rv; +} diff -puN /dev/null usr/kinit/fstype/minix_fs.h --- /dev/null +++ a/usr/kinit/fstype/minix_fs.h @@ -0,0 +1,85 @@ +#ifndef _LINUX_MINIX_FS_H +#define _LINUX_MINIX_FS_H + +/* + * The minix filesystem constants/structures + */ + +/* + * Thanks to Kees J Bot for sending me the definitions of the new + * minix filesystem (aka V2) with bigger inodes and 32-bit block + * pointers. + */ + +#define MINIX_ROOT_INO 1 + +/* Not the same as the bogus LINK_MAX in . Oh well. */ +#define MINIX_LINK_MAX 250 +#define MINIX2_LINK_MAX 65530 + +#define MINIX_I_MAP_SLOTS 8 +#define MINIX_Z_MAP_SLOTS 64 +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ +#define MINIX_VALID_FS 0x0001 /* Clean fs. */ +#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ + +#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) +#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) + +/* + * This is the original minix inode layout on disk. + * Note the 8-bit gid and atime and ctime. + */ +struct minix_inode { + __u16 i_mode; + __u16 i_uid; + __u32 i_size; + __u32 i_time; + __u8 i_gid; + __u8 i_nlinks; + __u16 i_zone[9]; +}; + +/* + * The new minix inode has all the time entries, as well as + * long block numbers and a third indirect block (7+1+1+1 + * instead of 7+1+1). Also, some previously 8-bit values are + * now 16-bit. The inode is now 64 bytes instead of 32. + */ +struct minix2_inode { + __u16 i_mode; + __u16 i_nlinks; + __u16 i_uid; + __u16 i_gid; + __u32 i_size; + __u32 i_atime; + __u32 i_mtime; + __u32 i_ctime; + __u32 i_zone[10]; +}; + +/* + * minix super-block data on disk + */ +struct minix_super_block { + __u16 s_ninodes; + __u16 s_nzones; + __u16 s_imap_blocks; + __u16 s_zmap_blocks; + __u16 s_firstdatazone; + __u16 s_log_zone_size; + __u32 s_max_size; + __u16 s_magic; + __u16 s_state; + __u32 s_zones; +}; + +struct minix_dir_entry { + __u16 inode; + char name[0]; +}; + +#endif diff -puN /dev/null usr/kinit/fstype/reiserfs_fs.h --- /dev/null +++ a/usr/kinit/fstype/reiserfs_fs.h @@ -0,0 +1,69 @@ +struct journal_params { + __u32 jp_journal_1st_block; /* where does journal start from on its + * device */ + __u32 jp_journal_dev; /* journal device st_rdev */ + __u32 jp_journal_size; /* size of the journal */ + __u32 jp_journal_trans_max; /* max number of blocks in a transaction. */ + __u32 jp_journal_magic; /* random value made on fs creation (this + * was sb_journal_block_count) */ + __u32 jp_journal_max_batch; /* max number of blocks to batch into a + * trans */ + __u32 jp_journal_max_commit_age; /* in seconds, how old can an async + * commit be */ + __u32 jp_journal_max_trans_age; /* in seconds, how old can a transaction + * be */ +}; + +/* this is the super from 3.5.X, where X >= 10 */ +struct reiserfs_super_block_v1 { + __u32 s_block_count; /* blocks count */ + __u32 s_free_blocks; /* free blocks count */ + __u32 s_root_block; /* root block number */ + struct journal_params s_journal; + __u16 s_blocksize; /* block size */ + __u16 s_oid_maxsize; /* max size of object id array, see + * get_objectid() commentary */ + __u16 s_oid_cursize; /* current size of object id array */ + __u16 s_umount_state; /* this is set to 1 when filesystem was + * umounted, to 2 - when not */ + char s_magic[10]; /* reiserfs magic string indicates that + * file system is reiserfs: + * "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */ + __u16 s_fs_state; /* it is set to used by fsck to mark which + * phase of rebuilding is done */ + __u32 s_hash_function_code; /* indicate, what hash function is being use + * to sort names in a directory*/ + __u16 s_tree_height; /* height of disk tree */ + __u16 s_bmap_nr; /* amount of bitmap blocks needed to address + * each block of file system */ + __u16 s_version; /* this field is only reliable on filesystem + * with non-standard journal */ + __u16 s_reserved_for_journal; /* size in blocks of journal area on main + * device, we need to keep after + * making fs with non-standard journal */ +} __attribute__ ((__packed__)); + +/* this is the on disk super block */ +struct reiserfs_super_block { + struct reiserfs_super_block_v1 s_v1; + __u32 s_inode_generation; + __u32 s_flags; /* Right now used only by inode-attributes, if enabled */ + unsigned char s_uuid[16]; /* filesystem unique identifier */ + unsigned char s_label[16]; /* filesystem volume label */ + char s_unused[88]; /* zero filled by mkreiserfs and + * reiserfs_convert_objectid_map_v1() + * so any additions must be updated + * there as well. */ +} __attribute__ ((__packed__)); + +#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" +#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" +#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" + +#define SB_V1_DISK_SUPER_BLOCK(s) (&((s)->s_v1)) +#define REISERFS_BLOCKSIZE(s) \ + __le32_to_cpu((SB_V1_DISK_SUPER_BLOCK(s)->s_blocksize)) +#define REISERFS_BLOCK_COUNT(s) \ + __le32_to_cpu((SB_V1_DISK_SUPER_BLOCK(s)->s_block_count)) +#define REISERFS_MAGIC(s) \ + (SB_V1_DISK_SUPER_BLOCK(s)->s_magic) diff -puN /dev/null usr/kinit/fstype/romfs_fs.h --- /dev/null +++ a/usr/kinit/fstype/romfs_fs.h @@ -0,0 +1,56 @@ +#ifndef __LINUX_ROMFS_FS_H +#define __LINUX_ROMFS_FS_H + +/* The basic structures of the romfs filesystem */ + +#define ROMBSIZE BLOCK_SIZE +#define ROMBSBITS BLOCK_SIZE_BITS +#define ROMBMASK (ROMBSIZE-1) +#define ROMFS_MAGIC 0x7275 + +#define ROMFS_MAXFN 128 + +#define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff)) +#define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff)) +#define __mk4(a,b,c,d) cpu_to_be32(__mkl(__mkw(a,b),__mkw(c,d))) +#define ROMSB_WORD0 __mk4('-','r','o','m') +#define ROMSB_WORD1 __mk4('1','f','s','-') + +/* On-disk "super block" */ + +struct romfs_super_block { + __be32 word0; + __be32 word1; + __be32 size; + __be32 checksum; + char name[0]; /* volume name */ +}; + +/* On disk inode */ + +struct romfs_inode { + __be32 next; /* low 4 bits see ROMFH_ */ + __be32 spec; + __be32 size; + __be32 checksum; + char name[0]; +}; + +#define ROMFH_TYPE 7 +#define ROMFH_HRD 0 +#define ROMFH_DIR 1 +#define ROMFH_REG 2 +#define ROMFH_SYM 3 +#define ROMFH_BLK 4 +#define ROMFH_CHR 5 +#define ROMFH_SCK 6 +#define ROMFH_FIF 7 +#define ROMFH_EXEC 8 + +/* Alignment */ + +#define ROMFH_SIZE 16 +#define ROMFH_PAD (ROMFH_SIZE-1) +#define ROMFH_MASK (~ROMFH_PAD) + +#endif diff -puN /dev/null usr/kinit/fstype/swap_fs.h --- /dev/null +++ a/usr/kinit/fstype/swap_fs.h @@ -0,0 +1,18 @@ +#ifndef __LINUX_SWAP_FS_H +#define __LINUX_SWAP_FS_H + +/* The basic structures of the swap super block */ +#define SWAP_MAGIC_L 10 +#define SWAP_RESERVED_L (1024 - SWAP_MAGIC_L) +#define SWAP_MAGIC_1 "SWAP-SPACE" +#define SWAP_MAGIC_2 "SWAPSPACE2" +/* The superblock is the last block in the first page */ +#define SWAP_OFFSET() ((getpagesize() - 1024) >> 10) + +/* On-disk "super block" */ +struct swap_super_block { + char reserved[SWAP_RESERVED_L]; + char magic[SWAP_MAGIC_L]; +}; + +#endif diff -puN /dev/null usr/kinit/fstype/xfs_sb.h --- /dev/null +++ a/usr/kinit/fstype/xfs_sb.h @@ -0,0 +1,16 @@ +/* + * Super block + * Fits into a sector-sized buffer at address 0 of each allocation group. + * Only the first of these is ever updated except during growfs. + */ + +struct xfs_buf; +struct xfs_mount; + +#define XFS_SB_MAGIC 0x58465342 /* 'XFSB' */ + +typedef struct xfs_sb { + __u32 sb_magicnum; /* magic number == XFS_SB_MAGIC */ + __u32 sb_blocksize; /* logical block size, bytes */ + __u64 sb_dblocks; /* number of data blocks */ +} xfs_sb_t; diff -puN /dev/null usr/kinit/getarg.c --- /dev/null +++ a/usr/kinit/getarg.c @@ -0,0 +1,57 @@ +#include +#include "kinit.h" + +/* + * Routines that hunt for a specific argument. Please note that + * they actually search the array backwards. That is because on the + * kernel command lines, it's legal to override an earlier argument + * with a later argument. + */ + +/* + * Was this boolean argument passed? If so return the index in the + * argv array for it. For conflicting boolean options, use the + * one with the higher index. The only case when the return value + * can be equal, is when they're both zero; so equality can be used + * as the default option choice. + * + * In other words, if two options "a" and "b" are opposites, and "a" + * is the default, this can be coded as: + * + * if (get_flag(argc,argv,"a") >= get_flag(argc,argv,"b")) + * do_a_stuff(); + * else + * do_b_stuff(); + */ +int get_flag(int argc, char *argv[], const char *name) +{ + int i; + + for (i = argc-1; i > 0; i--) { + if (!strcmp(argv[i], name)) + return i; + } + return 0; +} + +/* + * Was this textual parameter (foo=option) passed? + * + * This returns the latest instance of such an option in the argv array. + */ +char *get_arg(int argc, char *argv[], const char *name) +{ + int len = strlen(name); + char *ret = NULL; + int i; + + for (i = argc-1; i > 0; i--) { + if (argv[i] && strncmp(argv[i], name, len) == 0 && + (argv[i][len] != '\0')) { + ret = argv[i] + len; + break; + } + } + + return ret; +} diff -puN /dev/null usr/kinit/getintfile.c --- /dev/null +++ a/usr/kinit/getintfile.c @@ -0,0 +1,30 @@ +/* + * getintfile.c + * + * Open a file and read it, assuming it contains a single long value. + * Return 0 if we read a valid value, otherwise -1. + */ + +#include +#include + +int getintfile(const char *path, long *val) +{ + char buffer[64]; + char *ep; + FILE *f; + + f = fopen(path, "r"); + if (!f) + return -1; + + ep = buffer + fread(buffer, 1, sizeof buffer - 1, f); + fclose(f); + *ep = '\0'; + + *val = strtol(buffer, &ep, 0); + if (*ep && *ep != '\n') + return -1; + else + return 0; +} diff -puN /dev/null usr/kinit/initrd.c --- /dev/null +++ a/usr/kinit/initrd.c @@ -0,0 +1,199 @@ +/* + * kinit/initrd.c + * + * Handle initrd, thus putting the backwards into backwards compatible + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "do_mounts.h" +#include "kinit.h" +#include "xpio.h" + +#define BUF_SIZE 65536 /* Should be a power of 2 */ + +/* + * Copy the initrd to /dev/ram0, copy from the end to the beginning + * to avoid taking 2x the memory. + */ +static int rd_copy_uncompressed(int ffd, int dfd) +{ + char buffer[BUF_SIZE]; + off_t bytes; + struct stat st; + + DEBUG(("kinit: uncompressed initrd\n")); + + if (ffd < 0 || fstat(ffd, &st) || !S_ISREG(st.st_mode) || + (bytes = st.st_size) == 0) + return -1; + + while (bytes) { + ssize_t blocksize = ((bytes - 1) & (BUF_SIZE - 1)) + 1; + off_t offset = bytes - blocksize; + + DEBUG(("kinit: copying %zd bytes at offset %llu\n", + blocksize, offset)); + + if (xpread(ffd, buffer, blocksize, offset) != blocksize || + xpwrite(dfd, buffer, blocksize, offset) != blocksize) + return -1; + + ftruncate(ffd, offset); /* Free up memory */ + bytes = offset; + } + return 0; +} + +static int rd_copy_image(const char *path) +{ + int ffd = open(path, O_RDONLY); + int rv = -1; + unsigned char gzip_magic[2]; + + if (ffd < 0) + goto barf; + + if (xpread(ffd, gzip_magic, 2, 0) == 2 && + gzip_magic[0] == 037 && gzip_magic[1] == 0213) { + FILE *wfd = fopen("/dev/ram0", "w"); + if (!wfd) + goto barf; + rv = load_ramdisk_compressed(path, wfd, 0); + fclose(wfd); + } else { + int dfd = open("/dev/ram0", O_WRONLY); + if (dfd < 0) + goto barf; + rv = rd_copy_uncompressed(ffd, dfd); + close(dfd); + } + +barf: + if (ffd >= 0) + close(ffd); + return rv; +} + +/* + * Run /linuxrc, for emulation of old-style initrd + */ +static int run_linuxrc(int argc, char *argv[], dev_t root_dev) +{ + int root_fd, old_fd; + pid_t pid; + long realroot = Root_RAM0; + const char *ramdisk_name = "/dev/ram0"; + FILE *fp; + + DEBUG(("kinit: mounting initrd\n")); + mkdir("/root", 0700); + if (!mount_block(ramdisk_name, "/root", NULL, MS_VERBOSE, NULL)) + return -errno; + + /* Write the current "real root device" out to procfs */ + DEBUG(("kinit: real_root_dev = %#x\n", root_dev)); + fp = fopen("/proc/sys/kernel/real-root-dev", "w"); + fprintf(fp, "%u", root_dev); + fclose(fp); + + mkdir("/old", 0700); + root_fd = open_cloexec("/", O_RDONLY | O_DIRECTORY, 0); + old_fd = open_cloexec("/old", O_RDONLY | O_DIRECTORY, 0); + + if (root_fd < 0 || old_fd < 0) + return -errno; + + if (chdir("/root") || + mount(".", "/", NULL, MS_MOVE, NULL) || chroot(".")) + return -errno; + + pid = fork(); + if (pid == 0) { + setsid(); + /* Looks like linuxrc doesn't get the init environment + or parameters. Weird, but so is the whole linuxrc bit. */ + execl("/linuxrc", "linuxrc", NULL); + _exit(255); + } else if (pid > 0) { + DEBUG(("kinit: Waiting for linuxrc to complete...\n")); + while (waitpid(pid, NULL, 0) != pid) ; + DEBUG(("kinit: linuxrc done\n")); + } else { + return -errno; + } + + if (fchdir(old_fd) || + mount("/", ".", NULL, MS_MOVE, NULL) || + fchdir(root_fd) || chroot(".")) + return -errno; + + close(root_fd); + close(old_fd); + + getintfile("/proc/sys/kernel/real-root-dev", &realroot); + + /* If realroot is Root_RAM0, then the initrd did any necessary work */ + if (realroot == Root_RAM0) { + if (mount("/old", "/root", NULL, MS_MOVE, NULL)) + return -errno; + } else { + mount_root(argc, argv, (dev_t) realroot, NULL); + + /* If /root/initrd exists, move the initrd there, otherwise discard */ + if (!mount("/old", "/root/initrd", NULL, MS_MOVE, NULL)) { + /* We're good */ + } else { + int olddev = open(ramdisk_name, O_RDWR); + umount2("/old", MNT_DETACH); + if (olddev < 0 || + ioctl(olddev, BLKFLSBUF, (long)0) || + close(olddev)) { + fprintf(stderr, + "%s: Cannot flush initrd contents\n", + progname); + } + } + } + + rmdir("/old"); + return 0; +} + +int initrd_load(int argc, char *argv[], dev_t root_dev) +{ + if (access("/initrd.image", R_OK)) + return 0; /* No initrd */ + + DEBUG(("kinit: initrd found\n")); + + create_dev("/dev/ram0", Root_RAM0); + + if (rd_copy_image("/initrd.image") || unlink("/initrd.image")) { + fprintf(stderr, "%s: initrd installation failed (too big?)\n", + progname); + return 0; /* Failed to copy initrd */ + } + + DEBUG(("kinit: initrd copied\n")); + + if (root_dev != Root_RAM0) { + int err; + DEBUG(("kinit: running linuxrc\n")); + err = run_linuxrc(argc, argv, root_dev); + if (err) + fprintf(stderr, "%s: running linuxrc: %s\n", progname, + strerror(-err)); + return 1; /* initrd is root, or run_linuxrc took care of it */ + } else { + DEBUG(("kinit: permament (or pivoting) initrd, not running linuxrc\n")); + return 0; /* Mounting initrd as ordinary root */ + } +} diff -puN /dev/null usr/kinit/ipconfig/bootp_packet.h --- /dev/null +++ a/usr/kinit/ipconfig/bootp_packet.h @@ -0,0 +1,34 @@ +/* + * ipconfig/bootp_packet.h + */ +#ifndef BOOTP_PACKET_H +#define BOOTP_PACKET_H + +#include + +struct netdev; + +/* packet ops */ +#define BOOTP_REQUEST 1 +#define BOOTP_REPLY 2 + +/* your basic bootp packet */ +struct bootp_hdr { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + uint8_t chaddr[16]; + char server_name[64]; + char boot_file[128]; + /* 312 bytes of extensions */ +}; + +#endif diff -puN /dev/null usr/kinit/ipconfig/bootp_proto.c --- /dev/null +++ a/usr/kinit/ipconfig/bootp_proto.c @@ -0,0 +1,213 @@ +/* + * ipconfig/bootp_proto.c + * + * BOOTP packet protocol handling. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipconfig.h" +#include "netdev.h" +#include "bootp_packet.h" +#include "bootp_proto.h" +#include "packet.h" + +static uint8_t bootp_options[312] = { + [ 0] = 99, 130, 83, 99,/* RFC1048 magic cookie */ + [ 4] = 1, 4, /* 4- 9 subnet mask */ + [ 10] = 3, 4, /* 10- 15 default gateway */ + [ 16] = 5, 8, /* 16- 25 nameserver */ + [ 26] = 12, 32, /* 26- 59 host name */ + [ 60] = 40, 32, /* 60- 95 nis domain name */ + [ 96] = 17, 40, /* 96-137 boot path */ + [138] = 57, 2, 1, 150, /* 138-141 extension buffer */ + [142] = 255, /* end of list */ +}; + +/* + * Send a plain bootp request packet with options + */ +int bootp_send_request(struct netdev *dev) +{ + struct bootp_hdr bootp; + struct iovec iov[] = { + /* [0] = ip + udp headers */ + [1] = {&bootp, sizeof(bootp)}, + [2] = {bootp_options, 312} + }; + + memset(&bootp, 0, sizeof(struct bootp_hdr)); + + bootp.op = BOOTP_REQUEST, bootp.htype = dev->hwtype; + bootp.hlen = dev->hwlen; + bootp.xid = dev->bootp.xid; + bootp.ciaddr = dev->ip_addr; + bootp.secs = htons(time(NULL) - dev->open_time); + memcpy(bootp.chaddr, dev->hwaddr, 16); + + DEBUG(("-> bootp xid 0x%08x secs 0x%08x ", + bootp.xid, ntohs(bootp.secs))); + + return packet_send(dev, iov, 2); +} + +/* + * Parse a bootp reply packet + */ +int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr, + uint8_t *exts, int extlen) +{ + dev->bootp.gateway = hdr->giaddr; + dev->ip_addr = hdr->yiaddr; + dev->ip_server = hdr->siaddr; + dev->ip_netmask = INADDR_ANY; + dev->ip_broadcast = INADDR_ANY; + dev->ip_gateway = hdr->giaddr; + dev->ip_nameserver[0] = INADDR_ANY; + dev->ip_nameserver[1] = INADDR_ANY; + dev->hostname[0] = '\0'; + dev->nisdomainname[0] = '\0'; + dev->bootpath[0] = '\0'; + + if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 && + exts[2] == 83 && exts[3] == 99) { + uint8_t *ext; + + for (ext = exts + 4; ext - exts < extlen;) { + int len; + uint8_t opt = *ext++; + + if (opt == 0) + continue; + else if (opt == 255) + break; + + len = *ext++; + + switch (opt) { + case 1: /* subnet mask */ + if (len == 4) + memcpy(&dev->ip_netmask, ext, 4); + break; + case 3: /* default gateway */ + if (len >= 4) + memcpy(&dev->ip_gateway, ext, 4); + break; + case 6: /* DNS server */ + if (len >= 4) + memcpy(&dev->ip_nameserver, ext, + len >= 8 ? 8 : 4); + break; + case 12: /* host name */ + if (len > sizeof(dev->hostname) - 1) + len = sizeof(dev->hostname) - 1; + memcpy(&dev->hostname, ext, len); + dev->hostname[len] = '\0'; + break; + case 15: /* domain name */ + if (len > sizeof(dev->dnsdomainname) - 1) + len = sizeof(dev->dnsdomainname) - 1; + memcpy(&dev->dnsdomainname, ext, len); + dev->dnsdomainname[len] = '\0'; + break; + case 17: /* root path */ + if (len > sizeof(dev->bootpath) - 1) + len = sizeof(dev->bootpath) - 1; + memcpy(&dev->bootpath, ext, len); + dev->bootpath[len] = '\0'; + break; + case 26: /* interface MTU */ + if (len == 2) + dev->mtu = (ext[0] << 8) + ext[1]; + break; + case 28: /* broadcast addr */ + if (len == 4) + memcpy(&dev->ip_broadcast, ext, 4); + break; + case 40: /* NIS domain name */ + if (len > sizeof(dev->nisdomainname) - 1) + len = sizeof(dev->nisdomainname) - 1; + memcpy(&dev->nisdomainname, ext, len); + dev->nisdomainname[len] = '\0'; + break; + case 54: /* server identifier */ + if (len == 4 && !dev->ip_server) + memcpy(&dev->ip_server, ext, 4); + break; + } + + ext += len; + } + } + + /* + * Got packet. + */ + return 1; +} + +/* + * Receive a bootp reply and parse packet + */ +int bootp_recv_reply(struct netdev *dev) +{ + struct bootp_hdr bootp; + uint8_t bootp_options[312]; + struct iovec iov[] = { + /* [0] = ip + udp headers */ + [1] = {&bootp, sizeof(struct bootp_hdr)}, + [2] = {bootp_options, 312} + }; + int ret; + + ret = packet_recv(iov, 3); + if (ret <= 0) + return ret; + + if (ret < sizeof(struct bootp_hdr) || + bootp.op != BOOTP_REPLY || /* RFC951 7.5 */ + bootp.xid != dev->bootp.xid || + memcmp(bootp.chaddr, dev->hwaddr, 16)) + return 0; + + ret -= sizeof(struct bootp_hdr); + + return bootp_parse(dev, &bootp, bootp_options, ret); +} + +/* + * Initialise interface for bootp. + */ +int bootp_init_if(struct netdev *dev) +{ + short flags; + + /* + * Get the device flags + */ + if (netdev_getflags(dev, &flags)) + return -1; + + /* + * We can't do DHCP nor BOOTP if this device + * doesn't support broadcast. + */ + if (dev->mtu < 364 || (flags & IFF_BROADCAST) == 0) { + dev->caps &= ~(CAP_BOOTP | CAP_DHCP); + return 0; + } + + /* + * Get a random XID + */ + dev->bootp.xid = (uint32_t) lrand48(); + dev->open_time = time(NULL); + + return 0; +} diff -puN /dev/null usr/kinit/ipconfig/bootp_proto.h --- /dev/null +++ a/usr/kinit/ipconfig/bootp_proto.h @@ -0,0 +1,8 @@ +/* + * bootp_proto.h + */ +int bootp_send_request(struct netdev *dev); +int bootp_recv_reply(struct netdev *dev); +int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr, uint8_t * exts, + int extlen); +int bootp_init_if(struct netdev *dev); diff -puN /dev/null usr/kinit/ipconfig/dhcp_proto.c --- /dev/null +++ a/usr/kinit/ipconfig/dhcp_proto.c @@ -0,0 +1,212 @@ +/* + * ipconfig/dhcp_proto.c + * + * DHCP RFC 2131 and 2132 + */ +#include +#include +#include +#include +#include +#include + +#include "ipconfig.h" +#include "netdev.h" +#include "bootp_packet.h" +#include "bootp_proto.h" +#include "dhcp_proto.h" +#include "packet.h" + +static uint8_t dhcp_params[] = { + 1, /* subnet mask */ + 3, /* default gateway */ + 6, /* DNS server */ + 12, /* host name */ + 15, /* domain name */ + 17, /* root path */ + 26, /* interface mtu */ + 28, /* broadcast addr */ + 40, /* NIS domain name (why?) */ +}; + +static uint8_t dhcp_discover_hdr[] = { + 99, 130, 83, 99, /* bootp cookie */ + 53, 1, DHCPDISCOVER, /* dhcp message type */ + 55, sizeof(dhcp_params), /* parameter list */ +}; + +static uint8_t dhcp_request_hdr[] = { + 99, 130, 83, 99, /* boot cookie */ + 53, 1, DHCPREQUEST, /* dhcp message type */ +#define SERVER_IP_OFF 9 + 54, 4, 0, 0, 0, 0, /* server IP */ +#define REQ_IP_OFF 15 + 50, 4, 0, 0, 0, 0, /* requested IP address */ + 55, sizeof(dhcp_params), /* parameter list */ +}; + +static uint8_t dhcp_end[] = { + 255, +}; + +static struct iovec dhcp_discover_iov[] = { + /* [0] = ip + udp header */ + /* [1] = bootp header */ + [2] = {dhcp_discover_hdr, sizeof(dhcp_discover_hdr)}, + [3] = {dhcp_params, sizeof(dhcp_params)}, + [4] = {dhcp_end, sizeof(dhcp_end)} +}; + +static struct iovec dhcp_request_iov[] = { + /* [0] = ip + udp header */ + /* [1] = bootp header */ + [2] = {dhcp_request_hdr, sizeof(dhcp_request_hdr)}, + [3] = {dhcp_params, sizeof(dhcp_params)}, + [4] = {dhcp_end, sizeof(dhcp_end)} +}; + +/* + * Parse a DHCP response packet + */ +static int +dhcp_parse(struct netdev *dev, struct bootp_hdr *hdr, uint8_t * exts, int extlen) +{ + uint8_t type = 0; + uint32_t serverid = INADDR_NONE; + int ret = 0; + + if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 && + exts[2] == 83 && exts[3] == 99) { + uint8_t *ext; + + for (ext = exts + 4; ext - exts < extlen;) { + uint8_t len, *opt = ext++; + if (*opt == 0) + continue; + + len = *ext++; + + ext += len; + + if (*opt == 53) + type = opt[2]; + if (*opt == 54) + memcpy(&serverid, opt + 2, 4); + } + } + + switch (type) { + case DHCPOFFER: + ret = bootp_parse(dev, hdr, exts, extlen); + if (ret == 1 && serverid != INADDR_NONE) + dev->serverid = serverid; + DEBUG(("\n dhcp offer\n")); + break; + + case DHCPACK: + ret = bootp_parse(dev, hdr, exts, extlen); + DEBUG(("\n dhcp ack\n")); + break; + + case DHCPNAK: + ret = 2; + DEBUG(("\n dhcp nak\n")); + break; + } + return ret; +} + +/* + * Receive and parse a DHCP packet + */ +static int dhcp_recv(struct netdev *dev) +{ + struct bootp_hdr bootp; + uint8_t dhcp_options[1500]; + struct iovec iov[] = { + /* [0] = ip + udp header */ + [1] = {&bootp, sizeof(struct bootp_hdr)}, + [2] = {dhcp_options, sizeof(dhcp_options)} + }; + int ret; + + ret = packet_recv(iov, 3); + if (ret <= 0) + return ret; + + DEBUG(("\n dhcp xid %08x ", dev->bootp.xid)); + + if (ret < sizeof(struct bootp_hdr) || bootp.op != BOOTP_REPLY || /* RFC951 7.5 */ + bootp.xid != dev->bootp.xid || + memcmp(bootp.chaddr, dev->hwaddr, 16)) + return 0; + + ret -= sizeof(struct bootp_hdr); + + return dhcp_parse(dev, &bootp, dhcp_options, ret); +} + +static int dhcp_send(struct netdev *dev, struct iovec *vec, int len) +{ + struct bootp_hdr bootp; + + memset(&bootp, 0, sizeof(struct bootp_hdr)); + + bootp.op = BOOTP_REQUEST; + bootp.htype = dev->hwtype; + bootp.hlen = dev->hwlen; + bootp.xid = dev->bootp.xid; + bootp.ciaddr = dev->ip_addr; + bootp.giaddr = dev->bootp.gateway; + bootp.secs = htons(time(NULL) - dev->open_time); + memcpy(bootp.chaddr, dev->hwaddr, 16); + + vec[1].iov_base = &bootp; + vec[1].iov_len = sizeof(struct bootp_hdr); + + DEBUG(("xid %08x secs %d ", bootp.xid, ntohs(bootp.secs))); + + return packet_send(dev, vec, len); +} + +/* + * Send a DHCP discover packet + */ +int dhcp_send_discover(struct netdev *dev) +{ + dev->ip_addr = INADDR_ANY; + dev->ip_gateway = INADDR_ANY; + + DEBUG(("-> dhcp discover ")); + + return dhcp_send(dev, dhcp_discover_iov, 5); +} + +/* + * Receive a DHCP offer packet + */ +int dhcp_recv_offer(struct netdev *dev) +{ + return dhcp_recv(dev); +} + +/* + * Send a DHCP request packet + */ +int dhcp_send_request(struct netdev *dev) +{ + memcpy(&dhcp_request_hdr[SERVER_IP_OFF], &dev->serverid, 4); + memcpy(&dhcp_request_hdr[REQ_IP_OFF], &dev->ip_addr, 4); + + DEBUG(("-> dhcp request ")); + + return dhcp_send(dev, dhcp_request_iov, 5); +} + +/* + * Receive a DHCP ack packet + */ +int dhcp_recv_ack(struct netdev *dev) +{ + return dhcp_recv(dev); +} diff -puN /dev/null usr/kinit/ipconfig/dhcp_proto.h --- /dev/null +++ a/usr/kinit/ipconfig/dhcp_proto.h @@ -0,0 +1,18 @@ +/* + * ipconfig/dhcp_proto.h + */ + +/* DHCP message types */ +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 +#define DHCPINFORM 8 + +int dhcp_send_discover(struct netdev *dev); +int dhcp_recv_offer(struct netdev *dev); +int dhcp_send_request(struct netdev *dev); +int dhcp_recv_ack(struct netdev *dev); diff -puN /dev/null usr/kinit/ipconfig/ipconfig.h --- /dev/null +++ a/usr/kinit/ipconfig/ipconfig.h @@ -0,0 +1,35 @@ +/* + * ipconfig/ipconfig.h + */ + +#ifndef IPCONFIG_IPCONFIG_H +#define IPCONFIG_IPCONFIG_H + +#include +#include + +#define LOCAL_PORT 68 +#define REMOTE_PORT (LOCAL_PORT - 1) + +extern uint16_t cfg_local_port; +extern uint16_t cfg_remote_port; + +int ipconfig_main(int argc, char *argv[]); +uint32_t ipconfig_server_address(void *next); + +/* + * Note for gcc 3.2.2: + * + * If you're turning on debugging, make sure you get rid of -Os from + * the gcc command line, or else ipconfig will fail to link. + */ +#define IPC_DEBUG + +#undef DEBUG +#ifdef IPC_DEBUG +#define DEBUG(x) printf x +#else +#define DEBUG(x) do { } while(0) +#endif + +#endif /* IPCONFIG_IPCONFIG_H */ diff -puN /dev/null usr/kinit/ipconfig/Kbuild --- /dev/null +++ a/usr/kinit/ipconfig/Kbuild @@ -0,0 +1,31 @@ +# +# Kbuild file for ipconfig +# + +static-y := static/ipconfig +shared-y := shared/ipconfig + +# common .o files +objs := main.o netdev.o packet.o +# dhcp +objs += dhcp_proto.o +# bootp +objs += bootp_proto.o + + +# TODO - do we want a stripped version +# TODO - do we want the static.g + shared.g directories? + + +# Create built-in.o with all object files (used by kinit) +lib-y := $(objs) + +# .o files used to built executables +static/ipconfig-y := $(objs) +shared/ipconfig-y := $(objs) + +# Cleaning +clean-dirs := static shared + +# install binary +install-y := $(shared-y) diff -puN /dev/null usr/kinit/ipconfig/main.c --- /dev/null +++ a/usr/kinit/ipconfig/main.c @@ -0,0 +1,758 @@ +/* + * ipconfig/main.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for getopts */ + +#include + +#include "ipconfig.h" +#include "netdev.h" +#include "bootp_packet.h" +#include "bootp_proto.h" +#include "dhcp_proto.h" +#include "packet.h" + +static const char sysfs_class_net[] = "/sys/class/net"; +static const char *progname; +static jmp_buf abort_buf; +static char do_not_config; +static unsigned int default_caps = CAP_DHCP | CAP_BOOTP | CAP_RARP; +static int loop_timeout = -1; +static int configured; +static int bringup_first = 0; + +struct state { + int state; + int restart_state; + time_t expire; + int retry_period; + + struct netdev *dev; + struct state *next; +}; + +static inline const char *my_inet_ntoa(uint32_t addr) +{ + struct in_addr a; + + a.s_addr = addr; + + return inet_ntoa(a); +} + +static void print_device_config(struct netdev *dev) +{ + printf("IP-Config: %s complete (from %s):\n", dev->name, + my_inet_ntoa(dev->serverid ? dev->serverid : dev->ip_server)); + printf(" address: %-16s ", my_inet_ntoa(dev->ip_addr)); + printf("broadcast: %-16s ", my_inet_ntoa(dev->ip_broadcast)); + printf("netmask: %-16s\n", my_inet_ntoa(dev->ip_netmask)); + printf(" gateway: %-16s ", my_inet_ntoa(dev->ip_gateway)); + printf("dns0 : %-16s ", my_inet_ntoa(dev->ip_nameserver[0])); + printf("dns1 : %-16s\n", my_inet_ntoa(dev->ip_nameserver[1])); + if (dev->hostname[0]) + printf(" host : %-64s\n", dev->hostname); + if (dev->dnsdomainname[0]) + printf(" domain : %-64s\n", dev->dnsdomainname); + if (dev->nisdomainname[0]) + printf(" nisdomain: %-64s\n", dev->nisdomainname); + printf(" rootserver: %s ", my_inet_ntoa(dev->ip_server)); + printf("rootpath: %s\n", dev->bootpath); +} + +static void configure_device(struct netdev *dev) +{ + if (do_not_config) + return; + + if (netdev_setmtu(dev)) + printf("IP-Config: failed to set MTU on %s to %u\n", + dev->name, dev->mtu); + + if (netdev_setaddress(dev)) + printf("IP-Config: failed to set addresses on %s\n", dev->name); + if (netdev_setdefaultroute(dev)) + printf("IP-Config: failed to set default route on %s\n", + dev->name); +} + +static void dump_device_config(struct netdev *dev) +{ + char fn[40]; + FILE *f; + + snprintf(fn, sizeof(fn), "/tmp/net-%s.conf", dev->name); + f = fopen(fn, "w"); + if (f) { + fprintf(f, "DEVICE=%s\n", dev->name); + fprintf(f, "IPV4ADDR=%s\n", my_inet_ntoa(dev->ip_addr)); + fprintf(f, "IPV4BROADCAST=%s\n", + my_inet_ntoa(dev->ip_broadcast)); + fprintf(f, "IPV4NETMASK=%s\n", my_inet_ntoa(dev->ip_netmask)); + fprintf(f, "IPV4GATEWAY=%s\n", my_inet_ntoa(dev->ip_gateway)); + fprintf(f, "IPV4DNS0=%s\n", + my_inet_ntoa(dev->ip_nameserver[0])); + fprintf(f, "IPV4DNS1=%s\n", + my_inet_ntoa(dev->ip_nameserver[1])); + fprintf(f, "HOSTNAME=%s\n", dev->hostname); + fprintf(f, "DNSDOMAIN=%s\n", dev->dnsdomainname); + fprintf(f, "NISDOMAIN=%s\n", dev->nisdomainname); + fprintf(f, "ROOTSERVER=%s\n", my_inet_ntoa(dev->ip_server)); + fprintf(f, "ROOTPATH=%s\n", dev->bootpath); + fclose(f); + } +} + +static uint32_t inet_class_netmask(uint32_t ip) +{ + ip = ntohl(ip); + if (IN_CLASSA(ip)) + return htonl(IN_CLASSA_NET); + if (IN_CLASSB(ip)) + return htonl(IN_CLASSB_NET); + if (IN_CLASSC(ip)) + return htonl(IN_CLASSC_NET); + return INADDR_ANY; +} + +static void postprocess_device(struct netdev *dev) +{ + if (dev->ip_netmask == INADDR_ANY) { + dev->ip_netmask = inet_class_netmask(dev->ip_addr); + printf("IP-Config: %s guessed netmask %s\n", + dev->name, my_inet_ntoa(dev->ip_netmask)); + } + if (dev->ip_broadcast == INADDR_ANY) { + dev->ip_broadcast = + (dev->ip_addr & dev->ip_netmask) | ~dev->ip_netmask; + printf("IP-Config: %s guessed broadcast address %s\n", + dev->name, my_inet_ntoa(dev->ip_broadcast)); + } + if (dev->ip_nameserver[0] == INADDR_ANY) { + dev->ip_nameserver[0] = dev->ip_server; + printf("IP-Config: %s guessed nameserver address %s\n", + dev->name, my_inet_ntoa(dev->ip_nameserver[0])); + } +} + +static void complete_device(struct netdev *dev) +{ + postprocess_device(dev); + configure_device(dev); + dump_device_config(dev); + print_device_config(dev); + + ++configured; + + dev->next = ifaces; + ifaces = dev; +} + +static int process_receive_event(struct state *s, time_t now) +{ + int handled = 1; + + switch (s->state) { + case DEVST_BOOTP: + s->restart_state = DEVST_BOOTP; + switch (bootp_recv_reply(s->dev)) { + case -1: + s->state = DEVST_ERROR; + break; + case 1: + s->state = DEVST_COMPLETE; + DEBUG(("\n bootp reply\n")); + break; + } + break; + + case DEVST_DHCPDISC: + s->restart_state = DEVST_DHCPDISC; + switch (dhcp_recv_offer(s->dev)) { + case -1: + s->state = DEVST_ERROR; + break; + case 1: /* Offer received */ + s->state = DEVST_DHCPREQ; + dhcp_send_request(s->dev); + break; + } + break; + + case DEVST_DHCPREQ: + s->restart_state = DEVST_DHCPDISC; + switch (dhcp_recv_ack(s->dev)) { + case -1: /* error */ + s->state = DEVST_ERROR; + break; + case 1: /* ACK received */ + s->state = DEVST_COMPLETE; + break; + case 2: /* NAK received */ + s->state = DEVST_DHCPDISC; + break; + } + break; + } + + switch (s->state) { + case DEVST_COMPLETE: + complete_device(s->dev); + break; + + case DEVST_ERROR: + /* error occurred, try again in 10 seconds */ + s->expire = now + 10; + default: + DEBUG(("\n")); + handled = 0; + break; + } + + return handled; +} + +static void process_timeout_event(struct state *s, time_t now) +{ + int ret = 0; + + /* + * Is the link up? If not, try again in 1 second. + */ + if (!netdev_running(s->dev)) { + s->expire = now + 1; + s->state = s->restart_state; + return; + } + + /* + * If we had an error, restore a sane state to + * restart from. + */ + if (s->state == DEVST_ERROR) + s->state = s->restart_state; + + /* + * Now send a packet depending on our state. + */ + switch (s->state) { + case DEVST_BOOTP: + ret = bootp_send_request(s->dev); + s->restart_state = DEVST_BOOTP; + break; + + case DEVST_DHCPDISC: + ret = dhcp_send_discover(s->dev); + s->restart_state = DEVST_DHCPDISC; + break; + + case DEVST_DHCPREQ: + ret = dhcp_send_request(s->dev); + s->restart_state = DEVST_DHCPDISC; + break; + } + + if (ret == -1) { + s->state = DEVST_ERROR; + s->expire = now + 10; + } else { + s->expire = now + s->retry_period; + + s->retry_period *= 2; + if (s->retry_period > 60) + s->retry_period = 60; + } +} + +static struct state *slist; +struct netdev *ifaces; + +static int do_pkt_recv(int pkt_fd, time_t now) +{ + int ifindex, ret; + struct state *s; + + ret = packet_peek(&ifindex); + if (ret < 0) + goto bail; + + for (s = slist; s; s = s->next) { + if (s->dev->ifindex == ifindex) { + ret |= process_receive_event(s, now); + break; + } + } + + bail: + return ret; +} + +static int loop(void) +{ +#define NR_FDS 1 + struct pollfd fds[NR_FDS]; + struct state *s; + int pkt_fd; + int nr = 0; + struct timeval now, prev; + time_t start; + + pkt_fd = packet_open(); + if (pkt_fd == -1) { + perror("packet_open"); + return -1; + } + + fds[0].fd = pkt_fd; + fds[0].events = POLLRDNORM; + + gettimeofday(&now, NULL); + start = now.tv_sec; + while (1) { + int timeout = 60; + int pending = 0; + int done = 0; + int timeout_ms; + int x; + + for (s = slist; s; s = s->next) { + DEBUG(("%s: state = %d\n", s->dev->name, s->state)); + + if (s->state == DEVST_COMPLETE) { + done++; + continue; + } + + pending++; + + if (s->expire - now.tv_sec <= 0) { + DEBUG(("timeout\n")); + process_timeout_event(s, now.tv_sec); + } + + if (timeout > s->expire - now.tv_sec) + timeout = s->expire - now.tv_sec; + } + + if (pending == 0 || (bringup_first && done)) + break; + + timeout_ms = timeout * 1000; + + for (x = 0; x < 2; x++) { + int delta_ms; + + if (timeout_ms <= 0) + timeout_ms = 100; + + nr = poll(fds, NR_FDS, timeout_ms); + prev = now; + gettimeofday(&now, NULL); + + if ((fds[0].revents & POLLRDNORM)) { + nr = do_pkt_recv(pkt_fd, now.tv_sec); + if (nr == 1) + break; + else if (nr == 0) + packet_discard(); + } + + if (loop_timeout >= 0 && + now.tv_sec - start >= loop_timeout) { + printf("IP-Config: no response after %d " + "secs - giving up\n", loop_timeout); + goto bail; + } + + delta_ms = (now.tv_sec - prev.tv_sec) * 1000; + delta_ms += (now.tv_usec - prev.tv_usec) / 1000; + + DEBUG(("Delta: %d ms\n", delta_ms)); + + timeout_ms -= delta_ms; + } + } + bail: + packet_close(); + + return 0; +} + +static int add_one_dev(struct netdev *dev) +{ + struct state *state; + + state = malloc(sizeof(struct state)); + if (!state) + return -1; + + state->dev = dev; + state->expire = time(NULL); + state->retry_period = 1; + + /* + * Select the state that we start from. + */ + if (dev->caps & CAP_DHCP && dev->ip_addr == INADDR_ANY) { + state->restart_state = state->state = DEVST_DHCPDISC; + } else if (dev->caps & CAP_DHCP) { + state->restart_state = state->state = DEVST_DHCPREQ; + } else if (dev->caps & CAP_BOOTP) { + state->restart_state = state->state = DEVST_BOOTP; + } + + state->next = slist; + slist = state; + + return 0; +} + +static void parse_addr(uint32_t * addr, const char *ip) +{ + struct in_addr in; + if (inet_aton(ip, &in) == 0) { + fprintf(stderr, "%s: can't parse IP address '%s'\n", + progname, ip); + longjmp(abort_buf, 1); + } + *addr = in.s_addr; +} + +static unsigned int parse_proto(const char *ip) +{ + unsigned int caps = 0; + + if (*ip == '\0' || strcmp(ip, "on") == 0 || strcmp(ip, "any") == 0) + caps = CAP_BOOTP | CAP_DHCP | CAP_RARP; + else if (strcmp(ip, "both") == 0) + caps = CAP_BOOTP | CAP_RARP; + else if (strcmp(ip, "dhcp") == 0) + caps = CAP_BOOTP | CAP_DHCP; + else if (strcmp(ip, "bootp") == 0) + caps = CAP_BOOTP; + else if (strcmp(ip, "rarp") == 0) + caps = CAP_RARP; + else if (strcmp(ip, "none") == 0 || strcmp(ip, "static") == 0 + || strcmp(ip, "off") == 0) + goto bail; + else { + fprintf(stderr, "%s: invalid protocol '%s'\n", progname, ip); + longjmp(abort_buf, 1); + } + bail: + return caps; +} + +static int add_all_devices(struct netdev *template); + +static int parse_device(struct netdev *dev, const char *ip) +{ + char *cp; + int i, opt; + int is_ip = 0; + + DEBUG(("IP-Config: parse_device: \"%s\"\n", ip)); + + if (strncmp(ip, "ip=", 3) == 0) { + ip += 3; + is_ip = 1; + } else if (strncmp(ip, "nfsaddrs=", 9) == 0) { + ip += 9; + is_ip = 1; /* Not sure about this...? */ + } + + if (!strchr(ip, ':')) { + /* Only one option, e.g. "ip=dhcp", or it's an interface name */ + if (is_ip) { + dev->caps = parse_proto(ip); + bringup_first = 1; + } else { + dev->name = ip; + } + } else { + for (i = opt = 0; ip && *ip; ip = cp, opt++) { + if ((cp = strchr(ip, ':'))) { + *cp++ = '\0'; + } + if (opt > 6) { + fprintf(stderr, "%s: too many options for %s\n", + progname, dev->name); + longjmp(abort_buf, 1); + } + + if (*ip == '\0') + continue; + DEBUG(("IP-Config: opt #%d: '%s'\n", opt, ip)); + switch (opt) { + case 0: + parse_addr(&dev->ip_addr, ip); + dev->caps = 0; + break; + case 1: + parse_addr(&dev->ip_server, ip); + break; + case 2: + parse_addr(&dev->ip_gateway, ip); + break; + case 3: + parse_addr(&dev->ip_netmask, ip); + break; + case 4: + strncpy(dev->hostname, ip, SYS_NMLN - 1); + dev->hostname[SYS_NMLN - 1] = '\0'; + break; + case 5: + dev->name = ip; + break; + case 6: + dev->caps = parse_proto(ip); + break; + } + } + } + + if (dev->name == NULL || + dev->name[0] == '\0' || strcmp(dev->name, "all") == 0) { + add_all_devices(dev); + return 0; + } + return 1; +} + +static void bringup_device(struct netdev *dev) +{ + if (netdev_up(dev) == 0) { + if (dev->caps) { + add_one_dev(dev); + } else { + complete_device(dev); + } + } +} + +static void bringup_one_dev(struct netdev *template, struct netdev *dev) +{ + if (template->ip_addr != INADDR_NONE) + dev->ip_addr = template->ip_addr; + if (template->ip_server != INADDR_NONE) + dev->ip_server = template->ip_server; + if (template->ip_gateway != INADDR_NONE) + dev->ip_gateway = template->ip_gateway; + if (template->ip_netmask != INADDR_NONE) + dev->ip_netmask = template->ip_netmask; + if (template->ip_nameserver[0] != INADDR_NONE) + dev->ip_nameserver[0] = template->ip_nameserver[0]; + if (template->ip_nameserver[1] != INADDR_NONE) + dev->ip_nameserver[1] = template->ip_nameserver[1]; + if (template->hostname[0] != '\0') + strcpy(dev->hostname, template->hostname); + dev->caps &= template->caps; + + bringup_device(dev); +} + +static struct netdev *add_device(const char *info) +{ + struct netdev *dev; + int i; + + dev = malloc(sizeof(struct netdev)); + if (dev == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + longjmp(abort_buf, 1); + } + + memset(dev, 0, sizeof(struct netdev)); + dev->caps = default_caps; + + if (parse_device(dev, info) == 0) + goto bail; + + if (netdev_init_if(dev) == -1) + goto bail; + + if (bootp_init_if(dev) == -1) + goto bail; + + printf("IP-Config: %s hardware address", dev->name); + for (i = 0; i < dev->hwlen; i++) + printf("%c%02x", i == 0 ? ' ' : ':', dev->hwaddr[i]); + printf(" mtu %d%s%s\n", dev->mtu, + dev->caps & CAP_DHCP ? " DHCP" : + dev->caps & CAP_BOOTP ? " BOOTP" : "", + dev->caps & CAP_RARP ? " RARP" : ""); + return dev; + bail: + free(dev); + return NULL; +} + +static int add_all_devices(struct netdev *template) +{ + DIR *d; + struct dirent *de; + struct netdev *dev; + char t[PATH_MAX], p[255]; + int i, fd; + unsigned long flags; + + d = opendir(sysfs_class_net); + if (!d) + return 0; + + while ((de = readdir(d)) != NULL) { + /* This excludes devices beginning with dots or "dummy", as well as . or .. */ + if (de->d_name[0] == '.' || !strcmp(de->d_name, "..")) + continue; + i = snprintf(t, PATH_MAX - 1, "%s/%s/flags", sysfs_class_net, + de->d_name); + if (i < 0 || i >= PATH_MAX - 1) + continue; + t[i] = '\0'; + fd = open(t, O_RDONLY); + if (fd < 0) { + perror(t); + continue; + } + i = read(fd, &p, sizeof(p) - 1); + close(fd); + if (i < 0) { + perror(t); + continue; + } + p[i] = '\0'; + flags = strtoul(p, NULL, 0); + /* Heuristic for if this is a reasonable boot interface. + This is the same + logic the in-kernel ipconfig uses... */ + if (!(flags & IFF_LOOPBACK) && + (flags & (IFF_BROADCAST | IFF_POINTOPOINT))) { + DEBUG(("Trying to bring up %s\n", de->d_name)); + + if (!(dev = add_device(de->d_name))) + continue; + bringup_one_dev(template, dev); + } + } + closedir(d); + return 1; +} + +static int check_autoconfig(void) +{ + int ndev = 0, nauto = 0; + struct state *s; + + for (s = slist; s; s = s->next) { + ndev++; + if (s->dev->caps) + nauto++; + } + + if (ndev == 0) { + if (configured == 0) { + fprintf(stderr, "%s: no devices to configure\n", + progname); + longjmp(abort_buf, 1); + } + } + + return nauto; +} + +int main(int argc, char *argv[]) + __attribute__ ((weak, alias("ipconfig_main"))); + +int ipconfig_main(int argc, char *argv[]) +{ + struct netdev *dev; + int c, port; + int err; + + /* If progname is set we're invoked from another program */ + if (!progname) { + struct timeval now; + progname = argv[0]; + gettimeofday(&now, NULL); + srand48(now.tv_usec ^ (now.tv_sec << 24)); + } + + if ((err = setjmp(abort_buf))) + return err; + + do { + c = getopt(argc, argv, "c:d:onp:t:"); + if (c == EOF) + break; + + switch (c) { + case 'c': + default_caps = parse_proto(optarg); + break; + case 'p': + port = atoi(optarg); + if (port <= 0 || port > USHRT_MAX) { + fprintf(stderr, + "%s: invalid port number %d\n", + progname, port); + longjmp(abort_buf, 1); + } + cfg_local_port = port; + cfg_remote_port = cfg_local_port - 1; + break; + case 't': + loop_timeout = atoi(optarg); + if (loop_timeout < 0) { + fprintf(stderr, + "%s: invalid timeout %d\n", + progname, loop_timeout); + longjmp(abort_buf, 1); + } + break; + case 'o': + bringup_first = 1; + break; + case 'n': + do_not_config = 1; + break; + case 'd': + dev = add_device(optarg); + if (dev) + bringup_device(dev); + break; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + progname, optopt); + longjmp(abort_buf, 1); + } + } while (1); + + for (c = optind; c < argc; c++) { + dev = add_device(argv[c]); + if (dev) + bringup_device(dev); + } + + if (check_autoconfig()) { + if (cfg_local_port != LOCAL_PORT) { + printf("IP-Config: binding source port to %d, " + "dest to %d\n", cfg_local_port, cfg_remote_port); + } + loop(); + } + + return 0; +} diff -puN /dev/null usr/kinit/ipconfig/netdev.c --- /dev/null +++ a/usr/kinit/ipconfig/netdev.c @@ -0,0 +1,251 @@ +/* + * ipconfig/netdev.c + * + * ioctl-based device configuration + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netdev.h" + +static int cfd = -1; + +static void copy_name(struct netdev *dev, struct ifreq *ifr) +{ + strncpy(ifr->ifr_name, dev->name, sizeof(ifr->ifr_name)); + ifr->ifr_name[sizeof(ifr->ifr_name) - 1] = '\0'; +} + +int netdev_getflags(struct netdev *dev, short *flags) +{ + struct ifreq ifr; + + copy_name(dev, &ifr); + + if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) { + perror("SIOCGIFFLAGS"); + return -1; + } + + *flags = ifr.ifr_flags; + return 0; +} + +static int netdev_sif_addr(struct ifreq *ifr, int cmd, uint32_t addr) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; + + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = addr; + + return ioctl(cfd, cmd, ifr); +} + +int netdev_setaddress(struct netdev *dev) +{ + struct ifreq ifr; + + copy_name(dev, &ifr); + + if (dev->ip_addr != INADDR_ANY && + netdev_sif_addr(&ifr, SIOCSIFADDR, dev->ip_addr) == -1) { + perror("SIOCSIFADDR"); + return -1; + } + + if (dev->ip_broadcast != INADDR_ANY && + netdev_sif_addr(&ifr, SIOCSIFBRDADDR, dev->ip_broadcast) == -1) { + perror("SIOCSIFBRDADDR"); + return -1; + } + + if (dev->ip_netmask != INADDR_ANY && + netdev_sif_addr(&ifr, SIOCSIFNETMASK, dev->ip_netmask) == -1) { + perror("SIOCSIFNETMASK"); + return -1; + } + + return 0; +} + +int netdev_setdefaultroute(struct netdev *dev) +{ + struct rtentry r; + + if (dev->ip_gateway == INADDR_ANY) + return 0; + + memset(&r, 0, sizeof(r)); + + ((struct sockaddr_in *)&r.rt_dst)->sin_family = AF_INET; + ((struct sockaddr_in *)&r.rt_dst)->sin_addr.s_addr = INADDR_ANY; + ((struct sockaddr_in *)&r.rt_gateway)->sin_family = AF_INET; + ((struct sockaddr_in *)&r.rt_gateway)->sin_addr.s_addr = + dev->ip_gateway; + ((struct sockaddr_in *)&r.rt_genmask)->sin_family = AF_INET; + ((struct sockaddr_in *)&r.rt_genmask)->sin_addr.s_addr = INADDR_ANY; + r.rt_flags = RTF_UP | RTF_GATEWAY; + + if (ioctl(cfd, SIOCADDRT, &r) == -1 && errno != EEXIST) { + perror("SIOCADDRT"); + return -1; + } + return 0; +} + +int netdev_setmtu(struct netdev *dev) +{ + struct ifreq ifr; + + copy_name(dev, &ifr); + ifr.ifr_mtu = dev->mtu; + + return ioctl(cfd, SIOCSIFMTU, &ifr); +} + +static int netdev_gif_addr(struct ifreq *ifr, int cmd, uint32_t * ptr) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; + + if (ioctl(cfd, cmd, ifr) == -1) + return -1; + + *ptr = sin->sin_addr.s_addr; + + return 0; +} + +int netdev_up(struct netdev *dev) +{ + struct ifreq ifr; + + copy_name(dev, &ifr); + + if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) { + perror("SIOCGIFFLAGS"); + return -1; + } + + ifr.ifr_flags |= IFF_UP; + + if (ioctl(cfd, SIOCSIFFLAGS, &ifr) == -1) { + perror("SIOCSIFFLAGS"); + return -1; + } + return 0; +} + +int netdev_down(struct netdev *dev) +{ + struct ifreq ifr; + + copy_name(dev, &ifr); + + if (ioctl(cfd, SIOCGIFFLAGS, &ifr) == -1) { + perror("SIOCGIFFLAGS"); + return -1; + } + + ifr.ifr_flags &= ~IFF_UP; + + if (ioctl(cfd, SIOCSIFFLAGS, &ifr) == -1) { + perror("SIOCSIFFLAGS"); + return -1; + } + return 0; +} + +int netdev_init_if(struct netdev *dev) +{ + struct ifreq ifr; + + if (cfd == -1) + cfd = socket(AF_INET, SOCK_DGRAM, 0); + if (cfd == -1) { + fprintf(stderr, "ipconfig: %s: socket(AF_INET): %s\n", + dev->name, strerror(errno)); + return -1; + } + + copy_name(dev, &ifr); + + if (ioctl(cfd, SIOCGIFINDEX, &ifr) == -1) { + fprintf(stderr, "ipconfig: %s: SIOCGIFINDEX: %s\n", + dev->name, strerror(errno)); + return -1; + } + + dev->ifindex = ifr.ifr_ifindex; + + if (ioctl(cfd, SIOCGIFMTU, &ifr) == -1) { + fprintf(stderr, "ipconfig: %s: SIOCGIFMTU: %s\n", + dev->name, strerror(errno)); + return -1; + } + + dev->mtu = ifr.ifr_mtu; + + if (ioctl(cfd, SIOCGIFHWADDR, &ifr) == -1) { + fprintf(stderr, "ipconfig: %s: SIOCGIFHWADDR: %s\n", + dev->name, strerror(errno)); + return -1; + } + + dev->hwtype = ifr.ifr_hwaddr.sa_family; + dev->hwlen = 0; + + switch (dev->hwtype) { + case ARPHRD_ETHER: + dev->hwlen = 6; + break; + case ARPHRD_EUI64: + dev->hwlen = 8; + break; + case ARPHRD_LOOPBACK: + dev->hwlen = 0; + break; + default: + return -1; + } + + memcpy(dev->hwaddr, ifr.ifr_hwaddr.sa_data, dev->hwlen); + memset(dev->hwbrd, 0xff, dev->hwlen); + + /* + * Try to get the current interface information. + */ + if (dev->ip_addr == INADDR_NONE && + netdev_gif_addr(&ifr, SIOCGIFADDR, &dev->ip_addr) == -1) { + fprintf(stderr, "ipconfig: %s: SIOCGIFADDR: %s\n", + dev->name, strerror(errno)); + dev->ip_addr = 0; + dev->ip_broadcast = 0; + dev->ip_netmask = 0; + return 0; + } + + if (dev->ip_broadcast == INADDR_NONE && + netdev_gif_addr(&ifr, SIOCGIFBRDADDR, &dev->ip_broadcast) == -1) { + fprintf(stderr, "ipconfig: %s: SIOCGIFBRDADDR: %s\n", + dev->name, strerror(errno)); + dev->ip_broadcast = 0; + } + + if (dev->ip_netmask == INADDR_NONE && + netdev_gif_addr(&ifr, SIOCGIFNETMASK, &dev->ip_netmask) == -1) { + fprintf(stderr, "ipconfig: %s: SIOCGIFNETMASK: %s\n", + dev->name, strerror(errno)); + dev->ip_netmask = 0; + } + + return 0; +} diff -puN /dev/null usr/kinit/ipconfig/netdev.h --- /dev/null +++ a/usr/kinit/ipconfig/netdev.h @@ -0,0 +1,83 @@ +/* + * ipconfig/netdev.h + */ + +#ifndef IPCONFIG_NETDEV_H +#define IPCONFIG_NETDEV_H + +#include +#include + +#define BPLEN 40 + +struct netdev { + const char *name; /* Device name */ + unsigned int ifindex; /* interface index */ + unsigned int hwtype; /* ARPHRD_xxx */ + unsigned int hwlen; /* HW address length */ + uint8_t hwaddr[16]; /* HW address */ + uint8_t hwbrd[16]; /* Broadcast HW address */ + unsigned int mtu; /* Device mtu */ + unsigned int caps; /* Capabilities */ + time_t open_time; + + struct { /* BOOTP/DHCP info */ + int fd; + uint32_t xid; + uint32_t gateway; /* BOOTP/DHCP gateway */ + } bootp; + + struct { /* RARP information */ + int fd; + } rarp; + + uint32_t ip_addr; /* my address */ + uint32_t ip_broadcast; /* broadcast address */ + uint32_t ip_server; /* server address */ + uint32_t ip_netmask; /* my subnet mask */ + uint32_t ip_gateway; /* my gateway */ + uint32_t ip_nameserver[2]; /* two nameservers */ + uint32_t serverid; /* dhcp serverid */ + char hostname[SYS_NMLN]; /* hostname */ + char dnsdomainname[SYS_NMLN]; /* dns domain name */ + char nisdomainname[SYS_NMLN]; /* nis domain name */ + char bootpath[BPLEN]; /* boot path */ + struct netdev *next; /* next configured i/f */ +}; + +extern struct netdev *ifaces; + +/* + * Device capabilities + */ +#define CAP_BOOTP (1<<0) +#define CAP_DHCP (1<<1) +#define CAP_RARP (1<<2) + +/* + * Device states + */ +#define DEVST_UP 0 +#define DEVST_BOOTP 1 +#define DEVST_DHCPDISC 2 +#define DEVST_DHCPREQ 3 +#define DEVST_COMPLETE 4 +#define DEVST_ERROR 5 + +int netdev_getflags(struct netdev *dev, short *flags); +int netdev_setaddress(struct netdev *dev); +int netdev_setdefaultroute(struct netdev *dev); +int netdev_up(struct netdev *dev); +int netdev_down(struct netdev *dev); +int netdev_init_if(struct netdev *dev); +int netdev_setmtu(struct netdev *dev); + +static inline int netdev_running(struct netdev *dev) +{ + short flags; + int ret = netdev_getflags(dev, &flags); + + return ret ? 0 : !!(flags & IFF_RUNNING); +} + +#endif /* IPCONFIG_NETDEV_H */ diff -puN /dev/null usr/kinit/ipconfig/packet.c --- /dev/null +++ a/usr/kinit/ipconfig/packet.c @@ -0,0 +1,286 @@ +/* + * ipconfig/packet.c + * + * Packet socket handling glue. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipconfig.h" +#include "netdev.h" +#include "packet.h" + +static int pkt_fd = -1; + +uint16_t cfg_local_port = LOCAL_PORT; +uint16_t cfg_remote_port = REMOTE_PORT; + +int packet_open(void) +{ + int fd, one = 1; + + if (pkt_fd != -1) + return pkt_fd; + + /* + * Get a PACKET socket for IP traffic. + */ + fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); + if (fd == -1) { + perror("socket"); + return -1; + } + + /* + * We want to broadcast + */ + if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) == -1) { + perror("SO_BROADCAST"); + close(fd); + fd = -1; + } + + pkt_fd = fd; + + return fd; +} + +void packet_close(void) +{ + close(pkt_fd); + pkt_fd = -1; +} + +static unsigned int ip_checksum(uint16_t *hdr, int len) +{ + unsigned int chksum = 0; + + while (len) { + chksum += *hdr++; + chksum += *hdr++; + len--; + } + chksum = (chksum & 0xffff) + (chksum >> 16); + chksum = (chksum & 0xffff) + (chksum >> 16); + return (~chksum) & 0xffff; +} + +struct header { + struct iphdr ip; + struct udphdr udp; +} __attribute__ ((packed)); + +static struct header ipudp_hdrs = { + .ip = { + .ihl = 5, + .version = IPVERSION, + .frag_off = __constant_htons(IP_DF), + .ttl = 64, + .protocol = IPPROTO_UDP, + .saddr = INADDR_ANY, + .daddr = INADDR_BROADCAST, + }, + .udp = { + .source = __constant_htons(LOCAL_PORT), + .dest = __constant_htons(REMOTE_PORT), + .len = 0, + .check = 0, + }, +}; + +#ifdef IPC_DEBUG /* Only used by DEBUG(()) */ +static char *ntoa(uint32_t addr) +{ + struct in_addr in = { addr }; + return inet_ntoa(in); +} +#endif + +/* + * Send a packet. The options are listed in iov[1...iov_len]. + * iov[0] is reserved for the bootp packet header. + */ +int packet_send(struct netdev *dev, struct iovec *iov, int iov_len) +{ + struct sockaddr_ll sll; + struct msghdr msg = { + .msg_name = &sll, + .msg_namelen = sizeof(sll), + .msg_iov = iov, + .msg_iovlen = iov_len, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = 0 + }; + int i, len = 0; + + if (cfg_local_port != LOCAL_PORT) { + ipudp_hdrs.udp.source = htons(cfg_local_port); + ipudp_hdrs.udp.dest = htons(cfg_remote_port); + } + + DEBUG(("\n udp src %d dst %d", ntohs(ipudp_hdrs.udp.source), + ntohs(ipudp_hdrs.udp.dest))); + + DEBUG(("\n ip src %s ", ntoa(ipudp_hdrs.ip.saddr))); + DEBUG(("dst %s ", ntoa(ipudp_hdrs.ip.daddr))); + + /* + * Glue in the ip+udp header iovec + */ + iov[0].iov_base = &ipudp_hdrs; + iov[0].iov_len = sizeof(struct header); + + for (i = 0; i < iov_len; i++) + len += iov[i].iov_len; + + sll.sll_family = AF_PACKET; + sll.sll_protocol = htons(ETH_P_IP); + sll.sll_ifindex = dev->ifindex; + sll.sll_hatype = dev->hwtype; + sll.sll_pkttype = PACKET_BROADCAST; + sll.sll_halen = dev->hwlen; + memcpy(sll.sll_addr, dev->hwbrd, dev->hwlen); + + ipudp_hdrs.ip.tot_len = htons(len); + ipudp_hdrs.ip.check = 0; + ipudp_hdrs.ip.check = ip_checksum((uint16_t *) & ipudp_hdrs.ip, + ipudp_hdrs.ip.ihl); + + ipudp_hdrs.udp.len = htons(len - sizeof(struct iphdr)); + + DEBUG(("\n bytes %d\n", len)); + + return sendmsg(pkt_fd, &msg, 0); +} + +int packet_peek(int *ifindex) +{ + struct sockaddr_ll sll; + struct iphdr iph; + int ret, sllen = sizeof(struct sockaddr_ll); + + /* + * Peek at the IP header. + */ + ret = recvfrom(pkt_fd, &iph, sizeof(struct iphdr), + MSG_PEEK, (struct sockaddr *)&sll, &sllen); + if (ret == -1) + return -1; + + if (sll.sll_family != AF_PACKET) + goto discard_pkt; + + if (iph.ihl < 5 || iph.version != IPVERSION) + goto discard_pkt; + + *ifindex = sll.sll_ifindex; + + return 0; + +discard_pkt: + packet_discard(); + return 0; +} + +void packet_discard(void) +{ + struct iphdr iph; + struct sockaddr_ll sll; + socklen_t sllen = sizeof(sll); + + recvfrom(pkt_fd, &iph, sizeof(iph), 0, (struct sockaddr *)&sll, &sllen); +} + +/* + * Receive a bootp packet. The options are listed in iov[1...iov_len]. + * iov[0] must point to the bootp packet header. + */ +int packet_recv(struct iovec *iov, int iov_len) +{ + struct iphdr *ip, iph; + struct udphdr *udp; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = iov, + .msg_iovlen = iov_len, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = 0 + }; + int ret, iphl; + + ret = recvfrom(pkt_fd, &iph, sizeof(struct iphdr), + MSG_PEEK, NULL, NULL); + if (ret == -1) + return -1; + + if (iph.ihl < 5 || iph.version != IPVERSION) + goto discard_pkt; + + iphl = iph.ihl * 4; + + ip = malloc(iphl + sizeof(struct udphdr)); + if (!ip) + goto discard_pkt; + + udp = (struct udphdr *)((char *)ip + iphl); + + iov[0].iov_base = ip; + iov[0].iov_len = iphl + sizeof(struct udphdr); + + ret = recvmsg(pkt_fd, &msg, 0); + if (ret == -1) + goto free_pkt; + + DEBUG(("<- bytes %d ", ret)); + + if (ip_checksum((uint16_t *) ip, ip->ihl) != 0) + goto free_pkt; + + DEBUG(("\n ip src %s ", ntoa(ip->saddr))); + DEBUG(("dst %s ", ntoa(ip->daddr))); + + if (ntohs(ip->tot_len) > ret || ip->protocol != IPPROTO_UDP) + goto free_pkt; + + ret -= 4 * ip->ihl; + + DEBUG(("\n udp src %d dst %d ", ntohs(udp->source), + ntohs(udp->dest))); + + if (udp->source != htons(cfg_remote_port) || + udp->dest != htons(cfg_local_port)) + goto free_pkt; + + if (ntohs(udp->len) > ret) + goto free_pkt; + + ret -= sizeof(struct udphdr); + + free(ip); + + return ret; + +free_pkt: + free(ip); + return 0; + +discard_pkt: + DEBUG(("discarded\n")); + packet_discard(); + return 0; +} diff -puN /dev/null usr/kinit/ipconfig/packet.h --- /dev/null +++ a/usr/kinit/ipconfig/packet.h @@ -0,0 +1,9 @@ +/* + * ipconfig/packet.h + */ +int packet_open(void); +void packet_close(void); +int packet_send(struct netdev *dev, struct iovec *iov, int iov_len); +int packet_peek(int *ifindex); +void packet_discard(void); +int packet_recv(struct iovec *iov, int iov_len); diff -puN /dev/null usr/kinit/ipconfig/README --- /dev/null +++ a/usr/kinit/ipconfig/README @@ -0,0 +1,103 @@ +BOOTP/DHCP client for klibc +--------------------------- + +Usage: + +ipconfig [-c proto] [-d interface] [-n] [-p port] [-t timeout] [interface ...] + +-c proto Use PROTO as the configuration protocol for all + interfaces, unless overridden by specific interfaces. +-d interface Either the name of an interface, or a long spec. +-n Do nothing - just print the configuration that would + be performed. +-p port Send bootp/dhcp broadcasts from PORT, to PORT - 1. +-t timeout Give up on all unconfigured interfaces after TIMEOUT secs. + +You can configure multiple interfaces by passing multiple interface +specs on the command line, or by using the special interface name +"all". If you're autoconfiguring any interfaces, ipconfig will wait +until either all such interfaces have been configured, or the timeout +passes. + +PROTO can be one of the following, which selects the autoconfiguration +protocol to use: + +not specified use all protocols (the default) +dhcp use bootp and dhcp +bootp use bootp only +rarp use rarp (not currently supported) +none no autoconfiguration - either static config, or none at all + +An interface spec can be either short form, which is just the name of +an interface (eth0 or whatever), or long form. The long form consists +of up to seven elements, separated by colons: + +:::::: + + IP address of the client. If empty, the address will + either be determined by RARP/BOOTP/DHCP. What protocol + is used de- pends on the parameter. If this + parameter is not empty, autoconf will be used. + + IP address of the NFS server. If RARP is used to + determine the client address and this parameter is NOT + empty only replies from the specified server are + accepted. To use different RARP and NFS server, + specify your RARP server here (or leave it blank), and + specify your NFS server in the `nfsroot' parameter + (see above). If this entry is blank the address of the + server is used which answered the RARP/BOOTP/DHCP + request. + + IP address of a gateway if the server is on a different + subnet. If this entry is empty no gateway is used and the + server is assumed to be on the local network, unless a + value has been received by BOOTP/DHCP. + + Netmask for local network interface. If this is empty, + the netmask is derived from the client IP address assuming + classful addressing, unless overridden in BOOTP/DHCP reply. + + Name of the client. If empty, the client IP address is + used in ASCII notation, or the value received by + BOOTP/DHCP. + + Name of network device to use. If this is empty, all + devices are used for RARP/BOOTP/DHCP requests, and the + first one we receive a reply on is configured. If you + have only one device, you can safely leave this blank. + + Method to use for autoconfiguration. If this is either + 'rarp', 'bootp', or 'dhcp' the specified protocol is + used. If the value is 'both', 'all' or empty, all + protocols are used. 'off', 'static' or 'none' means + no autoconfiguration. + +IP addresses and netmasks must be either absent (defaulting to zero) +or presented in dotted-quad notation. + +An interface spec can be prefixed with either "ip=", "nfsaddrs=", both +of which are ignored. These (along with the ugliness of the long +form) are present for compatibility with the in-kernel ipconfig code +from 2.4 and earlier kernels. + +Here are a few examples of valid ipconfig command lines. + +Enable the loopback interface: + ipconfig 127.0.0.1:::::lo:none + +Try to configure eth0 using bootp for up to 30 seconds: + ipconfig -t 30 -c bootp eth0 + +Configure eth0 and eth1 using dhcp or bootp, and eth2 statically: + ipconfig -c any eth0 eth1 192.168.1.1:::::eth2:none + +-- + +From Russell's original README, and still true: + +The code in main.c is yucky imho. Needs cleaning. + +-- +Russell King (2002/10/22) +Bryan O'Sullivan (2003/04/29) diff -puN /dev/null usr/kinit/Kbuild --- /dev/null +++ a/usr/kinit/Kbuild @@ -0,0 +1,28 @@ +# +# Kbuild file for kinit +# + +static-y := kinit +kinit-y := kinit.o do_mounts.o ramdisk_load.o initrd.o +kinit-y += name_to_dev.o devname.o +kinit-y += getarg.o getintfile.o open.o readfile.o xpio.o +kinit-y += do_mounts_md.o do_mounts_mtd.o nfsroot.o resume.o + +kinit-y += ipconfig/ +kinit-y += nfsmount/ +kinit-y += run-init/ +kinit-y += fstype/ + +# Additional include paths files +KLIBCCFLAGS += -I$(srctree)/$(src)/ipconfig \ + -I$(srctree)/$(src)/nfsmount \ + -I$(srctree)/$(src)/run-init \ + -I$(srctree)/$(src)/fstype + +# Cleaning +targets := kinit kinit.g +subdir- := ipconfig nfsmount run-init fstype + + +# install binary +install-y := kinit diff -puN /dev/null usr/kinit/kinit.c --- /dev/null +++ a/usr/kinit/kinit.c @@ -0,0 +1,330 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kinit.h" +#include "ipconfig.h" +#include "run-init.h" + +const char *progname = "kinit"; +int mnt_procfs; +int mnt_sysfs; + +#ifdef INI_DEBUG +void dump_args(int argc, char *argv[]) +{ + int i; + + printf(" argc == %d\n", argc); + + for (i = 0; i < argc; i++) { + printf(" argv[%d]: \"%s\"\n", i, argv[i]); + } + + if (argv[argc] != NULL) { + printf(" argv[%d]: \"%s\" (SHOULD BE NULL)\n", + argc, argv[argc]); + } +} +#endif + + +static int do_ipconfig(int argc, char *argv[]) +{ + int i, a = 0; + char **args = alloca((argc + 1) * sizeof(char *)); + + if (!args) + return -1; + + args[a++] = (char *)"IP-Config"; + + DEBUG(("Running ipconfig\n")); + + for (i = 1; i < argc; i++) { + if (strncmp(argv[i], "ip=", 3) == 0 || + strncmp(argv[i], "nfsaddrs=", 9) == 0) { + args[a++] = argv[i]; + } + } + + if (a > 1) { + args[a] = NULL; + dump_args(a, args); + return ipconfig_main(a, args); + } + + return 0; +} + +static int split_cmdline(int cmdcmax, char *cmdv[], char *argv0, + char *cmdlines[], char *args[]) +{ + int was_space; + char c, *p; + int vmax = cmdcmax; + int v = 1; + int space; + + if (cmdv) + cmdv[0] = argv0; + + /* First, add the parsable command lines */ + + while (*cmdlines) { + p = *cmdlines++; + was_space = 1; + while (v < vmax) { + c = *p; + space = isspace(c); + if ((space || !c) && !was_space) { + if (cmdv) + *p = '\0'; + v++; + } else if (was_space) { + if (cmdv) + cmdv[v] = p; + } + + if (!c) + break; + + was_space = space; + p++; + } + } + + /* Second, add the explicit command line arguments */ + + while (*args && v < vmax) { + if (cmdv) + cmdv[v] = *args; + v++; + args++; + } + + if (cmdv) + cmdv[v] = NULL; + + return v; +} + +static int mount_sys_fs(const char *check, const char *fsname, + const char *fstype) +{ + struct stat st; + + if (stat(check, &st) == 0) { + return 0; + } + + mkdir(fsname, 0555); + + if (mount("none", fsname, fstype, 0, NULL) == -1) { + fprintf(stderr, "%s: could not mount %s as %s\n", + progname, fsname, fstype); + return -1; + } + + return 1; +} + +static void check_path(const char *path) +{ + struct stat st; + + if (stat(path, &st) == -1) { + if (errno != ENOENT) { + perror("stat"); + exit(1); + } + if (mkdir(path, 0755) == -1) { + perror("mkdir"); + exit(1); + } + } else if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "%s: '%s' not a directory\n", progname, path); + exit(1); + } +} + +static const char *find_init(const char *root, const char *user) +{ + const char *init_paths[] = { + "/sbin/init", "/bin/init", "/etc/init", "/bin/sh", NULL + }; + const char **p; + const char *path; + + if (chdir(root)) { + perror("chdir"); + exit(1); + } + + if (user) + DEBUG(("Checking for init: %s\n", user)); + + if (user && user[0] == '/' && !access(user+1, X_OK)) { + path = user; + } else { + for (p = init_paths; *p; p++) { + DEBUG(("Checking for init: %s\n", *p)); + if (!access(*p+1, X_OK)) + break; + } + path = *p; + } + chdir("/"); + return path; +} + +/* This is the argc and argv we pass to init */ +const char *init_path; +int init_argc; +char **init_argv; + +extern ssize_t readfile(const char *, char **); + +int main(int argc, char *argv[]) +{ + char **cmdv, **args; + char *cmdlines[3]; + int i; + const char *errmsg; + int ret = 0; + int cmdc; + int fd; + struct timeval now; + + gettimeofday(&now, NULL); + srand48(now.tv_usec ^ (now.tv_sec << 24)); + + /* Default parameters for anything init-like we execute */ + init_argc = argc; + init_argv = alloca((argc+1)*sizeof(char *)); + memcpy(init_argv, argv, (argc+1)*sizeof(char *)); + + if ((fd = open("/dev/console", O_RDWR)) != -1) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + + if (fd > STDERR_FILENO) { + close(fd); + } + } + + mnt_procfs = mount_sys_fs("/proc/cmdline", "/proc", "proc") >= 0; + if (!mnt_procfs) { + ret = 1; + goto bail; + } + + mnt_sysfs = mount_sys_fs("/sys/bus", "/sys", "sysfs") >= 0; + if (!mnt_sysfs) { + ret = 1; + goto bail; + } + + /* Construct the effective kernel command line. The + effective kernel command line consists of /arch.cmd, if + it exists, /proc/cmdline, plus any arguments after an -- + argument on the proper command line, in that order. */ + + ret = readfile("/arch.cmd", &cmdlines[0]); + if (ret < 0) + cmdlines[0] = ""; + + ret = readfile("/proc/cmdline", &cmdlines[1]); + if (ret < 0) { + fprintf(stderr, "%s: cannot read /proc/cmdline\n", progname); + ret = 1; + goto bail; + } + + cmdlines[2] = NULL; + + /* Find an -- argument, and if so append to the command line */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--")) { + i++; + break; + } + } + args = &argv[i]; /* Points either to first argument past -- or + to the final NULL */ + + /* Count the number of arguments */ + cmdc = split_cmdline(INT_MAX, NULL, argv[0], cmdlines, args); + + /* Actually generate the cmdline array */ + cmdv = (char **)alloca((cmdc+1)*sizeof(char *)); + if (split_cmdline(cmdc, cmdv, argv[0], cmdlines, args) != cmdc) { + ret = 1; + goto bail; + } + + /* Debugging... */ + dump_args(cmdc, cmdv); + + /* Resume from suspend-to-disk, if appropriate */ + /* If successful, does not return */ + do_resume(cmdc, cmdv); + + /* Initialize networking, if applicable */ + do_ipconfig(cmdc, cmdv); + + check_path("/root"); + do_mounts(cmdc, cmdv); + + if (mnt_procfs) { + umount2("/proc", 0); + mnt_procfs = 0; + } + + if (mnt_sysfs) { + umount2("/sys", 0); + mnt_sysfs = 0; + } + + init_path = find_init("/root", get_arg(cmdc, cmdv, "init=")); + if (!init_path) { + fprintf(stderr, "%s: init not found!\n", progname); + ret = 2; + goto bail; + } + + init_argv[0] = strrchr(init_path, '/') + 1; + + errmsg = run_init("/root", "/dev/console", init_path, init_argv); + + /* If run_init returned, something went bad */ + fprintf(stderr, "%s: %s: %s\n", progname, errmsg, strerror(errno)); + ret = 2; + goto bail; + +bail: + if (mnt_procfs) + umount2("/proc", 0); + + if (mnt_sysfs) + umount2("/sys", 0); + + /* + * If we get here, something bad probably happened, and the kernel + * will most likely panic. Drain console output so the user can + * figure out what happened. + */ + tcdrain(2); + tcdrain(1); + + return ret; +} diff -puN /dev/null usr/kinit/kinit.h --- /dev/null +++ a/usr/kinit/kinit.h @@ -0,0 +1,73 @@ +/* + * kinit/kinit.h + */ + +#ifndef KINIT_H +#define KINIT_H + +#include +#include +#include + +int do_mounts(int argc, char *argv[]); +int mount_nfs_root(int argc, char *argv[], int flags); +int ramdisk_load(int argc, char *argv[], dev_t root_dev); +void md_run(int argc, char *argv[]); +int do_resume(int argc, char *argv[]); +const char *bdevname(dev_t dev); + +extern int mnt_procfs; +extern int mnt_sysfs; + +extern int init_argc; +extern char **init_argv; +extern const char *progname; + +char *get_arg(int argc, char *argv[], const char *name); +int get_flag(int argc, char *argv[], const char *name); + +int open_cloexec(const char *path, int flags, mode_t mode); + +int getintfile(const char *path, long *val); + +ssize_t readfile(const char *path, char **pptr); +ssize_t freadfile(FILE *f, char **pptr); + +/* + * min()/max() macros that also do + * strict type-checking.. See the + * "unnecessary" pointer comparison. + * From the Linux kernel. + */ +#define min(x,y) ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x < _y ? _x : _y; }) + +#define max(x,y) ({ \ + typeof(x) _x = (x); \ + typeof(y) _y = (y); \ + (void) (&_x == &_y); \ + _x > _y ? _x : _y; }) + +#define INI_DEBUG + +#undef DEBUG +#ifdef INI_DEBUG +#define DEBUG(x) printf x +#else +#define DEBUG(x) do { } while (0) +#endif + +#ifdef INI_DEBUG +void dump_args(int argc, char *argv[]); +#else +static inline void dump_args(int argc, char *argv[]) +{ + (void)argc; + (void)argv; +} +#endif + +#endif /* KINIT_H */ diff -puN /dev/null usr/kinit/name_to_dev.c --- /dev/null +++ a/usr/kinit/name_to_dev.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "do_mounts.h" +#include "kinit.h" + +#define BUF_SZ 65536 + +/* Find dev_t for e.g. "hda,NULL" or "hdb,2" */ +static dev_t try_name(char *name, int part) +{ + char path[BUF_SZ]; + char buf[BUF_SZ]; + int range; + unsigned int major, minor; + dev_t res; + char *s; + int len; + int fd; + + /* read device number from /sys/block/.../dev */ + snprintf(path, sizeof(path), "/sys/block/%s/dev", name); + fd = open(path, 0, 0); + if (fd < 0) + goto fail; + len = read(fd, buf, BUF_SZ); + close(fd); + + if (len <= 0 || len == BUF_SZ || buf[len - 1] != '\n') + goto fail; + buf[len - 1] = '\0'; + major = strtoul(buf, &s, 10); + if (*s != ':') + goto fail; + minor = strtoul(s + 1, &s, 10); + if (*s) + goto fail; + res = makedev(major, minor); + + /* if it's there and we are not looking for a partition - that's it */ + if (!part) + return res; + + /* otherwise read range from .../range */ + snprintf(path, sizeof(path), "/sys/block/%s/range", name); + fd = open(path, 0, 0); + if (fd < 0) + goto fail; + len = read(fd, buf, 32); + close(fd); + if (len <= 0 || len == 32 || buf[len - 1] != '\n') + goto fail; + buf[len - 1] = '\0'; + range = strtoul(buf, &s, 10); + if (*s) + goto fail; + + /* if partition is within range - we got it */ + if (part < range) { + DEBUG(("kinit: try_name %s,%d = %s\n", name, part, + bdevname(res + part))); + return res + part; + } + + fail: + return (dev_t) 0; +} + +/* + * Convert a name into device number. We accept the following variants: + * + * 1) device number in hexadecimal represents itself + * 2) device number in major:minor decimal represents itself + * 3) /dev/nfs represents Root_NFS + * 4) /dev/ represents the device number of disk + * 5) /dev/ represents the device number + * of partition - device number of disk plus the partition number + * 6) /dev/p - same as the above, that form is + * used when disk name of partitioned disk ends on a digit. + * 7) an actual block device node in the initramfs filesystem + * + * If name doesn't have fall into the categories above, we return 0. + * Driverfs is used to check if something is a disk name - it has + * all known disks under bus/block/devices. If the disk name + * contains slashes, name of driverfs node has them replaced with + * dots. try_name() does the actual checks, assuming that driverfs + * is mounted on rootfs /sys. + */ + +static inline dev_t name_to_dev_t_real(const char *name) +{ + char *p; + dev_t res = 0; + char *s; + int part; + struct stat st; + int len; + const char *devname; + char *cptr, *e1, *e2; + int major, minor; + + + if (name[0] == '/') { + devname = name; + } else { + char *dname = alloca(strlen(name) + 6); + sprintf(dname, "/dev/%s", name); + devname = dname; + } + + if (!stat(devname, &st) && S_ISBLK(st.st_mode)) + return st.st_rdev; + + if (strncmp(name, "/dev/", 5)) { + if ((cptr = strchr(devname+5, ':')) && + cptr[1] != '\0') { + /* Colon-separated decimal device number */ + *cptr = '\0'; + major = strtoul(devname+5, &e1, 10); + minor = strtoul(cptr+1, &e2, 10); + if (!*e1 && !*e2) + return makedev(major, minor); + *cptr = ':'; + } else { + /* Hexadecimal device number */ + res = (dev_t) strtoul(name, &p, 16); + if (!*p) + return res; + } + } else { + name += 5; + } + + if (!strcmp(name, "nfs")) + return Root_NFS; + + if (!strcmp(name, "ram")) /* /dev/ram - historic alias for /dev/ram0 */ + return Root_RAM0; + + if (!strncmp(name, "mtd", 3)) + return Root_MTD; + + len = strlen(name); + s = alloca(len + 1); + memcpy(s, name, len + 1); + + for (p = s; *p; p++) + if (*p == '/') + *p = '!'; + res = try_name(s, 0); + if (res) + return res; + + while (p > s && isdigit(p[-1])) + p--; + if (p == s || !*p || *p == '0') + goto fail; + part = strtoul(p, NULL, 10); + *p = '\0'; + res = try_name(s, part); + if (res) + return res; + + if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') + goto fail; + p[-1] = '\0'; + res = try_name(s, part); + return res; + +fail: + return (dev_t) 0; +} + +dev_t name_to_dev_t(const char *name) +{ + dev_t dev = name_to_dev_t_real(name); + + DEBUG(("kinit: name_to_dev_t(%s) = %s\n", name, bdevname(dev))); + return dev; +} + +#ifdef TEST_NAMETODEV /* Standalone test */ + +int main(int argc, char *argv[]) +{ + int i; + + for (i = 1; i < argc; i++) + name_to_dev_t(argv[i]); + + return 0; +} + +#endif diff -puN /dev/null usr/kinit/nfsmount/dummypmap.c --- /dev/null +++ a/usr/kinit/nfsmount/dummypmap.c @@ -0,0 +1,188 @@ +/* + * dummypmap.c + * + * Enough portmapper functionality that mount doesn't hang trying + * to start lockd. Enables nfsroot with locking functionality. + * + * Note: the kernel will only speak to the local portmapper + * using RPC over UDP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sunrpc.h" + +extern const char *progname; + +struct portmap_call { + struct rpc_call rpc; + uint32_t program; + uint32_t version; + uint32_t proto; + uint32_t port; +}; + +struct portmap_reply { + struct rpc_reply rpc; + uint32_t port; +}; + +static int bind_portmap(void) +{ + int sock = socket(PF_INET, SOCK_DGRAM, 0); + struct sockaddr_in sin; + + if (sock < 0) + return -1; + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + sin.sin_port = htons(RPC_PMAP_PORT); + if (bind(sock, (struct sockaddr *)&sin, sizeof sin) < 0) { + int err = errno; + close(sock); + errno = err; + return -1; + } + + return sock; +} + +static const char *protoname(uint32_t proto) +{ + switch (ntohl(proto)) { + case IPPROTO_TCP: + return "tcp"; + case IPPROTO_UDP: + return "udp"; + default: + return NULL; + } +} + +static int dummy_portmap(int sock, FILE *portmap_file) +{ + struct sockaddr_in sin; + int pktlen, addrlen; + union { + struct portmap_call c; + unsigned char b[65536]; /* Max UDP packet size */ + } pkt; + struct portmap_reply rply; + + for (;;) { + addrlen = sizeof sin; + pktlen = recvfrom(sock, &pkt.c.rpc.hdr.udp, sizeof pkt, 0, + (struct sockaddr *)&sin, &addrlen); + + if (pktlen < 0) { + if (errno == EINTR) + continue; + + return -1; + } + + /* +4 to skip the TCP fragment header */ + if (pktlen + 4 < sizeof(struct portmap_call)) + continue; /* Bad packet */ + + if (pkt.c.rpc.hdr.udp.msg_type != htonl(RPC_CALL)) + continue; /* Bad packet */ + + memset(&rply, 0, sizeof rply); + + rply.rpc.hdr.udp.xid = pkt.c.rpc.hdr.udp.xid; + rply.rpc.hdr.udp.msg_type = htonl(RPC_REPLY); + + if (pkt.c.rpc.rpc_vers != htonl(2)) { + rply.rpc.reply_state = htonl(REPLY_DENIED); + /* state <- RPC_MISMATCH == 0 */ + } else if (pkt.c.rpc.program != htonl(PORTMAP_PROGRAM)) { + rply.rpc.reply_state = htonl(PROG_UNAVAIL); + } else if (pkt.c.rpc.prog_vers != htonl(2)) { + rply.rpc.reply_state = htonl(PROG_MISMATCH); + } else if (pkt.c.rpc.cred_len != 0 || pkt.c.rpc.vrf_len != 0) { + /* Can't deal with credentials data; the kernel + won't send them */ + rply.rpc.reply_state = htonl(SYSTEM_ERR); + } else { + switch (ntohl(pkt.c.rpc.proc)) { + case PMAP_PROC_NULL: + break; + case PMAP_PROC_SET: + if (pkt.c.proto == htonl(IPPROTO_TCP) || + pkt.c.proto == htonl(IPPROTO_UDP)) { + if (portmap_file) + fprintf(portmap_file, + "%u %u %s %u\n", + ntohl(pkt.c.program), + ntohl(pkt.c.version), + protoname(pkt.c.proto), + ntohl(pkt.c.port)); + rply.port = htonl(1); /* TRUE = success */ + } + break; + case PMAP_PROC_UNSET: + rply.port = htonl(1); /* TRUE = success */ + break; + case PMAP_PROC_GETPORT: + break; + case PMAP_PROC_DUMP: + break; + default: + rply.rpc.reply_state = htonl(PROC_UNAVAIL); + break; + } + } + + sendto(sock, &rply.rpc.hdr.udp, sizeof rply - 4, 0, + (struct sockaddr *)&sin, addrlen); + } +} + +pid_t start_dummy_portmap(const char *file) +{ + FILE *portmap_filep; + int sock; + pid_t spoof_portmap; + + portmap_filep = fopen(file, "w"); + if (!portmap_filep) { + fprintf(stderr, "%s: cannot write portmap file: %s\n", + progname, file); + return -1; + } + + sock = bind_portmap(); + if (sock == -1) { + if (errno == EINVAL || errno == EADDRINUSE) + return 0; /* Assume not needed */ + else { + fprintf(stderr, "%s: portmap spoofing failed\n", + progname); + return -1; + } + } + + spoof_portmap = fork(); + if (spoof_portmap == -1) { + fprintf(stderr, "%s: cannot fork\n", progname); + return -1; + } else if (spoof_portmap == 0) { + /* Child process */ + dummy_portmap(sock, portmap_filep); + _exit(255); /* Error */ + } else { + /* Parent process */ + close(sock); + return spoof_portmap; + } +} diff -puN /dev/null usr/kinit/nfsmount/dummypmap.h --- /dev/null +++ a/usr/kinit/nfsmount/dummypmap.h @@ -0,0 +1,13 @@ +/* + * dummyportmap.h + * + * Functions for the portmap spoofer + */ + +#ifndef NFSMOUNT_DUMMYPORTMAP_H +#define NFSMOUNT_DUMMYPORTMAP_H + +#include +pid_t start_dummy_portmap(const char *file); + +#endif /* NFSMOUNT_DUMMYPORTMAP_H */ diff -puN /dev/null usr/kinit/nfsmount/dummypmap_test.c --- /dev/null +++ a/usr/kinit/nfsmount/dummypmap_test.c @@ -0,0 +1,2 @@ +#define TEST +#include "dummypmap.c" diff -puN /dev/null usr/kinit/nfsmount/Kbuild --- /dev/null +++ a/usr/kinit/nfsmount/Kbuild @@ -0,0 +1,27 @@ +# +# kbuild file for nfsmount +# + +static-y := static/nfsmount +#FIXME - build is broken static-y := dummypmap +shared-y := shared/nfsmount + +objs := main.o mount.o portmap.o dummypmap.o sunrpc.o + +# Create built-in.o with all .o files (used by kinit) +lib-y := $(objs) + +# .o files used for executables +static/nfsmount-y := $(objs) +shared/nfsmount-y := $(objs) + +# dummypmap uses a single .o file (rename src file?) +dummypmap-y := dummypmap_test.o + +# TODO - do we want a stripped version +# TODO - do we want the static.g + shared.g directories? + +clean-dirs := static shared + +# Install binary +install-y := $(shared-y) diff -puN /dev/null usr/kinit/nfsmount/main.c --- /dev/null +++ a/usr/kinit/nfsmount/main.c @@ -0,0 +1,263 @@ +/* + * nfsmount/main.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For _KLIBC_NO_MMU */ + +#include + +#include "nfsmount.h" +#include "sunrpc.h" +#include "dummypmap.h" + +const char *progname; +static jmp_buf abort_buf; + +static struct nfs_mount_data mount_data = { + .version = NFS_MOUNT_VERSION, + .flags = NFS_MOUNT_NONLM | NFS_MOUNT_VER3 | NFS_MOUNT_TCP, + .rsize = 0, /* Server's choice */ + .wsize = 0, /* Server's choice */ + .timeo = 7, + .retrans = 3, + .acregmin = 3, + .acregmax = 60, + .acdirmin = 30, + .acdirmax = 60, + .namlen = NAME_MAX, +}; + +int nfs_port; + +static struct int_opts { + char *name; + int *val; +} int_opts[] = { + {"port", &nfs_port}, + {"rsize", &mount_data.rsize}, + {"wsize", &mount_data.wsize}, + {"timeo", &mount_data.timeo}, + {"retrans", &mount_data.retrans}, + {"acregmin", &mount_data.acregmin}, + {"acregmax", &mount_data.acregmax}, + {"acdirmin", &mount_data.acdirmin}, + {"acdirmax", &mount_data.acdirmax}, + {NULL, NULL} +}; + +static struct bool_opts { + char *name; + int and_mask; + int or_mask; +} bool_opts[] = { + {"soft", ~NFS_MOUNT_SOFT, NFS_MOUNT_SOFT}, + {"hard", ~NFS_MOUNT_SOFT, 0}, + {"intr", ~NFS_MOUNT_INTR, NFS_MOUNT_INTR}, + {"nointr", ~NFS_MOUNT_INTR, 0}, + {"posix", ~NFS_MOUNT_POSIX, NFS_MOUNT_POSIX}, + {"noposix", ~NFS_MOUNT_POSIX, 0}, + {"cto", ~NFS_MOUNT_NOCTO, 0}, + {"nocto", ~NFS_MOUNT_NOCTO, NFS_MOUNT_NOCTO}, + {"ac", ~NFS_MOUNT_NOAC, 0}, + {"noac", ~NFS_MOUNT_NOAC, NFS_MOUNT_NOAC}, + {"lock", ~NFS_MOUNT_NONLM, 0}, + {"nolock", ~NFS_MOUNT_NONLM, NFS_MOUNT_NONLM}, + {"v2", ~NFS_MOUNT_VER3, 0}, + {"v3", ~NFS_MOUNT_VER3, NFS_MOUNT_VER3}, + {"udp", ~NFS_MOUNT_TCP, 0}, + {"tcp", ~NFS_MOUNT_TCP, NFS_MOUNT_TCP}, + {"broken_suid", ~NFS_MOUNT_BROKEN_SUID, NFS_MOUNT_BROKEN_SUID}, + {"ro", ~NFS_MOUNT_KLIBC_RONLY, NFS_MOUNT_KLIBC_RONLY}, + {"rw", ~NFS_MOUNT_KLIBC_RONLY, 0}, + {NULL, 0, 0} +}; + +static int parse_int(const char *val, const char *ctx) +{ + char *end; + int ret; + + ret = (int)strtoul(val, &end, 0); + if (*val == '\0' || *end != '\0') { + fprintf(stderr, "%s: invalid value for %s\n", val, ctx); + longjmp(abort_buf, 1); + } + return ret; +} + +static void parse_opts(char *opts) +{ + char *cp, *val; + + while ((cp = strsep(&opts, ",")) != NULL) { + if (*cp == '\0') + continue; + if ((val = strchr(cp, '=')) != NULL) { + struct int_opts *opts = int_opts; + *val++ = '\0'; + while (opts->name && strcmp(opts->name, cp) != 0) + opts++; + if (opts->name) + *(opts->val) = parse_int(val, opts->name); + else { + fprintf(stderr, "%s: bad option '%s'\n", + progname, cp); + longjmp(abort_buf, 1); + } + } else { + struct bool_opts *opts = bool_opts; + while (opts->name && strcmp(opts->name, cp) != 0) + opts++; + if (opts->name) { + mount_data.flags &= opts->and_mask; + mount_data.flags |= opts->or_mask; + } else { + fprintf(stderr, "%s: bad option '%s'\n", + progname, cp); + longjmp(abort_buf, 1); + } + } + } +} + +static uint32_t parse_addr(const char *ip) +{ + struct in_addr in; + if (inet_aton(ip, &in) == 0) { + fprintf(stderr, "%s: can't parse IP address '%s'\n", + progname, ip); + longjmp(abort_buf, 1); + } + return in.s_addr; +} + +static void check_path(const char *path) +{ + struct stat st; + + if (stat(path, &st) == -1) { + perror("stat"); + longjmp(abort_buf, 1); + } else if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "%s: '%s' not a directory\n", progname, path); + longjmp(abort_buf, 1); + } +} + +int main(int argc, char *argv[]) + __attribute__ ((weak, alias("nfsmount_main"))); + +int nfsmount_main(int argc, char *argv[]) +{ + uint32_t server; + char *rem_name; + char *rem_path; + char *hostname; + char *path; + int c; + const char *portmap_file; + pid_t spoof_portmap; + int err; + + if ((err = setjmp(abort_buf))) + return err; + + /* Set these here to avoid longjmp warning */ + portmap_file = NULL; + spoof_portmap = 0; + server = 0; + + /* If progname is set we're invoked from another program */ + if (!progname) { + struct timeval now; + progname = argv[0]; + gettimeofday(&now, NULL); + srand48(now.tv_usec ^ (now.tv_sec << 24)); + } + + while ((c = getopt(argc, argv, "o:p:")) != EOF) { + switch (c) { + case 'o': + parse_opts(optarg); + break; + case 'p': + portmap_file = optarg; + break; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + progname, optopt); + return 1; + } + } + + if (optind == argc) { + fprintf(stderr, "%s: need a path\n", progname); + return 1; + } + + hostname = rem_path = argv[optind]; + + if ((rem_name = strdup(rem_path)) == NULL) { + perror("strdup"); + return 1; + } + + if ((rem_path = strchr(rem_path, ':')) == NULL) { + fprintf(stderr, "%s: need a server\n", progname); + return 1; + } + + *rem_path++ = '\0'; + + if (*rem_path != '/') { + fprintf(stderr, "%s: need a path\n", progname); + return 1; + } + + server = parse_addr(hostname); + + if (optind <= argc - 2) + path = argv[optind + 1]; + else + path = "/nfs_root"; + + check_path(path); + +#if! _KLIBC_NO_MMU + /* Note: uClinux can't fork(), so the spoof portmapper is not + available on uClinux. */ + if (portmap_file) + spoof_portmap = start_dummy_portmap(portmap_file); + + if (spoof_portmap == -1) + return 1; +#endif + + if (nfs_mount(rem_name, hostname, server, rem_path, path, + &mount_data) != 0) + return 1; + + /* If we set up the spoofer, tear it down now */ + if (spoof_portmap) { + kill(SIGTERM, spoof_portmap); + while (waitpid(spoof_portmap, NULL, 0) == -1 && + errno == EINTR) + ; + } + + free(rem_name); + + return 0; +} diff -puN /dev/null usr/kinit/nfsmount/mount.c --- /dev/null +++ a/usr/kinit/nfsmount/mount.c @@ -0,0 +1,357 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nfsmount.h" +#include "sunrpc.h" + +static uint32_t mount_port; + +struct mount_call { + struct rpc_call rpc; + uint32_t path_len; + char path[0]; +}; + +/* + * The following structure is the NFS v3 on-the-wire file handle, + * as defined in rfc1813. + * This differs from the structure used by the kernel, + * defined in : rfc has a long in network order, + * kernel has a short in native order. + * Both kernel and rfc use the name nfs_fh; kernel name is + * visible to user apps in some versions of libc. + * Use different name to avoid clashes. + */ +#define NFS_MAXFHSIZE_WIRE 64 +struct nfs_fh_wire { + uint32_t size; + char data[NFS_MAXFHSIZE_WIRE]; +} __attribute__ ((packed)); + +struct mount_reply { + struct rpc_reply reply; + uint32_t status; + struct nfs_fh_wire fh; +} __attribute__ ((packed)); + +#define MNT_REPLY_MINSIZE (sizeof(struct rpc_reply) + sizeof(uint32_t)) + +static int get_ports(uint32_t server, const struct nfs_mount_data *data) +{ + uint32_t nfs_ver, mount_ver; + uint32_t proto; + + if (data->flags & NFS_MOUNT_VER3) { + nfs_ver = NFS3_VERSION; + mount_ver = NFS_MNT3_VERSION; + } else { + nfs_ver = NFS2_VERSION; + mount_ver = NFS_MNT_VERSION; + } + + proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; + + if (nfs_port == 0) { + nfs_port = portmap(server, NFS_PROGRAM, nfs_ver, proto); + if (nfs_port == 0) { + if (proto == IPPROTO_TCP) { + struct in_addr addr = { server }; + fprintf(stderr, "NFS over TCP not " + "available from %s\n", inet_ntoa(addr)); + return -1; + } + nfs_port = NFS_PORT; + } + } + + if (mount_port == 0) { + mount_port = portmap(server, NFS_MNT_PROGRAM, mount_ver, proto); + if (mount_port == 0) + mount_port = MOUNT_PORT; + } + return 0; +} + +static inline int pad_len(int len) +{ + return (len + 3) & ~3; +} + +static inline void dump_params(uint32_t server, + const char *path, + const struct nfs_mount_data *data) +{ + (void)server; + (void)path; + (void)data; + +#ifdef NFS_DEBUG + struct in_addr addr = { server }; + + printf("NFS params:\n"); + printf(" server = %s, path = \"%s\", ", inet_ntoa(addr), path); + printf("version = %d, proto = %s\n", + data->flags & NFS_MOUNT_VER3 ? 3 : 2, + (data->flags & NFS_MOUNT_TCP) ? "tcp" : "udp"); + printf(" mount_port = %d, nfs_port = %d, flags = %08x\n", + mount_port, nfs_port, data->flags); + printf(" rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", + data->rsize, data->wsize, data->timeo, data->retrans); + printf(" acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", + data->acregmin, data->acregmax, data->acdirmin, data->acdirmax); + printf(" soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", + (data->flags & NFS_MOUNT_SOFT) != 0, + (data->flags & NFS_MOUNT_INTR) != 0, + (data->flags & NFS_MOUNT_POSIX) != 0, + (data->flags & NFS_MOUNT_NOCTO) != 0, + (data->flags & NFS_MOUNT_NOAC) != 0); +#endif +} + +static inline void dump_fh(const char *data, int len) +{ + (void)data; + (void)len; + +#ifdef NFS_DEBUG + int i = 0; + int max = len - (len % 8); + + printf("Root file handle: %d bytes\n", NFS2_FHSIZE); + + while (i < max) { + int j; + + printf(" %4d: ", i); + for (j = 0; j < 4; j++) { + printf("%02x %02x %02x %02x ", + data[i] & 0xff, data[i + 1] & 0xff, + data[i + 2] & 0xff, data[i + 3] & 0xff); + } + i += j; + printf("\n"); + } +#endif +} + +static struct mount_reply mnt_reply; + +static int mount_call(uint32_t proc, uint32_t version, + const char *path, struct client *clnt) +{ + struct mount_call *mnt_call = NULL; + size_t path_len, call_len; + struct rpc rpc; + int ret = 0; + + path_len = strlen(path); + call_len = sizeof(*mnt_call) + pad_len(path_len); + + if ((mnt_call = malloc(call_len)) == NULL) { + perror("malloc"); + goto bail; + } + + memset(mnt_call, 0, sizeof(*mnt_call)); + + mnt_call->rpc.program = htonl(NFS_MNT_PROGRAM); + mnt_call->rpc.prog_vers = htonl(version); + mnt_call->rpc.proc = htonl(proc); + mnt_call->path_len = htonl(path_len); + memcpy(mnt_call->path, path, path_len); + + rpc.call = (struct rpc_call *)mnt_call; + rpc.call_len = call_len; + rpc.reply = (struct rpc_reply *)&mnt_reply; + rpc.reply_len = sizeof(mnt_reply); + + if (rpc_call(clnt, &rpc) < 0) + goto bail; + + if (proc != MNTPROC_MNT) { + goto done; + } + + if (rpc.reply_len < MNT_REPLY_MINSIZE) { + fprintf(stderr, "incomplete reply: %zu < %zu\n", + rpc.reply_len, MNT_REPLY_MINSIZE); + goto bail; + } + + if (mnt_reply.status != 0) { + fprintf(stderr, "mount call failed: %d\n", + ntohl(mnt_reply.status)); + goto bail; + } + + goto done; + +bail: + ret = -1; + +done: + if (mnt_call) { + free(mnt_call); + } + + return ret; +} + +static int mount_v2(const char *path, + struct nfs_mount_data *data, struct client *clnt) +{ + int ret = mount_call(MNTPROC_MNT, NFS_MNT_VERSION, path, clnt); + + if (ret == 0) { + dump_fh((const char *)&mnt_reply.fh, NFS2_FHSIZE); + + data->root.size = NFS_FHSIZE; + memcpy(data->root.data, &mnt_reply.fh, NFS_FHSIZE); + memcpy(data->old_root.data, &mnt_reply.fh, NFS_FHSIZE); + } + + return ret; +} + +static inline int umount_v2(const char *path, struct client *clnt) +{ + return mount_call(MNTPROC_UMNT, NFS_MNT_VERSION, path, clnt); +} + +static int mount_v3(const char *path, + struct nfs_mount_data *data, struct client *clnt) +{ + int ret = mount_call(MNTPROC_MNT, NFS_MNT3_VERSION, path, clnt); + + if (ret == 0) { + size_t fhsize = ntohl(mnt_reply.fh.size); + + dump_fh((const char *)&mnt_reply.fh.data, fhsize); + + memset(data->old_root.data, 0, NFS_FHSIZE); + memset(&data->root, 0, sizeof(data->root)); + data->root.size = fhsize; + memcpy(&data->root.data, mnt_reply.fh.data, fhsize); + data->flags |= NFS_MOUNT_VER3; + } + + return ret; +} + +static inline int umount_v3(const char *path, struct client *clnt) +{ + return mount_call(MNTPROC_UMNT, NFS_MNT3_VERSION, path, clnt); +} + +int nfs_mount(const char *pathname, const char *hostname, + uint32_t server, const char *rem_path, const char *path, + struct nfs_mount_data *data) +{ + struct client *clnt = NULL; + struct sockaddr_in addr; + char mounted = 0; + int sock = -1; + int ret = 0; + int mountflags; + + if (get_ports(server, data) != 0) { + goto bail; + } + + dump_params(server, rem_path, data); + + if (data->flags & NFS_MOUNT_TCP) { + clnt = tcp_client(server, mount_port, CLI_RESVPORT); + } else { + clnt = udp_client(server, mount_port, CLI_RESVPORT); + } + + if (clnt == NULL) { + goto bail; + } + + if (data->flags & NFS_MOUNT_VER3) { + ret = mount_v3(rem_path, data, clnt); + } else { + ret = mount_v2(rem_path, data, clnt); + } + + if (ret == -1) { + goto bail; + } + mounted = 1; + + if (data->flags & NFS_MOUNT_TCP) { + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + } else { + sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + } + + if (sock == -1) { + perror("socket"); + goto bail; + } + + if (bindresvport(sock, 0) == -1) { + perror("bindresvport"); + goto bail; + } + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = server; + addr.sin_port = htons(nfs_port); + memcpy(&data->addr, &addr, sizeof(data->addr)); + + strncpy(data->hostname, hostname, sizeof(data->hostname)); + + data->fd = sock; + + mountflags = (data->flags & NFS_MOUNT_KLIBC_RONLY) ? MS_RDONLY : 0; + data->flags = data->flags & NFS_MOUNT_FLAGMASK; + ret = mount(pathname, path, "nfs", mountflags, data); + + if (ret == -1) { + if (errno == ENODEV) { + fprintf(stderr, "mount: the kernel lacks NFS v%d " + "support\n", + (data->flags & NFS_MOUNT_VER3) ? 3 : 2); + } else { + perror("mount"); + } + goto bail; + } + + DEBUG(("Mounted %s on %s\n", pathname, path)); + + goto done; + + bail: + if (mounted) { + if (data->flags & NFS_MOUNT_VER3) { + umount_v3(path, clnt); + } else { + umount_v2(path, clnt); + } + } + + ret = -1; + + done: + if (clnt) { + client_free(clnt); + } + + if (sock != -1) { + close(sock); + } + + return ret; +} diff -puN /dev/null usr/kinit/nfsmount/nfsmount.h --- /dev/null +++ a/usr/kinit/nfsmount/nfsmount.h @@ -0,0 +1,39 @@ +/* + * nfsmount/nfsmount.h + */ + +#ifndef NFSMOUNT_NFSMOUNT_H +#define NFSMOUNT_NFSMOUNT_H + +#include + +extern int nfs_port; + +extern int nfsmount_main(int argc, char *argv[]); +int nfs_mount(const char *rem_name, const char *hostname, + uint32_t server, const char *rem_path, + const char *path, struct nfs_mount_data *data); + +enum nfs_proto { + v2 = 2, + v3, +}; + +/* masked with NFS_MOUNT_FLAGMASK before mount() call */ +#define NFS_MOUNT_KLIBC_RONLY 0x00010000U +/* + * Note for gcc 3.2.2: + * + * If you're turning on debugging, make sure you get rid of -Os from + * the gcc command line, or else ipconfig will fail to link. + */ +#define NFS_DEBUG + +#undef DEBUG +#ifdef NFS_DEBUG +#define DEBUG(x) printf x +#else +#define DEBUG(x) do { } while(0) +#endif + +#endif /* NFSMOUNT_NFSMOUNT_H */ diff -puN /dev/null usr/kinit/nfsmount/portmap.c --- /dev/null +++ a/usr/kinit/nfsmount/portmap.c @@ -0,0 +1,73 @@ +#include +#include +#include /* __constant_hton* */ +#include +#include + +#include "nfsmount.h" +#include "sunrpc.h" + +struct portmap_call { + struct rpc_call rpc; + uint32_t program; + uint32_t version; + uint32_t proto; + uint32_t port; +}; + +struct portmap_reply { + struct rpc_reply rpc; + uint32_t port; +}; + +static struct portmap_call call = { + .rpc = { + .program = __constant_htonl(RPC_PMAP_PROGRAM), + .prog_vers = __constant_htonl(RPC_PMAP_VERSION), + .proc = __constant_htonl(PMAP_PROC_GETPORT), + } +}; + +uint32_t portmap(uint32_t server, uint32_t program, uint32_t version, uint32_t proto) +{ + struct portmap_reply reply; + struct client *clnt; + struct rpc rpc; + uint32_t port = 0; + + if ((clnt = tcp_client(server, RPC_PMAP_PORT, 0)) == NULL) { + if ((clnt = udp_client(server, RPC_PMAP_PORT, 0)) == NULL) { + goto bail; + } + } + + call.program = htonl(program); + call.version = htonl(version); + call.proto = htonl(proto); + + rpc.call = (struct rpc_call *)&call; + rpc.call_len = sizeof(call); + rpc.reply = (struct rpc_reply *)&reply; + rpc.reply_len = sizeof(reply); + + if (rpc_call(clnt, &rpc) < 0) + goto bail; + + if (rpc.reply_len < sizeof(reply)) { + fprintf(stderr, "incomplete reply: %zu < %zu\n", + rpc.reply_len, sizeof(reply)); + goto bail; + } + + port = ntohl(reply.port); + +bail: + DEBUG(("Port for %d/%d[%s]: %d\n", program, version, + proto == IPPROTO_TCP ? "tcp" : "udp", port)); + + if (clnt) { + client_free(clnt); + } + + return port; +} diff -puN /dev/null usr/kinit/nfsmount/README.locking --- /dev/null +++ a/usr/kinit/nfsmount/README.locking @@ -0,0 +1,26 @@ +I have implemented portmap spoofing in klibc nfsmount (released as +klibc-0.144) This is basically a vestigial portmap daemon which gets +launched before the mount() call and then just records any +transactions it gets to a file and sends back an affirmative reply. + +There are two ways to use it (this belongs in a README file, but it's +too late at night right now): + +a) Set a fixed portnumber in /proc/sys/nfs/nlm_tcpport and +/proc/sys/nfs/nlm_udpport before calling nfsmount; once the portmapper +starts feed that fixed portnumber to pmap_set(8). In this case the +pmap_file can be /dev/null. + +b) Allow the kernel to bind to any port and use the file produced by +nfsroot to feed to pmap_set (it should be directly compatible); this +means the file needs to be transferred to a place where the "real +root" can find it before run-init. + +In either case, it is imperative that the real portmapper is launched +before any program actually tries to create locks! + +To use it: + + # We need the loopback device to be up before we do this! + ipconfig 127.0.0.1:::::lo:none + nfsroot -p pmap_file -o lock server:/pathname /realpath diff -puN /dev/null usr/kinit/nfsmount/sunrpc.c --- /dev/null +++ a/usr/kinit/nfsmount/sunrpc.c @@ -0,0 +1,253 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nfsmount.h" +#include "sunrpc.h" + +/* + * The magic offset is needed here because RPC over TCP includes a + * field that RPC over UDP doesn't. Luvverly. + */ +static int rpc_do_reply(struct client *clnt, struct rpc *rpc, size_t off) +{ + int ret; + + if ((ret = read(clnt->sock, + ((char *)rpc->reply) + off, + rpc->reply_len - off)) == -1) { + perror("read"); + goto bail; + } else if (ret < sizeof(struct rpc_reply) - off) { + fprintf(stderr, "short read: %d < %zu\n", ret, + sizeof(struct rpc_reply) - off); + goto bail; + } + rpc->reply_len = ret + off; + + if ((!off && !(ntohl(rpc->reply->hdr.frag_hdr) & LAST_FRAG)) || + rpc->reply->hdr.udp.xid != rpc->call->hdr.udp.xid || + rpc->reply->hdr.udp.msg_type != htonl(RPC_REPLY)) { + fprintf(stderr, "bad reply\n"); + goto bail; + } + + if (ntohl(rpc->reply->state) != REPLY_OK) { + fprintf(stderr, "rpc failed: %d\n", ntohl(rpc->reply->state)); + goto bail; + } + + ret = 0; + goto done; + +bail: + ret = -1; +done: + return ret; +} + +static void rpc_header(struct client *clnt, struct rpc *rpc) +{ + (void)clnt; + + rpc->call->hdr.frag_hdr = htonl(LAST_FRAG | rpc->call_len); + rpc->call->hdr.udp.xid = lrand48(); + rpc->call->hdr.udp.msg_type = htonl(RPC_CALL); + rpc->call->rpc_vers = htonl(2); +} + +static int rpc_call_tcp(struct client *clnt, struct rpc *rpc) +{ + int ret; + + rpc_header(clnt, rpc); + + if ((ret = write(clnt->sock, rpc->call, rpc->call_len)) == -1) { + perror("write"); + goto bail; + } else if (ret < rpc->call_len) { + fprintf(stderr, "short write: %d < %zu\n", ret, rpc->call_len); + goto bail; + } + + ret = rpc_do_reply(clnt, rpc, 0); + goto done; + + bail: + ret = -1; + + done: + return ret; +} + +static int rpc_call_udp(struct client *clnt, struct rpc *rpc) +{ +#define NR_FDS 1 +#define TIMEOUT_MS 3000 +#define MAX_TRIES 100 +#define UDP_HDR_OFF (sizeof(struct rpc_header) - sizeof(struct rpc_udp_header)) + struct pollfd fds[NR_FDS]; + int ret = -1; + int i; + + rpc_header(clnt, rpc); + + fds[0].fd = clnt->sock; + fds[0].events = POLLRDNORM; + + rpc->call_len -= UDP_HDR_OFF; + + for (i = 0; i < MAX_TRIES; i++) { + int timeout_ms = TIMEOUT_MS + (lrand48() % (TIMEOUT_MS / 2)); + if ((ret = write(clnt->sock, + ((char *)rpc->call) + UDP_HDR_OFF, + rpc->call_len)) == -1) { + perror("write"); + goto bail; + } else if (ret < rpc->call_len) { + fprintf(stderr, "short write: %d < %zu\n", ret, + rpc->call_len); + goto bail; + } + for (; i < MAX_TRIES; i++) { + if ((ret = poll(fds, NR_FDS, timeout_ms)) == -1) { + perror("poll"); + goto bail; + } + if (ret == 0) { + DEBUG(("Timeout #%d\n", i + 1)); + break; + } + if ((ret = rpc_do_reply(clnt, rpc, UDP_HDR_OFF)) == 0) { + goto done; + } else { + DEBUG(("Failed on try #%d - retrying\n", + i + 1)); + } + } + } + + bail: + ret = -1; + + done: + return ret; +} + +struct client *tcp_client(uint32_t server, uint16_t port, uint32_t flags) +{ + struct client *clnt = malloc(sizeof(*clnt)); + struct sockaddr_in addr; + int sock; + + if (clnt == NULL) { + perror("malloc"); + goto bail; + } + + memset(clnt, 0, sizeof(clnt)); + + if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + perror("socket"); + goto bail; + } + + if ((flags & CLI_RESVPORT) && bindresvport(sock, 0) == -1) { + perror("bindresvport"); + goto bail; + } + + clnt->sock = sock; + clnt->call_stub = rpc_call_tcp; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = server; + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + perror("connect"); + goto bail; + } + + goto done; + bail: + if (clnt) { + free(clnt); + clnt = NULL; + } + done: + return clnt; +} + +struct client *udp_client(uint32_t server, uint16_t port, uint32_t flags) +{ + struct client *clnt = malloc(sizeof(*clnt)); + struct sockaddr_in addr; + int sock; + + if (clnt == NULL) { + perror("malloc"); + goto bail; + } + + memset(clnt, 0, sizeof(clnt)); + + if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + perror("socket"); + goto bail; + } + + if ((flags & CLI_RESVPORT) && bindresvport(sock, 0) == -1) { + perror("bindresvport"); + goto bail; + } else { + struct sockaddr_in me; + + me.sin_family = AF_INET; + me.sin_port = 0; + me.sin_addr.s_addr = INADDR_ANY; + + if (0 && bind(sock, (struct sockaddr *)&me, sizeof(me)) == -1) { + perror("bind"); + goto bail; + } + } + + clnt->sock = sock; + clnt->call_stub = rpc_call_udp; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = server; + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + perror("connect"); + goto bail; + } + + goto done; + bail: + if (clnt) { + free(clnt); + clnt = NULL; + } + done: + return clnt; +} + +void client_free(struct client *c) +{ + if (c->sock != -1) + close(c->sock); + free(c); +} + +int rpc_call(struct client *client, struct rpc *rpc) +{ + return client->call_stub(client, rpc); +} diff -puN /dev/null usr/kinit/nfsmount/sunrpc.h --- /dev/null +++ a/usr/kinit/nfsmount/sunrpc.h @@ -0,0 +1,99 @@ +/* + * sunrpc.h - open-coded SunRPC structures + */ +#ifndef NFSMOUNT_SUNRPC_H +#define NFSMOUNT_SUNRPC_H + +#include +#include + +#define SUNRPC_PORT 111 +#define MOUNT_PORT 627 + +#define RPC_CALL 0 +#define RPC_REPLY 1 + +#define PORTMAP_PROGRAM 100000 +#define NLM_PROGRAM 100021 + +#define RPC_PMAP_PROGRAM 100000 +#define RPC_PMAP_VERSION 2 +#define RPC_PMAP_PORT 111 + +#define PMAP_PROC_NULL 0 +#define PMAP_PROC_SET 1 +#define PMAP_PROC_UNSET 2 +#define PMAP_PROC_GETPORT 3 +#define PMAP_PROC_DUMP 4 + +#define LAST_FRAG 0x80000000 + +#define REPLY_OK 0 +#define REPLY_DENIED 1 + +#define SUCCESS 0 +#define PROG_UNAVAIL 1 +#define PROG_MISMATCH 2 +#define PROC_UNAVAIL 3 +#define GARBAGE_ARGS 4 +#define SYSTEM_ERR 5 + +struct rpc_udp_header { + uint32_t xid; + uint32_t msg_type; +}; + +struct rpc_header { + uint32_t frag_hdr; + struct rpc_udp_header udp; +}; + +struct rpc_call { + struct rpc_header hdr; + uint32_t rpc_vers; + + uint32_t program; + uint32_t prog_vers; + uint32_t proc; + uint32_t cred_flavor; + + uint32_t cred_len; + uint32_t vrf_flavor; + uint32_t vrf_len; +}; + +struct rpc_reply { + struct rpc_header hdr; + uint32_t reply_state; + uint32_t vrf_flavor; + uint32_t vrf_len; + uint32_t state; +}; + +struct rpc { + struct rpc_call *call; + size_t call_len; + struct rpc_reply *reply; + size_t reply_len; +}; + +struct client; + +typedef int (*call_stub) (struct client *, struct rpc *); + +struct client { + int sock; + call_stub call_stub; +}; + +#define CLI_RESVPORT 00000001 + +struct client *tcp_client(uint32_t server, uint16_t port, uint32_t flags); +struct client *udp_client(uint32_t server, uint16_t port, uint32_t flags); +void client_free(struct client *client); + +int rpc_call(struct client *client, struct rpc *rpc); + +uint32_t portmap(uint32_t server, uint32_t program, uint32_t version, uint32_t proto); + +#endif /* NFSMOUNT_SUNRPC_H */ diff -puN /dev/null usr/kinit/nfsroot.c --- /dev/null +++ a/usr/kinit/nfsroot.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "ipconfig.h" +#include "kinit.h" +#include "netdev.h" +#include "nfsmount.h" + +static char *sub_client(__u32 client, char *path, size_t len) +{ + struct in_addr addr = { client }; + char buf[len]; + + if (strstr(path, "%s") != NULL) { + if (client == INADDR_NONE) { + fprintf(stderr, "Root-NFS: no client address\n"); + exit(1); + } + + snprintf(buf, len, path, inet_ntoa(addr)); + strcpy(path, buf); + } + + return path; +} + +#define NFS_ARGC 6 +#define MOUNT_POINT "/root" + +int mount_nfs_root(int argc, char *argv[], int flags) +{ + (void)flags; /* FIXME - don't ignore this */ + + struct in_addr addr = { INADDR_NONE }; + __u32 client = INADDR_NONE; + const int len = 1024; + struct netdev *dev; + char *mtpt = MOUNT_POINT; + char *path = NULL; + char *dev_bootpath = NULL; + char root[len]; + char *x, *opts; + int ret = 0; + int a = 1; + char *nfs_argv[NFS_ARGC + 1] = { "NFS-Mount" }; + + for (dev = ifaces; dev; dev = dev->next) { + if (dev->ip_server != INADDR_NONE && + dev->ip_server != INADDR_ANY) { + addr.s_addr = dev->ip_server; + client = dev->ip_addr; + dev_bootpath = dev->bootpath; + break; + } + if (dev->ip_addr != INADDR_NONE && dev->ip_addr != INADDR_ANY) { + client = dev->ip_addr; + } + } + + /* + * if the "nfsroot" option is set then it overrides + * bootpath supplied by the boot server. + */ + if ((path = get_arg(argc, argv, "nfsroot=")) == NULL) { + if ((path = dev_bootpath) == NULL || path[0] == '\0') + /* no path - set a default */ + path = (char *)"/tftpboot/%s"; + } else if (dev_bootpath && dev_bootpath[0] != '\0') + fprintf(stderr, + "nfsroot=%s overrides boot server bootpath %s\n", + path, dev_bootpath); + + if ((opts = strchr(path, ',')) != NULL) { + *opts++ = '\0'; + nfs_argv[a++] = (char *)"-o"; + nfs_argv[a++] = opts; + } + + if ((x = strchr(path, ':')) == NULL) { + if (addr.s_addr == INADDR_NONE) { + fprintf(stderr, "Root-NFS: no server defined\n"); + exit(1); + } + + snprintf(root, len, "%s:%s", inet_ntoa(addr), path); + } else { + strcpy(root, path); + } + + nfs_argv[a++] = sub_client(client, root, len); + + DEBUG(("NFS-Root: mounting %s on %s with options \"%s\"\n", + nfs_argv[a-1], mtpt, opts ? opts : "")); + + nfs_argv[a++] = mtpt; + nfs_argv[a] = NULL; + assert(a <= NFS_ARGC); + + dump_args(a, nfs_argv); + + if ((ret = nfsmount_main(a, nfs_argv)) != 0) { + ret = -1; + goto done; + } + + done: + return ret; +} diff -puN /dev/null usr/kinit/open.c --- /dev/null +++ a/usr/kinit/open.c @@ -0,0 +1,18 @@ +/* + * open.c + * + * A quick hack to do an open() and set the cloexec flag + */ + +#include +#include + +int open_cloexec(const char *path, int flags, mode_t mode) +{ + int fd = open(path, flags, mode); + + if (fd >= 0) + fcntl(fd, F_SETFD, FD_CLOEXEC); + + return fd; +} diff -puN /dev/null usr/kinit/ramdisk_load.c --- /dev/null +++ a/usr/kinit/ramdisk_load.c @@ -0,0 +1,271 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kinit.h" +#include "do_mounts.h" +#include "fstype.h" +#include "zlib.h" + +#define BUF_SZ 65536 + +static void wait_for_key(void) +{ + /* Wait until the user presses Enter */ + while (getchar() != '\n') + ; +} + +static int change_disk(const char *devpath, int rfd, int disk) +{ + /* Try to eject and/or quiesce the device */ + sync(); + if (ioctl(rfd, FDEJECT, 0)) { + if (errno == ENOTTY) { + /* Not a floppy */ + ioctl(rfd, CDROMEJECT, 0); + } else { + /* Non-ejectable floppy */ + ioctl(rfd, FDRESET, FD_RESET_IF_NEEDED); + } + } + close(rfd); + + fprintf(stderr, + "\nPlease insert disk %d for ramdisk and press Enter...", disk); + wait_for_key(); + + return open(devpath, O_RDONLY); +} + +/* Also used in initrd.c */ +int load_ramdisk_compressed(const char *devpath, FILE * wfd, + off_t ramdisk_start) +{ + int rfd = -1; + unsigned long long ramdisk_size, ramdisk_left; + int disk = 1; + ssize_t bytes; + int rv; + unsigned char in_buf[BUF_SZ], out_buf[BUF_SZ]; + z_stream zs; + + zs.zalloc = Z_NULL; /* Use malloc() */ + zs.zfree = Z_NULL; /* Use free() */ + zs.next_in = Z_NULL; /* No data read yet */ + zs.avail_in = 0; + zs.next_out = out_buf; + zs.avail_out = BUF_SZ; + + if (inflateInit2(&zs, 32 + 15) != Z_OK) + goto err1; + + rfd = open(devpath, O_RDONLY); + if (rfd < 0) + goto err2; + + /* Set to the size of the medium, or "infinite" */ + if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size)) + ramdisk_size = ~0ULL; + + do { + /* Purge the output preferentially over reading new + input, so we don't end up overrunning the input by + accident and demanding a new disk which doesn't + exist... */ + if (zs.avail_out == 0) { + _fwrite(out_buf, BUF_SZ, wfd); + zs.next_out = out_buf; + zs.avail_out = BUF_SZ; + } else if (zs.avail_in == 0) { + if (ramdisk_start >= ramdisk_size) { + rfd = change_disk(devpath, rfd, ++disk); + if (rfd < 0) + goto err2; + + if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size)) + ramdisk_size = ~0ULL; + ramdisk_start = 0; + DEBUG(("New size = %llu\n", ramdisk_size)); + } + do { + ramdisk_left = ramdisk_size - ramdisk_start; + bytes = min(ramdisk_left, + (unsigned long long)BUF_SZ); + bytes = pread(rfd, in_buf, bytes, + ramdisk_start); + } while (bytes == -1 && errno == EINTR); + if (bytes <= 0) + goto err2; + ramdisk_start += bytes; + zs.next_in = in_buf; + zs.avail_in = bytes; + + /* Print dots if we're reading from a real block device */ + if (ramdisk_size != ~0ULL) + putc('.', stderr); + } + rv = inflate(&zs, Z_SYNC_FLUSH); + } while (rv == Z_OK || rv == Z_BUF_ERROR); + + DEBUG(("kinit: inflate returned %d\n", rv)); + + if (rv != Z_STREAM_END) + goto err2; + + /* Write the last */ + _fwrite(out_buf, BUF_SZ - zs.avail_out, wfd); + DEBUG(("kinit: writing %d bytes\n", BUF_SZ - zs.avail_out)); + + inflateEnd(&zs); + return 0; + +err2: + inflateEnd(&zs); +err1: + return -1; +} + +static int +load_ramdisk_raw(const char *devpath, FILE * wfd, off_t ramdisk_start, + unsigned long long fssize) +{ + unsigned long long ramdisk_size, ramdisk_left; + int disk = 1; + ssize_t bytes; + unsigned char buf[BUF_SZ]; + int rfd; + + rfd = open(devpath, O_RDONLY); + if (rfd < 0) + return -1; + + /* Set to the size of the medium, or "infinite" */ + if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size)) + ramdisk_size = ~0ULL; + + DEBUG(("start: %llu size: %llu fssize: %llu\n", + ramdisk_start, ramdisk_size, fssize)); + + while (fssize) { + + if (ramdisk_start >= ramdisk_size) { + rfd = change_disk(devpath, rfd, ++disk); + if (rfd < 0) + return -1; + + if (ioctl(rfd, BLKGETSIZE64, &ramdisk_size)) + ramdisk_size = ~0ULL; + ramdisk_start = 0; + } + + do { + ramdisk_left = + min(ramdisk_size - ramdisk_start, fssize); + bytes = min(ramdisk_left, (unsigned long long)BUF_SZ); + bytes = pread(rfd, buf, bytes, ramdisk_start); + } while (bytes == -1 && errno == EINTR); + if (bytes <= 0) + break; + _fwrite(buf, bytes, wfd); + + ramdisk_start += bytes; + fssize -= bytes; + + /* Print dots if we're reading from a real block device */ + if (ramdisk_size != ~0ULL) + putc('.', stderr); + } + + return !!fssize; +} + +int ramdisk_load(int argc, char *argv[], dev_t root_dev) +{ + const char *arg_prompt_ramdisk = get_arg(argc, argv, "prompt_ramdisk="); + const char *arg_ramdisk_blocksize = + get_arg(argc, argv, "ramdisk_blocksize="); + const char *arg_ramdisk_start = get_arg(argc, argv, "ramdisk_start="); + const char *arg_ramdisk_device = get_arg(argc, argv, "ramdisk_device="); + + int prompt_ramdisk = arg_prompt_ramdisk ? atoi(arg_prompt_ramdisk) : 0; + int ramdisk_blocksize = + arg_ramdisk_blocksize ? atoi(arg_ramdisk_blocksize) : 512; + off_t ramdisk_start = + arg_ramdisk_start + ? strtoumax(arg_ramdisk_start, NULL, 10) * ramdisk_blocksize : 0; + const char *ramdisk_device = + arg_ramdisk_device ? arg_ramdisk_device : "/dev/fd0"; + + dev_t ramdisk_dev; + int rfd; + FILE *wfd; + const char *fstype; + unsigned long long fssize; + int is_gzip = 0; + int err; + + if (prompt_ramdisk) { + fprintf(stderr, + "Please insert disk for ramdisk and press Enter..."); + wait_for_key(); + } + + ramdisk_dev = name_to_dev_t(ramdisk_device); + if (!ramdisk_dev) { + fprintf(stderr, + "Failure loading ramdisk: unknown device: %s\n", + ramdisk_device); + return 0; + } + + create_dev("/dev/rddev", ramdisk_dev); + create_dev("/dev/ram0", Root_RAM0); + rfd = open("/dev/rddev", O_RDONLY); + wfd = fopen("/dev/ram0", "w"); + + if (rfd < 0 || !wfd) { + perror("Could not open ramdisk device"); + return 0; + } + + /* Check filesystem type */ + if (identify_fs(rfd, &fstype, &fssize, ramdisk_start) || + (fssize == 0 && !(is_gzip = !strcmp(fstype, "gzip")))) { + fprintf(stderr, + "Failure loading ramdisk: unknown filesystem type\n"); + return 0; + } + + DEBUG(("kinit: ramdisk is %s, size %llu\n", fstype, fssize)); + + fprintf(stderr, "Loading ramdisk (%s) ...", is_gzip ? "gzip" : "raw"); + + close(rfd); + + if (is_gzip) + err = load_ramdisk_compressed("/dev/rddev", wfd, ramdisk_start); + else + err = load_ramdisk_raw("/dev/rddev", wfd, + ramdisk_start, fssize); + + fclose(wfd); + + putc('\n', stderr); + + if (err) { + perror("Failure loading ramdisk"); + return 0; + } + + return 1; +} diff -puN /dev/null usr/kinit/readfile.c --- /dev/null +++ a/usr/kinit/readfile.c @@ -0,0 +1,86 @@ +/* + * readfile.c + * + * Read the entire contents of a file into malloc'd storage. This + * is mostly useful for things like /proc files where we can't just + * fstat() to get the length and then mmap(). + * + * Returns the number of bytes read, or -1 on error. + */ + +#include +#include +#include +#include + +ssize_t freadfile(FILE *f, char **pp) +{ + size_t bs; /* Decent starting point... */ + size_t bf; /* Bytes free */ + size_t bu = 0; /* Bytes used */ + char *buffer, *nb; + size_t rv; + int old_errno = errno; + + bs = BUFSIZ; /* A guess as good as any */ + bf = bs; + buffer = malloc(bs); + + if (!buffer) + return -1; + + for (;;) { + errno = 0; + + while (bf && (rv = _fread(buffer + bu, bf, f))) { + bu += rv; + bf -= rv; + } + + if (errno && errno != EINTR && errno != EAGAIN) { + /* error */ + free(buffer); + return -1; + } + + if (bf) { + /* Hit EOF, no error */ + + /* Try to free superfluous memory */ + if ((nb = realloc(buffer, bu + 1))) + buffer = nb; + + /* Null-terminate result for good measure */ + buffer[bu] = '\0'; + + *pp = buffer; + errno = old_errno; + return bu; + } + + /* Double the size of the buffer */ + bf += bs; + bs += bs; + if (!(nb = realloc(buffer, bs))) { + /* out of memory error */ + free(buffer); + return -1; + } + buffer = nb; + } +} + +ssize_t readfile(const char *filename, char **pp) +{ + FILE *f = fopen(filename, "r"); + ssize_t rv; + + if (!f) + return -1; + + rv = freadfile(f, pp); + + fclose(f); + + return rv; +} diff -puN /dev/null usr/kinit/README --- /dev/null +++ a/usr/kinit/README @@ -0,0 +1,9 @@ +kinit - tiny init program +------------------------- + +This program is intended for use as /sbin/init in an initramfs +environment. It currently replaces the kernel's ipconfig and nfsroot +code. + +-- +Bryan O'Sullivan (2003/05/05) diff -puN /dev/null usr/kinit/resume.c --- /dev/null +++ a/usr/kinit/resume.c @@ -0,0 +1,75 @@ +/* + * resume.c + * + * Handle resume from suspend-to-disk + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For CONFIG_PM_STD_PARTITION */ + +#include "kinit.h" +#include "do_mounts.h" + +#ifndef CONFIG_PM_STD_PARTITION +# define CONFIG_PM_STD_PARTITION "" +#endif + +int do_resume(int argc, char *argv[]) +{ + const char *resume_file = CONFIG_PM_STD_PARTITION; + const char *resume_arg; + dev_t resume_device; + int powerfd = -1; + char device_string[64]; + int len; + + resume_arg = get_arg(argc, argv, "resume="); + resume_file = resume_arg ? resume_arg : resume_file; + if (!resume_file[0]) + return 0; /* No resume device specified */ + + /* Fix: we either should consider reverting the device back to + ordinary swap, or (better) put that code into swapon */ + if (get_flag(argc, argv, "noresume")) + return 0; /* Noresume requested */ + + resume_device = name_to_dev_t(resume_file); + + if (major(resume_device) == 0) { + fprintf(stderr, "Invalid resume device: %s\n", resume_file); + goto failure; + } + + if ((powerfd = open("/sys/power/resume", O_WRONLY)) < 0) + goto fail_r; + + len = snprintf(device_string, sizeof device_string, "%u:%u", + major(resume_device), minor(resume_device)); + + if (len >= sizeof device_string) + goto fail_r; /* This should never happen */ + + DEBUG(("kinit: trying to resume from %s\n", resume_file)); + + if (write(powerfd, device_string, len) != len) + goto fail_r; + + /* Okay, what are we still doing alive... */ + failure: + if (powerfd >= 0) + close(powerfd); + fprintf(stderr, "Resume failed, doing normal boot...\n"); + return -1; + + fail_r: + fprintf(stderr, + "Resume failed: cannot write /sys/power/resume (no kernel support?)\n"); + goto failure; +} diff -puN /dev/null usr/kinit/run-init/Kbuild --- /dev/null +++ a/usr/kinit/run-init/Kbuild @@ -0,0 +1,25 @@ +# +# Kbuild file for run-init +# + +static-y := static/run-init +shared-y := shared/run-init + +# common .o files +objs := run-init.o runinitlib.o + +# TODO - do we want a stripped version +# TODO - do we want the static.g + shared.g directories? + +# Create built-in.o with all object files (used by kinit) +lib-y := $(objs) + +# .o files used to built executables +static/run-init-y := $(objs) +shared/run-init-y := $(objs) + +# Cleaning +clean-dirs := static shared + +# install binary +install-y := $(shared-y) diff -puN /dev/null usr/kinit/run-init/run-init.c --- /dev/null +++ a/usr/kinit/run-init/run-init.c @@ -0,0 +1,95 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2006 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * run-init.c + * + * Usage: exec run-init [-c /dev/console] /real-root /sbin/init "$@" + * + * This program should be called as the last thing in a shell script + * acting as /init in an initramfs; it does the following: + * + * - Delete all files in the initramfs; + * - Remounts /real-root onto the root filesystem; + * - Chroots; + * - Opens /dev/console; + * - Spawns the specified init program (with arguments.) + */ + +#include +#include +#include +#include +#include +#include "run-init.h" + +static const char *program; + +static void __attribute__ ((noreturn)) usage(void) +{ + fprintf(stderr, + "Usage: exec %s [-c consoledev] /real-root /sbin/init [args]\n", + program); + exit(1); +} + +int main(int argc, char *argv[]) +{ + /* Command-line options and defaults */ + const char *console = "/dev/console"; + const char *realroot; + const char *init; + const char *error; + char **initargs; + + /* Variables... */ + int o; + + /* Parse the command line */ + program = argv[0]; + + while ((o = getopt(argc, argv, "c:")) != -1) { + if (o == 'c') { + console = optarg; + } else { + usage(); + } + } + + if (argc - optind < 2) + usage(); + + realroot = argv[optind]; + init = argv[optind + 1]; + initargs = argv + optind + 1; + + error = run_init(realroot, console, init, initargs); + + /* If run_init returns, something went wrong */ + fprintf(stderr, "%s: %s: %s\n", program, error, strerror(errno)); + return 1; +} diff -puN /dev/null usr/kinit/run-init/run-init.h --- /dev/null +++ a/usr/kinit/run-init/run-init.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2006 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * run-init.h + */ + +#ifndef RUN_INIT_H +#define RUN_INIT_H + +const char *run_init(const char *realroot, const char *console, + const char *init, char **initargs); + +#endif diff -puN /dev/null usr/kinit/run-init/runinitlib.c --- /dev/null +++ a/usr/kinit/run-init/runinitlib.c @@ -0,0 +1,216 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2006 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * runinitlib.c + * + * run_init(consoledev, realroot, init, initargs) + * + * This function should be called as the last thing in kinit, + * from initramfs, it does the following: + * + * - Delete all files in the initramfs; + * - Remounts /real-root onto the root filesystem; + * - Chroots; + * - Opens /dev/console; + * - Spawns the specified init program (with arguments.) + * + * On failure, returns a human-readable error message. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "run-init.h" + +/* Make it possible to compile on glibc by including constants that the + always-behind shipped glibc headers may not include. Classic example + on why the lack of ABI headers screw us up. */ +#ifndef TMPFS_MAGIC +# define TMPFS_MAGIC 0x01021994 +#endif +#ifndef RAMFS_MAGIC +# define RAMFS_MAGIC 0x858458f6 +#endif +#ifndef MS_MOVE +# define MS_MOVE 8192 +#endif + +static int nuke(const char *what); + +static int nuke_dirent(int len, const char *dir, const char *name, dev_t me) +{ + int bytes = len + strlen(name) + 2; + char path[bytes]; + int xlen; + struct stat st; + + xlen = snprintf(path, bytes, "%s/%s", dir, name); + assert(xlen < bytes); + + if (lstat(path, &st)) + return ENOENT; /* Return 0 since already gone? */ + + if (st.st_dev != me) + return 0; /* DO NOT recurse down mount points!!!!! */ + + return nuke(path); +} + +/* Wipe the contents of a directory, but not the directory itself */ +static int nuke_dir(const char *what) +{ + int len = strlen(what); + DIR *dir; + struct dirent *d; + int err = 0; + struct stat st; + + if (lstat(what, &st)) + return errno; + + if (!S_ISDIR(st.st_mode)) + return ENOTDIR; + + if (!(dir = opendir(what))) { + /* EACCES means we can't read it. Might be empty and removable; + if not, the rmdir() in nuke() will trigger an error. */ + return (errno == EACCES) ? 0 : errno; + } + + while ((d = readdir(dir))) { + /* Skip . and .. */ + if (d->d_name[0] == '.' && + (d->d_name[1] == '\0' || + (d->d_name[1] == '.' && d->d_name[2] == '\0'))) + continue; + + err = nuke_dirent(len, what, d->d_name, st.st_dev); + if (err) { + closedir(dir); + return err; + } + } + + closedir(dir); + + return 0; +} + +static int nuke(const char *what) +{ + int rv; + int err = 0; + + rv = unlink(what); + if (rv < 0) { + if (errno == EISDIR) { + /* It's a directory. */ + err = nuke_dir(what); + if (!err) + err = rmdir(what) ? errno : err; + } else { + err = errno; + } + } + + if (err) { + errno = err; + return err; + } else { + return 0; + } +} + +const char *run_init(const char *realroot, const char *console, + const char *init, char **initargs) +{ + struct stat rst, cst, ist; + struct statfs sfs; + int confd; + + /* First, change to the new root directory */ + if (chdir(realroot)) + return "chdir to new root"; + + /* This is a potentially highly destructive program. Take some + extra precautions. */ + + /* Make sure the current directory is not on the same filesystem + as the root directory */ + if (stat("/", &rst) || stat(".", &cst)) + return "stat"; + + if (rst.st_dev == cst.st_dev) + return "current directory on the same filesystem as the root"; + + /* The initramfs should have /init */ + if (stat("/init", &ist) || !S_ISREG(ist.st_mode)) + return "can't find /init on initramfs"; + + /* Make sure we're on a ramfs */ + if (statfs("/", &sfs)) + return "statfs /"; + if (sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC) + return "rootfs not a ramfs or tmpfs"; + + /* Okay, I think we should be safe... */ + + /* Delete rootfs contents */ + if (nuke_dir("/")) + return "nuking initramfs contents"; + + /* Overmount the root */ + if (mount(".", "/", NULL, MS_MOVE, NULL)) + return "overmounting root"; + + /* chroot, chdir */ + if (chroot(".") || chdir("/")) + return "chroot"; + + /* Open /dev/console */ + if ((confd = open(console, O_RDWR)) < 0) + return "opening console"; + dup2(confd, 0); + dup2(confd, 1); + dup2(confd, 2); + close(confd); + + /* Spawn init */ + execv(init, initargs); + return init; /* Failed to spawn init */ +} diff -puN /dev/null usr/kinit/xpio.c --- /dev/null +++ a/usr/kinit/xpio.c @@ -0,0 +1,51 @@ +/* + * kinit/xpio.c + * + * Looping versions of pread() and pwrite() + */ + +#include +#include +#include + +ssize_t xpread(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t ctr = 0; + ssize_t rv = 0; + char *bp = buf; + + while (count) { + rv = pread(fd, bp, count, offset); + + if (rv == 0 || (rv == -1 && errno != EINTR)) + break; + + bp += rv; + count -= rv; + offset += rv; + ctr += rv; + } + + return ctr ? ctr : rv; +} + +ssize_t xpwrite(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t ctr = 0; + ssize_t rv = 0; + char *bp = buf; + + while (count) { + rv = pwrite(fd, bp, count, offset); + + if (rv == 0 || (rv == -1 && errno != EINTR)) + break; + + bp += rv; + count -= rv; + offset += rv; + ctr += rv; + } + + return ctr ? ctr : rv; +} diff -puN /dev/null usr/kinit/xpio.h --- /dev/null +++ a/usr/kinit/xpio.h @@ -0,0 +1,11 @@ +/* + * kinit/xpio.h + */ + +#ifndef KINIT_XPIO_H +#define KINIT_XPIO_H + +ssize_t xpread(int fd, void *buf, size_t count, off_t offset); +ssize_t xpwrite(int fd, void *buf, size_t count, off_t offset); + +#endif /* KINIT_XPIO_H */ diff -puN /dev/null usr/klibc/abort.c --- /dev/null +++ a/usr/klibc/abort.c @@ -0,0 +1,18 @@ +/* + * abort.c + */ + +#include +#include +#include + +void abort(void) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGABRT); + sigprocmask(SIG_UNBLOCK, &set, NULL); + raise(SIGABRT); + _exit(255); /* raise() should have killed us */ +} diff -puN /dev/null usr/klibc/alarm.c --- /dev/null +++ a/usr/klibc/alarm.c @@ -0,0 +1,25 @@ +/* + * alarm.c + */ + +#include +#include + +#ifndef __NR_alarm + +/* Emulate alarm() via setitimer() */ + +unsigned int alarm(unsigned int seconds) +{ + struct itimerval iv; + + iv.it_interval.tv_sec = iv.it_interval.tv_usec = 0; + iv.it_value.tv_sec = seconds; + iv.it_value.tv_usec = 0; + + setitimer(ITIMER_REAL, &iv, &iv); + + return iv.it_value.tv_sec + (iv.it_value.tv_usec ? 1 : 0); +} + +#endif diff -puN /dev/null usr/klibc/arch/alpha/crt0.S --- /dev/null +++ a/usr/klibc/arch/alpha/crt0.S @@ -0,0 +1,22 @@ +# +# arch/alpha/crt0.S +# + + .text + .type _start,@function + .ent _start, 0 + .globl _start +_start: + .frame $30, 0, $26, 0 + mov $31, $15 + br $29, 1f +1: ldgp $29, 0($29) + .prologue 0 + + lda $16, 0($30) # ELF data structure + lda $17, 0($0) # atexit pointer + + jsr $26, __libc_init + + .size _start,.-_start + .end _start diff -puN /dev/null usr/klibc/arch/alpha/divide.c --- /dev/null +++ a/usr/klibc/arch/alpha/divide.c @@ -0,0 +1,59 @@ +#include +#include +#include + +#if BITS == 64 +typedef uint64_t uint; +typedef int64_t sint; +#else +typedef uint32_t uint; +typedef int32_t sint; +#endif + +#ifdef SIGNED +typedef sint xint; +#else +typedef uint xint; +#endif + +xint NAME(uint num, uint den) +{ + uint quot = 0, qbit = 1; + int minus = 0; + xint v; + + if (den == 0) { + /* This is really $16, but $16 and $24 are exchanged by a script */ + register unsigned long cause asm("$24") = GEN_INTDIV; + asm volatile ("call_pal %0"::"i" (PAL_gentrap), "r"(cause)); + return 0; /* If trap returns... */ + } +#if SIGNED + if ((sint) (num ^ den) < 0) + minus = 1; + if ((sint) num < 0) + num = -num; + if ((sint) den < 0) + den = -den; +#endif + + /* Left-justify denominator and count shift */ + while ((sint) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + v = (xint) (REM ? num : quot); + if (minus) + v = -v; + return v; +} diff -puN /dev/null usr/klibc/arch/alpha/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/alpha/Makefile.inc @@ -0,0 +1,60 @@ +# -*- makefile -*- +# +# arch/alpha/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +# Special CFLAGS for the divide code +DIVCFLAGS = $(KLIBCREQFLAGS) $(KLIBCARCHREQFLAGS) \ + -O3 -fomit-frame-pointer -fcall-saved-1 -fcall-saved-2 \ + -fcall-saved-3 -fcall-saved-4 -fcall-saved-5 -fcall-saved-6 \ + -fcall-saved-7 -fcall-saved-8 -ffixed-15 -fcall-saved-16 \ + -fcall-saved-17 -fcall-saved-18 -fcall-saved-19 -fcall-saved-20 \ + -fcall-saved-21 -fcall-saved-22 -ffixed-23 -fcall-saved-24 \ + -ffixed-25 -ffixed-27 + +KLIBCARCHOBJS := arch/$(KLIBCARCH)/pipe.o arch/$(KLIBCARCH)/setjmp.o +KLIBCARCHOBJS += arch/$(KLIBCARCH)/syscall.o arch/$(KLIBCARCH)/sysdual.o + +DIVOBJS += arch/$(KLIBCARCH)/__divqu.o \ + arch/$(KLIBCARCH)/__remqu.o \ + arch/$(KLIBCARCH)/__divq.o \ + arch/$(KLIBCARCH)/__remq.o \ + arch/$(KLIBCARCH)/__divlu.o \ + arch/$(KLIBCARCH)/__remlu.o \ + arch/$(KLIBCARCH)/__divl.o \ + arch/$(KLIBCARCH)/__reml.o + +KLIBCARCHOBJS += $(DIVOBJS) + +quiet_cmd_regswap = REGSWAP $@ + cmd_regswap = sed -e 's/\$$0\b/$$27/g' -e 's/\$$24\b/$$99/g' \ + -e 's/\$$16\b/$$24/g' -e 's/\$$17\b/$$25/g' \ + -e 's/\$$26\b/$$23/g' -e 's/\$$99\b/$$16/g' < $< > $@ + +# Use static pattern rule to avoid using a temporary file +$(addprefix $(obj)/,$(DIVOBJS:.o=.S)): $(obj)/arch/$(KLIBCARCH)/%.S: \ + $(obj)/arch/$(KLIBCARCH)/%.ss + $(call if_changed,regswap) + +quiet_cmd_genss = DIV-CC $@ + cmd_genss = $(CC) $(DIVCFLAGS) $(FILE_CFLAGS) \ + -DNAME=$(basename $(notdir $@)) -S -o $@ $< + +$(obj)/arch/$(KLIBCARCH)/%.ss: $(obj)/arch/$(KLIBCARCH)/divide.c + $(call if_changed,genss) + +$(obj)/arch/$(KLIBCARCH)/__divqu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=0 -DBITS=64 +$(obj)/arch/$(KLIBCARCH)/__remqu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=1 -DBITS=64 +$(obj)/arch/$(KLIBCARCH)/__divq.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=0 -DBITS=64 +$(obj)/arch/$(KLIBCARCH)/__remq.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=1 -DBITS=64 +$(obj)/arch/$(KLIBCARCH)/__divlu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=0 -DBITS=32 +$(obj)/arch/$(KLIBCARCH)/__remlu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=1 -DBITS=32 +$(obj)/arch/$(KLIBCARCH)/__divl.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=0 -DBITS=32 +$(obj)/arch/$(KLIBCARCH)/__reml.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=1 -DBITS=32 + +targets += $(DIVOBJS:.o=.S) $(DIVOBJS:.o=.ss) +clean-files += $(DIVOBJS:.o=.S) $(DIVOBJS:.o=.ss) diff -puN /dev/null usr/klibc/arch/alpha/MCONFIG --- /dev/null +++ a/usr/klibc/arch/alpha/MCONFIG @@ -0,0 +1,16 @@ +# -*- makefile -*- +# +# arch/alpha/MCONFIG +# +# Build configuration for this architecture +# + +KLIBCOPTFLAGS = -Os +KLIBCBITSIZE = 64 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 7 GB - normal binaries start at 4.5 GB, and the stack is below +# the binary. +KLIBCSHAREDFLAGS = -Ttext 0x1c0000200 diff -puN /dev/null usr/klibc/arch/alpha/pipe.S --- /dev/null +++ a/usr/klibc/arch/alpha/pipe.S @@ -0,0 +1,38 @@ +# +# arch/alpha/pipe.S +# + +# +# pipe() on alpha returns both file descriptors in registers -- +# $0 (v0) and $20 (a4) respectively. This is unlike any other system call, +# as far as I can tell. +# + +#include +#include + + .text + .align 3 + .type pipe, @function + .ent pipe, 0 + .globl pipe +pipe: + .frame sp,0,ra,0 + lda v0, __NR_pipe + callsys + beq a3, 1f + br pv, 2f # pv <- pc +2: + ldgp gp, 0(pv) + lda a1, errno + lda v0, -1(zero) + stl a3, 0(a1) + ret zero,(ra),1 +1: + stl v0, 0(a0) + lda v0, 0 + stl a4, 4(a0) + ret zero,(ra),1 + + .size pipe,.-pipe + .end pipe diff -puN /dev/null usr/klibc/arch/alpha/README-gcc --- /dev/null +++ a/usr/klibc/arch/alpha/README-gcc @@ -0,0 +1,22 @@ + The current Alpha chips don't provide hardware for integer + division. The C compiler expects the functions + + __divqu: 64-bit unsigned long divide + __remqu: 64-bit unsigned long remainder + __divq/__remq: signed 64-bit + __divlu/__remlu: unsigned 32-bit + __divl/__reml: signed 32-bit + + These are not normal C functions: instead of the normal calling + sequence, these expect their arguments in registers t10 and t11, and + return the result in t12 (aka pv). Register AT may be clobbered + (assembly temporary), anything else must be saved. + + Furthermore, the return address is in t9 instead of ra. + + Normal function Divide functions + --------------- ---------------- + v0 ($0) t12/pv ($27) + a0 ($16) t10 ($24) + a1 ($17) t11 ($25) + ra ($26) t9 ($23) diff -puN /dev/null usr/klibc/arch/alpha/setjmp.S --- /dev/null +++ a/usr/klibc/arch/alpha/setjmp.S @@ -0,0 +1,75 @@ +# +# setjmp.S +# + +# +# The jmp_buf looks like: +# +# s0..5 +# fp +# ra +# gp +# sp +# + +#include + + .text + .align 3 + .type setjmp,@function + .ent setjmp, 0 + .globl setjmp +setjmp: + lda v0, 0(zero) + stq s0, 0(a0) + stq s1, 8(a0) + stq s2, 16(a0) + stq s3, 24(a0) + stq s4, 32(a0) + stq s5, 40(a0) + stq fp, 48(a0) + stq ra, 56(a0) + stq gp, 64(a0) + stq sp, 72(a0) + stt $f2, 80(a0) + stt $f3, 88(a0) + stt $f4, 96(a0) + stt $f5, 104(a0) + stt $f6, 112(a0) + stt $f7, 120(a0) + stt $f8, 128(a0) + stt $f9, 136(a0) + ret zero,(ra),1 + + .size setjmp,.-setjmp + .end setjmp + + .type longjmp,@function + .ent longjmp, 0 + .globl longjmp +longjmp: + mov a1, v0 + ldq s0, 0(a0) + ldq s1, 8(a0) + ldq s2, 16(a0) + ldq s3, 24(a0) + ldq s4, 32(a0) + ldq s5, 40(a0) + ldq fp, 48(a0) + ldq ra, 56(a0) + ldq gp, 64(a0) + ldq sp, 72(a0) + ldt $f2, 80(a0) + ldt $f3, 88(a0) + ldt $f4, 96(a0) + ldt $f5, 104(a0) + ldt $f6, 112(a0) + ldt $f7, 120(a0) + ldt $f8, 128(a0) + ldt $f9, 136(a0) + /* We're bound to get a mispredict here, but at least give us + a chance to get the return stack back in sync... */ + ret zero,(ra),1 + + .size longjmp,.-longjmp + .end longjmp diff -puN /dev/null usr/klibc/arch/alpha/syscall.S --- /dev/null +++ a/usr/klibc/arch/alpha/syscall.S @@ -0,0 +1,26 @@ +# +# arch/alpha/syscall.S +# + +#include + + .text + .align 3 + .type __syscall_common,@function + .ent __syscall_common, 0 + .globl __syscall_common +__syscall_common: + .frame sp,0,ra,0 + callsys + beq a3, 1f + br pv, 2f # pv <- pc +2: + ldgp gp, 0(pv) + lda a1, errno + stl v0, 0(a1) + lda v0, -1(zero) +1: + ret zero,(ra),1 + + .size __syscall_common,.-__syscall_common + .end __syscall_common diff -puN /dev/null usr/klibc/arch/alpha/sysdual.S --- /dev/null +++ a/usr/klibc/arch/alpha/sysdual.S @@ -0,0 +1,33 @@ +# +# arch/alpha/sysdual.S +# + +# +# Some system calls have an alternate return value in r20 (a4). +# This system call stub is for system calls where that is +# the "real" return value. +# + +#include + + .text + .align 3 + .type __syscall_dual1,@function + .ent __syscall_dual1, 0 + .globl __syscall_dual1 +__syscall_dual1: + .frame sp,0,ra,0 + callsys + mov v0, a4 + beq a3, 1f + br pv, 2f # pv <- pc +2: + ldgp gp, 0(pv) + lda a1, errno + lda v0, -1(zero) + stl a3, 0(a1) +1: + ret zero,(ra),1 + + .size __syscall_dual1,.-__syscall_dual1 + .end __syscall_dual1 diff -puN /dev/null usr/klibc/arch/alpha/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/alpha/sysstub.ph @@ -0,0 +1,37 @@ +# -*- perl -*- +# +# arch/alpha/sysstub.ph +# +# Script to generate system call stubs +# + +# On Alpha, most system calls follow the standard convention, with the +# system call number in r0 (v0), return an error value in r19 (a3) as +# well as the return value in r0 (v0). +# +# A few system calls are dual-return with the second return value in +# r20 (a4). + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + $stype = $stype || 'common'; + $stype = 'common' if ( $stype eq 'dual0' ); + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.ent\t${fname}, 0\n"; # What is this? + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT "\tlda\tv0, __NR_${sname}(zero)\n"; + print OUT "\tbr __syscall_${stype}\n"; + print OUT "\t.size\t${fname},.-${fname}\n"; + print OUT "\t.end\t${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/arm/aeabi_nonsense.S --- /dev/null +++ a/usr/klibc/arch/arm/aeabi_nonsense.S @@ -0,0 +1,9 @@ + .text + .globl __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + .globl __aeabi_unwind_cpp_pr1 +__aeabi_unwind_cpp_pr1: + .globl __aeabi_unwind_cpp_pr2 +__aeabi_unwind_cpp_pr2: + .globl __aeabi_unwind_cpp_pr3 +__aeabi_unwind_cpp_pr3: diff -puN /dev/null usr/klibc/arch/arm/crt0.S --- /dev/null +++ a/usr/klibc/arch/arm/crt0.S @@ -0,0 +1,23 @@ +# +# arch/arm/crt0.S +# +# void _start(void) +# { +# __libc_init(elf_structure, atexit_ptr); +# } +# + + .text + .balign 4 + .type _start,#function + .globl _start + +#ifdef __thumb__ + .thumb_func +#endif + +_start: mov r0, sp + mov r1, #0 + bl __libc_init + + .size _start,.-_start diff -puN /dev/null usr/klibc/arch/arm/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/arm/Makefile.inc @@ -0,0 +1,23 @@ +# -*- makefile -*- +# +# arch/arm/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/arm/setjmp.o \ + arch/arm/syscall.o \ + arch/arm/vfork.o \ + arch/arm/aeabi_nonsense.o \ + libgcc/__udivmodsi4.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o \ + libgcc/__clzsi2.o \ + + diff -puN /dev/null usr/klibc/arch/arm/MCONFIG --- /dev/null +++ a/usr/klibc/arch/arm/MCONFIG @@ -0,0 +1,36 @@ +# -*- makefile -*- +# +# arch/arm/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +CPU_ARCH := armv4 +CPU_TUNE := strongarm + +KLIBCOPTFLAGS = -Os -march=$(CPU_ARCH) -mtune=$(CPU_TUNE) +KLIBCBITSIZE = 32 +KLIBCREQFLAGS = -fno-exceptions +KLIBCSTRIPFLAGS += -R .ARM.exidx + +ifeq ($(CONFIG_KLIBC_THUMB),y) +CPU_ARCH := $(CPU_ARCH)t +KLIBCREQFLAGS += -mthumb +KLIBCLDFLAGS += --thumb-entry _start +KLIBCEMAIN = --thumb-entry _start +KLIBCREQFLAGS += -mabi=aapcs-linux +KLIBCSHAREDFLAGS = -Ttext 0x380200 +else +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +KLIBCSHAREDFLAGS = -Ttext 0x01800200 +ifeq ($(CONFIG_AEABI),y) +KLIBCREQFLAGS += -mabi=aapcs-linux -mno-thumb-interwork +else +KLIBCREQFLAGS += -mabi=apcs-gnu -mno-thumb-interwork +endif +endif + diff -puN /dev/null usr/klibc/arch/arm/__muldi3.c --- /dev/null +++ a/usr/klibc/arch/arm/__muldi3.c @@ -0,0 +1,15 @@ +#include + +uint64_t __muldi3(uint64_t a, uint64_t b) +{ + uint32_t al = (uint32_t)a; + uint32_t ah = (uint32_t)(a >> 32); + uint32_t bl = (uint32_t)b; + uint32_t bh = (uint32_t)(b >> 32); + uint64_t v; + + v = (uint64_t)al * bl; + v += (uint64_t)(al*bh+ah*bl) << 32; + + return v; +} diff -puN /dev/null usr/klibc/arch/arm/setjmp.S --- /dev/null +++ a/usr/klibc/arch/arm/setjmp.S @@ -0,0 +1,102 @@ +# +# arch/arm/setjmp.S +# +# setjmp/longjmp for the ARM architecture +# + +#ifndef __thumb__ + +# +# "Pure ARM" version +# +# The jmp_buf is assumed to contain the following, in order: +# r4 +# r5 +# r6 +# r7 +# r8 +# r9 +# r10 +# fp +# sp +# lr +# + + .text + .balign 4 + .globl setjmp + .type setjmp, #function +setjmp: + stmia r0, {r4, r5, r6, r7, r8, r9, r10, fp, sp, lr} + mov r0, #0 + mov pc, lr + .size setjmp,.-setjmp + + .text + .balign 4 + .globl longjmp + .type longjmp, #function +longjmp: + ldmia r0, {r4, r5, r6, r7, r8, r9, r10, fp, sp, lr} + mov r0, r1 + mov pc, lr + .size longjmp,.-longjmp + +#else /* __thumb__ */ + +# +# Thumb version +# +# The jmp_buf is assumed to contain the following, in order: +# lr +# r4 +# r5 +# r6 +# r7 +# r8 +# r9 +# r10 +# fp +# sp +# + + .text + .balign 4 + .globl setjmp + .type setjmp, #function + .thumb_func +setjmp: + mov r3, lr + stmia r0!, {r3, r4, r5, r6, r7} + mov r3, r8 + mov r4, r9 + mov r5, r10 + mov r6, fp + mov r7, sp + stmia r0!, {r3, r4, r5, r6, r7} + mov r0, #0 + mov pc, lr + .size setjmp,.-setjmp + + .text + .balign 4 + .globl longjmp + .type longjmp, #function + .thumb_func +longjmp: + mov r2, r0 + add r0, #5*4 + ldmia r0!, {r3, r4, r5, r6, r7} + mov r8, r3 + mov r9, r4 + mov r10, r5 + mov fp, r6 + mov sp, r7 + ldmia r2!, {r3, r4, r5, r6, r7} + mov r0, r1 + bne 1f + mov r0, #1 +1: mov pc, r3 + .size longjmp,.-longjmp + +#endif /* __thumb__ */ diff -puN /dev/null usr/klibc/arch/arm/syscall.S --- /dev/null +++ a/usr/klibc/arch/arm/syscall.S @@ -0,0 +1,61 @@ +/* + * arch/arm/syscall.S + * + * System call common handling + */ + + .type __syscall_common,#function + .globl __syscall_common +#ifndef __thumb__ + /* ARM version - this is executed after the swi, unless + we are compiled in EABI mode */ + + .balign 4 +__syscall_common: +#ifdef __ARM_EABI__ + ldr r4, [sp,#16] + ldr r5, [sp,#20] + ldr r7, [lr] + swi 0 +#endif + cmn r0, #4096 + rsbcs r2, r0, #0 + ldrcs r3, 1f + mvncs r0, #0 + strcs r2, [r3] + ldmfd sp!,{r4,r5,r7,pc} + + .balign 4 +1: + .word errno + +#else + /* Thumb version - must still load r4 and r5 and run swi */ + + .thumb_func + .balign 2 +__syscall_common: + mov r7, lr + ldr r4, [sp,#16] + sub r7, #1 /* Remove the Thumb bit */ + ldr r5, [sp,#20] + ldrh r7, [r7] + swi 0 + ldr r1, 2f + cmp r0, r1 + bcc 1f + ldr r1, 3f + neg r2, r0 + mov r0, #1 + str r2, [r1] + neg r0, r0 +1: + pop {r4,r5,r7,pc} + + .balign 4 +2: + .word -4095 +3: + .word errno + +#endif diff -puN /dev/null usr/klibc/arch/arm/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/arm/sysstub.ph @@ -0,0 +1,58 @@ +# -*- perl -*- +# +# arch/arm/sysstub.ph +# +# Script to generate system call stubs +# + + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "#include \n"; + + print OUT " .text\n"; + print OUT " .type ${fname}, #function\n"; + print OUT " .globl ${fname}\n"; + + print OUT "#ifndef __thumb__\n"; + + print OUT "#ifndef __ARM_EABI__\n"; + + # ARM version first + print OUT " .balign 4\n"; + print OUT "${fname}:\n"; + print OUT " stmfd sp!,{r4,r5,lr}\n"; + print OUT " ldr r4,[sp,#12]\n"; + print OUT " ldr r5,[sp,#16]\n"; + print OUT " swi # __NR_${sname}\n"; + print OUT " b __syscall_common\n"; + + print OUT "#else /* __ARM_EABI__ */\n"; + + # ARM EABI version + print out " .balign 4\n"; + print OUT "${fname}:\n"; + print OUT " stmfd sp!,{r4,r5,r7,lr}\n"; + print OUT " bl __syscall_common\n"; + print OUT " .word __NR_${sname}\n"; + + print OUT "#endif /* __ARM_EABI__ */\n"; + print OUT "#else /* __thumb__ */\n"; + + # Thumb version + print OUT " .balign 8\n"; + print OUT " .thumb_func\n"; + print OUT "${fname}:\n"; + print OUT " push {r4,r5,r7,lr}\n"; + print OUT " bl __syscall_common\n"; + print OUT " .short __NR_${sname}\n"; + + print OUT "#endif /* __thumb__*/\n"; + + print OUT " .size __syscall${i},.-__syscall${i}\n"; +} + +1; diff -puN /dev/null usr/klibc/arch/arm/vfork.S --- /dev/null +++ a/usr/klibc/arch/arm/vfork.S @@ -0,0 +1,60 @@ +/* + * arch/arm/vfork.S + * + * vfork - nasty system call which must not use the stack. + */ + +#include + + .type vfork,#function + .globl vfork +#ifndef __thumb__ + + .balign 4 +vfork: +#ifdef __ARM_EABI__ + mov r3, r7 + mov r7, # __NR_vfork + swi 0 + mov r7, r3 +#else + swi # __NR_vfork +#endif + cmn r0, #4096 + rsbcs r2, r0, #0 + ldrcs r3, 1f + mvncs r0, #0 + strcs r2, [r3] + mov pc, lr + + .balign 4 +1: + .word errno + +#else + + .thumb_func + .balign 2 +vfork: + mov r3, r7 + mov r7, # __NR_vfork + swi 0 + mov r7, r3 + ldr r1, 2f + cmp r0, r1 + bcc 1f + ldr r1, 3f + neg r2, r0 + mov r0, #1 + str r2, [r1] + neg r0, r0 +1: + mov pc, lr + + .balign 4 +2: + .word -4095 +3: + .word errno + +#endif diff -puN /dev/null usr/klibc/arch/cris/crt0.S --- /dev/null +++ a/usr/klibc/arch/cris/crt0.S @@ -0,0 +1,27 @@ +# +# arch/cris/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .balign 4 + .type _start,@function + .globl _start +_start: + /* Save the address of the ELF argument array */ + move.d $sp,$r10 /* Address of ELF arguments */ + + /* atexit() function (assume null) */ + moveq 0,$r11 + + /* Set up a dummy stack frame to keep gcc from getting confused */ + push $r11 + push $r11 + jump __libc_init + + .size _start, .-_start diff -puN /dev/null usr/klibc/arch/cris/divide.c --- /dev/null +++ a/usr/klibc/arch/cris/divide.c @@ -0,0 +1,99 @@ +#include +#include + +#if BITS == 64 +typedef uint64_t unum; +typedef int64_t snum; +#else +typedef uint32_t unum; +typedef int32_t snum; +#endif + +#ifdef SIGNED +typedef snum xnum; +#else +typedef unum xnum; +#endif + +#ifdef __cris__ +static inline unum __attribute__ ((const))dstep(unum rs, unum rd) +{ + asm("dstep %1,%0": "+r"(rd):"r"(rs)); + return rd; +} + +static inline unum __attribute__ ((const))lz(unum rs) +{ + unum rd; + asm("lz %1,%0": "=r"(rd):"r"(rs)); + return rd; +} + +#else +/* For testing */ +static inline unum __attribute__ ((const))dstep(unum rs, unum rd) +{ + rd <<= 1; + if (rd >= rs) + rd -= rs; + + return rd; +} + +static inline unum __attribute__ ((const))lz(unum rs) +{ + unum rd = 0; + while (rs >= 0x7fffffff) { + rd++; + rs <<= 1; + } + return rd; +} + +#endif + +xnum NAME(unum num, unum den) +{ + unum quot = 0, qbit = 1; + int minus = 0; + xnum v; + + if (den == 0) { + raise(SIGFPE); + return 0; /* If signal ignored... */ + } + + if (den == 1) + return (xnum) (REM ? 0 : num); + +#if SIGNED + if ((snum) (num ^ den) < 0) + minus = 1; + if ((snum) num < 0) + num = -num; + if ((snum) den < 0) + den = -den; +#endif + + den--; + + /* Left-justify denominator and count shift */ + while ((snum) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + v = (xnum) (REM ? num : quot); + if (minus) + v = -v; + return v; +} diff -puN /dev/null usr/klibc/arch/cris/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/cris/Makefile.inc @@ -0,0 +1,34 @@ +# -*- makefile -*- +# +# arch/cris/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/__Umod.o \ + arch/$(KLIBCARCH)/__Udiv.o \ + arch/$(KLIBCARCH)/__Mod.o \ + arch/$(KLIBCARCH)/__Div.o \ + arch/$(KLIBCARCH)/__negdi2.o \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + arch/$(KLIBCARCH)/vfork.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + +arch/$(KLIBCARCH)/__Umod.o: arch/$(KLIBCARCH)/divide.c + $(CC) $(CFLAGS) -DSIGNED=0 -DREM=1 -DBITS=32 -DNAME=__Umod -c -o $@ $< +arch/$(KLIBCARCH)/__Udiv.o: arch/$(KLIBCARCH)/divide.c + $(CC) $(CFLAGS) -DSIGNED=0 -DREM=0 -DBITS=32 -DNAME=__Udiv -c -o $@ $< +arch/$(KLIBCARCH)/__Mod.o: arch/$(KLIBCARCH)/divide.c + $(CC) $(CFLAGS) -DSIGNED=1 -DREM=1 -DBITS=32 -DNAME=__Mod -c -o $@ $< +arch/$(KLIBCARCH)/__Div.o: arch/$(KLIBCARCH)/divide.c + $(CC) $(CFLAGS) -DSIGNED=1 -DREM=0 -DBITS=32 -DNAME=__Div -c -o $@ $< + +archclean: diff -puN /dev/null usr/klibc/arch/cris/MCONFIG --- /dev/null +++ a/usr/klibc/arch/cris/MCONFIG @@ -0,0 +1,26 @@ +# -*- makefile -*- +# +# arch/cris/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os -fomit-frame-pointer +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 224 MB - normal binaries start at 0 +# (lib?)gcc on cris seems to insist on producing .init and .fini sections +KLIBCSHAREDFLAGS = --section-start .init=0x0e000100 + +# The CRIS compiler needs an -iprefix to find libgcc includes when +# nostdinc is used. It also needs -mlinux to compile linux applications. +INCLUDE_PREFIX = $(shell $(CC) -print-libgcc-file-name | sed -e s/libgcc.a//) +KLIBCARCHREQFLAGS = -iprefix $(INCLUDE_PREFIX) -mlinux + +# Special flags needed for linking +KLIBCLDFLAGS += -mcrislinux diff -puN /dev/null usr/klibc/arch/cris/__negdi2.S --- /dev/null +++ a/usr/klibc/arch/cris/__negdi2.S @@ -0,0 +1,25 @@ +/* + * arch/cris/__negdi2.c + */ + +/* + * In 2's complement arithmetric, -x == (~x + 1), so + * -{h,l} = (~{h,l} + {0,1) + * -{h,l} = {~h,~l} + {0,1} + * -{h,l} = {~h + cy, ~l + 1} + * ... where cy = (l == 0) + * -{h,l} = {~h + cy, -l} + */ + + .text + .balign 4 + .type __negdi2,@function + .globl __negdi2 +__negdi2: + neg.d $r10,$r10 + seq $r12 + not $r11 + ret + add.d $r12,$r11 + + .size __negdi2, .-__negdi2 diff -puN /dev/null usr/klibc/arch/cris/setjmp.S --- /dev/null +++ a/usr/klibc/arch/cris/setjmp.S @@ -0,0 +1,37 @@ +# +# arch/cris/setjmp.S +# +# setjmp/longjmp for the cris architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# $r8..$r0 (in that order) +# $sp ($r14) +# return address +# + + .text + .balign 4 + .globl setjmp + .type setjmp, @function +setjmp: + movem $r8,[$r10+] /* Save $r8..$r0 at $r10... */ + move.d $sp,[$r10+] + move $srp,[$r10] + ret + moveq 0,$r10 + + .size setjmp,.-setjmp + + .text + .balign 4 + .globl longjmp + .type longjmp, @function +longjmp: + movem [$r10+],$r8 /* Load $r8..$r0 from $r10... */ + move.d [$r10+],$sp + jump [$r10] + move.d $r11,$r10 + + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/cris/syscall.S --- /dev/null +++ a/usr/klibc/arch/cris/syscall.S @@ -0,0 +1,30 @@ +/* + * arch/cris/syscall.S + * + * On cris, r9 contains the syscall number (set by generated stub); + * r10..r13 contain arguments 0-3 per the standard calling convention, + * and arguments 4-5 are passed in $mof and $srp; however, we have + * to save $srp around the system call. + */ + + .section ".text","ax" + .balign 4 + .globl __syscall_common + .type __syscall_common,@function +__syscall_common: + push $srp + move [$sp+4],$mof + move [$sp+8],$srp + break 13 + + cmps.w -4096,$r10 + blo 1f + neg.d $r10,$r11 + move.d $r11,[errno] + moveq -1,$r10 +1: + pop $srp + ret + nop + + .size __syscall_common,.-__syscall_common diff -puN /dev/null usr/klibc/arch/cris/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/cris/sysstub.ph @@ -0,0 +1,29 @@ +# -*- perl -*- +# +# arch/cris/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.type\t${fname},\@function\n"; + print OUT "\t.globl\t${fname}\n"; + print OUT "\t.balign\t4\n"; + print OUT "${fname}:\n"; + print OUT "#if __NR_${sname} <= 31\n"; + print OUT "\t moveq\t__NR_${sname}, \$r9\n"; + print OUT "#else\n"; + print OUT "\t move.d\t__NR_${sname}, \$r9\n"; + print OUT "#endif\n"; + print OUT "\tjump\t__syscall_common\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/cris/vfork.S --- /dev/null +++ a/usr/klibc/arch/cris/vfork.S @@ -0,0 +1,29 @@ +/* + * arch/cris/vfork.S + * + * On cris, r9 contains the syscall number (set by generated stub); + * r10..r13 contain arguments 0-3 per the standard calling convention. + * The return address is in $srp; so we just need to avoid the stack + * usage of the normal syscall stubs. + */ + +#include + + .section ".text","ax" + .balign 4 + .globl vfork + .type vfork,@function +vfork: + move.d __NR_vfork, $r9 + break 13 + + cmps.w -4096,$r10 + blo 1f + neg.d $r10,$r11 + move.d $r11,[errno] + moveq -1,$r10 +1: + ret + nop + + .size vfork,.-vfork diff -puN /dev/null usr/klibc/arch/i386/crt0.S --- /dev/null +++ a/usr/klibc/arch/i386/crt0.S @@ -0,0 +1,31 @@ +# +# arch/i386/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + # Save the address of the ELF argument array + movl %esp,%eax # Address of ELF arguments + # Set up a faux stack frame for the benefit of gdb + xorl %ebp,%ebp + push %ebp # Keep gdb from getting confused + push %ebp # Keep gdb from getting confused + # Push the arguments and called __libc_init() +#ifndef _REGPARM + push %edx # atexit() function + push %eax # ELF array +#endif + call __libc_init + # If __libc_init returns, problem... + hlt + + .size _start, .-_start diff -puN /dev/null usr/klibc/arch/i386/libgcc/__ashldi3.S --- /dev/null +++ a/usr/klibc/arch/i386/libgcc/__ashldi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashldi3.S + * + * 64-bit shl + */ + .text + .align 4 + .globl __ashldi3 + .type __ashldi3,@function +__ashldi3: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shldl %cl,%eax,%edx + shl %cl,%eax + ret + +1: + xorl %edx,%edx + shl %cl,%eax + xchgl %edx,%eax + ret + + .size __ashldi3,.-__ashldi3 diff -puN /dev/null usr/klibc/arch/i386/libgcc/__ashrdi3.S --- /dev/null +++ a/usr/klibc/arch/i386/libgcc/__ashrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashrdi3.S + * + * 64-bit sar + */ + .text + .align 4 + .globl __ashrdi3 + .type __ashrdi3,@function +__ashrdi3: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + sarl %cl,%edx + ret + +1: + sarl %cl,%edx + movl %edx,%eax + cdq + ret + + .size __ashrdi3,.-__ashrdi3 diff -puN /dev/null usr/klibc/arch/i386/libgcc/__lshrdi3.S --- /dev/null +++ a/usr/klibc/arch/i386/libgcc/__lshrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__lshrdi3.S + * + * 64-bit shr + */ + .text + .align 4 + .globl __lshrdi3 + .type __lshrdi3,@function +__lshrdi3: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + shrl %cl,%edx + ret + +1: + shrl %cl,%edx + xorl %eax,%eax + xchgl %edx,%eax + ret + + .size __lshrdi3,.-__lshrdi3 diff -puN /dev/null usr/klibc/arch/i386/libgcc/__muldi3.S --- /dev/null +++ a/usr/klibc/arch/i386/libgcc/__muldi3.S @@ -0,0 +1,34 @@ +/* + * arch/i386/libgcc/__muldi3.S + * + * 64*64 = 64 bit unsigned multiplication + */ + + .text + .align 4 + .globl __muldi3 + .type __muldi3,@function +__muldi3: + push %esi +#ifndef _REGPARM + movl 8(%esp),%eax + movl %eax,%esi + movl 16(%esp),%ecx + mull %ecx + imull 12(%esp),%ecx + imull 20(%esp),%esi + addl %ecx,%edx + addl %esi,%edx +#else + movl %eax,%esi + push %edx + mull %ecx + imull 8(%esp),%esi + addl %esi,%edx + pop %esi + imull %esi,%ecx + addl %ecx,%edx +#endif + pop %esi + ret + .size __muldi3,.-__muldi3 diff -puN /dev/null usr/klibc/arch/i386/libgcc/__negdi2.S --- /dev/null +++ a/usr/klibc/arch/i386/libgcc/__negdi2.S @@ -0,0 +1,21 @@ +/* + * arch/i386/libgcc/__negdi2.S + * + * 64-bit negation + */ + + .text + .align 4 + .globl __negdi2 + .type __negdi2,@function +__negdi2: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx +#endif + negl %edx + negl %eax + sbbl $0,%edx + ret + + .size __negdi2,.-__negdi2 diff -puN /dev/null usr/klibc/arch/i386/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/i386/Makefile.inc @@ -0,0 +1,30 @@ +# -*- makefile -*- +# +# arch/i386/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/socketcall.o \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + arch/$(KLIBCARCH)/varsyscall.o \ + arch/$(KLIBCARCH)/open.o \ + arch/$(KLIBCARCH)/openat.o \ + arch/$(KLIBCARCH)/sigreturn.o \ + arch/$(KLIBCARCH)/vfork.o \ + arch/$(KLIBCARCH)/libgcc/__ashldi3.o \ + arch/$(KLIBCARCH)/libgcc/__ashrdi3.o \ + arch/$(KLIBCARCH)/libgcc/__lshrdi3.o \ + arch/$(KLIBCARCH)/libgcc/__muldi3.o \ + arch/$(KLIBCARCH)/libgcc/__negdi2.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + +archclean: diff -puN /dev/null usr/klibc/arch/i386/MCONFIG --- /dev/null +++ a/usr/klibc/arch/i386/MCONFIG @@ -0,0 +1,33 @@ +# -*- makefile -*- +# +# arch/i386/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +# Enable this to compile with register parameters; only safe for +# gcc >= 3 + +ifeq ($(CONFIG_REGPARM),y) +REGPARM_OPT := -mregparm=3 -D_REGPARM=3 +endif + +gcc_align_option := $(call cc-option, \ + -falign-functions=0 -falign-jumps=0 -falign-loops=0, \ + -malign-functions=0 -malign-jumps=0 -malign-loops=0) +gcc_m32_option := $(call cc-option, -m32, ) + +KLIBCOPTFLAGS = -march=i386 -Os -g -fomit-frame-pointer $(gcc_align_option) +KLIBCLDFLAGS = -m elf_i386 +KLIBCREQFLAGS += $(REGPARM_OPT) +KLIBCARCHREQFLAGS += $(gcc_m32_option) + +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 96 MB - normal binaries start at 128 MB +KLIBCSHAREDFLAGS = -Ttext 0x06000200 diff -puN /dev/null usr/klibc/arch/i386/openat.S --- /dev/null +++ a/usr/klibc/arch/i386/openat.S @@ -0,0 +1,26 @@ +/* + * arch/i386/openat.S + * + * Handle the openat() system call - oddball due to the varadic + * prototype, which forces the use of the cdecl calling convention, + * and the need for O_LARGEFILE. + */ + +#include + +/* , despite the name, isn't assembly-safe */ +#define O_LARGEFILE 0100000 + +#ifdef __NR_openat /* Don't build if kernel headers too old */ + + .globl openat + .type openat,@function + +openat: + orl $O_LARGEFILE,12(%esp) + pushl $__NR_openat + jmp __syscall_varadic + + .size openat,.-openat + +#endif diff -puN /dev/null usr/klibc/arch/i386/open.S --- /dev/null +++ a/usr/klibc/arch/i386/open.S @@ -0,0 +1,29 @@ +/* + * arch/i386/open.S + * + * Handle the open() system call - oddball due to the varadic + * prototype, which forces the use of the cdecl calling convention, + * and the need for O_LARGEFILE. + */ + +#include + +/* , despite the name, isn't assembly-safe */ +#define O_LARGEFILE 0100000 + + .globl open + .type open,@function + +open: +#ifdef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx + orl $O_LARGEFILE,%edx +#else + orl $O_LARGEFILE,8(%esp) +#endif + pushl $__NR_open + jmp __syscall_common + + .size open,.-open diff -puN /dev/null usr/klibc/arch/i386/setjmp.S --- /dev/null +++ a/usr/klibc/arch/i386/setjmp.S @@ -0,0 +1,58 @@ +# +# arch/i386/setjmp.S +# +# setjmp/longjmp for the i386 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# %ebx +# %esp +# %ebp +# %esi +# %edi +# +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: +#ifdef _REGPARM + movl %eax,%edx +#else + movl 4(%esp),%edx +#endif + popl %ecx # Return address, and adjust the stack + xorl %eax,%eax # Return value + movl %ebx,(%edx) + movl %esp,4(%edx) # Post-return %esp! + pushl %ecx # Make the call/return stack happy + movl %ebp,8(%edx) + movl %esi,12(%edx) + movl %edi,16(%edx) + movl %ecx,20(%edx) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: +#ifdef _REGPARM + xchgl %eax,%edx +#else + movl 4(%esp),%edx # jmp_ptr address + movl 8(%esp),%eax # Return value +#endif + movl (%edx),%ebx + movl 4(%edx),%esp + movl 8(%edx),%ebp + movl 12(%edx),%esi + movl 16(%edx),%edi + jmp *20(%edx) + + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/i386/sigreturn.S --- /dev/null +++ a/usr/klibc/arch/i386/sigreturn.S @@ -0,0 +1,15 @@ +# +# arch/i386/sigreturn.S +# + +#include + + .text + .align 4 + .globl __sigreturn + .type __sigreturn,@function +__sigreturn: + pop %eax # Have no idea why this is needed... + movl $__NR_sigreturn,%eax + int $0x80 + .size __sigreturn,.-__sigreturn diff -puN /dev/null usr/klibc/arch/i386/socketcall.S --- /dev/null +++ a/usr/klibc/arch/i386/socketcall.S @@ -0,0 +1,55 @@ +# +# socketcall.S +# +# Socketcalls use the following convention: +# %eax = __NR_socketcall +# %ebx = socketcall number +# %ecx = pointer to arguments (up to 6) +# + +#include + +#ifdef __i386__ + + .text + .align 4 + .globl __socketcall_common + .type __socketcall_common, @function + +__socketcall_common: + xchgl %ebx,(%esp) # The stub passes the socketcall # on stack + +#ifdef _REGPARM + pushl 16(%esp) # Arg 6 + pushl 16(%esp) # Arg 5 + pushl 16(%esp) # Arg 4 + pushl %ecx + pushl %edx + pushl %eax + movl %esp,%ecx +#else + leal 8(%esp),%ecx # Arguments already contiguous on-stack +#endif + + movl $__NR_socketcall,%eax + int $0x80 + +#ifdef _REGPARM + addl $6*4, %esp +#endif + + cmpl $-4095,%eax # Error return? + + popl %ebx + + jb 1f + + negl %eax + movl %eax,errno + orl $-1,%eax # Return -1 +1: + ret + + .size __socketcall_common,.-__socketcall_common + +#endif diff -puN /dev/null usr/klibc/arch/i386/syscall.S --- /dev/null +++ a/usr/klibc/arch/i386/syscall.S @@ -0,0 +1,69 @@ +/* + * arch/i386/syscall.S + * + * Common tail-handling code for system calls. + * + * The arguments are on the stack; the system call number in %eax. + */ + +#define ARG(n) (4*n+20)(%esp) + + .text + .align 4 + .globl __syscall_common + .type __syscall_common,@function +__syscall_common: +#ifdef _REGPARM + xchgl %ebx,(%esp) +#else + popl %eax + pushl %ebx +#endif + pushl %esi + pushl %edi + pushl %ebp + +#ifdef _REGPARM + xchgl %eax,%ebx + xchgl %ecx,%edx + movl ARG(0),%esi + movl ARG(1),%edi + movl ARG(2),%ebp +#else + movl ARG(0),%ebx # Syscall arguments + movl ARG(1),%ecx + movl ARG(2),%edx + movl ARG(3),%esi + movl ARG(4),%edi + movl ARG(5),%ebp +#endif + .globl __syscall_common_tail +__syscall_common_tail: + int $0x80 + + cmpl $-4095,%eax + + popl %ebp + popl %edi + popl %esi + popl %ebx + + jb 1f + + # Error return, must set errno + negl %eax + movl %eax,errno + orl $-1,%eax # Return -1 + +1: + ret + + .size __syscall_common,.-__syscall_common + +#ifndef _REGPARM + + .globl __syscall_varadic + .type __syscall_varadic,@function +__syscall_varadic = __syscall_common + +#endif diff -puN /dev/null usr/klibc/arch/i386/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/i386/sysstub.ph @@ -0,0 +1,26 @@ +# -*- perl -*- +# +# arch/i386/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + + $stype = 'common' if ( $stype eq '' ); + + print OUT "\tpushl \$__NR_${sname}\n"; + print OUT "\tjmp __syscall_$stype\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/i386/varsyscall.S --- /dev/null +++ a/usr/klibc/arch/i386/varsyscall.S @@ -0,0 +1,36 @@ +/* + * arch/i386/varsyscall.S + * + * Common tail-handling code for varadic system calls (which always + * use the cdecl convention.) + * + * The arguments are on the stack; the system call number in %eax. + */ + +#ifdef _REGPARM + +#define ARG(n) (4*n+20)(%esp) + + .text + .align 4 + .globl __syscall_varadic + .type __syscall_varadic,@function +__syscall_varadic: + popl %eax + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + + movl ARG(0),%ebx # Syscall arguments + movl ARG(1),%ecx + movl ARG(2),%edx + movl ARG(3),%esi + movl ARG(4),%edi + movl ARG(5),%ebp + + jmp __syscall_common_tail + + .size __syscall_varadic,.-__syscall_varadic + +#endif diff -puN /dev/null usr/klibc/arch/i386/vfork.S --- /dev/null +++ a/usr/klibc/arch/i386/vfork.S @@ -0,0 +1,26 @@ +# +# usr/klibc/arch/i386/vfork.S +# +# vfork is nasty - there must be nothing at all on the stack above +# the stack frame of the enclosing function. +# + +#include + + .text + .align 4 + .globl vfork + .type vfork, @function +vfork: + popl %edx /* Return address */ + movl $__NR_vfork, %eax + int $0x80 + pushl %edx + cmpl $-4095, %eax + jae 1f + ret +1: + negl %eax + movl %eax, errno + orl $-1, %eax + ret diff -puN /dev/null usr/klibc/arch/ia64/crt0.S --- /dev/null +++ a/usr/klibc/arch/ia64/crt0.S @@ -0,0 +1,27 @@ + +#include + + .align 32 + .global _start + + .proc _start + .type _start,@function +_start: + .prologue + .save rp, r0 + + alloc r2 = ar.pfs,0,0,2,0 + movl r3 = FPSR_DEFAULT + ;; + adds out0= 16,sp /* argc pointer */ + movl gp = @gprel(0f) +0: mov r9 = ip + ;; + sub gp = r9, gp /* back-compute gp value */ + + .body + br.call.sptk.few rp = __libc_init + ;; + break 0 /* break miserably if we ever return */ + + .endp _start diff -puN /dev/null usr/klibc/arch/ia64/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/ia64/Makefile.inc @@ -0,0 +1,26 @@ +# -*- makefile -*- +# +# arch/ia64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/vfork.o \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/pipe.o \ + arch/$(KLIBCARCH)/syscall.o \ + libgcc/__divdi3.o \ + libgcc/__divsi3.o \ + libgcc/__udivdi3.o \ + libgcc/__udivsi3.o \ + libgcc/__umodsi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmodsi4.o \ + libgcc/__udivmoddi4.o + +KLIBCARCHSOOBJS = $(patsubst %o,%.lo,%(KLIBCARCHOBJS)) + +archclean: diff -puN /dev/null usr/klibc/arch/ia64/MCONFIG --- /dev/null +++ a/usr/klibc/arch/ia64/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/ia64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os +KLIBCBITSIZE = 64 diff -puN /dev/null usr/klibc/arch/ia64/pipe.c --- /dev/null +++ a/usr/klibc/arch/ia64/pipe.c @@ -0,0 +1,41 @@ +/* + * pipe.c + */ + +#include +#include + +#define ASM_CLOBBERS ,"out2", "out3", "out4", "out5", "out6", "out7", \ + /* Non-stacked integer registers, minus r8, r9, r10, r15. */ \ + "r2", "r3", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \ + "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \ + "r28", "r29", "r30", "r31", \ + /* Predicate registers. */ \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + /* Non-rotating fp registers. */ \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + /* Branch registers. */ \ + "b6", "b7" + +int pipe(int *filedes) +{ + register long _r8 asm("r8"); + register long _r9 asm("r9"); + register long _r10 asm("r10"); + register long _r15 asm("r15") = __NR_pipe; + register long _out0 asm("out0") = (long)filedes; + long _retval; + __asm __volatile(__IA64_BREAK:"=r"(_r8), "=r"(_r10), "=r"(_r15), + "=r"(_out0), "=r"(_r9) + :"2"(_r15), "3"(_out0) + :"memory" ASM_CLOBBERS); + if (_r10 == -1) { + errno = _r8; + _retval = -1; + } else { + filedes[0] = _r8; + filedes[1] = _r9; + _retval = 0; + } + return _retval; +} diff -puN /dev/null usr/klibc/arch/ia64/setjmp.S --- /dev/null +++ a/usr/klibc/arch/ia64/setjmp.S @@ -0,0 +1,343 @@ +/* + * IA-64 specific setjmp/longjmp routines + * + * Inspired by setjmp.s from the FreeBSD kernel. + */ + +#define J_UNAT 0 +#define J_NATS 0x8 +#define J_PFS 0x10 +#define J_BSP 0x18 +#define J_RNAT 0x20 +#define J_PREDS 0x28 +#define J_LC 0x30 +#define J_R4 0x38 +#define J_R5 0x40 +#define J_R6 0x48 +#define J_R7 0x50 +#define J_SP 0x58 +#define J_F2 0x60 +#define J_F3 0x70 +#define J_F4 0x80 +#define J_F5 0x90 +#define J_F16 0xa0 +#define J_F17 0xb0 +#define J_F18 0xc0 +#define J_F19 0xd0 +#define J_F20 0xe0 +#define J_F21 0xf0 +#define J_F22 0x100 +#define J_F23 0x110 +#define J_F24 0x120 +#define J_F25 0x130 +#define J_F26 0x140 +#define J_F27 0x150 +#define J_F28 0x160 +#define J_F29 0x170 +#define J_F30 0x180 +#define J_F31 0x190 +#define J_FPSR 0x1a0 +#define J_B0 0x1a8 +#define J_B1 0x1b0 +#define J_B2 0x1b8 +#define J_B3 0x1c0 +#define J_B4 0x1c8 +#define J_B5 0x1d0 +#define J_SIGMASK 0x1d8 +#define J_SIGSET 0x1e0 +#define J_GP 0x1f0 + +// int setjmp(struct jmp_buffer *) +// +// Setup a non-local goto. +// +// Description: +// +// SetJump stores the current register set in the area pointed to +// by "save". It returns zero. Subsequent calls to "LongJump" will +// restore the registers and return non-zero to the same location. +// +// On entry, r32 contains the pointer to the jmp_buffer +// + .align 32 + .global setjmp + .proc setjmp +setjmp: + // + // Make sure buffer is aligned at 16byte boundary + // + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + add r10 = J_PREDS, r32 // skip Unats & pfs save area + add r11 = J_BSP, r32 + // + // save immediate context + // + mov r2 = ar.bsp // save backing store pointer + mov r3 = pr // save predicates + flushrs + ;; + // + // save user Unat register + // + mov r16 = ar.lc // save loop count register + mov r14 = ar.unat // save user Unat register + + st8 [r10] = r3, J_LC-J_PREDS + st8 [r11] = r2, J_R4-J_BSP + ;; + st8 [r10] = r16, J_R5-J_LC + st8 [r32] = r14, J_NATS // Note: Unat at the + // beginning of the save area + mov r15 = ar.pfs + ;; + // + // save preserved general registers & NaT's + // + st8.spill [r11] = r4, J_R6-J_R4 + ;; + st8.spill [r10] = r5, J_R7-J_R5 + ;; + st8.spill [r11] = r6, J_SP-J_R6 + ;; + st8.spill [r10] = r7, J_F3-J_R7 + ;; + st8.spill [r11] = sp, J_F2-J_SP + ;; + // + // save spilled Unat and pfs registers + // + mov r2 = ar.unat // save Unat register after spill + ;; + st8 [r32] = r2, J_PFS-J_NATS // save unat for spilled regs + ;; + st8 [r32] = r15 // save pfs + // + // save floating registers + // + stf.spill [r11] = f2, J_F4-J_F2 + stf.spill [r10] = f3, J_F5-J_F3 + ;; + stf.spill [r11] = f4, J_F16-J_F4 + stf.spill [r10] = f5, J_F17-J_F5 + ;; + stf.spill [r11] = f16, J_F18-J_F16 + stf.spill [r10] = f17, J_F19-J_F17 + ;; + stf.spill [r11] = f18, J_F20-J_F18 + stf.spill [r10] = f19, J_F21-J_F19 + ;; + stf.spill [r11] = f20, J_F22-J_F20 + stf.spill [r10] = f21, J_F23-J_F21 + ;; + stf.spill [r11] = f22, J_F24-J_F22 + stf.spill [r10] = f23, J_F25-J_F23 + ;; + stf.spill [r11] = f24, J_F26-J_F24 + stf.spill [r10] = f25, J_F27-J_F25 + ;; + stf.spill [r11] = f26, J_F28-J_F26 + stf.spill [r10] = f27, J_F29-J_F27 + ;; + stf.spill [r11] = f28, J_F30-J_F28 + stf.spill [r10] = f29, J_F31-J_F29 + ;; + stf.spill [r11] = f30, J_FPSR-J_F30 + stf.spill [r10] = f31, J_B0-J_F31 // size of f31 + fpsr + // + // save FPSR register & branch registers + // + mov r2 = ar.fpsr // save fpsr register + mov r3 = b0 + ;; + st8 [r11] = r2, J_B1-J_FPSR + st8 [r10] = r3, J_B2-J_B0 + mov r2 = b1 + mov r3 = b2 + ;; + st8 [r11] = r2, J_B3-J_B1 + st8 [r10] = r3, J_B4-J_B2 + mov r2 = b3 + mov r3 = b4 + ;; + st8 [r11] = r2, J_B5-J_B3 + st8 [r10] = r3 + mov r2 = b5 + ;; + st8 [r11] = r2 + ;; + // + // return + // + mov r8 = r0 // return 0 from setjmp + mov ar.unat = r14 // restore unat + br.ret.sptk b0 + .endp setjmp + +// +// void longjmp(struct jmp_buffer *, int val) +// +// Perform a non-local goto. +// +// Description: +// +// LongJump initializes the register set to the values saved by a +// previous 'SetJump' and jumps to the return location saved by that +// 'SetJump'. This has the effect of unwinding the stack and returning +// for a second time to the 'SetJump'. +// + + .align 32 + .global longjmp + .proc longjmp +longjmp: + // + // Make sure buffer is aligned at 16byte boundary + // + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + // + // caching the return value as we do invala in the end + // + mov r8 = r33 // return value + + // + // get immediate context + // + mov r14 = ar.rsc // get user RSC conf + add r10 = J_PFS, r32 // get address of pfs + add r11 = J_NATS, r32 + ;; + ld8 r15 = [r10], J_BSP-J_PFS // get pfs + ld8 r2 = [r11], J_LC-J_NATS // get unat for spilled regs + ;; + mov ar.unat = r2 + ;; + ld8 r16 = [r10], J_PREDS-J_BSP // get backing store pointer + mov ar.rsc = r0 // put RSE in enforced lazy + mov ar.pfs = r15 + ;; + + // + // while returning from longjmp the BSPSTORE and BSP needs to be + // same and discard all the registers allocated after we did + // setjmp. Also, we need to generate the RNAT register since we + // did not flushed the RSE on setjmp. + // + mov r17 = ar.bspstore // get current BSPSTORE + ;; + cmp.ltu p6,p7 = r17, r16 // is it less than BSP of +(p6) br.spnt.few .flush_rse + mov r19 = ar.rnat // get current RNAT + ;; + loadrs // invalidate dirty regs + br.sptk.many .restore_rnat // restore RNAT + +.flush_rse: + flushrs + ;; + mov r19 = ar.rnat // get current RNAT + mov r17 = r16 // current BSPSTORE + ;; +.restore_rnat: + // + // check if RNAT is saved between saved BSP and curr BSPSTORE + // + mov r18 = 0x3f + ;; + dep r18 = r18,r16,3,6 // get RNAT address + ;; + cmp.ltu p8,p9 = r18, r17 // RNAT saved on RSE + ;; +(p8) ld8 r19 = [r18] // get RNAT from RSE + ;; + mov ar.bspstore = r16 // set new BSPSTORE + ;; + mov ar.rnat = r19 // restore RNAT + mov ar.rsc = r14 // restore RSC conf + + + ld8 r3 = [r11], J_R4-J_LC // get lc register + ld8 r2 = [r10], J_R5-J_PREDS // get predicates + ;; + mov pr = r2, -1 + mov ar.lc = r3 + // + // restore preserved general registers & NaT's + // + ld8.fill r4 = [r11], J_R6-J_R4 + ;; + ld8.fill r5 = [r10], J_R7-J_R5 + ld8.fill r6 = [r11], J_SP-J_R6 + ;; + ld8.fill r7 = [r10], J_F2-J_R7 + ld8.fill sp = [r11], J_F3-J_SP + ;; + // + // restore floating registers + // + ldf.fill f2 = [r10], J_F4-J_F2 + ldf.fill f3 = [r11], J_F5-J_F3 + ;; + ldf.fill f4 = [r10], J_F16-J_F4 + ldf.fill f5 = [r11], J_F17-J_F5 + ;; + ldf.fill f16 = [r10], J_F18-J_F16 + ldf.fill f17 = [r11], J_F19-J_F17 + ;; + ldf.fill f18 = [r10], J_F20-J_F18 + ldf.fill f19 = [r11], J_F21-J_F19 + ;; + ldf.fill f20 = [r10], J_F22-J_F20 + ldf.fill f21 = [r11], J_F23-J_F21 + ;; + ldf.fill f22 = [r10], J_F24-J_F22 + ldf.fill f23 = [r11], J_F25-J_F23 + ;; + ldf.fill f24 = [r10], J_F26-J_F24 + ldf.fill f25 = [r11], J_F27-J_F25 + ;; + ldf.fill f26 = [r10], J_F28-J_F26 + ldf.fill f27 = [r11], J_F29-J_F27 + ;; + ldf.fill f28 = [r10], J_F30-J_F28 + ldf.fill f29 = [r11], J_F31-J_F29 + ;; + ldf.fill f30 = [r10], J_FPSR-J_F30 + ldf.fill f31 = [r11], J_B0-J_F31 ;; + + // + // restore branch registers and fpsr + // + ld8 r16 = [r10], J_B1-J_FPSR // get fpsr + ld8 r17 = [r11], J_B2-J_B0 // get return pointer + ;; + mov ar.fpsr = r16 + mov b0 = r17 + ld8 r2 = [r10], J_B3-J_B1 + ld8 r3 = [r11], J_B4-J_B2 + ;; + mov b1 = r2 + mov b2 = r3 + ld8 r2 = [r10], J_B5-J_B3 + ld8 r3 = [r11] + ;; + mov b3 = r2 + mov b4 = r3 + ld8 r2 = [r10] + ld8 r21 = [r32] // get user unat + ;; + mov b5 = r2 + mov ar.unat = r21 + + // + // invalidate ALAT + // + invala ;; + + br.ret.sptk b0 + .endp longjmp diff -puN /dev/null usr/klibc/arch/ia64/syscall.S --- /dev/null +++ a/usr/klibc/arch/ia64/syscall.S @@ -0,0 +1,20 @@ +# +# arch/ia64/syscall.S +# + +#include + + .text + .align 32 + .proc __syscall_error + .globl __syscall_error +__syscall_error: + addl r2 = @ltoffx(errno),gp + ;; + ld8.mov r3 = [r2],errno + ;; + st4 [r3] = r8 + mov r8 = -1 + br.ret.sptk.many b0 + .size __syscall_error, .-__syscall_error + .endp __syscall_error diff -puN /dev/null usr/klibc/arch/ia64/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/ia64/sysstub.ph @@ -0,0 +1,29 @@ +# -*- perl -*- +# +# arch/ia64/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.align 32\n"; + print OUT "\t.proc ${fname}\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT "\tmov\tr15 = __NR_${sname}\n"; + print OUT "\tbreak __BREAK_SYSCALL\n"; + print OUT "\tcmp.eq p6,p0 = -1,r10\n"; + print OUT "(p6)\tbr.few __syscall_error\n"; + print OUT "\tbr.ret.sptk.many b0\n"; + print OUT "\t.size\t${fname},.-${fname}\n"; + print OUT "\t.endp\t${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/ia64/vfork.S --- /dev/null +++ a/usr/klibc/arch/ia64/vfork.S @@ -0,0 +1,42 @@ +/* + * ia64 specific vfork syscall + * + * Written By: Martin Hicks + * + */ + +/* This syscall is a special case of the clone syscall */ +#include +#include +#include + +/* These are redefined here because linux/sched.h isn't safe for + * inclusion in asm. + */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if parent wants the child to wake it up on exit */ + +/* pid_t vfork(void) */ +/* Implemented as clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + + .align 32 + .proc vfork + .global vfork +vfork: + alloc r2=ar.pfs,0,0,2,0 + mov r15=__NR_clone + mov out0=CLONE_VM|CLONE_VFORK|SIGCHLD + mov out1=0 + ;; + break 0x100000 // Do the syscall + ;; + addl r15=0,r1 + cmp.eq p7,p6 = -1,r10 + ;; + ld8 r14=[r15] + ;; +(p7) st4 [r14]=r8 + ;; +(p7) mov r8=-1 + br.ret.sptk.many b0 + .endp vfork diff -puN /dev/null usr/klibc/arch/m32r/crt0.S --- /dev/null +++ a/usr/klibc/arch/m32r/crt0.S @@ -0,0 +1,24 @@ +# +# arch/m32r/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .balign 4 + .type _start,@function + .globl _start +_start: + /* Save the address of the ELF argument array */ + mv r0, sp + + /* atexit() function (assume null) */ + xor r1, r1 + + bl __libc_init + + .size _start, .-_start diff -puN /dev/null usr/klibc/arch/m32r/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/m32r/Makefile.inc @@ -0,0 +1,19 @@ +# -*- makefile -*- +# +# arch/m32r/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + +archclean: diff -puN /dev/null usr/klibc/arch/m32r/MCONFIG --- /dev/null +++ a/usr/klibc/arch/m32r/MCONFIG @@ -0,0 +1,18 @@ +# -*- makefile -*- +# +# arch/m32r/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 224 MB - normal binaries start at 0 (?) +# (lib?)gcc on cris seems to insist on producing .init and .fini sections +KLIBCSHAREDFLAGS = --section-start .init=0x0e000100 diff -puN /dev/null usr/klibc/arch/m32r/setjmp.S --- /dev/null +++ a/usr/klibc/arch/m32r/setjmp.S @@ -0,0 +1,47 @@ +# +# arch/m32r/setjmp.S +# +# setjmp/longjmp for the M32R architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# r8-r15 +# +# Note that r14 is the return address register and +# r15 is the stack pointer. +# + + .text + .balign 4 + .globl setjmp + .type setjmp, @function +setjmp: + st r8, @r0 + st r9, @+r0 + st r10, @+r0 + st r11, @+r0 + st r12, @+r0 + st r13, @+r0 + st r14, @+r0 + st r15, @+r0 + xor r0, r0 + jmp r14 + .size setjmp,.-setjmp + + .text + .balign 4 + .globl longjmp + .type longjmp, @function +longjmp: + ld r8, @r0+ + ld r9, @r0+ + ld r10, @r0+ + ld r11, @r0+ + ld r12, @r0+ + ld r13, @r0+ + ld r14, @r0+ + ld r15, @r0 + mv r0, r1 + jmp r14 + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/m32r/syscall.S --- /dev/null +++ a/usr/klibc/arch/m32r/syscall.S @@ -0,0 +1,29 @@ +/* + * arch/m32r/syscall.S + * + * r7 contains the syscall number (set by stub); + * r0..r3 contains arguments 0-3 per standard calling convention; + * r4..r5 contains arguments 4-5, but we have to get those from + * the stack. + */ + + .section ".text","ax" + .balign 4 + .globl __syscall_common + .type __syscall_common,@function +__syscall_common: + ld r4,@sp + ld r5,@(4,sp) + trap #2 + cmpi r0, #-4096 + bnc 1f + jmp r14 +1: + seth r2,#high(errno) + or3 r2,r2,#low(errno) + neg r1,r0 + st r1,@r7 + ldi r0,#-1 + jmp r14 + + .size __syscall_common,.-__syscall_common diff -puN /dev/null usr/klibc/arch/m32r/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/m32r/sysstub.ph @@ -0,0 +1,25 @@ +# -*- perl -*- +# +# arch/m32r/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.type\t${fname},\@function\n"; + print OUT "\t.globl\t${fname}\n"; + print OUT "\t.balign\t4\n"; + print OUT "${fname}:\n"; + print OUT "\tldi\tr7,#__NR_${sname}\n"; + print OUT "\tbra\t__syscall_common\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/m68k/crt0.S --- /dev/null +++ a/usr/klibc/arch/m68k/crt0.S @@ -0,0 +1,27 @@ +# +# arch/m68k/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + # Zero out the frame pointer to be nice to the debugger + movea.l #0,%a6 + # Save the address of the ELF argument array + move.l %a7, %d0 + # Push a zero on the stack in lieu of atexit pointer + clr.l -(%sp) + # Push ELF argument pointer on the stack + move.l %d0, -(%a7) + + jbsr __libc_init + + .size _start, .-_start diff -puN /dev/null usr/klibc/arch/m68k/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/m68k/Makefile.inc @@ -0,0 +1,25 @@ +# -*- makefile -*- +# +# arch/m68k/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + arch/$(KLIBCARCH)/vfork.o + +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 2816 MB - normal binaries start at 2048 MB if I read the link +# script right. Not sure if there is a fundamental reason +# to not duck below the halfway point... +KLIBCSHAREDFLAGS = -Ttext 0xb0000000 + +archclean: diff -puN /dev/null usr/klibc/arch/m68k/MCONFIG --- /dev/null +++ a/usr/klibc/arch/m68k/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/m68k/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os -fomit-frame-pointer +KLIBCBITSIZE = 32 diff -puN /dev/null usr/klibc/arch/m68k/setjmp.S --- /dev/null +++ a/usr/klibc/arch/m68k/setjmp.S @@ -0,0 +1,43 @@ +# +# arch/m68k/setjmp.S +# +# setjmp/longjmp for the m68k architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# %d2..%d7 +# %a2..%a7 +# return address +# + + .text + .align 2 + .globl setjmp + .type setjmp, @function +setjmp: + move.l (%sp)+, %d0 | Return address + movea.l (%sp), %a0 | Buffer address + | Postincrement mode is not permitted here... + movem.l %d2-%d7/%a2-%a7, (%a0) + move.l %d0, 48(%a0) | Return address + move.l %d0, -(%sp) | Restore return address + clr.l %d0 | Return value + movea.l %d0, %a0 | Redundant return... + rts + + .size setjmp,.-setjmp + + .text + .align 2 + .globl longjmp + .type longjmp, @function +longjmp: + move.l 4(%sp), %a0 | Buffer address + move.l 8(%sp), %d0 | Return value + movem.l (%a0)+, %d2-%d7/%a2-%a7 + movea.l (%a0), %a1 + movea.l %d0, %a0 | Redundant return... + jmp.l (%a1) + + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/m68k/syscall.S --- /dev/null +++ a/usr/klibc/arch/m68k/syscall.S @@ -0,0 +1,27 @@ +/* + * arch/m68k/syscall.S + * + * Common tail-handling code for system calls. + * + * The arguments are on the stack; the system call number in %d0. + */ + + .text + .align 2 + .globl __syscall_common + .type __syscall_common, @function +__syscall_common: + movem.l %d2-%d6, -(%sp) /* 5 registers saved */ + movem.l 24(%sp), %d1-%d6 + trap #0 + cmpi.l #-4095, %d0 + blt.l 1f + neg.l %d0 + move.l %d0, (errno) + moveq #-1, %d0 +1: + movea.l %d0, %a0 /* Redundant return */ + movem.l (%sp)+, %d2-%d6 /* Restore registers */ + rts + + .size __syscall_common,.-__syscall_common diff -puN /dev/null usr/klibc/arch/m68k/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/m68k/sysstub.ph @@ -0,0 +1,26 @@ +# -*- perl -*- +# +# arch/m68k/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + + $stype = 'common' if ( $stype eq '' ); + + print OUT "\tmove.l\t# __NR_${sname}, %d0\n"; + print OUT "\tbr\t__syscall_$stype\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/m68k/vfork.S --- /dev/null +++ a/usr/klibc/arch/m68k/vfork.S @@ -0,0 +1,28 @@ +# +# usr/klibc/arch/m68k/vfork.S +# +# vfork is nasty - there must be nothing at all on the stack above +# the stack frame of the enclosing function. +# + +#include + + .text + .align 2 + .globl vfork + .type vfork, @function +vfork: + move.l (%sp)+, %d1 /* Return address */ + move.l # __NR_vfork, %d0 + trap #0 + move.l %d1, -(%sp) + cmpi.l #-4095, %d0 + blt.l 1f + neg.l %d0 + move.l %d0, (errno) + moveq #-1, %d0 +1: + movea.l %d0, %a0 + rts + + .size vfork, .-vfork diff -puN /dev/null usr/klibc/arch/mips64/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/mips64/Makefile.inc @@ -0,0 +1,10 @@ +# -*- makefile -*- +# +# arch/mips64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +archclean: diff -puN /dev/null usr/klibc/arch/mips64/MCONFIG --- /dev/null +++ a/usr/klibc/arch/mips64/MCONFIG @@ -0,0 +1,11 @@ +# -*- makefile -*- +# +# arch/mips64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os +KLIBCBITSIZE = 64 diff -puN /dev/null usr/klibc/arch/mips/crt0.S --- /dev/null +++ a/usr/klibc/arch/mips/crt0.S @@ -0,0 +1,25 @@ +# +# arch/mips/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + +#include + +NESTED(__start, 32, sp) + subu sp, 32 + sw zero, 16(sp) + + lui gp, %hi(_gp) # Initialize gp + addiu gp, gp, _gp + + addiu a0, sp, 32 # Pointer to ELF entry structure + move a1, v0 # Kernel-provided atexit() pointer + + jal __libc_init + + END(__start) diff -puN /dev/null usr/klibc/arch/mips/klibc.ld --- /dev/null +++ a/usr/klibc/arch/mips/klibc.ld @@ -0,0 +1,214 @@ +/* Linker script for klibc.so, needed because of the the damned + GNU ld script headers problem */ + +ENTRY(__start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + /* This address needs to be reachable using normal inter-module + calls, and work on the memory models for this architecture */ + /* 2 MB -- the normal starting point for text is 4 MB */ + . = 0x00200400; + .interp : { *(.interp) } + .reginfo : { *(.reginfo) } + .dynamic : { *(.dynamic) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .text : + { + _ftext = . ; + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.mips16.fn.*) *(.mips16.call.*) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(8192); + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + .data : + { + _fdata = . ; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin*.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + _gp = ALIGN(16) + 0x7ff0; + .got : { *(.got.plt) *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + _fbss = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } + . = ALIGN(32 / 8); + _end = .; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff -puN /dev/null usr/klibc/arch/mips/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/mips/Makefile.inc @@ -0,0 +1,29 @@ +# -*- makefile -*- +# +# arch/mips/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/pipe.o \ + arch/$(KLIBCARCH)/vfork.o \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + libgcc/__clzsi2.o \ + libgcc/__ashldi3.o \ + libgcc/__ashrdi3.o \ + libgcc/__lshrdi3.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + + +KLIBCARCHSOOBJS = $(patsubst %.o,%.lo,$(KLIBCARCHOBJS)) + + +archclean: diff -puN /dev/null usr/klibc/arch/mips/MCONFIG --- /dev/null +++ a/usr/klibc/arch/mips/MCONFIG @@ -0,0 +1,15 @@ +# -*- makefile -*- +# +# arch/mips/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHREQFLAGS = -fno-pic -mno-abicalls -G 0 +KLIBCOPTFLAGS = -Os +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +KLIBCSHAREDFLAGS = -T $(src)/arch/$(KLIBCARCH)/klibc.ld diff -puN /dev/null usr/klibc/arch/mips/pipe.S --- /dev/null +++ a/usr/klibc/arch/mips/pipe.S @@ -0,0 +1,16 @@ +#include +#include +#include + +LEAF(pipe) + li v0, __NR_pipe + syscall + bnez a3, 1f + sw v0, (a0) + sw v1, 4(a0) + li v0, 0 + b 2f +1: sw v0, errno + li v0, -1 +2: jr ra + END(pipe) diff -puN /dev/null usr/klibc/arch/mips/setjmp.S --- /dev/null +++ a/usr/klibc/arch/mips/setjmp.S @@ -0,0 +1,80 @@ +# +# arch/mips/setjmp.S +# +# setjmp/longjmp for the MIPS architecture +# +# The jmp_buf is assumed to contain the following, in order: +# s0..s7 +# gp +# sp +# s8 +# ra +# f20..f31 +# fcr31 +# + +#include + +LEAF(setjmp) + sw s0, 0(a0) + sw s1, 4(a0) + sw s2, 8(a0) + sw s3, 12(a0) + sw s4, 16(a0) + sw s5, 20(a0) + sw s6, 24(a0) + sw s7, 28(a0) + sw gp, 32(a0) + sw sp, 36(a0) + sw s8, 40(a0) + sw ra, 44(a0) + cfc1 t0,$31 + swc1 $f20,48(a0) + swc1 $f21,52(a0) + swc1 $f22,56(a0) + swc1 $f23,60(a0) + swc1 $f24,64(a0) + swc1 $f25,68(a0) + swc1 $f26,72(a0) + swc1 $f27,76(a0) + swc1 $f28,80(a0) + swc1 $f29,84(a0) + swc1 $f30,88(a0) + swc1 $f31,92(a0) + sw t0,96(a0) + move v0,zero + jr ra + + END(setjmp) + +LEAF(longjmp) + lw s0, 0(a0) + lw s1, 4(a0) + lw s2, 8(a0) + lw s3, 12(a0) + lw s4, 16(a0) + lw s5, 20(a0) + lw s6, 24(a0) + lw s7, 28(a0) + lw gp, 32(a0) + lw sp, 36(a0) + lw s8, 40(a0) + lw ra, 44(a0) + lw t0, 96(a0) + lwc1 $f20,48(a0) + lwc1 $f21,52(a0) + lwc1 $f22,56(a0) + lwc1 $f23,60(a0) + lwc1 $f24,64(a0) + lwc1 $f25,68(a0) + lwc1 $f26,72(a0) + lwc1 $f27,76(a0) + lwc1 $f28,80(a0) + lwc1 $f29,84(a0) + lwc1 $f30,88(a0) + lwc1 $f31,92(a0) + ctc1 t0,$31 + move v0,a1 + jr ra + + END(longjmp) diff -puN /dev/null usr/klibc/arch/mips/syscall.S --- /dev/null +++ a/usr/klibc/arch/mips/syscall.S @@ -0,0 +1,16 @@ +#include +#include +#include + + .set noreorder + +LEAF(__syscall_common) + syscall + beqz a3, 1f + # sw is actually two instructions; the first one goes + # in the branch delay slot + # XXX: Break this up manually; as it is now it generates warnings. + sw v0, errno + li v0, -1 +1: jr ra + END(__syscall_common) diff -puN /dev/null usr/klibc/arch/mips/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/mips/sysstub.ph @@ -0,0 +1,30 @@ +# -*- perl -*- +# +# arch/mips/sysstub.ph +# +# Script to generate system call stubs +# + +# On MIPS, most system calls follow the standard convention, with the +# system call number in r0 (v0), return an error value in r19 (a3) as +# well as the return value in r0 (v0). + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + $stype = $stype || 'common'; + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "#include \n"; + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.set noreorder\n"; + print OUT "\n"; + print OUT "LEAF(${fname})\n"; + print OUT "\tj\t__syscall_${stype}\n"; + print OUT "\t li\tv0, __NR_${sname}\n"; + print OUT "\tEND(${fname})\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/mips/vfork.S --- /dev/null +++ a/usr/klibc/arch/mips/vfork.S @@ -0,0 +1,16 @@ +#include +#include +#include + +#define CLONE_VM 0x00000100 +#define CLONE_VFORK 0x00004000 +#define SIGCHLD 18 + + .set noreorder + +LEAF(vfork) + li a0, CLONE_VFORK | CLONE_VM | SIGCHLD + li a1, 0 + j __syscall_common + li v0, __NR_clone + END(vfork) diff -puN /dev/null usr/klibc/arch/parisc/crt0.S --- /dev/null +++ a/usr/klibc/arch/parisc/crt0.S @@ -0,0 +1,37 @@ + .align 4 + + .import $global$, data + .import __libc_init, code + + .global _start + .export _start, ENTRY + .type _start,@function + + .proc + .callinfo + +_start: +/* extend the stack by 64-bytes */ + ldo 64(%sp), %sp + +/* %r25 = argc + * %r24 = argv + * envp = argv + (argc + 1) + * elfdata = (argv - 4) + */ + ldo -4(%r24), %r26 + +/* load global data */ + ldil L%$global$, %dp + ldo R%$global$(%dp), %dp + +/* parisc abi puts the atexit pointer in %r23, see ELF_PLAT_INIT() */ + copy %r23, %r25 + +/* branch to __libc_init */ + bl __libc_init,%r2 + nop +/* break miserably if we ever return */ + iitlbp %r0,(%sr0,%r0) /* illegal instruction */ + nop + .procend diff -puN /dev/null usr/klibc/arch/parisc/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/parisc/Makefile.inc @@ -0,0 +1,16 @@ +# -*- makefile -*- +# +# arch/parisc/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o + +KLIBCARCHOOBJS = $(patsubst %o,%.lo,%(KLIBCARCHOBJS)) + +archclean: diff -puN /dev/null usr/klibc/arch/parisc/MCONFIG --- /dev/null +++ a/usr/klibc/arch/parisc/MCONFIG @@ -0,0 +1,12 @@ +# -*- makefile -*- +# +# arch/parisc/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os -fomit-frame-pointer +KLIBCBITSIZE = 32 +KLIBCSHAREDFLAGS = -Ttext 0x40001000 diff -puN /dev/null usr/klibc/arch/parisc/setjmp.S --- /dev/null +++ a/usr/klibc/arch/parisc/setjmp.S @@ -0,0 +1,88 @@ +/* + * parisc specific setjmp/longjmp routines + * + */ + + .text + .align 4 + .global setjmp + .export setjmp, code + .proc + .callinfo +setjmp: + stw %r3,0(%r26) + stw %r4,8(%r26) + stw %r5,12(%r26) + stw %r6,16(%r26) + stw %r7,20(%r26) + stw %r8,24(%r26) + stw %r9,28(%r26) + stw %r10,32(%r26) + stw %r11,36(%r26) + stw %r12,40(%r26) + stw %r13,44(%r26) + stw %r14,48(%r26) + stw %r15,52(%r26) + stw %r16,56(%r26) + stw %r17,60(%r26) + stw %r18,64(%r26) + stw %r19,68(%r26) + stw %r27,72(%r26) + stw %r30,76(%r26) + stw %rp,80(%r26) + ldo 88(%r26),%r19 + fstd,ma %fr12,8(%r19) + fstd,ma %fr13,8(%r19) + fstd,ma %fr14,8(%r19) + fstd,ma %fr15,8(%r19) + fstd,ma %fr16,8(%r19) + fstd,ma %fr17,8(%r19) + fstd,ma %fr18,8(%r19) + fstd,ma %fr19,8(%r19) + fstd,ma %fr20,8(%r19) + fstd %fr21,0(%r19) + bv %r0(%rp) + copy %r0,%r28 + .procend + + .text + .align 4 + .global longjmp + .export longjmp, code + .proc + .callinfo +longjmp: + ldw 0(%r26),%r3 + ldw 8(%r26),%r4 + ldw 12(%r26),%r5 + ldw 16(%r26),%r6 + ldw 20(%r26),%r7 + ldw 24(%r26),%r8 + ldw 28(%r26),%r9 + ldw 32(%r26),%r10 + ldw 36(%r26),%r11 + ldw 40(%r26),%r12 + ldw 44(%r26),%r13 + ldw 48(%r26),%r14 + ldw 52(%r26),%r15 + ldw 56(%r26),%r16 + ldw 60(%r26),%r17 + ldw 64(%r26),%r18 + ldw 68(%r26),%r19 + ldw 72(%r26),%r27 + ldw 76(%r26),%r30 + ldw 80(%r26),%rp + ldo 88(%r26),%r20 + fldd,ma 8(%r20),%fr12 + fldd,ma 8(%r20),%fr13 + fldd,ma 8(%r20),%fr14 + fldd,ma 8(%r20),%fr15 + fldd,ma 8(%r20),%fr16 + fldd,ma 8(%r20),%fr17 + fldd,ma 8(%r20),%fr18 + fldd,ma 8(%r20),%fr19 + fldd,ma 8(%r20),%fr20 + fldd 0(%r20),%fr21 + bv %r0(%rp) + copy %r25,%r28 + .procend diff -puN /dev/null usr/klibc/arch/parisc/syscall.S --- /dev/null +++ a/usr/klibc/arch/parisc/syscall.S @@ -0,0 +1,36 @@ +/* + * arch/parisc/syscall.S + * + * %r20 contains the system call number, %r2 contains whence we came + * + */ + + .text + .align 64 ; cache-width aligned + .globl __syscall_common + .type __syscall_common,@function +__syscall_common: + ldo 0x40(%sp),%sp + stw %rp,-0x54(%sp) ; save return pointer + + ldw -0x74(%sp),%r22 ; %arg4 + ldw -0x78(%sp),%r21 ; %arg5 + + ble 0x100(%sr2, %r0) ; jump to gateway page + nop ; can we move a load here? + + ldi -0x1000,%r19 ; %r19 = -4096 + sub %r0,%ret0,%r22 ; %r22 = -%ret0 + cmpb,>>=,n %r19,%ret0,1f ; if %ret0 >= -4096UL + ldi -1,%ret0 ; nullified on taken forward + + /* store %r22 to errno... */ + ldil L%errno,%r1 + ldo R%errno(%r1),%r1 + stw %r22,0(%r1) +1: + ldw -0x54(%sp),%rp ; restore return pointer + bv %r0(%rp) ; jump back + ldo -0x40(%sp),%sp + + .size __syscall_common,.-__syscall_common diff -puN /dev/null usr/klibc/arch/parisc/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/parisc/sysstub.ph @@ -0,0 +1,28 @@ +# -*- perl -*- +# +# arch/parisc/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.align 4\n"; + print OUT "\t.import __syscall_common, code\n"; + print OUT "\t.global ${fname}\n"; + print OUT "\t.export ${fname}, code\n"; + print OUT "\t.proc\n"; + print OUT "\.callinfo\n"; + print OUT "${fname}:\n"; + print OUT "\tb\t__syscall_common\n"; + print OUT "\t ldo\t__NR_${sname}(%r0),%r20\n"; + print OUT "\t.procend\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/ppc64/crt0.S --- /dev/null +++ a/usr/klibc/arch/ppc64/crt0.S @@ -0,0 +1,32 @@ +# +# arch/ppc64/crt0.S +# +# void _start(void) +# { +# /* Divine up argc, argv, and envp */ +# environ = envp; +# exit(main(argc, argv, envp)); +# } +# + + .section ".toc","aw" +.LC0: .tc environ[TC],environ + + .section ".opd","aw" + .align 3 + .globl _start +_start: + .quad ._start + .quad .TOC.@tocbase, 0 + + .text + .globl ._start + .type ._start,@function +._start: + stdu %r1,-32(%r1) + addi %r3,%r1,32 + li %r4,0 /* fini (unused) */ + b .__libc_init + nop + + .size _start,.-_start diff -puN /dev/null usr/klibc/arch/ppc64/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/ppc64/Makefile.inc @@ -0,0 +1,25 @@ +# -*- makefile -*- +# +# arch/ppc64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o + +KLIBCARCHSOOBJS = $(patsubst %.o,%.lo,$(KLIBCARCHOBJS)) + +INTERP_O = interp1.o + +interp.o: interp1.o klibc.got + $(LD) $(KLIBCLDFLAGS) -r -o $@ interp1.o klibc.got + +klibc.got: $(SOHASH) + $(OBJCOPY) -j .got $< $@ + +archclean: + rm -f klibc.got diff -puN /dev/null usr/klibc/arch/ppc64/MCONFIG --- /dev/null +++ a/usr/klibc/arch/ppc64/MCONFIG @@ -0,0 +1,26 @@ +# -*- makefile -*- +# +# arch/ppc64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHREQFLAGS = -m64 -mcall-aixdesc +KLIBCOPTFLAGS = -Os +KLIBCBITSIZE = 64 +KLIBCLDFLAGS = -m elf64ppc + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 256-16 MB - normal binaries start at 256 MB, and jumps are limited +# to +/- 16 MB +KLIBCSHAREDFLAGS = -Ttext 0x0f000200 + +# The kernel so far has both asm-ppc* and asm-powerpc. +KLIBCARCHINCFLAGS = -I$(KLIBCKERNELOBJ)arch/$(KLIBCARCH)/include + +# The asm include files live in asm-powerpc +KLIBCASMARCH = powerpc diff -puN /dev/null usr/klibc/arch/ppc64/setjmp.S --- /dev/null +++ a/usr/klibc/arch/ppc64/setjmp.S @@ -0,0 +1,85 @@ +# +# arch/ppc64/setjmp.S +# +# Basic setjmp/longjmp implementation +# + + .text + .align 4 + + .section ".opd","aw" +setjmp: + .quad .setjmp,.TOC.@tocbase,0 + .previous + .size setjmp,24 + .type .setjmp,@function + .globl setjmp + .globl .setjmp +.setjmp: + mflr %r11 /* save return address */ + mfcr %r12 /* save condition register */ + std %r2,0(%r3) /* save TOC pointer (not needed) */ + stdu %r1,8(%r3) /* save stack pointer */ + stdu %r11,8(%r3) + stdu %r12,8(%r3) + stdu %r13,8(%r3) /* save caller saved regs */ + stdu %r14,8(%r3) + stdu %r15,8(%r3) + stdu %r16,8(%r3) + stdu %r17,8(%r3) + stdu %r18,8(%r3) + stdu %r19,8(%r3) + stdu %r20,8(%r3) + stdu %r21,8(%r3) + stdu %r22,8(%r3) + stdu %r23,8(%r3) + stdu %r24,8(%r3) + stdu %r25,8(%r3) + stdu %r26,8(%r3) + stdu %r27,8(%r3) + stdu %r28,8(%r3) + stdu %r29,8(%r3) + stdu %r30,8(%r3) + std %r31,8(%r3) + li %r3,0 /* indicate success */ + blr /* return */ + + .size .setjmp,.-.setjmp + .section ".opd","aw" +longjmp: + .quad .longjmp,.TOC.@tocbase,0 + .previous + .size longjmp,24 + .type .longjmp,@function + .globl longjmp + .globl .longjmp +.longjmp: + ld %r2,0(%r3) /* restore TOC pointer (not needed) */ + ldu %r1,8(%r3) /* restore stack */ + ldu %r11,8(%r3) + ldu %r12,8(%r3) + ldu %r13,8(%r3) /* restore caller saved regs */ + ldu %r14,8(%r3) + ldu %r15,8(%r3) + ldu %r16,8(%r3) + ldu %r17,8(%r3) + ldu %r18,8(%r3) + ldu %r19,8(%r3) + ldu %r20,8(%r3) + ldu %r21,8(%r3) + ldu %r22,8(%r3) + ldu %r23,8(%r3) + ldu %r24,8(%r3) + ldu %r25,8(%r3) + ldu %r26,8(%r3) + ldu %r27,8(%r3) + ldu %r28,8(%r3) + ldu %r29,8(%r3) + ldu %r30,8(%r3) + ld %r31,8(%r3) + mtlr %r11 /* restore LR */ + mtcr %r12 /* restore CR */ + mr %r3,%r4 /* get return value */ + blr /* return */ + + .size .longjmp,.-.longjmp diff -puN /dev/null usr/klibc/arch/ppc64/syscall.c --- /dev/null +++ a/usr/klibc/arch/ppc64/syscall.c @@ -0,0 +1,14 @@ +/* + * arch/ppc64/syscall.c + * + * Common error-handling path for system calls. + * The return value from __syscall_error becomes the + * return value from the system call. + */ +#include + +long int __syscall_error(long int err) +{ + errno = err; + return -1; +} diff -puN /dev/null usr/klibc/arch/ppc64/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/ppc64/sysstub.ph @@ -0,0 +1,31 @@ +# -*- perl -*- +# +# arch/ppc64/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "\t.section \".opd\",\"aw\"\n"; + print OUT "\t.align 3\n"; + print OUT "${fname}:\n"; + print OUT "\t.quad .${fname},.TOC.\@tocbase,0\n"; + print OUT "\t.text\n"; + print OUT "\t.type .${fname},\@function\n"; + print OUT "\t.globl .${fname}\n"; + print OUT ".${fname}:\n"; + print OUT "\tli 0,__NR_${sname}\n"; + print OUT "\tsc\n"; + print OUT "\tbnslr\n"; + print OUT "\tb .__syscall_error\n"; + print OUT "\t.size .${fname},.-.${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/ppc/crt0.S --- /dev/null +++ a/usr/klibc/arch/ppc/crt0.S @@ -0,0 +1,23 @@ +# +# arch/ppc/crt0.S +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + stwu 1,-16(1) + addi 3,1,16 + /* + * the SVR4abippc.pdf specifies r7 as a pointer to + * a termination function point + * However, Section 8.4.1 of the LSB API docs say that + * The value to be placed into register r7, the termination + * function pointer, is not passed to the process. + * So we stub it out, instead. + */ + li 4,0 + bl __libc_init + + .size _start,.-_start diff -puN /dev/null usr/klibc/arch/ppc/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/ppc/Makefile.inc @@ -0,0 +1,22 @@ +# -*- makefile -*- +# +# arch/ppc/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + + +KLIBCARCHSOOBJS = $(patsubst %.o,%.lo,$(KLIBCARCHOBJS)) + +archclean: diff -puN /dev/null usr/klibc/arch/ppc/MCONFIG --- /dev/null +++ a/usr/klibc/arch/ppc/MCONFIG @@ -0,0 +1,29 @@ +# -*- makefile -*- +# +# arch/ppc/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +gcc_m32_option := $(call cc-option, -m32, ) + +KLIBCOPTFLAGS = -Os +KLIBCLDFLAGS = -m elf32ppclinux +KLIBCARCHREQFLAGS += $(gcc_m32_option) + +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 256-16 MB - normal binaries start at 256 MB, and jumps are limited +# to +/- 16 MB +KLIBCSHAREDFLAGS = -Ttext 0x0f800200 + +# The kernel so far has both asm-ppc* and asm-powerpc. +KLIBCARCHINCFLAGS = -I$(KLIBCKERNELOBJ)arch/$(KLIBCARCH)/include + +# The asm include files live in asm-powerpc +KLIBCASMARCH = powerpc diff -puN /dev/null usr/klibc/arch/ppc/setjmp.S --- /dev/null +++ a/usr/klibc/arch/ppc/setjmp.S @@ -0,0 +1,34 @@ +# +# arch/ppc/setjmp.S +# +# Basic setjmp/longjmp implementation +# This file was derived from the equivalent file in NetBSD +# + + .text + .align 4 + .type setjmp,@function + .globl setjmp +setjmp: + mflr %r11 /* save return address */ + mfcr %r12 /* save condition register */ + mr %r10,%r1 /* save stack pointer */ + mr %r9,%r2 /* save GPR2 (not needed) */ + stmw %r9,0(%r3) /* save r9..r31 */ + li %r3,0 /* indicate success */ + blr /* return */ + + .size setjmp,.-setjmp + + .type longjmp,@function + .globl longjmp +longjmp: + lmw %r9,0(%r3) /* save r9..r31 */ + mtlr %r11 /* restore LR */ + mtcr %r12 /* restore CR */ + mr %r2,%r9 /* restore GPR2 (not needed) */ + mr %r1,%r10 /* restore stack */ + mr %r3,%r4 /* get return value */ + blr /* return */ + + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/ppc/syscall.S --- /dev/null +++ a/usr/klibc/arch/ppc/syscall.S @@ -0,0 +1,16 @@ +/* + * arch/ppc/syscall.S + * + * Common error-handling path for system calls. + */ + + .text + .align 2 + .globl __syscall_error + .type __syscall_error,@function +__syscall_error: + lis 9,errno@ha + stw 3,errno@l(9) + li 3,-1 + blr + .size __syscall_error,.-__syscall_error diff -puN /dev/null usr/klibc/arch/ppc/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/ppc/sysstub.ph @@ -0,0 +1,25 @@ +# -*- perl -*- +# +# arch/ppc/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT "\tli 0,__NR_${sname}\n"; + print OUT "\tsc\n"; + print OUT "\tbnslr\n"; + print OUT "\tb __syscall_error\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/README --- /dev/null +++ a/usr/klibc/arch/README @@ -0,0 +1,81 @@ +To port klibc to a new architecture, you need: + +a) A directory structure + +Each archtecture has a klibc/arch/ directory, which should include an +MCONFIG and a Makefile.inc file, and an include/arch/ directory, which +includes some architecture-specific header files, including +klibc/archconfig.h. + + +b) Architecture-specific configuration + (include/arch/*/klibc/sysconfig.h) + +This file can set configuration variables from +include/klibc/sysconfig.h. + + +c) Startup code + (klibc/arch/*/crt0.S) + +The crt0.S assembly routine typically corresponds to the following +pseudo-C code. In addition, each architecture needs any support +routines that gcc-generated code expects to find in the system library +-- Alpha, for example, needs divide subroutines. + +The "getenvtest" test program is a very good test for proper crt0.S +functionality. + + +extern __noreturn __libc_init(void *, void *); + +__noreturn _start(void) +{ + void *elf_data = get_elf_data_address(); /* Usually the stack address */ + void *atexit_ptr = get_atexit_ptr(); /* Usually in a register */ + + /* Some architectures need this for debugging to work */ + setup_null_stack_frame_if_necessary(); + + __libc_init(elf_data, atexit_ptr); +} + + +d) A setenv implementation + (klibc/arch/*/setjmp.S, include/arch/*klibc/archsetjmp.h) + +On most (but not all!) architectures, this entails creating a setjmp +buffer big enough to hold all callee-saved registers, plus the stack +pointer and the return address. In setjmp.S you have: + +* A "setjmp" function that writes out the callee-saved registers, the + stack pointer and the return address to the buffer pointed to by the + first argument, and then returns zero normally. + + On some architectures you need to take some kind of action to make + sure the contents of the stack is actually manifest in memory and + not cached in the CPU. In some cases (e.g. on SPARC) this will + automatically spill the registers onto the stack; then they don't + need to be spilled into the jmp_buf. + +* A "longjmp" function that read back these same registers from the + jmp_buf pointed to by the first argument, and returns the second + argument *to the address specified in the jmp_buf*. + + On some architectures you need to take some kind of action to flush + any cached stack data or return stack. + + +e) Any support functions needed by gcc, *unless* they are in libgcc + *and* libgcc is usable for klibc on your particular platform. If + libgcc isn't usable for klibc (on MIPS, for example, libgcc is + compiled in a way that is not compatible with klibc) there are + reasonably good clones of most of the libgcc functions in the libgcc + directory. To use them, add them to ARCHOBJS in + klibc/arch/*/Makefile.inc. + + +f) A link location for the shared klibc. This should be specified in + SHAREDFLAGS in klibc/arch/*/MCONFIG. + + This is not applicable to no-MMU architectures. diff -puN /dev/null usr/klibc/arch/s390/crt0.S --- /dev/null +++ a/usr/klibc/arch/s390/crt0.S @@ -0,0 +1,35 @@ +# +# arch/s390/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + .text + .align 4 + .type _start,@function + .globl _start + +#ifndef __s390x__ + +_start: + lr %r2,%r15 + lhi %r3,0 + ahi %r15,-96 + bras %r1,.L0 +.L0: + l %r1,.L1-.L0(%r1) + br %r1 +.L1: + .long __libc_init +#else + +_start: + lgr %r2,%r15 + lghi %r3,0 + aghi %r15,-160 + jg __libc_init +#endif + .size _start,.-_start diff -puN /dev/null usr/klibc/arch/s390/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/s390/Makefile.inc @@ -0,0 +1,38 @@ +# -*- makefile -*- +# +# arch/s390/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ifneq ("$(KLIBCARCH)", "s390x") + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCHDIR)/setjmp.o \ + arch/$(KLIBCARCHDIR)/mmap.o \ + arch/$(KLIBCARCHDIR)/syscall.o \ + libgcc/__clzsi2.o \ + libgcc/__ashldi3.o \ + libgcc/__ashrdi3.o \ + libgcc/__lshrdi3.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + +else + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCHDIR)/setjmp.o \ + arch/$(KLIBCARCHDIR)/mmap.o \ + arch/$(KLIBCARCHDIR)/syscall.o + +endif + +KLIBCARCHSOOBJS = $(patsubst %.o,%.lo,$(KLIBCARCHOBJS)) + + +archclean: diff -puN /dev/null usr/klibc/arch/s390/MCONFIG --- /dev/null +++ a/usr/klibc/arch/s390/MCONFIG @@ -0,0 +1,23 @@ +# -*- makefile -*- +# +# arch/s390/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os + +ifneq ("$(KLIBCARCH)", "s390x") + KLIBCBITSIZE = 32 + KLIBCCFLAGS += -m31 + KLIBCLDFLAGS += -m elf_s390 +else + KLIBCBITSIZE = 64 + KLIBCCFLAGS += -m64 + KLIBCLDFLAGS += -m elf64_s390 +endif + +KLIBCASMARCH = s390 +KLIBCSHAREDFLAGS = -Ttext 0x40000200 diff -puN /dev/null usr/klibc/arch/s390/mmap.c --- /dev/null +++ a/usr/klibc/arch/s390/mmap.c @@ -0,0 +1,75 @@ +#include +#include +#include + +struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +#ifndef __s390x__ + +void *__mmap2(void *addr, size_t len, int prot, int flags, int fd, long offset) +{ + struct mmap_arg_struct args = { + (unsigned long)addr, + (unsigned long)len, + (unsigned long)prot, + (unsigned long)flags, + (unsigned long)fd, + (unsigned long)offset, + }; + + register struct mmap_arg_struct *__arg1 asm("2") = &args; + register long __svcres asm("2"); + unsigned long __res; + + __asm__ __volatile__(" svc %b1\n" + : "=d"(__svcres) + : "i"(__NR_mmap2), "0"(__arg1) + : "1", "cc", "memory"); + __res = __svcres; + if (__res >= (unsigned long)-4095) { + errno = -__res; + __res = -1; + } + return (void *)__res; +} + +#else /* __s390x__ */ + +void * mmap(void * addr, size_t len, int prot, int flags, + int fd, off_t offset) +{ + struct mmap_arg_struct args = { + (unsigned long) addr, + (unsigned long) len, + (unsigned long) prot, + (unsigned long) flags, + (unsigned long) fd, + (unsigned long) offset, + }; + + register struct mmap_arg_struct *__arg1 asm("2") = &args; + register long __svcres asm("2"); + unsigned long __res; + + __asm__ __volatile__ ( + " svc %b1\n" + : "=d" (__svcres) + : "i" (__NR_mmap), + "0" (__arg1) + : "1", "cc", "memory"); + __res = __svcres; + if (__res >= (unsigned long)-4095) { + errno = -__res; + __res = -1; + } + return (void *)__res; +} + +#endif /* __s390x__ */ diff -puN /dev/null usr/klibc/arch/s390/setjmp.S --- /dev/null +++ a/usr/klibc/arch/s390/setjmp.S @@ -0,0 +1,66 @@ +# +# arch/s390/setjmp.S +# +# setjmp/longjmp for the s390 architecture +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function + +#ifndef __s390x__ + +setjmp: + stm %r6,%r15,0(%r2) # save all general registers + std %f4,40(%r2) # save fp registers f4 and f6 + std %f6,48(%r2) + lhi %r2,0 # return 0 + br %r14 + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: + lr %r1,%r2 # jmp_buf + lr %r2,%r3 # return value + ld %f6,48(%r1) # restore all saved registers + ld %f4,40(%r1) + lm %r6,%r15,0(%r1) + br %r14 # return to restored address + + .size longjmp,.-longjmp + +#else + +setjmp: + stmg %r6,%r15,0(%r2) # save all general registers + std %f1,80(%r2) # save fp registers f4 and f6 + std %f3,88(%r2) + std %f5,96(%r2) + std %f7,104(%r2) + lghi %r2,0 # return 0 + br %r14 + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: + lgr %r1,%r2 # jmp_buf + lgr %r2,%r3 # return value + ld %f7,104(%r1) # restore all saved registers + ld %f5,96(%r1) + ld %f3,88(%r1) + ld %f1,80(%r1) + lmg %r6,%r15,0(%r1) + br %r14 # return to restored address + + .size longjmp,.-longjmp + +#endif diff -puN /dev/null usr/klibc/arch/s390/syscall.c --- /dev/null +++ a/usr/klibc/arch/s390/syscall.c @@ -0,0 +1,16 @@ +/* + * arch/s390/syscall.c + * + * Common error-handling path for system calls. + * The return value from __syscall_common becomes the + * return value from the system call. + */ +#include + +unsigned long __syscall_common(unsigned long err) +{ + if (err < -4095UL) + return err; + errno = -err; + return -1; +} diff -puN /dev/null usr/klibc/arch/s390/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/s390/sysstub.ph @@ -0,0 +1,40 @@ +# -*- perl -*- +# +# arch/s390/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT ".if __NR_${sname} < 256\n"; + print OUT "\tsvc __NR_${sname}\n"; + print OUT ".else\n"; + print OUT "\tla %r1,__NR_${sname}\n"; + print OUT "\tsvc 0\n"; + print OUT ".endif\n"; + + print OUT "#ifndef __s390x__\n"; + + print OUT "\tbras %r3,1f\n"; + print OUT "\t.long __syscall_common\n"; + print OUT "1:\tl %r3,0(%r3)\n"; + print OUT "\tbr %r3\n"; + + print OUT "#else\n"; + + print OUT "\tbrasl %r3,__syscall_common\n"; + + print OUT "#endif\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/sh/crt0.S --- /dev/null +++ a/usr/klibc/arch/sh/crt0.S @@ -0,0 +1,27 @@ +# +# arch/sh/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 2 + .type _start,#function + .globl _start + +_start: + mov r15, r4 + mov #0, r5 + mov.l 1f, r0 + + jsr @r0 + nop + + .align 2 +1: .long __libc_init + + .size _start,.-_start diff -puN /dev/null usr/klibc/arch/sh/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/sh/Makefile.inc @@ -0,0 +1,15 @@ +# -*- makefile -*- +# +# arch/sh/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHOBJS = arch/sh/setjmp.o \ + arch/sh/syscall.o + +ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS)) + +archclean: diff -puN /dev/null usr/klibc/arch/sh/MCONFIG --- /dev/null +++ a/usr/klibc/arch/sh/MCONFIG @@ -0,0 +1,18 @@ +# -*- makefile -*- +# +# arch/sh/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +ARCHREGFLAGS = -m4 -mno-implicit-fp +KLIBCOPTFLAGS = -Os -fomit-frame-pointer +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 2 MB -- the normal starting point for text is 4 MB. +KLIBCSHAREDFLAGS = -Ttext 0x00200200 diff -puN /dev/null usr/klibc/arch/sh/setjmp.S --- /dev/null +++ a/usr/klibc/arch/sh/setjmp.S @@ -0,0 +1,64 @@ +# +# arch/sh/setjmp.S +# +# setjmp/longjmp for the SuperH architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# +# r8 +# r9 +# r10 +# r11 +# r12 +# r13 +# r14 +# r15 +# pr +# + + .text + .align 2 + + .globl setjmp + .type setjmp, #function + +setjmp: + add #(9*4), r4 + sts.l pr, @-r4 + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + rts + mov #0, r0 + + .size setjmp,.-setjmp + + .align 2 + .globl longjmp + .type setjmp, #function + +longjmp: + mov.l @r4+, r8 + mov.l @r4+, r9 + mov.l @r4+, r10 + mov.l @r4+, r11 + mov.l @r4+, r12 + mov.l @r4+, r13 + mov.l @r4+, r14 + mov.l @r4+, r15 + lds.l @r4+, pr + mov r5, r0 + tst r0, r0 + bf 1f + mov #1, r0 ! in case val==0 +1: rts + nop + + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/sh/syscall.S --- /dev/null +++ a/usr/klibc/arch/sh/syscall.S @@ -0,0 +1,35 @@ +/* + * arch/sh/syscall.S + * + * On sh, r3 contains the syscall number (set by generated stub); + * r4..r7 contain arguments 0-3 per the standard calling convention, + * and arguments 4-5 are passed in r0 and r1. + * + * The return value is in r3 rather than standard r0. + */ + + .section ".text.syscall","ax" + .align 2 + .globl ___syscall_common + .type ___syscall_common,@function +___syscall_common: + mov.l @(sp),r0 + mov.l @(4,sp),r1 + trapa #0x15 + mov.l 1f,r0 + cmp/hs r0,r3 + bt/s 3f + neg r3,r4 + mov.l 2f,r5 + mov.l r4,@r5 + rts + mov #-1,r0 +3: + rts + mov r3,r0 + + .align 2 +1: .long -4096 /* Errno limit */ +2: .long errno + + .size ___syscall_common,.-___syscall_common diff -puN /dev/null usr/klibc/arch/sh/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/sh/sysstub.ph @@ -0,0 +1,34 @@ +# -*- perl -*- +# +# arch/sh/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.section\t\".text.syscall\",\"ax\"\n"; + print OUT "\t.type\t${fname},\#function\n"; + print OUT "\t.globl\t${fname}\n"; + print OUT "\t.align\t2\n"; + print OUT "${fname}:\n"; + print OUT "\tbra\t__syscall_common\n"; + print OUT "#if __NR_${sname} >= 128\n"; + print OUT "\t mov.l\t1f, r3\n"; + print OUT "#else\n"; + print OUT "\t mov\t# __NR_${sname}, r3\n"; + print OUT "#endif\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + print OUT "\n"; + print OUT "#if __NR_${sname} >= 128\n"; + print OUT "\t.align\t2\n"; + print OUT "1:\t.long\t__NR_${sname}\n"; + print OUT "#endif\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/sparc64/crt0.S --- /dev/null +++ a/usr/klibc/arch/sparc64/crt0.S @@ -0,0 +1,2 @@ +#define TARGET_PTR_SIZE 64 +#include "../sparc/crt0i.S" diff -puN /dev/null usr/klibc/arch/sparc64/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/sparc64/Makefile.inc @@ -0,0 +1,16 @@ +# -*- makefile -*- +# +# arch/sparc64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/pipe.o \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + arch/$(KLIBCARCH)/sysfork.o + +archclean: diff -puN /dev/null usr/klibc/arch/sparc64/MCONFIG --- /dev/null +++ a/usr/klibc/arch/sparc64/MCONFIG @@ -0,0 +1,21 @@ +# -*- makefile -*- +# +# arch/sparc64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHREQFLAGS = -m64 -mptr64 -D__sparc64__ +KLIBCOPTFLAGS = -Os +KLIBCBITSIZE = 64 + +KLIBCLDFLAGS = -m elf64_sparc + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# Normal binaries start at 1 MB; the linker wants 1 MB alignment, +# and call instructions have a 30-bit signed offset, << 2. +KLIBCSHAREDFLAGS = -Ttext 0x80000200 diff -puN /dev/null usr/klibc/arch/sparc64/pipe.S --- /dev/null +++ a/usr/klibc/arch/sparc64/pipe.S @@ -0,0 +1,30 @@ +/* + * arch/sparc64/pipe.S + * + * The pipe system call are special on sparc[64]: + * they return the two file descriptors in %o0 and %o1. + */ + +#include + + .globl pipe + .type pipe,#function + .align 4 +pipe: + mov __NR_pipe, %g1 + or %o0, 0, %g4 + t 0x6d + bcc %xcc, 1f + nop + sethi %hi(errno), %g4 + or %g4, %lo(errno), %g4 + st %o0,[%g4] + retl + mov -1, %o0 +1: + st %o0,[%g4] + st %o1,[%g4+4] + retl + mov 0, %o0 + + .size pipe,.-pipe diff -puN /dev/null usr/klibc/arch/sparc64/setjmp.S --- /dev/null +++ a/usr/klibc/arch/sparc64/setjmp.S @@ -0,0 +1,55 @@ +! +! setjmp.S +! +! Basic setjmp/longjmp +! +! This code was based on the equivalent code in NetBSD +! + +! +! The jmp_buf contains the following entries: +! sp +! fp +! pc +! + .text + .align 4 + .global setjmp + .type setjmp, @function +setjmp: + stx %sp,[%o0+0] ! Callers stack pointer + stx %o7,[%o0+8] ! Return pc + stx %fp,[%o0+16] ! Frame pointer + retl ! Return + clr %o0 ! ...0 + + .size setjmp,.-setjmp + + + .globl longjmp + .type longjmp, @function +longjmp: + mov %o1, %g4 ! save return value + mov %o0, %g1 ! save target + ldx [%g1+16],%g5 ! get callers frame +1: + cmp %fp, %g5 ! compare against desired frame + bl,a 1b ! if below... + restore ! pop frame and loop + be,a 2f ! if there... + ldx [%g1+0],%o2 ! fetch return %sp + +.Lbotch: + unimp 0 ! ... error ... + +2: + cmp %o2, %sp ! %sp must not decrease + bl .Lbotch + nop + mov %o2, %sp ! it is OK, put it in place + + ldx [%g1+8],%o3 ! fetch %pc + jmp %o3 + 8 ! if sucess... + mov %g4,%o0 ! return %g4 + + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/sparc64/syscall.S --- /dev/null +++ a/usr/klibc/arch/sparc64/syscall.S @@ -0,0 +1,18 @@ +/* + * arch/sparc64/syscall.S + * + * Common system-call stub; %g1 already set to syscall number + */ + + .globl __syscall_common + .type __syscall_common,#function + .align 4 +__syscall_common: + t 0x6d + bcc %xcc, 1f + sethi %hi(errno), %g4 + or %g4, %lo(errno), %g4 + st %o0,[%g4] +1: + retl + movcs %xcc, -1, %o0 diff -puN /dev/null usr/klibc/arch/sparc64/sysfork.S --- /dev/null +++ a/usr/klibc/arch/sparc64/sysfork.S @@ -0,0 +1,26 @@ +/* + * arch/sparc64/sysfork.S + * + * The fork and vfork system calls are special on sparc[64]: + * they return the "other process" pid in %o0 and the + * "is child" flag in %o1 + * + * Common system-call stub; %g1 already set to syscall number + */ + + .globl __syscall_forkish + .type __syscall_forkish,#function + .align 4 +__syscall_forkish: + t 0x6d + sub %o1, 1, %o1 + bcc,a %xcc, 1f + and %o0, %o1, %o0 + sethi %hi(errno), %g4 + or %g4, %lo(errno), %g4 + st %o0, [%g4] + retl + mov -1, %o0 +1: + retl + nop diff -puN /dev/null usr/klibc/arch/sparc64/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/sparc64/sysstub.ph @@ -0,0 +1,25 @@ +# -*- perl -*- +# +# arch/sparc64/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + $stype = $stype || 'common'; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT "\tb __syscall_${stype}\n"; + print OUT "\t mov\t__NR_${sname}, %g1\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/sparc/crt0i.S --- /dev/null +++ a/usr/klibc/arch/sparc/crt0i.S @@ -0,0 +1,100 @@ +! This file derived from the equivalent in newlib +! +! C run time start off + +! This file supports: +! +! - both 32bit pointer and 64bit pointer environments (at compile time) +! - an imposed stack bias (of 2047) (at run time) +! - medium/low and medium/anywhere code models (at run time) + +! Initial stack setup: +! +! bottom of stack (higher memory address) +! ... +! text of environment strings +! text of argument strings +! envp[envc] = 0 (4/8 bytes) +! ... +! env[0] (4/8 bytes) +! argv[argc] = 0 (4/8 bytes) +! ... +! argv[0] (4/8 bytes) +! argc (4/8 bytes) +! register save area (64 bits by 16 registers = 128 bytes) +! top of stack (%sp) + +! Stack Bias: +! +! It is the responsibility of the o/s to set this up. +! We handle both a 0 and 2047 value for the stack bias. + +! Medium/Anywhere code model support: +! +! In this model %g4 points to the start of the data segment. +! The text segment can go anywhere, but %g4 points to the *data* segment. +! It is up to the compiler/linker to get this right. +! +! Since this model is statically linked the start of the data segment +! is known at link time. Eg: +! +! sethi %hh(data_start), %g1 +! sethi %lm(data_start), %g4 +! or %g1, %hm(data_start), %g1 +! or %g4, %lo(data_start), %g4 +! sllx %g1, 32, %g1 +! or %g4, %g1, %g4 +! +! FIXME: For now we just assume 0. + +! FIXME: if %g1 contains a non-zero value, atexit() should be invoked +! with this value. + + + .text + .align 4 + .globl _start + .type _start, @function +_start: + clr %fp + +! We use %g4 even if the code model is Medium/Low (simplifies the code). + + clr %g4 ! Medium/Anywhere base reg + +! If there is a stack bias in effect, account for it in %g5. Then always +! add %g5 to stack references below. This way the code can be used with +! or without an imposed bias. + + andcc %sp, 1, %g5 + bz,a .LNoBias + nop + mov 2047, %g5 +.LNoBias: + add %sp, %g5, %g5 + +! On entry, the kernel leaves room for one register frame, but +! the C API wants more free space. Thus, we need to drop the stack +! pointer additionally. + +#if TARGET_PTR_SIZE == 32 + sub %sp, 32, %sp ! make room for incoming arguments +#else /* TARGET_PTR_SIZE == 64 */ + sub %sp, 64, %sp ! make room for incoming arguments +#endif + +! Set up pointers to the ELF data structure (argc, argv, ...) +! Pass as the first argument to __libc_init +#if TARGET_PTR_SIZE == 32 + add %g5, 0x40, %o0 +#else /* TARGET_PTR_SIZE == 64 */ + add %g5, 0x80, %o0 +#endif + + call __libc_init + mov %g1, %o1 ! This is the "atexit" pointer; + ! pass as the second argument to __libc_init + +! If __libc_init returns, something is hosed. Try an illegal insn. +! If that does not work, the o/s is hosed more than we are. + .long 0 diff -puN /dev/null usr/klibc/arch/sparc/crt0.S --- /dev/null +++ a/usr/klibc/arch/sparc/crt0.S @@ -0,0 +1,2 @@ +#define TARGET_PTR_SIZE 32 +#include "crt0i.S" diff -puN /dev/null usr/klibc/arch/sparc/divrem.m4 --- /dev/null +++ a/usr/klibc/arch/sparc/divrem.m4 @@ -0,0 +1,276 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp + * $NetBSD: divrem.m4,v 1.4 1997/10/09 10:07:54 lukem Exp $ + */ + +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +#if defined(LIBC_SCCS) && !defined(lint) + .asciz "@(#)divrem.m4 8.1 (Berkeley) 6/4/93" +#endif /* LIBC_SCCS and not lint */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * NAME name of function to generate + * OP OP=div => %o0 / %o1; OP=rem => %o0 % %o1 + * S S=true => signed; S=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TWOSUPN 2^N, for label generation (m4 exponentiation currently broken) + * TOPBITS number of bits in the top `decade' of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + +define(N, `4') +define(TWOSUPN, `16') +define(WORDSIZE, `32') +define(TOPBITS, eval(WORDSIZE - N*((WORDSIZE-1)/N))) + +define(dividend, `%o0') +define(divisor, `%o1') +define(Q, `%o2') +define(R, `%o3') +define(ITER, `%o4') +define(V, `%o5') + +/* m4 reminder: ifelse(a,b,c,d) => if a is b, then c, else d */ +define(T, `%g1') +define(SC, `%g7') +ifelse(S, `true', `define(SIGN, `%g6')') + +/* + * This is the recursive definition for developing quotient digits. + * + * Parameters: + * $1 the current depth, 1 <= $1 <= N + * $2 the current accumulation of quotient bits + * N max depth + * + * We add a new bit to $2 and either recurse or insert the bits in + * the quotient. R, Q, and V are inputs and outputs as defined above; + * the condition codes are expected to reflect the input R, and are + * modified to reflect the output R. + */ +define(DEVELOP_QUOTIENT_BITS, +` ! depth $1, accumulated bits $2 + bl L.$1.eval(TWOSUPN+$2) + srl V,1,V + ! remainder is positive + subcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2+1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2+1)')') +L.$1.eval(TWOSUPN+$2): + ! remainder is negative + addcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2-1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2-1)')') + ifelse($1, 1, `9:')') + +#include +#include + +FUNC(NAME) +ifelse(S, `true', +` ! compute sign of result; if neither is negative, no problem + orcc divisor, dividend, %g0 ! either negative? + bge 2f ! no, go do the divide + ifelse(OP, `div', + `xor divisor, dividend, SIGN', + `mov dividend, SIGN') ! compute sign in any case + tst divisor + bge 1f + tst dividend + ! divisor is definitely negative; dividend might also be negative + bge 2f ! if dividend not negative... + neg divisor ! in any case, make divisor nonneg +1: ! dividend is negative, divisor is nonnegative + neg dividend ! make dividend nonnegative +2: +') + ! Ready to divide. Compute size of quotient; scale comparand. + orcc divisor, %g0, V + bnz 1f + mov dividend, R + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + t ST_DIV0 + retl + clr %o0 + +1: + cmp R, V ! if divisor exceeds dividend, done + blu Lgot_result ! (and algorithm fails otherwise) + clr Q + sethi %hi(1 << (WORDSIZE - TOPBITS - 1)), T + cmp R, T + blu Lnot_really_big + clr ITER + + ! `Here the dividend is >= 2^(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R.' + 1: + cmp V, T + bgeu 3f + mov 1, SC + sll V, N, V + b 1b + inc ITER + + ! Now compute SC. + 2: addcc V, V, V + bcc Lnot_too_big + inc SC + + ! We get here if the divisor overflowed while shifting. + ! This means that R has the high-order bit set. + ! Restore V and subtract from R. + sll T, TOPBITS, T ! high order bit + srl V, 1, V ! rest of V + add V, T, V + b Ldo_single_div + dec SC + + Lnot_too_big: + 3: cmp V, R + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! V > R: went too far: back up 1 step + ! srl V, 1, V + ! dec SC + ! do single-bit divide steps + ! + ! We have to be careful here. We know that R >= V, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if R >= 0. Because both R and V may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + deccc SC + bl Lend_regular_divide + nop + sub R, V, R + mov 1, Q + b Lend_single_divloop + nop + Lsingle_divloop: + sll Q, 1, Q + bl 1f + srl V, 1, V + ! R >= 0 + sub R, V, R + b 2f + inc Q + 1: ! R < 0 + add R, V, R + dec Q + 2: + Lend_single_divloop: + deccc SC + bge Lsingle_divloop + tst R + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll V, N, V + cmp V, R + bleu 1b + inccc ITER + be Lgot_result + dec ITER + + tst R ! set up for initial iteration +Ldivloop: + sll Q, N, Q + DEVELOP_QUOTIENT_BITS(1, 0) +Lend_regular_divide: + deccc ITER + bge Ldivloop + tst R + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) +ifelse(OP, `div', +` dec Q +', ` add R, divisor, R +') + +Lgot_result: +ifelse(S, `true', +` ! check to see if answer should be < 0 + tst SIGN + bl,a 1f + ifelse(OP, `div', `neg Q', `neg R') +1:') + retl + ifelse(OP, `div', `mov Q, %o0', `mov R, %o0') diff -puN /dev/null usr/klibc/arch/sparc/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/sparc/Makefile.inc @@ -0,0 +1,48 @@ +# -*- makefile -*- +# +# arch/sparc/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +m4-targets := arch/$(KLIBCARCH)/sdiv.o arch/$(KLIBCARCH)/srem.o \ + arch/$(KLIBCARCH)/udiv.o arch/$(KLIBCARCH)/urem.o + +KLIBCARCHOBJS = $(m4-targets) \ + arch/$(KLIBCARCH)/smul.o \ + arch/$(KLIBCARCH)/umul.o \ + arch/$(KLIBCARCH)/__muldi3.o \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/pipe.o \ + arch/$(KLIBCARCH)/syscall.o \ + arch/$(KLIBCARCH)/sysfork.o \ + libgcc/__ashldi3.o \ + libgcc/__ashrdi3.o \ + libgcc/__lshrdi3.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o \ + libgcc/__clzsi2.o \ + + +adir := $(obj)/arch/$(KLIBCARCH) + +$(adir)/sdiv.S: m4 := define(NAME,\`.div')define(OP,\`div')define(S,\`true') +$(adir)/srem.S: m4 := define(NAME,\`.rem')define(OP,\`rem')define(S,\`true') +$(adir)/udiv.S: m4 := define(NAME,\`.udiv')define(OP,\`div')define(S,\`false') +$(adir)/urem.S: m4 := define(NAME,\`.urem')define(OP,\`rem')define(S,\`false') + +targets += $(m4-targets) $(m4-targets:.o=.S) + +quiet_cmd_m4 = M4 $@ + cmd_m4 = (echo "$(m4)"; cat $^) | m4 > $@ + +# build .o from .S +$(addprefix $(obj)/,$(m4-targets)): $(adir)/%.o : $(adir)/%.S +# build .S from .m4 +$(addprefix $(obj)/,$(m4-targets:.o=.S)): $(src)/arch/$(KLIBCARCH)/divrem.m4 + $(call if_changed,m4) diff -puN /dev/null usr/klibc/arch/sparc/MCONFIG --- /dev/null +++ a/usr/klibc/arch/sparc/MCONFIG @@ -0,0 +1,19 @@ +# -*- makefile -*- +# +# arch/sparc/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCOPTFLAGS = -Os -m32 -mptr32 +KLIBCBITSIZE = 32 +KLIBCARCHREQFLAGS += -D__sparc32__ + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# Normal binaries start at 64K; the linker wants 64K alignment, +# and call instructions have a 30-bit signed offset, << 2. +KLIBCSHAREDFLAGS = -Ttext 0x40000100 diff -puN /dev/null usr/klibc/arch/sparc/__muldi3.S --- /dev/null +++ a/usr/klibc/arch/sparc/__muldi3.S @@ -0,0 +1,27 @@ + .global .umul + .section ".text" + .align 4 + .global __muldi3 + .type __muldi3, #function + .proc 017 +__muldi3: + save %sp, -104, %sp + mov %i1, %o0 + call .umul, 0 + mov %i3, %o1 + mov %o0, %l2 + mov %o1, %l3 + mov %i1, %o0 + call .umul, 0 + mov %i2, %o1 + mov %i0, %o1 + mov %o0, %l0 + call .umul, 0 + mov %i3, %o0 + mov 0, %l1 + add %l0, %o0, %l0 + addcc %l3, %l1, %i1 + addx %l2, %l0, %i0 + jmp %i7+8 + restore + .size __muldi3, .-__muldi3 diff -puN /dev/null usr/klibc/arch/sparc/pipe.S --- /dev/null +++ a/usr/klibc/arch/sparc/pipe.S @@ -0,0 +1,30 @@ +/* + * arch/sparc/pipe.S + * + * The pipe system call are special on sparc[64]: + * they return the two file descriptors in %o0 and %o1. + */ + +#include + + .globl pipe + .type pipe,#function + .align 4 +pipe: + mov __NR_pipe, %g1 + or %o0, 0, %g4 + t 0x10 + bcc 1f + nop + sethi %hi(errno), %g4 + or %g4, %lo(errno), %g4 + st %o0,[%g4] + retl + mov -1, %o0 +1: + st %o0,[%g4] + st %o1,[%g4+4] + retl + mov 0, %o0 + + .size pipe,.-pipe diff -puN /dev/null usr/klibc/arch/sparc/setjmp.S --- /dev/null +++ a/usr/klibc/arch/sparc/setjmp.S @@ -0,0 +1,38 @@ +! +! setjmp.S +! +! Basic setjmp/longjmp +! +! This code was based on the equivalent code in NetBSD +! + +#include +#include + +! +! The jmp_buf contains the following entries: +! sp +! fp +! pc +! +ENTRY(setjmp) + st %sp,[%o0+0] ! Callers stack pointer + st %o7,[%o0+4] ! Return pc + st %fp,[%o0+8] ! Frame pointer + retl ! Return + clr %o0 ! ...0 + +ENTRY(longjmp) + sub %sp, 64, %sp ! set up a local stack frame +0: + t ST_FLUSHWIN ! flush register windows out to memory + ! + ! We restore the saved stack pointer to %fp, then issue + ! a restore instruction which will reload the register + ! window from the stack. + ! + ld [%o0+4], %o7 /* restore return pc */ + ld [%o0+0], %fp /* and stack pointer */ + + retl ! success, return %g6 + restore %o1, 0, %o0 diff -puN /dev/null usr/klibc/arch/sparc/smul.S --- /dev/null +++ a/usr/klibc/arch/sparc/smul.S @@ -0,0 +1,160 @@ +/* $NetBSD: mul.S,v 1.3 1997/07/16 14:37:42 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: mul.s,v 1.5 92/06/25 13:24:03 torek Exp + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 + .asciz "@(#)mul.s 8.1 (Berkeley) 6/4/93" +#else + RCSID("$NetBSD: mul.S,v 1.3 1997/07/16 14:37:42 christos Exp $") +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * Signed multiply, from Appendix E of the Sparc Version 8 + * Architecture Manual. + * + * Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the upper 32 bits of + * the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. + */ + +FUNC(.mul) + mov %o0, %y ! multiplier -> Y + andncc %o0, 0xfff, %g0 ! test bits 12..31 + be Lmul_shortway ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear N and V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + ! If %o0 was negative, the result is + ! (%o0 * %o1) + (%o1 << 32)) + ! We fix that here. + + tst %o0 + bge 1f + rd %y, %o0 + + ! %o0 was indeed negative; fix upper 32 bits of result by subtracting + ! %o1 (i.e., return %o4 - %o1 in %o1). + retl + sub %o4, %o1, %o1 + +1: + retl + mov %o4, %o1 + +Lmul_shortway: + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the low part of the + * result; %y has the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * --hi-- ----low-part---- + * + * The upper 12 bits of %o4 should be sign-extended to form the + * high part of the product (i.e., highpart = %o4 >> 20). + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20, zero fill at left + or %o5, %o0, %o0 ! construct low part of result + retl + sra %o4, 20, %o1 ! ... and extract high part of result diff -puN /dev/null usr/klibc/arch/sparc/syscall.S --- /dev/null +++ a/usr/klibc/arch/sparc/syscall.S @@ -0,0 +1,19 @@ +/* + * arch/sparc/syscall.S + * + * Common system-call stub; %g1 already set to syscall number + */ + + .globl __syscall_common + .type __syscall_common,#function + .align 4 +__syscall_common: + t 0x10 + bcc 1f + sethi %hi(errno), %g4 + or %g4, %lo(errno), %g4 + st %o0,[%g4] + mov -1, %o0 +1: + retl + nop diff -puN /dev/null usr/klibc/arch/sparc/sysfork.S --- /dev/null +++ a/usr/klibc/arch/sparc/sysfork.S @@ -0,0 +1,25 @@ +/* + * arch/sparc/sysfork.S + * + * The fork and vfork system calls are special on sparc[64]: + * they return the "other process" pid in %o0 and the + * "is child" flag in %o1 + * + * Common system-call stub; %g1 already set to syscall number + */ + + .globl __syscall_forkish + .type __syscall_forkish,#function + .align 4 +__syscall_forkish: + t 0x10 + sub %o1, 1, %o1 + bcc,a 1f + and %o0, %o1, %o0 + sethi %hi(errno), %g4 + or %g4, %lo(errno), %g4 + st %o0,[%g4] + mov -1, %o0 +1: + retl + nop diff -puN /dev/null usr/klibc/arch/sparc/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/sparc/sysstub.ph @@ -0,0 +1,25 @@ +# -*- perl -*- +# +# arch/sparc32/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + $stype = $stype || 'common'; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT "\tb __syscall_${stype}\n"; + print OUT "\t mov\t__NR_${sname}, %g1\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/sparc/umul.S --- /dev/null +++ a/usr/klibc/arch/sparc/umul.S @@ -0,0 +1,193 @@ +/* $NetBSD: umul.S,v 1.3 1997/07/16 14:37:44 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: umul.s,v 1.4 92/06/25 13:24:05 torek Exp + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 + .asciz "@(#)umul.s 8.1 (Berkeley) 6/4/93" +#else + RCSID("$NetBSD: umul.S,v 1.3 1997/07/16 14:37:44 christos Exp $") +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the + * upper 32 bits of the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. Short + * multiplies require 25 instruction cycles, and long ones require + * 45 instruction cycles. + * + * On return, overflow has occurred (%o1 is not zero) if and only if + * the Z condition code is clear, allowing, e.g., the following: + * + * call .umul + * nop + * bnz overflow (or tnz) + */ + +FUNC(.umul) + or %o0, %o1, %o4 + mov %o0, %y ! multiplier -> Y + andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args + be Lmul_shortway ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear N and V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + + /* + * Normally, with the shift-and-add approach, if both numbers are + * positive you get the correct result. WIth 32-bit two's-complement + * numbers, -x is represented as + * + * x 32 + * ( 2 - ------ ) mod 2 * 2 + * 32 + * 2 + * + * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s, + * we can treat this as if the radix point were just to the left + * of the sign bit (multiply by 2^32), and get + * + * -x = (2 - x) mod 2 + * + * Then, ignoring the `mod 2's for convenience: + * + * x * y = xy + * -x * y = 2y - xy + * x * -y = 2x - xy + * -x * -y = 4 - 2x - 2y + xy + * + * For signed multiplies, we subtract (x << 32) from the partial + * product to fix this problem for negative multipliers (see mul.s). + * Because of the way the shift into the partial product is calculated + * (N xor V), this term is automatically removed for the multiplicand, + * so we don't have to adjust. + * + * But for unsigned multiplies, the high order bit wasn't a sign bit, + * and the correction is wrong. So for unsigned multiplies where the + * high order bit is one, we end up with xy - (y << 32). To fix it + * we add y << 32. + */ + tst %o1 + bl,a 1f ! if %o1 < 0 (high order bit = 1), + add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half) +1: rd %y, %o0 ! get lower half of product + retl + addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0 + +Lmul_shortway: + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above), + * and overflow is impossible (the answer is at most 24 bits long). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the result; %y has + * the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * -----result----- + * + * The 12 bits of %o4 left of the `result' area are all zero; + * in fact, all top 20 bits of %o4 are zero. + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20 + or %o5, %o0, %o0 + retl + addcc %g0, %g0, %o1 ! %o1 = zero, and set Z diff -puN /dev/null usr/klibc/arch/x86_64/crt0.S --- /dev/null +++ a/usr/klibc/arch/x86_64/crt0.S @@ -0,0 +1,22 @@ +# +# arch/x86_64/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + movq %rsp,%rdi # Offset of the ELF data structure + movq %rdx,%rsi # The atexit() pointer (if any) + call __libc_init + # We should never get here... + hlt + + .size _start,.-_start diff -puN /dev/null usr/klibc/arch/x86_64/Makefile.inc --- /dev/null +++ a/usr/klibc/arch/x86_64/Makefile.inc @@ -0,0 +1,18 @@ +# -*- makefile -*- +# +# arch/x86_64/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + arch/$(KLIBCARCH)/sigreturn.o \ + arch/$(KLIBCARCH)/vfork.o + +KLIBCARCHSOOBJS = $(patsubst %.o,%.lo,$(KLIBCARCHOBJS)) + +archclean: diff -puN /dev/null usr/klibc/arch/x86_64/MCONFIG --- /dev/null +++ a/usr/klibc/arch/x86_64/MCONFIG @@ -0,0 +1,35 @@ +# -*- makefile -*- +# +# arch/x86-64/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# +# Blatantly copied and modified from i386 version by Mats Petersson, AMD. +# + +# +# NOTE: -fno-asynchronous-unwind-tables produce significantly smaller +# binaries (20% smaller), but makes the code completely useless for +# debugging using gdb. +# +KLIBCARCHREQFLAGS = -m64 +ifeq ($(DEBUG),y) +KLIBCOPTFLAGS = -Os -fomit-frame-pointer \ + -falign-functions=1 -falign-jumps=1 -falign-loops=1 +else +KLIBCOPTFLAGS = -Os -fno-asynchronous-unwind-tables -fomit-frame-pointer \ + -falign-functions=1 -falign-jumps=1 -falign-loops=1 +endif +KLIBCBITSIZE = 64 +KLIBCLDFLAGS = -m elf_x86_64 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 2 MB - normal binaries start at 4 MB +KLIBCSHAREDFLAGS = -Ttext 0x00200200 + +# Additional asm- directories needed during installation +ASMARCH = asm-i386 diff -puN /dev/null usr/klibc/arch/x86_64/setjmp.S --- /dev/null +++ a/usr/klibc/arch/x86_64/setjmp.S @@ -0,0 +1,54 @@ +# +# arch/x86_64/setjmp.S +# +# setjmp/longjmp for the x86-64 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# %rbx +# %rsp (post-return) +# %rbp +# %r12 +# %r13 +# %r14 +# %r15 +# +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: + pop %rsi # Return address, and adjust the stack + xorl %eax,%eax # Return value + movq %rbx,(%rdi) + movq %rsp,8(%rdi) # Post-return %rsp! + push %rsi # Make the call/return stack happy + movq %rbp,16(%rdi) + movq %r12,24(%rdi) + movq %r13,32(%rdi) + movq %r14,40(%rdi) + movq %r15,48(%rdi) + movq %rsi,56(%rdi) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: + movl %esi,%eax # Return value (int) + movq (%rdi),%rbx + movq 8(%rdi),%rsp + movq 16(%rdi),%rbp + movq 24(%rdi),%r12 + movq 32(%rdi),%r13 + movq 40(%rdi),%r14 + movq 48(%rdi),%r15 + jmp *56(%rdi) + + .size longjmp,.-longjmp diff -puN /dev/null usr/klibc/arch/x86_64/sigreturn.S --- /dev/null +++ a/usr/klibc/arch/x86_64/sigreturn.S @@ -0,0 +1,15 @@ +/* + * arch/x86_64/sigreturn.S + */ + +#include + + .text + .align 4 + .globl __sigreturn + .type __sigreturn,@function +__sigreturn: + movl $__NR_rt_sigreturn,%eax + syscall + + .size __sigreturn,.-__sigreturn diff -puN /dev/null usr/klibc/arch/x86_64/syscall.S --- /dev/null +++ a/usr/klibc/arch/x86_64/syscall.S @@ -0,0 +1,28 @@ +/* + * arch/x86-64/syscall.S + * + * Common tail-handling code for system calls. + * + * The arguments are in the standard argument registers; the system + * call number in %eax. + */ + .text + .align 4 + .globl __syscall_common + .type __syscall_common,@function +__syscall_common: + movq %rcx,%r10 # The kernel uses %r10 istf %rcx + syscall + + cmpq $-4095,%rax + jnb 1f + ret + + # Error return, must set errno +1: + negl %eax + movl %eax,errno(%rip) # errno is type int, so 32 bits + orq $-1,%rax # orq $-1 smaller than movq $-1 + ret + + .size __syscall_common,.-__syscall_common diff -puN /dev/null usr/klibc/arch/x86_64/sysstub.ph --- /dev/null +++ a/usr/klibc/arch/x86_64/sysstub.ph @@ -0,0 +1,23 @@ +# -*- perl -*- +# +# arch/x86_64/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT "\tmovl \$__NR_${sname},%eax\n"; # Zero-extends to 64 bits + print OUT "\tjmp __syscall_common\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff -puN /dev/null usr/klibc/arch/x86_64/vfork.S --- /dev/null +++ a/usr/klibc/arch/x86_64/vfork.S @@ -0,0 +1,26 @@ +# +# usr/klibc/arch/x86_64/vfork.S +# +# vfork is nasty - there must be nothing at all on the stack above +# the stack frame of the enclosing function. +# + +#include + + .text + .align 4 + .globl vfork + .type vfork, @function +vfork: + pop %rdx /* Return address */ + movl $__NR_vfork, %eax + syscall + push %rdx + cmpq $-4095, %rax + jae 1f + ret +1: + negl %eax + movl %eax, errno(%rip) + orq $-1, %rax + ret diff -puN /dev/null usr/klibc/asprintf.c --- /dev/null +++ a/usr/klibc/asprintf.c @@ -0,0 +1,30 @@ +/* + * asprintf.c + */ + +#include +#include +#include + +int asprintf(char **bufp, const char *format, ...) +{ + va_list ap, ap1; + int rv; + int bytes; + char *p; + + va_start(ap, format); + va_copy(ap1, ap); + + bytes = vsnprintf(NULL, 0, format, ap1) + 1; + va_end(ap1); + + *bufp = p = malloc(bytes); + if (!p) + return -1; + + rv = vsnprintf(p, bytes, format, ap); + va_end(ap); + + return rv; +} diff -puN /dev/null usr/klibc/assert.c --- /dev/null +++ a/usr/klibc/assert.c @@ -0,0 +1,14 @@ +/* + * assert.c + */ + +#include +#include +#include +#include + +__noreturn __assert_fail(const char *expr, const char *file, unsigned int line) +{ + printf("Assertion %s failed, file %s, line %u\n", expr, file, line); + abort(); +} diff -puN /dev/null usr/klibc/atexit.c --- /dev/null +++ a/usr/klibc/atexit.c @@ -0,0 +1,10 @@ +/* + * atexit.c + */ + +#include + +int atexit(void (*fctn) (void)) +{ + return on_exit((void (*)(int, void *))fctn, NULL); +} diff -puN /dev/null usr/klibc/atexit.h --- /dev/null +++ a/usr/klibc/atexit.h @@ -0,0 +1,18 @@ +/* + * atexit.h + * + * atexit()/on_exit() internal definitions + */ + +#ifndef ATEXIT_H +#define ATEXIT_H + +struct atexit { + void (*fctn) (int, void *); + void *arg; /* on_exit() parameter */ + struct atexit *next; +}; + +extern struct atexit *__atexit_list; + +#endif /* ATEXIT_H */ diff -puN /dev/null usr/klibc/atoi.c --- /dev/null +++ a/usr/klibc/atoi.c @@ -0,0 +1,3 @@ +#define TYPE int +#define NAME atoi +#include "atox.c" diff -puN /dev/null usr/klibc/atol.c --- /dev/null +++ a/usr/klibc/atol.c @@ -0,0 +1,3 @@ +#define TYPE long +#define NAME atol +#include "atox.c" diff -puN /dev/null usr/klibc/atoll.c --- /dev/null +++ a/usr/klibc/atoll.c @@ -0,0 +1,3 @@ +#define TYPE long long +#define NAME atoll +#include "atox.c" diff -puN /dev/null usr/klibc/atox.c --- /dev/null +++ a/usr/klibc/atox.c @@ -0,0 +1,14 @@ +/* + * atox.c + * + * atoi(), atol(), atoll() + */ + +#include +#include +#include + +TYPE NAME(const char *nptr) +{ + return (TYPE) strntoumax(nptr, (char **)NULL, 10, ~(size_t) 0); +} diff -puN /dev/null usr/klibc/brk.c --- /dev/null +++ a/usr/klibc/brk.c @@ -0,0 +1,24 @@ +/* brk.c - Change data segment size */ + +/* Written 2000 by Werner Almesberger */ + +#include +#include +#include + +char *__current_brk; /* Common with sbrk.c */ + +/* + * The Linux brk() isn't what most people expect, so we call the + * system call __brk() and provide a wrapper. + */ +int brk(void *end_data_segment) +{ + char *new_brk; + + new_brk = __brk(end_data_segment); + if (new_brk != end_data_segment) + return -1; + __current_brk = new_brk; + return 0; +} diff -puN /dev/null usr/klibc/bsd_signal.c --- /dev/null +++ a/usr/klibc/bsd_signal.c @@ -0,0 +1,11 @@ +/* + * bsd_signal.c + */ + +#include + +__sighandler_t bsd_signal(int signum, __sighandler_t handler) +{ + /* BSD signal() semantics */ + return __signal(signum, handler, SA_RESTART); +} diff -puN /dev/null usr/klibc/bsearch.c --- /dev/null +++ a/usr/klibc/bsearch.c @@ -0,0 +1,26 @@ +/* + * bsearch.c + */ + +#include + +void *bsearch(const void *key, const void *base, size_t nmemb, + size_t size, int (*cmp) (const void *, const void *)) +{ + while (nmemb) { + size_t mididx = nmemb / 2; + const void *midobj = base + mididx * size; + int diff = cmp(key, midobj); + + if (diff == 0) + return (void *)midobj; + + if (diff > 0) { + base = midobj + size; + nmemb -= mididx + 1; + } else + nmemb = mididx; + } + + return NULL; +} diff -puN /dev/null usr/klibc/calloc.c --- /dev/null +++ a/usr/klibc/calloc.c @@ -0,0 +1,20 @@ +/* + * calloc.c + */ + +#include +#include + +/* FIXME: This should look for multiplication overflow */ + +void *calloc(size_t nmemb, size_t size) +{ + void *ptr; + + size *= nmemb; + ptr = malloc(size); + if (ptr) + memset(ptr, 0, size); + + return ptr; +} diff -puN /dev/null usr/klibc/CAVEATS --- /dev/null +++ a/usr/klibc/CAVEATS @@ -0,0 +1,60 @@ + ------------------------------------------------- + Please note the following caveats to using klibc: + ------------------------------------------------- + +optimization: +------------- + +Compiling with -O0 is not supported. It may or may not work; please +use -O1 if you want to do maximize debuggability. + +Compiling with -O0 is more likely to work on gcc 3. + + +setjmp()/longjmp(): +------------------- + +setjmp() and longjmp() *do not* save signal state. sigsetjmp() and +siglongjmp() *do* save the signal mask -- regardless of the value of +the extra argument. + +The standards actually state that if you pass longjmp() a final value +of zero the library should change that to a 1! Presumably the reason +is so people who write broken code can get away with writing +longjmp(buf); or something equally bad. If you pass longjmp() a final +value of 0 you get what you deserve -- setjmp() will happily return 0. + + +stdio: +------ + +Only a small subset of the stdio functions are implemented. Those +that are implemented do not buffer, although they *do* trap EINTR or +short read/writes and iterate. + +_fread() and _fwrite(), which take only one size argument (like +read/write), but do handle EINTR/short return are also available. + + +namespaces: +----------- + +klibc frequently includes headers in other headers in a way that +exposes more symbols than POSIX says they should. "Live with it." + + +theading: +--------- + +klibc is not thread-safe. Consequently, clone() or any of the +pthreads functions are not included. + + +bsd_signal vs sysv_signal: +-------------------------- + +There is no signal() call, because you never know if you want +Linux/SysV semantics (SA_RESETHAND) or GNU/BSD semantics (SA_RESTART). +The best, in *any* circumstances, is to never use signal() and instead +use sigaction(), but in order to simplify porting you can use either +sysv_signal() or bsd_signal(), depending on what you actually want. diff -puN /dev/null usr/klibc/clearenv.c --- /dev/null +++ a/usr/klibc/clearenv.c @@ -0,0 +1,17 @@ +/* + * clearenv.c + * + * Empty the environment + */ + +#include +#include +#include "env.h" + +/* Note: if environ has been malloc'd, it will be freed on the next + setenv() or putenv() */ +int clearenv(void) +{ + environ = (char **)__null_environ; + return 0; +} diff -puN /dev/null usr/klibc/closelog.c --- /dev/null +++ a/usr/klibc/closelog.c @@ -0,0 +1,18 @@ +/* + * closelog.c + */ + +#include +#include + +extern int __syslog_fd; + +void closelog(void) +{ + int logfd = __syslog_fd; + + if (logfd != -1) { + close(logfd); + __syslog_fd = -1; + } +} diff -puN /dev/null usr/klibc/creat.c --- /dev/null +++ a/usr/klibc/creat.c @@ -0,0 +1,12 @@ +/* + * creat.c + */ + +#include +#include +#include + +int creat(const char *pathname, mode_t mode) +{ + return open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); +} diff -puN /dev/null usr/klibc/ctype/ctypefunc.h --- /dev/null +++ a/usr/klibc/ctype/ctypefunc.h @@ -0,0 +1,13 @@ +/* + * ctype/ctype.h + * + * Common header for out-of-line ctype functions + */ + +#define __CTYPE_NO_INLINE +#include + +#define CTYPEFUNC(X) \ + int X(int c) { \ + return __ctype_##X(c); \ + } diff -puN /dev/null usr/klibc/ctype/isalnum.c --- /dev/null +++ a/usr/klibc/ctype/isalnum.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isalnum) diff -puN /dev/null usr/klibc/ctype/isalpha.c --- /dev/null +++ a/usr/klibc/ctype/isalpha.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isalpha) diff -puN /dev/null usr/klibc/ctype/isascii.c --- /dev/null +++ a/usr/klibc/ctype/isascii.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isascii) diff -puN /dev/null usr/klibc/ctype/isblank.c --- /dev/null +++ a/usr/klibc/ctype/isblank.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isblank) diff -puN /dev/null usr/klibc/ctype/iscntrl.c --- /dev/null +++ a/usr/klibc/ctype/iscntrl.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(iscntrl) diff -puN /dev/null usr/klibc/ctype/isdigit.c --- /dev/null +++ a/usr/klibc/ctype/isdigit.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isdigit) diff -puN /dev/null usr/klibc/ctype/isgraph.c --- /dev/null +++ a/usr/klibc/ctype/isgraph.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isgraph) diff -puN /dev/null usr/klibc/ctype/islower.c --- /dev/null +++ a/usr/klibc/ctype/islower.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(islower) diff -puN /dev/null usr/klibc/ctype/isprint.c --- /dev/null +++ a/usr/klibc/ctype/isprint.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isprint) diff -puN /dev/null usr/klibc/ctype/ispunct.c --- /dev/null +++ a/usr/klibc/ctype/ispunct.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(ispunct) diff -puN /dev/null usr/klibc/ctype/isspace.c --- /dev/null +++ a/usr/klibc/ctype/isspace.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isspace) diff -puN /dev/null usr/klibc/ctype/isupper.c --- /dev/null +++ a/usr/klibc/ctype/isupper.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isupper) diff -puN /dev/null usr/klibc/ctype/isxdigit.c --- /dev/null +++ a/usr/klibc/ctype/isxdigit.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isxdigit) diff -puN /dev/null usr/klibc/ctypes.c --- /dev/null +++ a/usr/klibc/ctypes.c @@ -0,0 +1,284 @@ +/* + * ctypes.c + * + * This is the array that defines classes. + * This assumes ISO 8859-1. + */ + +#include + +const unsigned char __ctypes[257] = { + 0, /* EOF */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl | __ctype_space, /* BS */ + __ctype_cntrl | __ctype_space, /* TAB */ + __ctype_cntrl | __ctype_space, /* LF */ + __ctype_cntrl | __ctype_space, /* VT */ + __ctype_cntrl | __ctype_space, /* FF */ + __ctype_cntrl | __ctype_space, /* CR */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_print | __ctype_space, /* space */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_print | __ctype_space, /* NBSP */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_lower, /* lower accented */ + + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ +}; diff -puN /dev/null usr/klibc/ctype/tolower.c --- /dev/null +++ a/usr/klibc/ctype/tolower.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(tolower) diff -puN /dev/null usr/klibc/ctype/toupper.c --- /dev/null +++ a/usr/klibc/ctype/toupper.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(toupper) diff -puN /dev/null usr/klibc/daemon.c --- /dev/null +++ a/usr/klibc/daemon.c @@ -0,0 +1,35 @@ +/* + * daemon.c - "daemonize" a process + */ + +#include +#include +#include + +int daemon(int nochdir, int noclose) +{ + int nullfd; + pid_t f; + + if (!nochdir) { + if (chdir("/")) + return -1; + } + + if (!noclose) { + if ((nullfd = open("/dev/null", O_RDWR)) < 0 || + dup2(nullfd, 0) < 0 || + dup2(nullfd, 1) < 0 || + dup2(nullfd, 2) < 0) + return -1; + close(nullfd); + } + + f = fork(); + if (f < 0) + return -1; + else if (f > 0) + _exit(0); + + return setsid(); +} diff -puN /dev/null usr/klibc/env.h --- /dev/null +++ a/usr/klibc/env.h @@ -0,0 +1,10 @@ +#ifndef ENV_H +#define ENV_H + +/* str should be a duplicated version of the input string; + len is the length of the key including the = sign */ +int __put_env(char *str, size_t len, int overwrite); + +extern char *const __null_environ[]; + +#endif diff -puN /dev/null usr/klibc/exec_l.c --- /dev/null +++ a/usr/klibc/exec_l.c @@ -0,0 +1,59 @@ +/* + * exec_l.c + * + * Common implementation of execl() execle() execlp() + */ + +#include +#include +#include + +int NAME(const char *path, const char *arg0, ...) +{ + va_list ap, cap; + int argc = 1, rv; + const char **argv, **argp; + const char *arg; + char *const *envp; + + va_start(ap, arg0); + va_copy(cap, ap); + + /* Count the number of arguments */ + do { + arg = va_arg(cap, const char *); + argc++; + } while (arg); + + va_end(cap); + + /* Allocate memory for the pointer array */ + argp = argv = alloca(argc * sizeof(const char *)); + if (!argv) { + va_end(ap); + return -1; + } + + /* Copy the list into an array */ + *argp++ = arg0; + do { + *argp++ = arg = va_arg(ap, const char *); + } while (arg); + +#if EXEC_E + /* execle() takes one more argument for the environment pointer */ + envp = va_arg(ap, char *const *); +#else + envp = environ; +#endif + +#if EXEC_P + rv = execvpe(path, (char * const *)argv, envp); +#else + rv = execve(path, (char * const *)argv, envp); +#endif + + va_end(ap); + + return rv; +} diff -puN /dev/null usr/klibc/execl.c --- /dev/null +++ a/usr/klibc/execl.c @@ -0,0 +1,8 @@ +/* + * execl.c + */ + +#define NAME execl +#define EXEC_P 0 +#define EXEC_E 0 +#include "exec_l.c" diff -puN /dev/null usr/klibc/execle.c --- /dev/null +++ a/usr/klibc/execle.c @@ -0,0 +1,8 @@ +/* + * execle.c + */ + +#define NAME execle +#define EXEC_P 0 +#define EXEC_E 1 +#include "exec_l.c" diff -puN /dev/null usr/klibc/execlp.c --- /dev/null +++ a/usr/klibc/execlp.c @@ -0,0 +1,8 @@ +/* + * execlp.c + */ + +#define NAME execlp +#define EXEC_P 1 +#define EXEC_E 0 +#include "exec_l.c" diff -puN /dev/null usr/klibc/execlpe.c --- /dev/null +++ a/usr/klibc/execlpe.c @@ -0,0 +1,8 @@ +/* + * execlpe.c + */ + +#define NAME execlpe +#define EXEC_P 1 +#define EXEC_E 1 +#include "exec_l.c" diff -puN /dev/null usr/klibc/execv.c --- /dev/null +++ a/usr/klibc/execv.c @@ -0,0 +1,11 @@ +/* + * execv.c + */ + +#include +#include + +int execv(const char *path, char *const *argv) +{ + return execve(path, argv, environ); +} diff -puN /dev/null usr/klibc/execvp.c --- /dev/null +++ a/usr/klibc/execvp.c @@ -0,0 +1,11 @@ +/* + * execvp.c + */ + +#include +#include + +int execvp(const char *path, char *const *argv) +{ + return execvpe(path, argv, environ); +} diff -puN /dev/null usr/klibc/execvpe.c --- /dev/null +++ a/usr/klibc/execvpe.c @@ -0,0 +1,75 @@ +/* + * execvpe.c + * + * execvpe() function (from which we build execlp, execlpe, execvp). + * + * This version of execvpe() will *not* spawn /bin/sh if the command + * return ENOEXEC. That's what #! is for, folks! + * + * Since execlpe() and execvpe() aren't in POSIX, nor in glibc, + * I have followed QNX precedent in the implementation of the PATH: + * the PATH that is used is the one in the current environment, not + * in the new environment. Otherwise it would be impossible to pass + * a different PATH to the new process than the one one would want to + * use to search. + */ + +#include +#include +#include +#include +#include + +#define DEFAULT_PATH "/bin:/usr/bin:." + +int execvpe(const char *file, char *const *argv, char *const *envp) +{ + char path[PATH_MAX]; + const char *searchpath, *esp; + size_t prefixlen, filelen, totallen; + + if (strchr(file, '/')) /* Specific path */ + return execve(file, argv, envp); + + filelen = strlen(file); + + searchpath = getenv("PATH"); + if (!searchpath) + searchpath = DEFAULT_PATH; + + errno = ENOENT; /* Default errno, if execve() doesn't + change it */ + + do { + esp = strchr(searchpath, ':'); + if (esp) + prefixlen = esp - searchpath; + else + prefixlen = strlen(searchpath); + + if (prefixlen == 0 || searchpath[prefixlen - 1] == '/') { + totallen = prefixlen + filelen; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + memcpy(path + prefixlen, file, filelen); + } else { + totallen = prefixlen + filelen + 1; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + path[prefixlen] = '/'; + memcpy(path + prefixlen + 1, file, filelen); + } + path[totallen] = '\0'; + + execve(path, argv, envp); + if (errno == E2BIG || errno == ENOEXEC || + errno == ENOMEM || errno == ETXTBSY) + break; /* Report this as an error, no more search */ + + searchpath = esp + 1; + } while (esp); + + return -1; +} diff -puN /dev/null usr/klibc/exit.c --- /dev/null +++ a/usr/klibc/exit.c @@ -0,0 +1,30 @@ +/* + * exit.c + * + * exit(), including the handling of the atexit chain. + */ + +#include +#include +#include +#include "atexit.h" + +/* Link chain for atexit/on_exit */ +struct atexit *__atexit_list; + +__noreturn exit(int rv) +{ + struct atexit *ap; + + for (ap = __atexit_list; ap; ap = ap->next) { + /* This assumes extra args are harmless. They should + be in all normal C ABIs, but if an architecture has + some particularly bizarre ABI this might be worth + watching out for. */ + ap->fctn(rv, ap->arg); + } + + /* Handle any library destructors if we ever start using them... */ + + _exit(rv); +} diff -puN /dev/null usr/klibc/fgetc.c --- /dev/null +++ a/usr/klibc/fgetc.c @@ -0,0 +1,19 @@ +/* + * fgetc.c + * + * Extremely slow fgetc implementation, using _fread(). If people + * actually need character-oriented input to be fast, we may actually + * have to implement buffering. Sigh. + */ + +#include +#include +#include +#include + +int fgetc(FILE *f) +{ + unsigned char ch; + + return (_fread(&ch, 1, f) == 1) ? (int)ch : EOF; +} diff -puN /dev/null usr/klibc/fgets.c --- /dev/null +++ a/usr/klibc/fgets.c @@ -0,0 +1,31 @@ +/* + * fgets.c + * + * This will be very slow due to the implementation of getc(), + * but we don't have anywhere to put characters we don't need from + * the input. + */ + +#include + +char *fgets(char *s, int n, FILE *f) +{ + int ch; + char *p = s; + + while (n > 1) { + ch = getc(f); + if (ch == EOF) { + *p = '\0'; + return NULL; + } + *p++ = ch; + n--; + if (ch == '\n') + break; + } + if (n) + *p = '\0'; + + return s; +} diff -puN /dev/null usr/klibc/fopen.c --- /dev/null +++ a/usr/klibc/fopen.c @@ -0,0 +1,39 @@ +/* + * fopen.c + */ + +#include +#include +#include + +/* This depends on O_RDONLY == 0, O_WRONLY == 1, O_RDWR == 2 */ + +FILE *fopen(const char *file, const char *mode) +{ + int flags = O_RDONLY; + int plus = 0; + + while (*mode) { + switch (*mode++) { + case 'r': + flags = O_RDONLY; + break; + case 'w': + flags = O_WRONLY | O_CREAT | O_TRUNC; + break; + case 'a': + flags = O_WRONLY | O_CREAT | O_APPEND; + break; + case '+': + plus = 1; + break; + } + } + + if (plus) { + flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; + } + + /* Note: __create_file(-1) == NULL, so this is safe */ + return __create_file(open(file, flags, 0666)); +} diff -puN /dev/null usr/klibc/fork.c --- /dev/null +++ a/usr/klibc/fork.c @@ -0,0 +1,21 @@ +/* + * fork.c + * + * This is normally just a syscall stub, but at least one system + * doesn't have sys_fork, only sys_clone... + */ + +#include +#include +#include +#include +#include + +#if !_KLIBC_NO_MMU && !defined(__NR_fork) + +pid_t fork(void) +{ + return __clone(SIGCHLD, 0); +} + +#endif /* __NR_fork */ diff -puN /dev/null usr/klibc/fprintf.c --- /dev/null +++ a/usr/klibc/fprintf.c @@ -0,0 +1,19 @@ +/* + * fprintf.c + */ + +#include +#include + +#define BUFFER_SIZE 16384 + +int fprintf(FILE * file, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(file, format, ap); + va_end(ap); + return rv; +} diff -puN /dev/null usr/klibc/fputc.c --- /dev/null +++ a/usr/klibc/fputc.c @@ -0,0 +1,14 @@ +/* + * fputc.c + * + * gcc "printf decompilation" expects this to exist... + */ + +#include + +int fputc(int c, FILE *f) +{ + unsigned char ch = c; + + return _fwrite(&ch, 1, f) == 1 ? ch : EOF; +} diff -puN /dev/null usr/klibc/fputs.c --- /dev/null +++ a/usr/klibc/fputs.c @@ -0,0 +1,15 @@ +/* + * fputs.c + * + * This isn't quite fputs() in the stdio sense, since we don't + * have stdio, but it takes a file descriptor argument instead + * of the FILE *. + */ + +#include +#include + +int fputs(const char *s, FILE *file) +{ + return _fwrite(s, strlen(s), file); +} diff -puN /dev/null usr/klibc/fread2.c --- /dev/null +++ a/usr/klibc/fread2.c @@ -0,0 +1,13 @@ +/* + * fread2.c + * + * The actual fread() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include + +size_t fread(void *ptr, size_t size, size_t nmemb, FILE * f) +{ + return _fread(ptr, size * nmemb, f) / size; +} diff -puN /dev/null usr/klibc/fread.c --- /dev/null +++ a/usr/klibc/fread.c @@ -0,0 +1,33 @@ +/* + * fread.c + */ + +#include +#include +#include + +size_t _fread(void *buf, size_t count, FILE *f) +{ + size_t bytes = 0; + ssize_t rv; + char *p = buf; + + while (count) { + rv = read(fileno(f), p, count); + if (rv == -1) { + if (errno == EINTR) { + errno = 0; + continue; + } else + break; + } else if (rv == 0) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} diff -puN /dev/null usr/klibc/fstatfs.c --- /dev/null +++ a/usr/klibc/fstatfs.c @@ -0,0 +1,19 @@ +/* + * fstatfs.c + * + * On architectures which do fstatfs64, wrap the system call + */ + +#include +#include + +#ifdef __NR_fstatfs64 + +extern int __fstatfs64(int, size_t, struct statfs *); + +int fstatfs(int fd, struct statfs *buf) +{ + return __fstatfs64(fd, sizeof *buf, buf); +} + +#endif diff -puN /dev/null usr/klibc/fwrite2.c --- /dev/null +++ a/usr/klibc/fwrite2.c @@ -0,0 +1,13 @@ +/* + * fwrite2.c + * + * The actual fwrite() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include + +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * f) +{ + return _fwrite(ptr, size * nmemb, f) / size; +} diff -puN /dev/null usr/klibc/fwrite.c --- /dev/null +++ a/usr/klibc/fwrite.c @@ -0,0 +1,33 @@ +/* + * fwrite.c + */ + +#include +#include +#include + +size_t _fwrite(const void *buf, size_t count, FILE *f) +{ + size_t bytes = 0; + ssize_t rv; + const char *p = buf; + + while (count) { + rv = write(fileno(f), p, count); + if (rv == -1) { + if (errno == EINTR) { + errno = 0; + continue; + } else + break; + } else if (rv == 0) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} diff -puN /dev/null usr/klibc/getcwd.c --- /dev/null +++ a/usr/klibc/getcwd.c @@ -0,0 +1,15 @@ +/* + * getcwd.c + * + * The system call behaves differently than the library function. + */ + +#include +#include + +extern int __getcwd(char *buf, size_t size); + +char *getcwd(char *buf, size_t size) +{ + return (__getcwd(buf, size) < 0) ? NULL : buf; +} diff -puN /dev/null usr/klibc/getdomainname.c --- /dev/null +++ a/usr/klibc/getdomainname.c @@ -0,0 +1,25 @@ +/* + * getdomainname.c + */ + +#include +#include +#include +#include + +int getdomainname(char *name, size_t len) +{ + struct utsname un; + + if (!uname(&un)) + return -1; + + if (len < strlen(un.domainname) + 1) { + errno = EINVAL; + return -1; + } + + strcpy(name, un.domainname); + + return 0; +} diff -puN /dev/null usr/klibc/getenv.c --- /dev/null +++ a/usr/klibc/getenv.c @@ -0,0 +1,24 @@ +/* + * getenv.c + */ + +#include +#include +#include + +char *getenv(const char *name) +{ + char **p, *q; + int len = strlen(name); + + if (!environ) + return NULL; + + for (p = environ; (q = *p); p++) { + if (!strncmp(name, q, len) && q[len] == '=') { + return q + (len + 1); + } + } + + return NULL; +} diff -puN /dev/null usr/klibc/gethostname.c --- /dev/null +++ a/usr/klibc/gethostname.c @@ -0,0 +1,25 @@ +/* + * gethostname.c + */ + +#include +#include +#include +#include + +int gethostname(char *name, size_t len) +{ + struct utsname un; + + if (!uname(&un)) + return -1; + + if (len < strlen(un.nodename) + 1) { + errno = EINVAL; + return -1; + } + + strcpy(name, un.nodename); + + return 0; +} diff -puN /dev/null usr/klibc/getopt.c --- /dev/null +++ a/usr/klibc/getopt.c @@ -0,0 +1,97 @@ +/* + * getopt.c + * + * Simple POSIX getopt(), no GNU extensions... + */ + +#include +#include +#include + +char *optarg; +int optind, opterr, optopt; +static struct getopt_private_state { + const char *optptr; + const char *last_optstring; + char *const *last_argv; +} pvt; + +int getopt(int argc, char *const *argv, const char *optstring) +{ + const char *carg; + const char *osptr; + int opt; + + /* getopt() relies on a number of different global state + variables, which can make this really confusing if there is + more than one use of getopt() in the same program. This + attempts to detect that situation by detecting if the + "optstring" or "argv" argument have changed since last time + we were called; if so, reinitialize the query state. */ + + if (optstring != pvt.last_optstring || argv != pvt.last_argv || + optind < 1 || optind > argc) { + /* optind doesn't match the current query */ + pvt.last_optstring = optstring; + pvt.last_argv = argv; + optind = 1; + pvt.optptr = NULL; + } + + carg = argv[optind]; + + /* First, eliminate all non-option cases */ + + if (!carg || carg[0] != '-' || !carg[1]) { + return -1; + } + + if (carg[1] == '-' && !carg[2]) { + optind++; + return -1; + } + + if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { + /* Someone frobbed optind, change to new opt. */ + pvt.optptr = carg + 1; + } + + opt = *pvt.optptr++; + + if (opt != ':' && (osptr = strchr(optstring, opt))) { + if (osptr[1] == ':') { + if (*pvt.optptr) { + /* Argument-taking option with attached + argument */ + optarg = (char *)pvt.optptr; + optind++; + } else { + /* Argument-taking option with non-attached + argument */ + if (argv[optind + 1]) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + optind++; + return (optstring[0] == ':') + ? ':' : '?'; + } + } + return opt; + } else { + /* Non-argument-taking option */ + /* pvt.optptr will remember the exact position to + resume at */ + if (!*pvt.optptr) + optind++; + return opt; + } + } else { + /* Unknown option */ + optopt = opt; + if (!*pvt.optptr) + optind++; + return '?'; + } +} diff -puN /dev/null usr/klibc/getpgrp.c --- /dev/null +++ a/usr/klibc/getpgrp.c @@ -0,0 +1,10 @@ +/* + * getpgrp.c + */ + +#include + +pid_t getpgrp(void) +{ + return getpgid(0); +} diff -puN /dev/null usr/klibc/getpriority.c --- /dev/null +++ a/usr/klibc/getpriority.c @@ -0,0 +1,23 @@ +/* + * getpriority.c + * + * Needs to do some post-syscall mangling to distinguish error returns... + * but only on some platforms. Sigh. + */ + +#include +#include +#include +#include + +#if !defined(__alpha__) && !defined(__ia64__) + +extern int __getpriority(int, int); + +int getpriority(int which, int who) +{ + int rv = __getpriority(which, who); + return (rv < 0) ? rv : 20-rv; +} + +#endif diff -puN /dev/null usr/klibc/getpt.c --- /dev/null +++ a/usr/klibc/getpt.c @@ -0,0 +1,17 @@ +/* + * getpt.c + * + * GNU extension to the standard Unix98 pty suite + */ + +#include +#include +#include +#include +#include +#include + +int getpt(void) +{ + return open("/dev/ptmx", O_RDWR | O_NOCTTY); +} diff -puN /dev/null usr/klibc/globals.c --- /dev/null +++ a/usr/klibc/globals.c @@ -0,0 +1,10 @@ +/* + * globals.c + * + * These have to be defined somewhere... + */ +#include +#include + +int errno; +char **environ; diff -puN /dev/null usr/klibc/inet/bindresvport.c --- /dev/null +++ a/usr/klibc/inet/bindresvport.c @@ -0,0 +1,46 @@ +/* + * inet/bindresvport.c + */ + +#include +#include +#include +#include +#include +#include + +#define START_PORT 768 +#define END_PORT IPPORT_RESERVED +#define NUM_PORTS (END_PORT - START_PORT) + +int bindresvport(int sd, struct sockaddr_in *sin) +{ + struct sockaddr_in me; + static short port; + int ret = 0; + int i; + + if (sin == NULL) { + memset(&me, 0, sizeof(me)); + sin = &me; + sin->sin_family = AF_INET; + } else if (sin->sin_family != AF_INET) { + errno = EPFNOSUPPORT; + return -1; + } + + if (port == 0) + port = START_PORT + (getpid() % NUM_PORTS); + + for (i = 0; i < NUM_PORTS; i++, port++) { + if (port == END_PORT) + port = START_PORT; + sin->sin_port = htons(port); + + ret = bind(sd, (struct sockaddr *)sin, sizeof(*sin)); + if (ret != -1) + break; + } + + return ret; +} diff -puN /dev/null usr/klibc/inet/inet_addr.c --- /dev/null +++ a/usr/klibc/inet/inet_addr.c @@ -0,0 +1,14 @@ +/* + * inet/inet_addr.c + */ + +#include +#include + +uint32_t inet_addr(const char *str) +{ + struct in_addr a; + int rv = inet_aton(str, &a); + + return rv ? INADDR_NONE : a.s_addr; +} diff -puN /dev/null usr/klibc/inet/inet_aton.c --- /dev/null +++ a/usr/klibc/inet/inet_aton.c @@ -0,0 +1,22 @@ +/* + * inet/inet_aton.c + */ + +#include +#include + +int inet_aton(const char *str, struct in_addr *addr) +{ + union { + uint8_t b[4]; + uint32_t l; + } a; + + if (sscanf(str, "%hhu.%hhu.%hhu.%hhu", + &a.b[0], &a.b[1], &a.b[2], &a.b[3]) == 4) { + addr->s_addr = a.l; /* Always in network byte order */ + return 1; + } else { + return 0; + } +} diff -puN /dev/null usr/klibc/inet/inet_ntoa.c --- /dev/null +++ a/usr/klibc/inet/inet_ntoa.c @@ -0,0 +1,16 @@ +/* + * inet/inet_ntoa.c + */ + +#include +#include +#include + +char *inet_ntoa(struct in_addr addr) +{ + static char name[16]; + const uint8_t *cp = (const uint8_t *) &addr.s_addr; + + sprintf(name, "%u.%u.%u.%u", cp[0], cp[1], cp[2], cp[3]); + return name; +} diff -puN /dev/null usr/klibc/inet/inet_ntop.c --- /dev/null +++ a/usr/klibc/inet/inet_ntop.c @@ -0,0 +1,53 @@ +/* + * inet/inet_ntop.c + */ + +#include +#include +#include +#include +#include + +const char *inet_ntop(int af, const void *cp, char *buf, size_t len) +{ + size_t xlen; + + switch (af) { + case AF_INET: + { + const uint8_t *bp = (const uint8_t *) + &((const struct in_addr *)cp)->s_addr; + + xlen = snprintf(buf, len, "%u.%u.%u.%u", + bp[0], bp[1], bp[2], bp[3]); + } + break; + + case AF_INET6: + { + const struct in6_addr *s = (const struct in6_addr *)cp; + + xlen = snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(s->s6_addr16[0]), + ntohs(s->s6_addr16[1]), + ntohs(s->s6_addr16[2]), + ntohs(s->s6_addr16[3]), + ntohs(s->s6_addr16[4]), + ntohs(s->s6_addr16[5]), + ntohs(s->s6_addr16[6]), + ntohs(s->s6_addr16[7])); + } + break; + + default: + errno = EAFNOSUPPORT; + return NULL; + } + + if (xlen > len) { + errno = ENOSPC; + return NULL; + } + + return buf; +} diff -puN /dev/null usr/klibc/inet/inet_pton.c --- /dev/null +++ a/usr/klibc/inet/inet_pton.c @@ -0,0 +1,78 @@ +/* + * inet/inet_pton.c + */ + +#include +#include +#include +#include +#include +#include +#include + +static inline int hexval(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + return ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'f') { + return ch - 'a' + 10; + } else { + return -1; + } +} + +int inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return inet_aton(src, (struct in_addr *)dst); + + case AF_INET6: + { + struct in6_addr *d = (struct in6_addr *)dst; + int colons = 0, dcolons = 0; + int i; + const char *p; + + /* A double colon will increment colons by 2, + dcolons by 1 */ + for (p = dst; *p; p++) { + if (p[0] == ':') { + colons++; + if (p[1] == ':') + dcolons++; + } else if (!isxdigit(*p)) + return 0; /* Invalid address */ + } + + if (colons > 7 || dcolons > 1 + || (!dcolons && colons != 7)) + return 0; /* Invalid address */ + + memset(d, 0, sizeof(struct in6_addr)); + + i = 0; + for (p = dst; *p; p++) { + if (*p == ':') { + if (p[1] == ':') { + i += (8 - colons); + } else { + i++; + } + } else { + d->s6_addr16[i] = + htons((ntohs(d->s6_addr16[i]) << 4) + + hexval(*p)); + } + } + + return 1; + } + + default: + errno = EAFNOSUPPORT; + return -1; + } +} diff -puN /dev/null usr/klibc/interp.S --- /dev/null +++ a/usr/klibc/interp.S @@ -0,0 +1,13 @@ +# +# This is a hack to generate the .intrp section, which then +# ld turns into an PT_INTERP header. +# +# NOTE: The .interp section needs to be "a", or it doesnt work... +# + + .section ".interp","a" + .ascii LIBDIR + .ascii "/klibc-" + .ascii SOHASH + .ascii ".so" + .byte 0 diff -puN /dev/null usr/klibc/isatty.c --- /dev/null +++ a/usr/klibc/isatty.c @@ -0,0 +1,20 @@ +/* + * isatty.c + */ + +#include +#include +#include + +int isatty(int fd) +{ + int old_errno = errno; + int istty; + pid_t dummy; + + /* All ttys support TIOCGPGRP */ + istty = !ioctl(fd, TIOCGPGRP, &dummy); + errno = old_errno; + + return istty; +} diff -puN /dev/null usr/klibc/jrand48.c --- /dev/null +++ a/usr/klibc/jrand48.c @@ -0,0 +1,24 @@ +/* + * jrand48.c + */ + +#include +#include + +long jrand48(unsigned short xsubi[3]) +{ + uint64_t x; + + /* The xsubi[] array is littleendian by spec */ + x = (uint64_t) (uint16_t) xsubi[0] + + ((uint64_t) (uint16_t) xsubi[1] << 16) + + ((uint64_t) (uint16_t) xsubi[2] << 32); + + x = (0x5deece66dULL * x) + 0xb; + + xsubi[0] = (unsigned short)(uint16_t) x; + xsubi[1] = (unsigned short)(uint16_t) (x >> 16); + xsubi[2] = (unsigned short)(uint16_t) (x >> 32); + + return (long)(int32_t) (x >> 16); +} diff -puN /dev/null usr/klibc/Kbuild --- /dev/null +++ a/usr/klibc/Kbuild @@ -0,0 +1,186 @@ +# +# Kbuild file for klibc +# + +# Tell that we are building klibc +klibc-build := y + +libc-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \ + asprintf.o vasprintf.o \ + vsscanf.o sscanf.o ctypes.o \ + strntoumax.o strntoimax.o \ + atoi.o atol.o atoll.o \ + strtol.o strtoll.o strtoul.o strtoull.o \ + strtoimax.o strtoumax.o \ + globals.o exit.o atexit.o onexit.o \ + execl.o execle.o execv.o execvpe.o execvp.o execlp.o execlpe.o \ + fork.o vfork.o wait.o wait3.o waitpid.o system.o \ + setpgrp.o getpgrp.o daemon.o \ + printf.o vprintf.o fprintf.o vfprintf.o perror.o \ + statfs.o fstatfs.o umount.o \ + open.o openat.o fopen.o fread.o fread2.o fgetc.o fgets.o \ + fwrite.o fwrite2.o fputc.o fputs.o puts.o putchar.o \ + sleep.o usleep.o strtotimespec.o strtotimeval.o \ + raise.o abort.o assert.o alarm.o pause.o \ + __signal.o sysv_signal.o bsd_signal.o siglist.o sigabbrev.o \ + siglongjmp.o \ + sigaction.o sigpending.o sigprocmask.o sigsuspend.o \ + pselect.o ppoll.o \ + brk.o sbrk.o malloc.o realloc.o calloc.o mmap.o \ + memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \ + memmove.o memchr.o memrchr.o \ + strcasecmp.o strncasecmp.o strndup.o strerror.o strsignal.o \ + strcat.o strchr.o strcmp.o strcpy.o strdup.o strlen.o strnlen.o \ + strncat.o strlcpy.o strlcat.o \ + strstr.o strncmp.o strncpy.o strrchr.o \ + strxspn.o strspn.o strcspn.o strpbrk.o strsep.o strtok.o \ + gethostname.o getdomainname.o getcwd.o \ + seteuid.o setegid.o \ + getenv.o setenv.o putenv.o __put_env.o unsetenv.o \ + clearenv.o nullenv.o \ + getopt.o readdir.o remove.o \ + syslog.o closelog.o pty.o getpt.o isatty.o reboot.o \ + time.o utime.o llseek.o nice.o getpriority.o \ + qsort.o bsearch.o \ + lrand48.o jrand48.o mrand48.o nrand48.o srand48.o seed48.o \ + inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \ + inet/inet_ntop.o inet/inet_pton.o inet/bindresvport.o \ + send.o recv.o \ + ctype/isalnum.o ctype/isalpha.o ctype/isascii.o \ + ctype/isblank.o ctype/iscntrl.o ctype/isdigit.o \ + ctype/isgraph.o ctype/islower.o ctype/isprint.o \ + ctype/ispunct.o ctype/isspace.o ctype/isupper.o \ + ctype/isxdigit.o ctype/tolower.o ctype/toupper.o + +libc-$(CONFIG_KLIBC_ERRLIST) += errlist.o + +ifeq ($(CONFIG_KLIBC_ERRLIST),y) +KLIBCCFLAGS_strerror.o += -DWITH_ERRLIST +endif + +libc-$(CONFIG_KLIBC_ZLIB) += \ + zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/gzio.o \ + zlib/uncompr.o zlib/deflate.o zlib/trees.o zlib/zutil.o \ + zlib/inflate.o zlib/infback.o zlib/inftrees.o zlib/inffast.o + +# zlib specific flag +KLIBCCFLAGS += -DDYNAMIC_CRC_TABLE + +##### +# Add any architecture-specific rules +include $(obj)/arch/$(KLIBCARCHDIR)/Makefile.inc + +##### +# Shared definitions +LIB := libc.a +SOLIB := libc.so +SOHASH := klibc.so +CRT0 := arch/$(KLIBCARCHDIR)/crt0.o +INTERP_O := interp.o + +always := $(CRT0) $(LIB) $(SOLIB) $(SOHASH) $(INTERP_O) +LIB := $(call objectify,$(LIB)) +SOLIB := $(call objectify,$(SOLIB)) +SOHASH := $(call objectify,$(SOHASH)) +CRT0 := $(call objectify,$(CRT0)) +INTERP_O := $(call objectify,$(INTERP_O)) + +SOLIBHASH = $(shell cat $(SOLIB).hash) + +targets += arch/$(KLIBCARCHDIR)/crt0.o +targets += $(libc-y) $(KLIBCARCHOBJS) + +# Generate syscall stubs +subdir-y += syscalls +# Generate socket calls stubs +subdir-y += socketcalls + +# Tell make to descend before building libs +$(obj)/syscalls/syscalls.list: $(obj)/syscalls +$(obj)/socketcalls/socketcalls.list: $(obj)/socketcalls + +##### +# Readable errormessages extracted from src.. +targets += errlist.c +quiet_cmd_errlist = GEN $@ + cmd_errlist = $(PERL) $< $(KLIBCCPPFLAGS) -errlist > $@ || rm -f $@ + +$(obj)/errlist.c: $(srctree)/$(src)/makeerrlist.pl + $(call cmd,errlist) + +# full list of dependencies for klibc +libc-deps = $(call objectify, $(libc-y) $(KLIBCARCHOBJS)) \ + $(call objectify, syscalls/syscalls.list socketcalls/socketcalls.list) + +###### +# Build static library: libc.a +targets += libc.a __static_init.o +quiet_cmd_libc = KLIBCAR $@ + cmd_libc = rm -f $@; \ + $(KLIBCAR) cq $@ \ + $(patsubst %.list,`cat %.list`,$(filter-out FORCE,$^)); \ + $(KLIBCRANLIB) $@ + +$(LIB): $(call objectify,__static_init.o) $(libc-deps) FORCE + $(call if_changed,libc) + +###### +# Build shared library +targets += libc.so __shared_init.o + +quiet_cmd_libcso = KLIBCLD $@ + cmd_libcso = $(KLIBCLD) $(KLIBCLDFLAGS) $(KLIBCSHAREDFLAGS) -o $@ \ + --start-group \ + $(patsubst %.list,`cat %.list`,$(filter-out FORCE,$^)) \ + $(KLIBCLIBGCC) \ + --end-group + +$(SOLIB): $(CRT0) $(call objectify,__shared_init.o) $(libc-deps) FORCE + $(call if_changed,libcso) + + +##### +# Build sha1 hash values +targets += klibc.so libc.so.hash +hostprogs-y := sha1hash +clean-files += klibc-???????????????????????????.so + +quiet_cmd_solibhash = HASH $@ + cmd_solibhash = $(KLIBCNM) $< | egrep '^[0-9a-fA-F]+ [ADRTW] ' | \ + sort | $(obj)/sha1hash > $@ +$(SOLIB).hash: $(SOLIB) $(obj)/sha1hash FORCE + $(call if_changed,solibhash) + +quiet_cmd_sohash = GEN $@ + cmd_sohash = cat $< > $@; \ + $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@; \ + rm -f $(obj)/klibc-???????????????????????????.so; \ + ln -f $@ $(obj)/klibc-$(SOLIBHASH).so +$(SOHASH): $(SOLIB) $(SOLIB).hash + $(call cmd,sohash) + + +##### +# build interp.o +targets += interp.o + +quiet_cmd_interp = BUILD $@ + cmd_interp = $(KLIBCCC) $(klibccflags) -D__ASSEMBLY__ \ + -DLIBDIR=\"$(SHLIBDIR)\" \ + -DSOHASH=\"$(SOLIBHASH)\" \ + -c -o $@ $< + +$(INTERP_O): $(obj)/interp.S $(SOLIB).hash + $(call if_changed,interp) + +##### +# Install klibc +install-rule: + @echo " INSTALL klibc to $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib" + $(Q)$(foreach f, $(LIB) $(SOLIB) $(CRT0) $(INTERP_O), \ + $(shell $(install-data) $(f) \ + $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib)) + $(Q)$(install-lib) $(obj)/klibc-$(SOLIBHASH).so \ + $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib + $(Q)$(install-lib) $(obj)/klibc-$(SOLIBHASH).so \ + $(INSTALLROOT)$(SHLIBDIR) diff -puN /dev/null usr/klibc/libc_init.c --- /dev/null +++ a/usr/klibc/libc_init.c @@ -0,0 +1,107 @@ +/* + * libc_init.c + * + * This function takes the raw data block set up by the ELF loader + * in the kernel and parses it. It is invoked by crt0.S which makes + * any necessary adjustments and passes calls this function using + * the standard C calling convention. + * + * The arguments are: + * uintptr_t *elfdata -- The ELF loader data block; usually from the stack. + * Basically a pointer to argc. + * void (*onexit)(void) -- Function to install into onexit + */ + +/* + * Several Linux ABIs don't pass the onexit pointer, and the ones that + * do never use it. Therefore, unless USE_ONEXIT is defined, we just + * ignore the onexit pointer. + */ +/* #define USE_ONEXIT */ + +#include +#include +#include +#include +#include +#include "atexit.h" + +/* This file is included from __static_init.c or __shared_init.c */ +#ifndef SHARED +# error "SHARED should be defined to 0 or 1" +#endif + +char **environ; +unsigned int __page_size, __page_shift; + +struct auxentry { + uintptr_t type; + uintptr_t v; +}; + +__noreturn __libc_init(uintptr_t * elfdata, void (*onexit) (void)) +{ + int argc; + char **argv, **envp, **envend; + struct auxentry *auxentry; +#if SHARED + typedef int (*main_t) (int, char **, char **); + main_t MAIN = NULL; +#else + extern int main(int, char **, char **); +#define MAIN main +#endif + unsigned int page_size = 0, page_shift = 0; + +#ifdef USE_ONEXIT + if (onexit) { + static struct atexit at_exit; + + at_exit.fctn = (void (*)(int, void *))onexit; + /* at_exit.next = NULL already */ + __atexit_list = &at_exit; + } +#else + (void)onexit; /* Ignore this... */ +#endif + + argc = (int)*elfdata++; + argv = (char **)elfdata; + envp = argv + (argc + 1); + + /* The auxillary entry vector is after all the environment vars */ + for (envend = envp; *envend; envend++) ; + auxentry = (struct auxentry *)(envend + 1); + + while (auxentry->type) { + switch (auxentry->type) { +#if SHARED + case AT_ENTRY: + MAIN = (main_t) (auxentry->v); + break; +#endif + case AT_PAGESZ: + page_size = (unsigned int)(auxentry->v); + break; + } + auxentry++; + } + + __page_size = page_size; + +#if __GNUC__ >= 4 + /* unsigned int is 32 bits on all our architectures */ + page_shift = __builtin_clz(page_size) ^ 31; +#elif defined(__i386__) || defined(__x86_64__) + asm("bsrl %1,%0": "=r"(page_shift):"r"(page_size)); +#else + while (page_size > 1) { + page_shift++; + page_size >>= 1; + } +#endif + __page_shift = page_shift; + + environ = envp; + exit(MAIN(argc, argv, envp)); +} diff -puN /dev/null usr/klibc/libgcc/__ashldi3.c --- /dev/null +++ a/usr/klibc/libgcc/__ashldi3.c @@ -0,0 +1,23 @@ +/* + * libgcc/__ashldi3.c + */ + +#include +#include + +uint64_t __ashldi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vh = (vl << c); + vl = 0; + } else { + vh = (vh << c) + (vl >> (32 - c)); + vl = (vl << c); + } + + return ((uint64_t) vh << 32) + vl; +} diff -puN /dev/null usr/klibc/libgcc/__ashrdi3.c --- /dev/null +++ a/usr/klibc/libgcc/__ashrdi3.c @@ -0,0 +1,23 @@ +/* + * libgcc/__ashrdi3.c + */ + +#include +#include + +uint64_t __ashrdi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vl = ((int32_t) vh >> c); + vh = (int32_t) vh >> 31; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = ((int32_t) vh >> c); + } + + return ((uint64_t) vh << 32) + vl; +} diff -puN /dev/null usr/klibc/libgcc/__clzsi2.c --- /dev/null +++ a/usr/klibc/libgcc/__clzsi2.c @@ -0,0 +1,36 @@ +/* + * libgcc/__clzsi2.c + * + * Returns the leading number of 0 bits in the argument + */ + +#include +#include + +uint32_t __clzsi2(uint32_t v) +{ + int p = 31; + + if (v & 0xffff0000) { + p -= 16; + v >>= 16; + } + if (v & 0xff00) { + p -= 8; + v >>= 8; + } + if (v & 0xf0) { + p -= 4; + v >>= 4; + } + if (v & 0xc) { + p -= 2; + v >>= 2; + } + if (v & 0x2) { + p -= 1; + v >>= 1; + } + + return p; +} diff -puN /dev/null usr/klibc/libgcc/__divdi3.c --- /dev/null +++ a/usr/klibc/libgcc/__divdi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __divdi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} diff -puN /dev/null usr/klibc/libgcc/__divsi3.c --- /dev/null +++ a/usr/klibc/libgcc/__divsi3.c @@ -0,0 +1,29 @@ +/* + * libgcc/__divsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +int32_t __divsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmodsi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} diff -puN /dev/null usr/klibc/libgcc/__lshrdi3.c --- /dev/null +++ a/usr/klibc/libgcc/__lshrdi3.c @@ -0,0 +1,23 @@ +/* + * libgcc/__lshrdi3.c + */ + +#include +#include + +uint64_t __lshrdi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vl = (vh >> c); + vh = 0; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = (vh >> c); + } + + return ((uint64_t) vh << 32) + vl; +} diff -puN /dev/null usr/klibc/libgcc/__moddi3.c --- /dev/null +++ a/usr/klibc/libgcc/__moddi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__moddi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __moddi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmoddi4(num, den, (uint64_t *) & v); + if (minus) + v = -v; + + return v; +} diff -puN /dev/null usr/klibc/libgcc/__modsi3.c --- /dev/null +++ a/usr/klibc/libgcc/__modsi3.c @@ -0,0 +1,29 @@ +/* + * libgcc/__modsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +int32_t __modsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmodsi4(num, den, (uint32_t *) & v); + if (minus) + v = -v; + + return v; +} diff -puN /dev/null usr/klibc/libgcc/__udivdi3.c --- /dev/null +++ a/usr/klibc/libgcc/__udivdi3.c @@ -0,0 +1,13 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __udivdi3(uint64_t num, uint64_t den) +{ + return __udivmoddi4(num, den, NULL); +} diff -puN /dev/null usr/klibc/libgcc/__udivmoddi4.c --- /dev/null +++ a/usr/klibc/libgcc/__udivmoddi4.c @@ -0,0 +1,32 @@ +#include +#include + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if (den == 0) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int64_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} diff -puN /dev/null usr/klibc/libgcc/__udivmodsi4.c --- /dev/null +++ a/usr/klibc/libgcc/__udivmodsi4.c @@ -0,0 +1,32 @@ +#include +#include + +uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem_p) +{ + uint32_t quot = 0, qbit = 1; + + if (den == 0) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int32_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} diff -puN /dev/null usr/klibc/libgcc/__udivsi3.c --- /dev/null +++ a/usr/klibc/libgcc/__udivsi3.c @@ -0,0 +1,13 @@ +/* + * libgcc/__divsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +uint32_t __udivsi3(uint32_t num, uint32_t den) +{ + return __udivmodsi4(num, den, NULL); +} diff -puN /dev/null usr/klibc/libgcc/__umoddi3.c --- /dev/null +++ a/usr/klibc/libgcc/__umoddi3.c @@ -0,0 +1,16 @@ +/* + * arch/i386/libgcc/__umoddi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __umoddi3(uint64_t num, uint64_t den) +{ + uint64_t v; + + (void)__udivmoddi4(num, den, &v); + return v; +} diff -puN /dev/null usr/klibc/libgcc/__umodsi3.c --- /dev/null +++ a/usr/klibc/libgcc/__umodsi3.c @@ -0,0 +1,16 @@ +/* + * libgcc/__umodsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +uint32_t __umodsi3(uint32_t num, uint32_t den) +{ + uint32_t v; + + (void)__udivmodsi4(num, den, &v); + return v; +} diff -puN /dev/null usr/klibc/LICENSE --- /dev/null +++ a/usr/klibc/LICENSE @@ -0,0 +1,73 @@ +This license applies to all files in directory and its subdirectories, +unless otherwise noted in individual files. + + +Some files are derived from files derived from the include/ directory +of the Linux kernel, and are licensed under the terms of the GNU +General Public License, version 2, as released by the Free Software +Foundation, Inc.; incorporated herein by reference. + + ----- + +Some files are derived from files copyrighted by the Regents of The +University of California, and are available under the following +license: + +Note: The advertising clause in the license appearing on BSD Unix +files was officially rescinded by the Director of the Office of +Technology Licensing of the University of California on July 22 +1999. He states that clause 3 is "hereby deleted in its entirety." + + * Copyright (c) + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + + ----- + +For all remaining files, the following license applies: + + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * Any copyright notice(s) and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff -puN /dev/null usr/klibc/llseek.c --- /dev/null +++ a/usr/klibc/llseek.c @@ -0,0 +1,30 @@ +/* + * llseek.c + * + * On 32-bit platforms, we need to use the _llseek() system call + * rather than lseek(), to be able to handle large disks. _llseek() + * isn't just a normal syscall which takes a 64-bit argument; it needs + * to return a 64-bit value and so takes an extra pointer. + */ + +#include +#include +#include + +#if _BITSIZE == 32 + +extern int __llseek(int fd, unsigned long hi, unsigned long lo, off_t * res, + int whence); + +off_t lseek(int fd, off_t offset, int whence) +{ + off_t result; + int rv; + + rv = __llseek(fd, (unsigned long)(offset >> 32), (unsigned long)offset, + &result, whence); + + return rv ? (off_t) - 1 : result; +} + +#endif diff -puN /dev/null usr/klibc/lrand48.c --- /dev/null +++ a/usr/klibc/lrand48.c @@ -0,0 +1,13 @@ +/* + * lrand48.c + */ + +#include +#include + +unsigned short __rand48_seed[3]; /* Common with mrand48.c, srand48.c */ + +long lrand48(void) +{ + return (uint32_t) jrand48(__rand48_seed) >> 1; +} diff -puN /dev/null usr/klibc/makeerrlist.pl --- /dev/null +++ a/usr/klibc/makeerrlist.pl @@ -0,0 +1,98 @@ +#!/usr/bin/perl +# +# This creates sys_errlist from through somewhat +# heuristic matching. It presumes the relevant entries are of the form +# #define Exxxx /* comment */ +# + +use FileHandle; + +%errors = (); +%errmsg = (); +$maxerr = -1; +@includelist = (); # Include directories + +sub parse_file($) { + my($file) = @_; + my($fh) = new FileHandle; + my($line, $error, $msg); + my($kernelonly) = 0; + my($root); + + print STDERR "opening $file\n" unless ( $quiet ); + + $ok = 0; + foreach $root ( @includelist ) { + if ( $fh->open($root.'//'.$file, '<') ) { + $ok = 1; + last; + } + } + + if ( ! $ok ) { + die "$0: Cannot find file $file\n"; + } + + while ( defined($line = <$fh>) ) { + if ( $kernelonly ) { + if ( $line =~ /^\#\s*endif/ ) { + $kernelonly--; + } elsif ( $line =~ /^\#\sif/ ) { + $kernelonly++; + } + } else { + if ( $line =~ /^\#\s*define\s+([A-Z0-9_]+)\s+([0-9]+)\s*\/\*\s*(.*\S)\s*\*\// ) { + $error = $1; + $errno = $2+0; + $msg = $3; + print STDERR "$error ($errno) => \"$msg\"\n" unless ( $quiet ); + $errors{$errno} = $error; + $errmsg{$errno} = $msg; + $maxerr = $errno if ( $errno > $maxerr ); + } elsif ( $line =~ /^\#\s*include\s+[\<\"](.*)[\>\"]/ ) { + parse_file($1); + } elsif ( $line =~ /^\#\s*ifdef\s+__KERNEL__/ ) { + $kernelonly++; + } + } + } + close($fh); + print STDERR "closing $file\n" unless ( $quiet ); +} + +$v = $ENV{'KBUILD_VERBOSE'}; +$quiet = defined($v) ? !$v : 0; + +foreach $arg ( @ARGV ) { + if ( $arg eq '-q' ) { + $quiet = 1; + } elsif ( $arg =~ /^-(errlist|errnos|maxerr)$/ ) { + $type = $arg; + } elsif ( $arg =~ '^\-I' ) { + push(@includelist, "$'"); + } else { + # Ignore + } +} + +parse_file('linux/errno.h'); + +if ( $type eq '-errlist' ) { + print "#include \n"; + printf "const int sys_nerr = %d;\n", $maxerr+1; + printf "const char * const sys_errlist[%d] = {\n", $maxerr+1; + foreach $e ( sort(keys(%errors)) ) { + printf " [%s] = \"%s\",\n", $errors{$e}, $errmsg{$e}; + } + print "};\n"; +} elsif ( $type eq '-errnos' ) { + print "#include \n"; + printf "const int sys_nerr = %d;\n", $maxerr+1; + printf "const char * const sys_errlist[%d] = {\n", $maxerr+1; + foreach $e ( sort(keys(%errors)) ) { + printf " [%s] = \"%s\",\n", $errors{$e}, $errors{$e}; + } + print "};\n"; +} elsif ( $type eq '-maxerr' ) { + print $maxerr, "\n"; +} diff -puN /dev/null usr/klibc/malloc.c --- /dev/null +++ a/usr/klibc/malloc.c @@ -0,0 +1,200 @@ +/* + * malloc.c + * + * Very simple linked-list based malloc()/free(). + */ + +#include +#include +#include +#include "malloc.h" + +/* Both the arena list and the free memory list are double linked + list with head node. This the head node. Note that the arena list + is sorted in order of address. */ +struct free_arena_header __malloc_head = { + { + ARENA_TYPE_HEAD, + 0, + &__malloc_head, + &__malloc_head, + }, + &__malloc_head, + &__malloc_head +}; + +static void *__malloc_from_block(struct free_arena_header *fp, size_t size) +{ + size_t fsize; + struct free_arena_header *nfp, *na; + + fsize = fp->a.size; + + /* We need the 2* to account for the larger requirements of a + free block */ + if (fsize >= size + 2 * sizeof(struct arena_header)) { + /* Bigger block than required -- split block */ + nfp = (struct free_arena_header *)((char *)fp + size); + na = fp->a.next; + + nfp->a.type = ARENA_TYPE_FREE; + nfp->a.size = fsize - size; + fp->a.type = ARENA_TYPE_USED; + fp->a.size = size; + + /* Insert into all-block chain */ + nfp->a.prev = fp; + nfp->a.next = na; + na->a.prev = nfp; + fp->a.next = nfp; + + /* Replace current block on free chain */ + nfp->next_free = fp->next_free; + nfp->prev_free = fp->prev_free; + fp->next_free->prev_free = nfp; + fp->prev_free->next_free = nfp; + } else { + /* Allocate the whole block */ + fp->a.type = ARENA_TYPE_USED; + + /* Remove from free chain */ + fp->next_free->prev_free = fp->prev_free; + fp->prev_free->next_free = fp->next_free; + } + + return (void *)(&fp->a + 1); +} + +static struct free_arena_header *__free_block(struct free_arena_header *ah) +{ + struct free_arena_header *pah, *nah; + + pah = ah->a.prev; + nah = ah->a.next; + if (pah->a.type == ARENA_TYPE_FREE && + (char *)pah + pah->a.size == (char *)ah) { + /* Coalesce into the previous block */ + pah->a.size += ah->a.size; + pah->a.next = nah; + nah->a.prev = pah; + +#ifdef DEBUG_MALLOC + ah->a.type = ARENA_TYPE_DEAD; +#endif + + ah = pah; + pah = ah->a.prev; + } else { + /* Need to add this block to the free chain */ + ah->a.type = ARENA_TYPE_FREE; + + ah->next_free = __malloc_head.next_free; + ah->prev_free = &__malloc_head; + __malloc_head.next_free = ah; + ah->next_free->prev_free = ah; + } + + /* In either of the previous cases, we might be able to merge + with the subsequent block... */ + if (nah->a.type == ARENA_TYPE_FREE && + (char *)ah + ah->a.size == (char *)nah) { + ah->a.size += nah->a.size; + + /* Remove the old block from the chains */ + nah->next_free->prev_free = nah->prev_free; + nah->prev_free->next_free = nah->next_free; + ah->a.next = nah->a.next; + nah->a.next->a.prev = ah; + +#ifdef DEBUG_MALLOC + nah->a.type = ARENA_TYPE_DEAD; +#endif + } + + /* Return the block that contains the called block */ + return ah; +} + +void *malloc(size_t size) +{ + struct free_arena_header *fp; + struct free_arena_header *pah; + size_t fsize; + + if (size == 0) + return NULL; + + /* Add the obligatory arena header, and round up */ + size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; + + for (fp = __malloc_head.next_free; fp->a.type != ARENA_TYPE_HEAD; + fp = fp->next_free) { + if (fp->a.size >= size) { + /* Found fit -- allocate out of this block */ + return __malloc_from_block(fp, size); + } + } + + /* Nothing found... need to request a block from the kernel */ + fsize = (size + MALLOC_CHUNK_MASK) & ~MALLOC_CHUNK_MASK; + +#if _KLIBC_MALLOC_USES_SBRK + fp = (struct free_arena_header *)sbrk(fsize); +#else + fp = (struct free_arena_header *) + mmap(NULL, fsize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +#endif + + if (fp == (struct free_arena_header *)MAP_FAILED) { + return NULL; /* Failed to get a block */ + } + + /* Insert the block into the management chains. We need to set + up the size and the main block list pointer, the rest of + the work is logically identical to free(). */ + fp->a.type = ARENA_TYPE_FREE; + fp->a.size = fsize; + + /* We need to insert this into the main block list in the proper + place -- this list is required to be sorted. Since we most likely + get memory assignments in ascending order, search backwards for + the proper place. */ + for (pah = __malloc_head.a.prev; pah->a.type != ARENA_TYPE_HEAD; + pah = pah->a.prev) { + if (pah < fp) + break; + } + + /* Now pah points to the node that should be the predecessor of + the new node */ + fp->a.next = pah->a.next; + fp->a.prev = pah; + pah->a.next = fp; + fp->a.next->a.prev = fp; + + /* Insert into the free chain and coalesce with adjacent blocks */ + fp = __free_block(fp); + + /* Now we can allocate from this block */ + return __malloc_from_block(fp, size); +} + +void free(void *ptr) +{ + struct free_arena_header *ah; + + if (!ptr) + return; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + +#ifdef DEBUG_MALLOC + assert(ah->a.type == ARENA_TYPE_USED); +#endif + + __free_block(ah); + + /* Here we could insert code to return memory to the system. */ +} diff -puN /dev/null usr/klibc/malloc.h --- /dev/null +++ a/usr/klibc/malloc.h @@ -0,0 +1,47 @@ +/* + * malloc.h + * + * Internals for the memory allocator + */ + +#include +#include +#include + +/* + * This structure should be a power of two. This becomes the + * alignment unit. + */ +struct free_arena_header; + +struct arena_header { + size_t type; + size_t size; /* Also gives the location of the next entry */ + struct free_arena_header *next, *prev; +}; + +#ifdef DEBUG_MALLOC +#define ARENA_TYPE_USED 0x64e69c70 +#define ARENA_TYPE_FREE 0x012d610a +#define ARENA_TYPE_HEAD 0x971676b5 +#define ARENA_TYPE_DEAD 0xeeeeeeee +#else +#define ARENA_TYPE_USED 0 +#define ARENA_TYPE_FREE 1 +#define ARENA_TYPE_HEAD 2 +#endif + +#define MALLOC_CHUNK_MASK (_KLIBC_MALLOC_CHUNK_SIZE-1) + +#define ARENA_SIZE_MASK (~(sizeof(struct arena_header)-1)) + +/* + * This structure should be no more than twice the size of the + * previous structure. + */ +struct free_arena_header { + struct arena_header a; + struct free_arena_header *next_free, *prev_free; +}; + +extern struct free_arena_header __malloc_head; diff -puN /dev/null usr/klibc/memccpy.c --- /dev/null +++ a/usr/klibc/memccpy.c @@ -0,0 +1,23 @@ +/* + * memccpy.c + * + * memccpy() + */ + +#include +#include + +void *memccpy(void *dst, const void *src, int c, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n--) { + *q++ = ch = *p++; + if (ch == (char)c) + return q; + } + + return NULL; /* No instance of "c" found */ +} diff -puN /dev/null usr/klibc/memchr.c --- /dev/null +++ a/usr/klibc/memchr.c @@ -0,0 +1,19 @@ +/* + * memchr.c + */ + +#include +#include + +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = s; + + while (n--) { + if (*sp == (unsigned char)c) + return (void *)sp; + sp++; + } + + return NULL; +} diff -puN /dev/null usr/klibc/memcmp.c --- /dev/null +++ a/usr/klibc/memcmp.c @@ -0,0 +1,19 @@ +/* + * memcmp.c + */ + +#include + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *c1 = s1, *c2 = s2; + int d = 0; + + while (n--) { + d = (int)*c1++ - (int)*c2++; + if (d) + break; + } + + return d; +} diff -puN /dev/null usr/klibc/memcpy.c --- /dev/null +++ a/usr/klibc/memcpy.c @@ -0,0 +1,29 @@ +/* + * memcpy.c + */ + +#include +#include + +void *memcpy(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile ("cld ; rep ; movsl ; movl %3,%0 ; rep ; movsb":"+c" (nl), + "+S"(p), "+D"(q) + :"r"(n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile ("cld ; rep ; movsq ; movl %3,%%ecx ; rep ; movsb":"+c" + (nq), "+S"(p), "+D"(q) + :"r"((uint32_t) (n & 7))); +#else + while (n--) { + *q++ = *p++; + } +#endif + + return dst; +} diff -puN /dev/null usr/klibc/memmem.c --- /dev/null +++ a/usr/klibc/memmem.c @@ -0,0 +1,52 @@ +/* + * memmem.c + * + * Find a byte string inside a longer byte string + * + * This uses the "Not So Naive" algorithm, a very simple but + * usually effective algorithm, see: + * + * http://www-igm.univ-mlv.fr/~lecroq/string/ + */ + +#include + +void *memmem(const void *haystack, size_t n, const void *needle, size_t m) +{ + const unsigned char *y = (const unsigned char *)haystack; + const unsigned char *x = (const unsigned char *)needle; + + size_t j, k, l; + + if (m > n || !m || !n) + return NULL; + + if (1 != m) { + if (x[0] == x[1]) { + k = 2; + l = 1; + } else { + k = 1; + l = 2; + } + + j = 0; + while (j <= n - m) { + if (x[1] != y[j + 1]) { + j += k; + } else { + if (!memcmp(x + 2, y + j + 2, m - 2) + && x[0] == y[j]) + return (void *)&y[j]; + j += l; + } + } + } else + do { + if (*y == *x) + return (void *)y; + y++; + } while (--n); + + return NULL; +} diff -puN /dev/null usr/klibc/memmove.c --- /dev/null +++ a/usr/klibc/memmove.c @@ -0,0 +1,36 @@ +/* + * memmove.c + */ + +#include + +void *memmove(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) || defined(__x86_64__) + if (q < p) { + asm volatile("cld ; rep ; movsb" + : "+c" (n), "+S"(p), "+D"(q)); + } else { + p += (n - 1); + q += (n - 1); + asm volatile("std ; rep ; movsb" + : "+c" (n), "+S"(p), "+D"(q)); + } +#else + if (q < p) { + while (n--) { + *q++ = *p++; + } + } else { + p += n; + q += n; + while (n--) { + *--q = *--p; + } + } +#endif + + return dst; +} diff -puN /dev/null usr/klibc/memrchr.c --- /dev/null +++ a/usr/klibc/memrchr.c @@ -0,0 +1,19 @@ +/* + * memrchr.c + */ + +#include +#include + +void *memrchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = (const unsigned char *)s + n - 1; + + while (n--) { + if (*sp == (unsigned char)c) + return (void *)sp; + sp--; + } + + return NULL; +} diff -puN /dev/null usr/klibc/memset.c --- /dev/null +++ a/usr/klibc/memset.c @@ -0,0 +1,30 @@ +/* + * memset.c + */ + +#include +#include + +void *memset(void *dst, int c, size_t n) +{ + char *q = dst; + +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile ("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb" + : "+c" (nl), "+D" (q) + : "a" ((unsigned char)c * 0x01010101U), "r" (n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile ("cld ; rep ; stosq ; movl %3,%%ecx ; rep ; stosb" + :"+c" (nq), "+D" (q) + : "a" ((unsigned char)c * 0x0101010101010101U), + "r" ((uint32_t) n & 7)); +#else + while (n--) { + *q++ = c; + } +#endif + + return dst; +} diff -puN /dev/null usr/klibc/memswap.c --- /dev/null +++ a/usr/klibc/memswap.c @@ -0,0 +1,24 @@ +/* + * memswap() + * + * Swaps the contents of two nonoverlapping memory areas. + * This really could be done faster... + */ + +#include + +void memswap(void *m1, void *m2, size_t n) +{ + char *p = m1; + char *q = m2; + char tmp; + + while (n--) { + tmp = *p; + *p = *q; + *q = tmp; + + p++; + q++; + } +} diff -puN /dev/null usr/klibc/mmap.c --- /dev/null +++ a/usr/klibc/mmap.c @@ -0,0 +1,40 @@ +/* + * mmap.c + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Set in SYSCALLS whether or not we should use an unadorned mmap() system + * call (typical on 64-bit architectures). + */ +#if !_KLIBC_NO_MMU && _KLIBC_USE_MMAP2 + +/* This architecture uses mmap2(). The Linux mmap2() system call takes + a page offset as the offset argument. We need to make sure we have + the proper conversion in place. */ + +extern void *__mmap2(void *, size_t, int, int, int, size_t); + +void *mmap(void *start, size_t length, int prot, int flags, int fd, + off_t offset) +{ + const int mmap2_shift = _KLIBC_MMAP2_SHIFT; + const off_t mmap2_mask = ((off_t) 1 << mmap2_shift) - 1; + + if (offset & mmap2_mask) { + errno = EINVAL; + return MAP_FAILED; + } + + return __mmap2(start, length, prot, flags, fd, + (size_t) offset >> mmap2_shift); +} + +#endif diff -puN /dev/null usr/klibc/mrand48.c --- /dev/null +++ a/usr/klibc/mrand48.c @@ -0,0 +1,13 @@ +/* + * mrand48.c + */ + +#include +#include + +unsigned short __rand48_seed[3]; /* Common with lrand48.c, srand48.c */ + +long mrand48(void) +{ + return jrand48(__rand48_seed); +} diff -puN /dev/null usr/klibc/nice.c --- /dev/null +++ a/usr/klibc/nice.c @@ -0,0 +1,19 @@ +/* + * nice.c + */ + +#include +#include +#include +#include + +#ifndef __NR_nice + +int nice(int inc) +{ + pid_t me = getpid(); + return setpriority(me, PRIO_PROCESS, + getpriority(me, PRIO_PROCESS) + inc); +} + +#endif diff -puN /dev/null usr/klibc/nrand48.c --- /dev/null +++ a/usr/klibc/nrand48.c @@ -0,0 +1,11 @@ +/* + * nrand48.c + */ + +#include +#include + +long nrand48(unsigned short xsubi[3]) +{ + return (long)((uint32_t) jrand48(xsubi) >> 1); +} diff -puN /dev/null usr/klibc/nullenv.c --- /dev/null +++ a/usr/klibc/nullenv.c @@ -0,0 +1,8 @@ +/* + * nullenv.c + */ + +#include +#include "env.h" + +char * const __null_environ[] = { NULL }; diff -puN /dev/null usr/klibc/onexit.c --- /dev/null +++ a/usr/klibc/onexit.c @@ -0,0 +1,23 @@ +/* + * onexit.c + */ + +#include +#include +#include "atexit.h" + +int on_exit(void (*fctn) (int, void *), void *arg) +{ + struct atexit *as = malloc(sizeof(struct atexit)); + + if (!as) + return -1; + + as->fctn = fctn; + as->arg = arg; + + as->next = __atexit_list; + __atexit_list = as; + + return 0; +} diff -puN /dev/null usr/klibc/openat.c --- /dev/null +++ a/usr/klibc/openat.c @@ -0,0 +1,22 @@ +/* + * openat.c + * + * On 32-bit platforms we need to pass O_LARGEFILE to the openat() + * system call, to indicate that we're 64-bit safe. + */ + +#define _KLIBC_IN_OPEN_C +#include +#include +#include + +#if _BITSIZE == 32 && !defined(__i386__) && defined(__NR_openat) + +extern int __openat(int, const char *, int, mode_t); + +int openat(int dirfd, const char *pathname, int flags, mode_t mode) +{ + return __openat(dirfd, pathname, flags | O_LARGEFILE, mode); +} + +#endif diff -puN /dev/null usr/klibc/open.c --- /dev/null +++ a/usr/klibc/open.c @@ -0,0 +1,22 @@ +/* + * open.c + * + * On 32-bit platforms we need to pass O_LARGEFILE to the open() + * system call, to indicate that we're 64-bit safe. + */ + +#define _KLIBC_IN_OPEN_C +#include +#include +#include + +#if _BITSIZE == 32 && !defined(__i386__) + +extern int __open(const char *, int, mode_t); + +int open(const char *pathname, int flags, mode_t mode) +{ + return __open(pathname, flags | O_LARGEFILE, mode); +} + +#endif diff -puN /dev/null usr/klibc/pause.c --- /dev/null +++ a/usr/klibc/pause.c @@ -0,0 +1,17 @@ +/* + * pause.c + */ + +#include +#include +#include +#include + +#ifndef __NR_pause + +int pause(void) +{ + return select(0, NULL, NULL, NULL, NULL); +} + +#endif diff -puN /dev/null usr/klibc/perror.c --- /dev/null +++ a/usr/klibc/perror.c @@ -0,0 +1,13 @@ +/* + * perror.c + */ + +#include +#include +#include + +void perror(const char *s) +{ + int e = errno; + fprintf(stderr, "%s: %s\n", s, strerror(e)); +} diff -puN /dev/null usr/klibc/ppoll.c --- /dev/null +++ a/usr/klibc/ppoll.c @@ -0,0 +1,19 @@ +/* + * ppoll.c + */ + +#include +#include + +#ifdef __NR_ppoll + +__extern int __ppoll(struct pollfd *, nfds_t, struct timespec *, + const sigset_t *, size_t); + +int ppoll(struct pollfd *ufds, nfds_t nfds, struct timespec *timeout, + const sigset_t * sigmask) +{ + return __ppoll(ufds, nfds, timeout, sigmask, sizeof *sigmask); +} + +#endif diff -puN /dev/null usr/klibc/printf.c --- /dev/null +++ a/usr/klibc/printf.c @@ -0,0 +1,19 @@ +/* + * printf.c + */ + +#include +#include + +#define BUFFER_SIZE 16384 + +int printf(const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(stdout, format, ap); + va_end(ap); + return rv; +} diff -puN /dev/null usr/klibc/pselect.c --- /dev/null +++ a/usr/klibc/pselect.c @@ -0,0 +1,42 @@ +/* + * pselect.c + */ + +#include +#include + +#if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG + +/* Don't need to do anything here; use syscall stub directly */ + +#elif defined(__NR_pselect7) + +__extern int __pselect7(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const sigset_t *, size_t); + +int pselect(int n, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, + const struct timespec *timeout, const sigset_t * sigmask) +{ + return __pselect7(n, readfds, writefds, exceptfds, + timeout, sigmask, sizeof *sigmask); +} + +#elif defined(__NR_pselect6) + +struct __pselect6 { + const sigset_t *sigmask; + size_t sigsize; +}; + +__extern int __pselect6(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const struct __pselect6 *); + +int pselect(int n, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, + const struct timespec *timeout, const sigset_t * sigmask) +{ + struct __pselect6 extended_sigmask = { sigmask, sizeof *sigmask }; + return __pselect6(n, readfds, writefds, exceptfds, + timeout, &extended_sigmask); +} + +#endif diff -puN /dev/null usr/klibc/pty.c --- /dev/null +++ a/usr/klibc/pty.c @@ -0,0 +1,31 @@ +/* + * pty.c + * + * Basic Unix98 PTY functionality; assumes devpts mounted on /dev/pts + */ + +#include +#include +#include +#include +#include + +char *ptsname(int fd) +{ + static char buffer[32]; /* Big enough to hold even a 64-bit pts no */ + unsigned int ptyno; + + if (ioctl(fd, TIOCGPTN, &ptyno)) + return NULL; + + snprintf(buffer, sizeof buffer, "/dev/pts/%u", ptyno); + + return buffer; +} + +int unlockpt(int fd) +{ + int unlock = 0; + + return ioctl(fd, TIOCSPTLCK, &unlock); +} diff -puN /dev/null usr/klibc/putchar.c --- /dev/null +++ a/usr/klibc/putchar.c @@ -0,0 +1,15 @@ +/* + * putchar.c + * + * - gcc wants this + */ + +#include + +#undef putchar /* Defined as a macro */ +int putchar(int); + +int putchar(int c) +{ + return fputc(c, stdout); +} diff -puN /dev/null usr/klibc/__put_env.c --- /dev/null +++ a/usr/klibc/__put_env.c @@ -0,0 +1,74 @@ +/* + * __put_env.c - common code for putenv() and setenv() + */ + +#include +#include +#include +#include +#include "env.h" + +static size_t __environ_size; +static char **__environ_alloc; + +/* str should be a duplicated version of the input string; + len is the length of the key including the = sign */ + +int __put_env(char *str, size_t len, int overwrite) +{ + static char *const null_environ = { NULL }; + char **p, *q; + char **newenv; + size_t n; + + if (!environ) + environ = (char **)null_environ; + + n = 1; /* Include space for final NULL */ + for (p = environ; (q = *p); p++) { + n++; + if (!strncmp(q, str, len)) { + if (!overwrite) + free(str); + else + *p = str; /* Possible memory leak... */ + return 0; + } + } + + if (__environ_alloc && environ != __environ_alloc) { + free(__environ_alloc); + __environ_alloc = NULL; + } + + /* Need to extend the environment */ + if (n < __environ_size) { + p[1] = NULL; + *p = str; + return 0; + } else { + if (__environ_alloc) { + newenv = + realloc(__environ_alloc, + (__environ_size << 1) * sizeof(char *)); + if (!newenv) + return -1; + + __environ_size <<= 1; + } else { + /* Make a reasonable guess how much more space + we need */ + size_t newsize = n + 32; + newenv = malloc(newsize * sizeof(char *)); + if (!newenv) + return -1; + + memcpy(newenv, environ, n * sizeof(char *)); + __environ_size = newsize; + } + newenv[n-1] = str; /* Old NULL position */ + newenv[n] = NULL; + environ = newenv; + } + return 0; +} diff -puN /dev/null usr/klibc/putenv.c --- /dev/null +++ a/usr/klibc/putenv.c @@ -0,0 +1,37 @@ +/* + * putenv.c + */ + +#include +#include +#include +#include +#include "env.h" + +int putenv(const char *str) +{ + char *s; + const char *e, *z; + + if (!str) { + errno = EINVAL; + return -1; + } + + e = NULL; + for (z = str; *z; z++) { + if (*z == '=') + e = z; + } + + if (!e) { + errno = EINVAL; + return -1; + } + + s = strdup(str); + if (!s) + return -1; + + return __put_env(s, e - str, 1); +} diff -puN /dev/null usr/klibc/puts.c --- /dev/null +++ a/usr/klibc/puts.c @@ -0,0 +1,13 @@ +/* + * puts.c + */ + +#include + +int puts(const char *s) +{ + if (fputs(s, stdout) < 0) + return -1; + + return _fwrite("\n", 1, stdout); +} diff -puN /dev/null usr/klibc/qsort.c --- /dev/null +++ a/usr/klibc/qsort.c @@ -0,0 +1,42 @@ +/* + * qsort.c + * + * This is actually combsort. It's an O(n log n) algorithm with + * simplicity/small code size being its main virtue. + */ + +#include +#include + +static inline size_t newgap(size_t gap) +{ + gap = (gap * 10) / 13; + if (gap == 9 || gap == 10) + gap = 11; + + if (gap < 1) + gap = 1; + return gap; +} + +void qsort(void *base, size_t nmemb, size_t size, + int (*compar) (const void *, const void *)) +{ + size_t gap = nmemb; + size_t i, j; + char *p1, *p2; + int swapped; + + do { + gap = newgap(gap); + swapped = 0; + + for (i = 0, p1 = base; i < nmemb - gap; i++, p1 += size) { + j = i + gap; + if (compar(p1, p2 = (char *)base + j * size) > 0) { + memswap(p1, p2, size); + swapped = 1; + } + } + } while (gap > 1 || swapped); +} diff -puN /dev/null usr/klibc/raise.c --- /dev/null +++ a/usr/klibc/raise.c @@ -0,0 +1,11 @@ +/* + * raise.c + */ + +#include +#include + +int raise(int signal) +{ + return kill(getpid(), signal); +} diff -puN /dev/null usr/klibc/readdir.c --- /dev/null +++ a/usr/klibc/readdir.c @@ -0,0 +1,57 @@ +/* + * readdir.c: opendir/readdir/closedir + */ + +#include +#include +#include + +#define __KLIBC_DIRENT_INTERNALS +#include + +DIR *opendir(const char *name) +{ + DIR *dp = malloc(sizeof(DIR)); + + if (!dp) + return NULL; + + dp->__fd = open(name, O_DIRECTORY | O_RDONLY); + + if (dp->__fd < 0) { + free(dp); + return NULL; + } + + dp->bytes_left = 0; + + return dp; +} + +struct dirent *readdir(DIR *dir) +{ + struct dirent *dent; + int rv; + + if (!dir->bytes_left) { + rv = getdents(dir->__fd, dir->buffer, sizeof(dir->buffer)); + if (rv <= 0) + return NULL; + dir->bytes_left = rv; + dir->next = dir->buffer; + } + + dent = dir->next; + dir->next = (struct dirent *)((char *)dir->next + dent->d_reclen); + dir->bytes_left -= dent->d_reclen; + + return dent; +} + +int closedir(DIR *dir) +{ + int rv; + rv = close(dir->__fd); + free(dir); + return rv; +} diff -puN /dev/null usr/klibc/README --- /dev/null +++ a/usr/klibc/README @@ -0,0 +1,80 @@ +This is klibc, what is intended to be a minimalistic libc subset for +use with initramfs. It is deliberately written for small size, +minimal entaglement, and portability, not speed. It is definitely a +work in progress, and a lot of things are still missing. + + +The build procedure is not very polished yet, but it should work like +this: + +a) In the source root directory (the directory above the one in which + this file is found) create a symlink called "linux" pointing to a + reasonably recent Linux kernel tree (2.4 or 2.6 should be OK.) + This tree must have the include/asm symlink set up for the + architecture you're compiling for, and include/linux/autoconf.h + must exist. The easiest way to make sure of all of these is to do + a "make config" or any of its variants on the kernel tree is + question, followed by a "make dep" (2.4) or "make prepare" (2.6). + +b) If you're cross-compiling, you need to set KLIBCARCH to the + appropriate architecture, and set CROSS_COMPILE to your toolchain + prefix. + + IMPORTANT: if you're on a 64-bit machine with a 32-bit userland + (ia64, mips64, ppc64 sparc64, s390x or x86_64), and you want to + build the 32-bit version: you need to set KLIBCARCH to the 32-bit + architecture as well as set up the linux/include/asm symlink to + point to the 32-bit architecture. Building the 32-bit architecture + usually (but not always) produces smaller binaries, and is likely + to be better tested. + + If you are on ARM, and want to build a thumb version of the library + (this is supported), change OPTFLAGS in arch/arm/MCONFIG to build + thumb code. + + The following is the last known status of various architectures: + + alpha: Working + arm-thumb: Untested + arm: Working + arm26: Not yet ported + cris: Working + h8300: Not yet ported + i386: Working + ia64: Working + m32r: Untested + m68k: Untested + m68knommu: Not yet ported + mips: Working + mips64: Not yet ported + parisc: Working + parisc64: Not yet ported + ppc: Working + ppc64: Working + s390: Working static, shared untested + s390x: Working + sh: Untested + sh64: Not yet ported + sparc: Working + sparc64: Untested + v850: Not yet ported + x86-64: Working + xtensa: Not yet ported + + Shared library support requires recent binutils on many + architectures. + + Note that even the "working" ones likely have bugs. Please report + them if you run into them. + +c) Type "make" and pray... + +d) Try the test programs in the tests/ directory. They should run... + +Contact the klibc mailing list: + + http://www.zytor.com/mailman/listinfo/klibc + +... for more info. + + -hpa diff -puN /dev/null usr/klibc/realloc.c --- /dev/null +++ a/usr/klibc/realloc.c @@ -0,0 +1,48 @@ +/* + * realloc.c + */ + +#include +#include + +#include "malloc.h" + +/* FIXME: This is cheesy, it should be fixed later */ + +void *realloc(void *ptr, size_t size) +{ + struct free_arena_header *ah; + void *newptr; + size_t oldsize; + + if (!ptr) + return malloc(size); + + if (size == 0) { + free(ptr); + return NULL; + } + + /* Add the obligatory arena header, and round up */ + size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + + if (ah->a.size >= size && size >= (ah->a.size >> 2)) { + /* This field is a good size already. */ + return ptr; + } else { + /* Make me a new block. This is kind of bogus; we should + be checking the adjacent blocks to see if we can do an + in-place adjustment... fix that later. */ + + oldsize = ah->a.size - sizeof(struct arena_header); + + newptr = malloc(size); + memcpy(newptr, ptr, (size < oldsize) ? size : oldsize); + free(ptr); + + return newptr; + } +} diff -puN /dev/null usr/klibc/reboot.c --- /dev/null +++ a/usr/klibc/reboot.c @@ -0,0 +1,15 @@ +/* + * reboot.c + */ + +#include +#include +#include + +/* This provides the one-argument glibc-ish version of reboot. + The full four-argument system call is available as __reboot(). */ + +int reboot(int flag) +{ + return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, flag, NULL); +} diff -puN /dev/null usr/klibc/recv.c --- /dev/null +++ a/usr/klibc/recv.c @@ -0,0 +1,11 @@ +/* + * recv.c + */ + +#include +#include + +int recv(int s, void *buf, size_t len, unsigned int flags) +{ + return recvfrom(s, buf, len, flags, NULL, 0); +} diff -puN /dev/null usr/klibc/remove.c --- /dev/null +++ a/usr/klibc/remove.c @@ -0,0 +1,18 @@ +/* + * remove.c + */ + +#include +#include +#include + +int remove(const char *pathname) +{ + int rv; + + rv = unlink(pathname); + if (rv == -1 && errno == EISDIR) + return rmdir(pathname); + + return rv; +} diff -puN /dev/null usr/klibc/sbrk.c --- /dev/null +++ a/usr/klibc/sbrk.c @@ -0,0 +1,45 @@ +/* sbrk.c - Change data segment size */ + +/* Written 2000 by Werner Almesberger */ +/* Modified 2003-2004 for klibc by H. Peter Anvin */ + +#include +#include +#include +#include +#include "malloc.h" + +#if !_KLIBC_NO_MMU /* uClinux doesn't have brk() */ + +char *__current_brk; /* Common with brk.c */ + +/* p is an address, a is alignment; must be a power of 2 */ +static inline void *align_up(void *p, uintptr_t a) +{ + return (void *)(((uintptr_t) p + a - 1) & ~(a - 1)); +} + +void *sbrk(ptrdiff_t increment) +{ + char *start, *end, *new_brk; + + if (!__current_brk) + __current_brk = __brk(NULL); + + start = align_up(__current_brk, _KLIBC_SBRK_ALIGNMENT); + end = start + increment; + + new_brk = __brk(end); + + if (new_brk == (void *)-1) + return (void *)-1; + else if (new_brk < end) { + errno = ENOMEM; + return (void *)-1; + } + + __current_brk = new_brk; + return start; +} + +#endif /* !_KLIBC_NO_MMU */ diff -puN /dev/null usr/klibc/seed48.c --- /dev/null +++ a/usr/klibc/seed48.c @@ -0,0 +1,18 @@ +/* + * seed48.c + */ + +#include +#include +#include + +unsigned short __rand48_seed[3]; + +unsigned short *seed48(const unsigned short xsubi[3]) +{ + static unsigned short oldseed[3]; + memcpy(oldseed, __rand48_seed, sizeof __rand48_seed); + memcpy(__rand48_seed, xsubi, sizeof __rand48_seed); + + return oldseed; +} diff -puN /dev/null usr/klibc/send.c --- /dev/null +++ a/usr/klibc/send.c @@ -0,0 +1,11 @@ +/* + * send.c + */ + +#include +#include + +int send(int s, const void *buf, size_t len, unsigned int flags) +{ + return sendto(s, buf, len, flags, NULL, 0); +} diff -puN /dev/null usr/klibc/setegid.c --- /dev/null +++ a/usr/klibc/setegid.c @@ -0,0 +1,10 @@ +/* + * setegid.c + */ + +#include + +int setegid(gid_t egid) +{ + return setregid(-1, egid); +} diff -puN /dev/null usr/klibc/setenv.c --- /dev/null +++ a/usr/klibc/setenv.c @@ -0,0 +1,42 @@ +/* + * setenv.c + */ + +#include +#include +#include +#include +#include "env.h" + +int setenv(const char *name, const char *val, int overwrite) +{ + const char *z; + char *s; + size_t l1, l2; + + if (!name || !name[0]) { + errno = EINVAL; + return -1; + } + + l1 = 0; + for (z = name; *z; z++) { + l1++; + if (*z == '=') { + errno = EINVAL; + return -1; + } + } + + l2 = strlen(val); + + s = malloc(l1 + l2 + 2); + if (!s) + return -1; + + memcpy(s, name, l1); + s[l1] = '='; + memcpy(s + l1 + 1, val, l2 + 1); + + return __put_env(s, l1 + 1, overwrite); +} diff -puN /dev/null usr/klibc/seteuid.c --- /dev/null +++ a/usr/klibc/seteuid.c @@ -0,0 +1,10 @@ +/* + * seteuid.c + */ + +#include + +int seteuid(uid_t euid) +{ + return setreuid(-1, euid); +} diff -puN /dev/null usr/klibc/setpgrp.c --- /dev/null +++ a/usr/klibc/setpgrp.c @@ -0,0 +1,10 @@ +/* + * setpgrp.c + */ + +#include + +int setpgrp(void) +{ + return setpgid(0, 0); +} diff -puN /dev/null usr/klibc/sha1hash.c --- /dev/null +++ a/usr/klibc/sha1hash.c @@ -0,0 +1,317 @@ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +----------------- +Modified 7/98 +By James H. Brown +Still 100% Public Domain + +Corrected a problem which generated improper hash values on 16 bit machines +Routine SHA1Update changed from + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int +len) +to + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned +long len) + +The 'len' parameter was declared an int which works fine on 32 bit machines. +However, on 16 bit machines an int is too small for the shifts being done +against +it. This caused the hash function to generate incorrect values if len was +greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). + +Since the file IO in main() reads 16K at a time, any file 8K or larger would +be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million +"a"s). + +I also changed the declaration of variables i & j in SHA1Update to +unsigned long from unsigned int for the same reason. + +These changes should make no difference to any 32 bit implementations since +an +int and a long are the same size in those environments. + +-- +I also corrected a few compiler warnings generated by Borland C. +1. Added #include for exit() prototype +2. Removed unused variable 'j' in SHA1Final +3. Changed exit(0) to return(0) at end of main. + +ALL changes I made can be located by searching for comments containing 'JHB' +----------------- +Modified 8/98 +By Steve Reid +Still 100% public domain + +1- Removed #include and used return() instead of exit() +2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) +3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net + +----------------- +Modified 4/01 +By Saul Kravitz +Still 100% PD +Modified to run on Compaq Alpha hardware. + +----------------- +Modified 2/03 +By H. Peter Anvin +Still 100% PD +Modified to run on any hardware with and +Changed the driver program + +*/ + +/* +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define SHA1HANDSOFF */ + +#include +#include +#include +#include /* For htonl/ntohl/htons/ntohs */ + +/* #include */ /* prototype for exit() - JHB */ +/* Using return() instead of exit() - SWR */ + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len); /* +JHB */ +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0(i) (block->l[i] = ntohl(block->l[i])) +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +#ifdef VERBOSE /* SAK */ +void SHAPrintContext(SHA1_CTX *context, char *msg){ + printf("%s (%d,%d) %x %x %x %x %x\n", + msg, + context->count[0], context->count[1], + context->state[0], + context->state[1], + context->state[2], + context->state[3], + context->state[4]); +} +#endif + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]) +{ +uint32_t a, b, c, d, e; +typedef union { + unsigned char c[64]; + uint32_t l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len) /* +JHB */ +{ +uint32_t i, j; /* JHB */ + +#ifdef VERBOSE + SHAPrintContext(context, "before"); +#endif + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +#ifdef VERBOSE + SHAPrintContext(context, "after "); +#endif +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +uint32_t i; /* JHB */ +unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() +*/ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = 0; /* JHB */ + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(finalcount, 0, 8); /* SWR */ +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +/*************************************************************/ + +/* This is not quite the MIME base64 algorithm: it uses _ instead of /, + and instead of padding the output with = characters we just make the + output shorter. */ +char *mybase64(uint8_t digest[20]) +{ + static const char charz[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + uint8_t input[21]; + static char output[28]; + int i, j; + uint8_t *p; + char *q; + uint32_t bv; + + memcpy(input, digest, 20); + input[20] = 0; /* Pad to multiple of 3 bytes */ + + p = input; q = output; + for ( i = 0 ; i < 7 ; i++ ) { + bv = (p[0] << 16) | (p[1] << 8) | p[2]; + p += 3; + for ( j = 0 ; j < 4 ; j++ ) { + *q++ = charz[(bv >> 18) & 0x3f]; + bv <<= 6; + } + } + *--q = '\0'; /* The last character is not significant */ + return output; +} + +int main(int argc, char** argv) +{ + int i; + SHA1_CTX context; + uint8_t digest[20], buffer[16384]; + FILE* file; + + if (argc < 2) { + file = stdin; + } + else { + if (!(file = fopen(argv[1], "rb"))) { + fputs("Unable to open file.", stderr); + return(-1); + } + } + SHA1Init(&context); + while (!feof(file)) { /* note: what if ferror(file) */ + i = fread(buffer, 1, 16384, file); + SHA1Update(&context, buffer, i); + } + SHA1Final(digest, &context); + fclose(file); + + puts(mybase64(digest)); + + return 0; +} diff -puN /dev/null usr/klibc/__shared_init.c --- /dev/null +++ a/usr/klibc/__shared_init.c @@ -0,0 +1,2 @@ +#define SHARED 1 +#include "libc_init.c" diff -puN /dev/null usr/klibc/sigabbrev.c --- /dev/null +++ a/usr/klibc/sigabbrev.c @@ -0,0 +1,121 @@ +/* + * sigabbrev.h + * + * Construct the abbreviated signal list + */ + +#include +#include + +const char *const sys_sigabbrev[NSIG] = { +#ifdef SIGABRT + [SIGABRT] = "ABRT", +#endif +#ifdef SIGALRM + [SIGALRM] = "ALRM", +#endif +#ifdef SIGBUS + [SIGBUS] = "BUS", +#endif +#ifdef SIGCHLD + [SIGCHLD] = "CHLD", +#endif +#if defined(SIGCLD) && (SIGCHLD != SIGCLD) + [SIGCLD] = "CLD", +#endif +#ifdef SIGEMT + [SIGEMT] = "EMT", +#endif +#ifdef SIGFPE + [SIGFPE] = "FPE", +#endif +#ifdef SIGHUP + [SIGHUP] = "HUP", +#endif +#ifdef SIGILL + [SIGILL] = "ILL", +#endif + /* SIGINFO == SIGPWR */ +#ifdef SIGINT + [SIGINT] = "INT", +#endif +#ifdef SIGIO + [SIGIO] = "IO", +#endif +#if defined(SIGIOT) && (SIGIOT != SIGABRT) + [SIGIOT] = "IOT", +#endif +#ifdef SIGKILL + [SIGKILL] = "KILL", +#endif +#if defined(SIGLOST) && (SIGLOST != SIGIO) && (SIGLOST != SIGPWR) + [SIGLOST] = "LOST", +#endif +#ifdef SIGPIPE + [SIGPIPE] = "PIPE", +#endif +#if defined(SIGPOLL) && (SIGPOLL != SIGIO) + [SIGPOLL] = "POLL", +#endif +#ifdef SIGPROF + [SIGPROF] = "PROF", +#endif +#ifdef SIGPWR + [SIGPWR] = "PWR", +#endif +#ifdef SIGQUIT + [SIGQUIT] = "QUIT", +#endif + /* SIGRESERVE == SIGUNUSED */ +#ifdef SIGSEGV + [SIGSEGV] = "SEGV", +#endif +#ifdef SIGSTKFLT + [SIGSTKFLT] = "STKFLT", +#endif +#ifdef SIGSTOP + [SIGSTOP] = "STOP", +#endif +#ifdef SIGSYS + [SIGSYS] = "SYS", +#endif +#ifdef SIGTERM + [SIGTERM] = "TERM", +#endif +#ifdef SIGTSTP + [SIGTSTP] = "TSTP", +#endif +#ifdef SIGTTIN + [SIGTTIN] = "TTIN", +#endif +#ifdef SIGTTOU + [SIGTTOU] = "TTOU", +#endif +#ifdef SIGURG + [SIGURG] = "URG", +#endif +#ifdef SIGUSR1 + [SIGUSR1] = "USR1", +#endif +#ifdef SIGUSR2 + [SIGUSR2] = "USR2", +#endif +#ifdef SIGVTALRM + [SIGVTALRM] = "VTALRM", +#endif +#ifdef SIGWINCH + [SIGWINCH] = "WINCH", +#endif +#ifdef SIGXCPU + [SIGXCPU] = "XCPU", +#endif +#ifdef SIGXFSZ + [SIGXFSZ] = "XFSZ", +#endif +#ifdef SIGTRAP + [SIGTRAP] = "TRAP", +#endif +#ifdef SIGCONT + [SIGCONT] = "CONT", +#endif +}; diff -puN /dev/null usr/klibc/sigaction.c --- /dev/null +++ a/usr/klibc/sigaction.c @@ -0,0 +1,60 @@ +/* + * sigaction.c + */ + +#include +#include +#include + +__extern void __sigreturn(void); +__extern int __sigaction(int, const struct sigaction *, struct sigaction *); +#ifdef __sparc__ +__extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *, + void (*)(void), size_t); +#else +__extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *, + size_t); +#endif + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int rv; + +#if _KLIBC_NEEDS_SA_RESTORER + struct sigaction sa; + + if (act && !(act->sa_flags & SA_RESTORER)) { + sa = *act; + act = &sa; + + /* The kernel can't be trusted to have a valid default + restorer */ + sa.sa_flags |= SA_RESTORER; + sa.sa_restorer = &__sigreturn; + } +#endif + +#if _KLIBC_USE_RT_SIG +# ifdef __sparc__ + { + void (*restorer)(void); + restorer = (act && act->sa_flags & SA_RESTORER) + ? (void (*)(void))((uintptr_t)act->sa_restorer - 8) + : NULL; + rv = __rt_sigaction(sig, act, oact, restorer, sizeof(sigset_t)); + } +# else + rv = __rt_sigaction(sig, act, oact, sizeof(sigset_t)); +# endif +#else + rv = __sigaction(sig, act, oact); +#endif + +#if _KLIBC_NEEDS_SA_RESTORER + if (oact && (oact->sa_restorer == &__sigreturn)) { + oact->sa_flags &= ~SA_RESTORER; + } +#endif + + return rv; +} diff -puN /dev/null usr/klibc/siglist.c --- /dev/null +++ a/usr/klibc/siglist.c @@ -0,0 +1,121 @@ +/* + * siglist.h + * + * Construct the signal list + */ + +#include +#include + +const char *const sys_siglist[NSIG] = { +#ifdef SIGABRT + [SIGABRT] = "Aborted", +#endif +#ifdef SIGALRM + [SIGALRM] = "Alarm clock", +#endif +#ifdef SIGBUS + [SIGBUS] = "Bus error", +#endif +#ifdef SIGCHLD + [SIGCHLD] = "Child exited", +#endif +#if defined(SIGCLD) && (SIGCHLD != SIGCLD) + [SIGCLD] = "Child exited", +#endif +#ifdef SIGEMT + [SIGEMT] = "Emulation trap", +#endif +#ifdef SIGFPE + [SIGFPE] = "Floating point exception", +#endif +#ifdef SIGHUP + [SIGHUP] = "Hangup", +#endif +#ifdef SIGILL + [SIGILL] = "Illegal instruction", +#endif + /* SIGINFO == SIGPWR */ +#ifdef SIGINT + [SIGINT] = "Interrupt", +#endif +#ifdef SIGIO + [SIGIO] = "I/O possible", +#endif +#if defined(SIGIOT) && (SIGIOT != SIGABRT) + [SIGIOT] = "I/O trap", +#endif +#ifdef SIGKILL + [SIGKILL] = "Killed", +#endif +#if defined(SIGLOST) && (SIGLOST != SIGIO) && (SIGLOST != SIGPWR) + [SIGLOST] = "Lock lost", +#endif +#ifdef SIGPIPE + [SIGPIPE] = "Broken pipe", +#endif +#if defined(SIGPOLL) && (SIGPOLL != SIGIO) + [SIGPOLL] = "Pollable event", +#endif +#ifdef SIGPROF + [SIGPROF] = "Profiling timer expired", +#endif +#ifdef SIGPWR + [SIGPWR] = "Power failure", +#endif +#ifdef SIGQUIT + [SIGQUIT] = "Quit", +#endif + /* SIGRESERVE == SIGUNUSED */ +#ifdef SIGSEGV + [SIGSEGV] = "Segment violation", +#endif +#ifdef SIGSTKFLT + [SIGSTKFLT] = "Stack fault", +#endif +#ifdef SIGSTOP + [SIGSTOP] = "Stopped (signal)", +#endif +#ifdef SIGSYS + [SIGSYS] = "Bad system call", +#endif +#ifdef SIGTERM + [SIGTERM] = "Terminated", +#endif +#ifdef SIGTSTP + [SIGTSTP] = "Stopped", +#endif +#ifdef SIGTTIN + [SIGTTIN] = "Stopped (tty input)", +#endif +#ifdef SIGTTOU + [SIGTTOU] = "Stopped (tty output)", +#endif +#ifdef SIGURG + [SIGURG] = "Urgent I/O condition", +#endif +#ifdef SIGUSR1 + [SIGUSR1] = "User signal 1", +#endif +#ifdef SIGUSR2 + [SIGUSR2] = "User signal 2", +#endif +#ifdef SIGVTALRM + [SIGVTALRM] = "Virtual timer expired", +#endif +#ifdef SIGWINCH + [SIGWINCH] = "Window size changed", +#endif +#ifdef SIGXCPU + [SIGXCPU] = "CPU time limit exceeded", +#endif +#ifdef SIGXFSZ + [SIGXFSZ] = "File size limit exceeded", +#endif +#ifdef SIGTRAP + [SIGTRAP] = "Trace/breakpoint trap", +#endif +#ifdef SIGCONT + [SIGCONT] = "Continue", +#endif +}; diff -puN /dev/null usr/klibc/siglongjmp.c --- /dev/null +++ a/usr/klibc/siglongjmp.c @@ -0,0 +1,15 @@ +/* + * siglongjmp.c + * + * sigsetjmp() is a macro, by necessity (it's either that or write + * it in assembly), but siglongjmp() is a normal function. + */ + +#include +#include + +__noreturn siglongjmp(sigjmp_buf buf, int retval) +{ + sigprocmask(SIG_SETMASK, &buf->__sigs, NULL); + longjmp(buf->__jmpbuf, retval); +} diff -puN /dev/null usr/klibc/__signal.c --- /dev/null +++ a/usr/klibc/__signal.c @@ -0,0 +1,20 @@ +/* + * __signal.c + */ + +#include + +__sighandler_t __signal(int signum, __sighandler_t handler, int flags) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sa.sa_flags = flags; + sigemptyset(&sa.sa_mask); + + if (sigaction(signum, &sa, &sa)) { + return (__sighandler_t) SIG_ERR; + } else { + return (__sighandler_t) sa.sa_handler; + } +} diff -puN /dev/null usr/klibc/sigpending.c --- /dev/null +++ a/usr/klibc/sigpending.c @@ -0,0 +1,18 @@ +/* + * sigpending.c + */ + +#include +#include +#include + +#if _KLIBC_USE_RT_SIG + +__extern int __rt_sigpending(sigset_t *, size_t); + +int sigpending(sigset_t * set) +{ + return __rt_sigpending(set, sizeof(sigset_t)); +} + +#endif diff -puN /dev/null usr/klibc/sigprocmask.c --- /dev/null +++ a/usr/klibc/sigprocmask.c @@ -0,0 +1,18 @@ +/* + * sigprocmask.c + */ + +#include +#include +#include + +#if _KLIBC_USE_RT_SIG + +__extern int __rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t); + +int sigprocmask(int how, const sigset_t * set, sigset_t * oset) +{ + return __rt_sigprocmask(how, set, oset, sizeof(sigset_t)); +} + +#endif diff -puN /dev/null usr/klibc/sigsuspend.c --- /dev/null +++ a/usr/klibc/sigsuspend.c @@ -0,0 +1,18 @@ +/* + * sigsuspend.c + */ + +#include +#include +#include + +#if _KLIBC_USE_RT_SIG + +__extern int __rt_sigsuspend(const sigset_t *, size_t); + +int sigsuspend(const sigset_t * mask) +{ + return __rt_sigsuspend(mask, sizeof *mask); +} + +#endif diff -puN /dev/null usr/klibc/sleep.c --- /dev/null +++ a/usr/klibc/sleep.c @@ -0,0 +1,20 @@ +/* + * sleep.c + */ + +#include +#include + +unsigned int sleep(unsigned int seconds) +{ + struct timespec ts; + + ts.tv_sec = seconds; + ts.tv_nsec = 0; + if (!nanosleep(&ts, &ts)) + return 0; + else if (errno == EINTR) + return ts.tv_sec; + else + return -1; +} diff -puN /dev/null usr/klibc/snprintf.c --- /dev/null +++ a/usr/klibc/snprintf.c @@ -0,0 +1,16 @@ +/* + * snprintf.c + */ + +#include + +int snprintf(char *buffer, size_t n, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, n, format, ap); + va_end(ap); + return rv; +} diff -puN /dev/null usr/klibc/SOCKETCALLS.def --- /dev/null +++ a/usr/klibc/SOCKETCALLS.def @@ -0,0 +1,21 @@ +/* -*- c -*- + * + * These are calls that are invoked via the socketcall mechanism + * Note that on most architectures this is simply #included into + * SYSCALLS.def. + */ + int socket(int, int, int); + int bind(int, struct sockaddr *, int); + int connect(int, struct sockaddr *, socklen_t); + int listen(int, int); + int accept(int, struct sockaddr *, socklen_t *); + int getsockname(int, struct sockaddr *, socklen_t *); + int getpeername(int, struct sockaddr *, socklen_t *); + int socketpair(int, int, int, int *); + int sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); + int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *); + int shutdown(int, int); + int setsockopt(int, int, int, const void *, socklen_t); + int getsockopt(int, int, int, void *, socklen_t *); + int sendmsg(int, const struct msghdr *, unsigned int); + int recvmsg(int, struct msghdr *, unsigned int); diff -puN /dev/null usr/klibc/socketcalls/Kbuild --- /dev/null +++ a/usr/klibc/socketcalls/Kbuild @@ -0,0 +1,50 @@ +# +# Generate socket calls based on SOCKETCALLS.def +# + +# Include automatically generated Makefile fragment. +# It contains definition of socketcall-objs specifying name of all .o files +ifeq ($(clean),) +-include $(obj)/socketcalls.mk +endif + +# Listing of all .o files +always := socketcalls.list + +##### +# Generate socket calls stubs +# Based on input from SOCKETCALLS.def generate socket call stubs +targets := socketcalls.list +targets += socketcalls.mk +targets += SOCKETCALLS.i +targets += $(socketcall-objs) +clean-files += *.S *.c *.o *.list + +EXTRA_KLIBCCFLAGS := -I$(srctree)/$(src) + +quiet_cmd_makelist = LIST $@ + cmd_makelist = echo '$(filter-out FORCE,$^)' > $@ + +# Create list of all files +$(obj)/socketcalls.list: $(call objectify,$(socketcall-objs)) FORCE + $(call if_changed,makelist) + +# Generate assembler file (.i) +# We pass -ansi to keep cpp from define e.g. "i386" as well as "__i386__" +quiet_cmd_socketcall.i = GEN $@ + cmd_socketcall.i = $(KLIBCCC) $(klibccflags) -D__ASSEMBLY__ \ + -ansi -x c -E -o $@ $< +$(obj)/SOCKETCALLS.i: $(KLIBCSRC)/SOCKETCALLS.def FORCE + $(call if_changed_dep,socketcall.i) + +# Generate socketcall stubs +quiet_cmd_socketcalls = GEN $@ + cmd_socketcalls = $(PERL) $(KLIBCSRC)/socketcalls.pl \ + $(obj)/SOCKETCALLS.i \ + $(KLIBCARCH) $(obj) > $@ \ + || ( rm -f $@ ; exit 1 ) + +$(obj)/socketcalls.mk: $(KLIBCSRC)/socketcalls.pl \ + $(obj)/SOCKETCALLS.i \ + $(src)/socketcommon.h + $(call cmd,socketcalls) diff -puN /dev/null usr/klibc/socketcalls.pl --- /dev/null +++ a/usr/klibc/socketcalls.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl + +$v = $ENV{'KBUILD_VERBOSE'}; +$quiet = defined($v) ? !$v : 0; + +@args = (); +for $arg ( @ARGV ) { + if ( $arg =~ /^-/ ) { + if ( $arg eq '-q' ) { + $quiet = 1; + } else { + die "$0: Unknown option: $arg\n"; + } + } else { + push(@args, $arg); + } +} +($file, $arch, $outputdir) = @args; + +if (!open(FILE, "< $file")) { + die "$file: $!\n"; +} + +print "socketcall-objs := "; +while ( defined($line = ) ) { + chomp $line; + $line =~ s/\s*(|\#.*|\/\/.*)$//; # Strip comments and trailing blanks + next unless $line; + + if ( $line =~ /^\s*\<\?\>\s*(.*)\s+([_a-zA-Z][_a-zA-Z0-9]+)\s*\((.*)\)\s*\;$/ ) { + $type = $1; + $name = $2; + $argv = $3; + + @args = split(/\s*\,\s*/, $argv); + @cargs = (); + + $i = 0; + for $arg ( @args ) { + push(@cargs, "$arg a".$i++); + } + $nargs = $i; + print " \\\n\t${name}.o"; + + if ( $arch eq 'i386' ) { + open(OUT, "> ${outputdir}/${name}.S") + or die "$0: Cannot open ${outputdir}/${name}.S\n"; + + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.align 4\n"; + print OUT "\t.globl ${name}\n"; + print OUT "\t.type ${name},\@function\n"; + print OUT "${name}:\n"; + print OUT "\tpushl \$SYS_\U${name}\n"; + print OUT "\tjmp __socketcall_common\n"; + print OUT "\t.size ${name},.-${name}\n"; + close(OUT); + } else { + open(OUT, "> ${outputdir}/${name}.c") + or die "$0: Cannot open ${outputdir}/${name}.c\n"; + + print OUT "#include \"socketcommon.h\"\n"; + print OUT "\n"; + print OUT "#ifndef __NR_${name}\n\n"; + + print OUT "extern long __socketcall(int, const unsigned long *);\n\n"; + + print OUT "$type $name (", join(', ', @cargs), ")\n"; + print OUT "{\n"; + print OUT " unsigned long args[$nargs];\n"; + for ( $i = 0 ; $i < $nargs ; $i++ ) { + print OUT " args[$i] = (unsigned long)a$i;\n"; + } + print OUT " return ($type) __socketcall(SYS_\U${name}\E, args);\n"; + print OUT "}\n\n"; + + print OUT "#endif\n"; + + close(OUT); + } + } else { + die "$file:$.: Could not parse input\n"; + } +} + +print "\n"; diff -puN /dev/null usr/klibc/socketcalls/socketcommon.h --- /dev/null +++ a/usr/klibc/socketcalls/socketcommon.h @@ -0,0 +1,16 @@ +/* + * socketcommon.h + * + * Common header file for socketcall stubs + */ + +#define __IN_SYS_COMMON +#include +#include +#include +#include +#include +#include +#include +#include +#include diff -puN /dev/null usr/klibc/sprintf.c --- /dev/null +++ a/usr/klibc/sprintf.c @@ -0,0 +1,18 @@ +/* + * sprintf.c + */ + +#include +#include + +int sprintf(char *buffer, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, ~(size_t) 0, format, ap); + va_end(ap); + + return rv; +} diff -puN /dev/null usr/klibc/srand48.c --- /dev/null +++ a/usr/klibc/srand48.c @@ -0,0 +1,15 @@ +/* + * srand48.c + */ + +#include +#include + +unsigned short __rand48_seed[3]; /* Common with mrand48.c, lrand48.c */ + +void srand48(long seedval) +{ + __rand48_seed[0] = 0x330e; + __rand48_seed[1] = (unsigned short)seedval; + __rand48_seed[2] = (unsigned short)((uint32_t) seedval >> 16); +} diff -puN /dev/null usr/klibc/sscanf.c --- /dev/null +++ a/usr/klibc/sscanf.c @@ -0,0 +1,17 @@ +/* + * sscanf() + */ + +#include + +int sscanf(const char *str, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsscanf(str, format, ap); + va_end(ap); + + return rv; +} diff -puN /dev/null usr/klibc/statfs.c --- /dev/null +++ a/usr/klibc/statfs.c @@ -0,0 +1,19 @@ +/* + * statfs.c + * + * On architectures which do statfs64, wrap the system call + */ + +#include +#include + +#ifdef __NR_statfs64 + +extern int __statfs64(const char *, size_t, struct statfs *); + +int statfs(const char *path, struct statfs *buf) +{ + return __statfs64(path, sizeof *buf, buf); +} + +#endif diff -puN /dev/null usr/klibc/__static_init.c --- /dev/null +++ a/usr/klibc/__static_init.c @@ -0,0 +1,2 @@ +#define SHARED 0 +#include "libc_init.c" diff -puN /dev/null usr/klibc/strcasecmp.c --- /dev/null +++ a/usr/klibc/strcasecmp.c @@ -0,0 +1,24 @@ +/* + * strcasecmp.c + */ + +#include +#include + +int strcasecmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (1) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} diff -puN /dev/null usr/klibc/strcat.c --- /dev/null +++ a/usr/klibc/strcat.c @@ -0,0 +1,11 @@ +/* + * strcat.c + */ + +#include + +char *strcat(char *dst, const char *src) +{ + strcpy(strchr(dst, '\0'), src); + return dst; +} diff -puN /dev/null usr/klibc/strchr.c --- /dev/null +++ a/usr/klibc/strchr.c @@ -0,0 +1,19 @@ +/* + * strchr.c + */ + +#include +#include + +char *strchr(const char *s, int c) +{ + while (*s != (char)c) { + if (!*s) + return NULL; + s++; + } + + return (char *)s; +} + +__ALIAS(char *, index, (const char *, int), strchr) diff -puN /dev/null usr/klibc/strcmp.c --- /dev/null +++ a/usr/klibc/strcmp.c @@ -0,0 +1,21 @@ +/* + * strcmp.c + */ + +#include + +int strcmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (1) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} diff -puN /dev/null usr/klibc/strcpy.c --- /dev/null +++ a/usr/klibc/strcpy.c @@ -0,0 +1,20 @@ +/* + * strcpy.c + * + * strcpy() + */ + +#include + +char *strcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + do { + *q++ = ch = *p++; + } while (ch); + + return dst; +} diff -puN /dev/null usr/klibc/strcspn.c --- /dev/null +++ a/usr/klibc/strcspn.c @@ -0,0 +1,10 @@ +/* + * strcspn + */ + +#include "strxspn.h" + +size_t strcspn(const char *s, const char *reject) +{ + return __strxspn(s, reject, 1); +} diff -puN /dev/null usr/klibc/strdup.c --- /dev/null +++ a/usr/klibc/strdup.c @@ -0,0 +1,17 @@ +/* + * strdup.c + */ + +#include +#include + +char *strdup(const char *s) +{ + int l = strlen(s) + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + + return d; +} diff -puN /dev/null usr/klibc/strerror.c --- /dev/null +++ a/usr/klibc/strerror.c @@ -0,0 +1,33 @@ +/* + * strerror.c + */ + +#include + +char *strerror(int errnum) +{ + static char message[32] = "error "; /* enough for error 2^63-1 */ + char numbuf[32]; + char *p; + unsigned int e = (unsigned int)errnum; + +#ifdef WITH_ERRLIST + extern const int sys_nerr; + extern const char *const sys_errlist[]; + + if (e < (unsigned int)sys_nerr && sys_errlist[e]) + return (char *)sys_errlist[e]; +#endif + + p = numbuf + sizeof numbuf; + *--p = '\0'; + + do { + *--p = (e % 10) + '0'; + e /= 10; + } while (e); + + memcpy(message + 6, p, (numbuf + sizeof numbuf) - p); + + return message; +} diff -puN /dev/null usr/klibc/strlcat.c --- /dev/null +++ a/usr/klibc/strlcat.c @@ -0,0 +1,31 @@ +/* + * strlcat.c + */ + +#include +#include + +size_t strlcat(char *dst, const char *src, size_t size) +{ + size_t bytes = 0; + char *q = dst; + const char *p = src; + char ch; + + while (bytes < size && *q) { + q++; + bytes++; + } + if (bytes == size) + return (bytes + strlen(src)); + + while ((ch = *p++)) { + if (bytes + 1 < size) + *q++ = ch; + + bytes++; + } + + *q = '\0'; + return bytes; +} diff -puN /dev/null usr/klibc/strlcpy.c --- /dev/null +++ a/usr/klibc/strlcpy.c @@ -0,0 +1,27 @@ +/* + * strlcpy.c + */ + +#include +#include + +size_t strlcpy(char *dst, const char *src, size_t size) +{ + size_t bytes = 0; + char *q = dst; + const char *p = src; + char ch; + + while ((ch = *p++)) { + if (bytes + 1 < size) + *q++ = ch; + + bytes++; + } + + /* If size == 0 there is no space for a final null... */ + if (size) + *q = '\0'; + + return bytes; +} diff -puN /dev/null usr/klibc/strlen.c --- /dev/null +++ a/usr/klibc/strlen.c @@ -0,0 +1,13 @@ +/* + * strlen() + */ + +#include + +size_t strlen(const char *s) +{ + const char *ss = s; + while (*ss) + ss++; + return ss - s; +} diff -puN /dev/null usr/klibc/strncasecmp.c --- /dev/null +++ a/usr/klibc/strncasecmp.c @@ -0,0 +1,24 @@ +/* + * strncasecmp.c + */ + +#include +#include + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (n--) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} diff -puN /dev/null usr/klibc/strncat.c --- /dev/null +++ a/usr/klibc/strncat.c @@ -0,0 +1,22 @@ +/* + * strncat.c + */ + +#include +#include + +char *strncat(char *dst, const char *src, size_t n) +{ + char *q = strchr(dst, '\0'); + const char *p = src; + char ch; + + while (n--) { + *q++ = ch = *p++; + if (!ch) + return dst; + } + *q = '\0'; + + return dst; +} diff -puN /dev/null usr/klibc/strncmp.c --- /dev/null +++ a/usr/klibc/strncmp.c @@ -0,0 +1,21 @@ +/* + * strncmp.c + */ + +#include + +int strncmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (n--) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} diff -puN /dev/null usr/klibc/strncpy.c --- /dev/null +++ a/usr/klibc/strncpy.c @@ -0,0 +1,24 @@ +/* + * strncpy.c + */ + +#include + +char *strncpy(char *dst, const char *src, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n) { + n--; + *q++ = ch = *p++; + if (!ch) + break; + } + + /* The specs say strncpy() fills the entire buffer with NUL. Sigh. */ + memset(q, 0, n); + + return dst; +} diff -puN /dev/null usr/klibc/strndup.c --- /dev/null +++ a/usr/klibc/strndup.c @@ -0,0 +1,17 @@ +/* + * strndup.c + */ + +#include +#include + +char *strndup(const char *s, size_t n) +{ + int l = n > strlen(s) ? strlen(s) + 1 : n + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + d[n] = '\0'; + return d; +} diff -puN /dev/null usr/klibc/strnlen.c --- /dev/null +++ a/usr/klibc/strnlen.c @@ -0,0 +1,18 @@ +/* + * strnlen() + */ + +#include + +size_t strnlen(const char *s, size_t maxlen) +{ + const char *ss = s; + + /* Important: the maxlen test must precede the reference through ss; + since the byte beyond the maximum may segfault */ + while ((maxlen > 0) && *ss) { + ss++; + maxlen--; + } + return ss - s; +} diff -puN /dev/null usr/klibc/strntoimax.c --- /dev/null +++ a/usr/klibc/strntoimax.c @@ -0,0 +1,13 @@ +/* + * strntoimax.c + * + * strntoimax() + */ + +#include +#include + +intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n) +{ + return (intmax_t) strntoumax(nptr, endptr, base, n); +} diff -puN /dev/null usr/klibc/strntoumax.c --- /dev/null +++ a/usr/klibc/strntoumax.c @@ -0,0 +1,76 @@ +/* + * strntoumax.c + * + * The strntoumax() function and associated + */ + +#include +#include +#include + +static inline int digitval(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else { + return -1; + } +} + +uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) +{ + int minus = 0; + uintmax_t v = 0; + int d; + + while (n && isspace((unsigned char)*nptr)) { + nptr++; + n--; + } + + /* Single optional + or - */ + if (n) { + char c = *nptr; + if (c == '-' || c == '+') { + minus = (c == '-'); + nptr++; + n--; + } + } + + if (base == 0) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + base = 16; + } else if (n >= 1 && nptr[0] == '0') { + n--; + nptr++; + base = 8; + } else { + base = 10; + } + } else if (base == 16) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + } + } + + while (n && (d = digitval(*nptr)) >= 0 && d < base) { + v = v * base + d; + n--; + nptr++; + } + + if (endptr) + *endptr = (char *)nptr; + + return minus ? -v : v; +} diff -puN /dev/null usr/klibc/strpbrk.c --- /dev/null +++ a/usr/klibc/strpbrk.c @@ -0,0 +1,12 @@ +/* + * strpbrk + */ + +#include "strxspn.h" + +char *strpbrk(const char *s, const char *accept) +{ + const char *ss = s + __strxspn(s, accept, 1); + + return *ss ? (char *)ss : NULL; +} diff -puN /dev/null usr/klibc/strrchr.c --- /dev/null +++ a/usr/klibc/strrchr.c @@ -0,0 +1,21 @@ +/* + * strrchr.c + */ + +#include +#include + +char *strrchr(const char *s, int c) +{ + const char *found = NULL; + + while (*s) { + if (*s == (char)c) + found = s; + s++; + } + + return (char *)found; +} + +__ALIAS(char *, rindex, (const char *, int), strrchr) diff -puN /dev/null usr/klibc/strsep.c --- /dev/null +++ a/usr/klibc/strsep.c @@ -0,0 +1,21 @@ +/* + * strsep.c + */ + +#include + +char *strsep(char **stringp, const char *delim) +{ + char *s = *stringp; + char *e; + + if (!s) + return NULL; + + e = strpbrk(s, delim); + if (e) + *e++ = '\0'; + + *stringp = e; + return s; +} diff -puN /dev/null usr/klibc/strsignal.c --- /dev/null +++ a/usr/klibc/strsignal.c @@ -0,0 +1,26 @@ +/* + * strsignal.c + */ + +#include +#include +#include + +char *strsignal(int sig) +{ + static char buf[64]; + + if ((unsigned)sig < _NSIG && sys_siglist[sig]) + return (char *)sys_siglist[sig]; + +#ifdef SIGRTMIN + if (sig >= SIGRTMIN && sig <= SIGRTMAX) { + snprintf(buf, sizeof buf, "Real-time signal %d", + sig - SIGRTMIN); + return buf; + } +#endif + + snprintf(buf, sizeof buf, "Signal %d", sig); + return buf; +} diff -puN /dev/null usr/klibc/strspn.c --- /dev/null +++ a/usr/klibc/strspn.c @@ -0,0 +1,10 @@ +/* + * strspn + */ + +#include "strxspn.h" + +size_t strspn(const char *s, const char *accept) +{ + return __strxspn(s, accept, 0); +} diff -puN /dev/null usr/klibc/strstr.c --- /dev/null +++ a/usr/klibc/strstr.c @@ -0,0 +1,11 @@ +/* + * strstr.c + */ + +#include + +char *strstr(const char *haystack, const char *needle) +{ + return (char *)memmem(haystack, strlen(haystack), needle, + strlen(needle)); +} diff -puN /dev/null usr/klibc/strtoimax.c --- /dev/null +++ a/usr/klibc/strtoimax.c @@ -0,0 +1,3 @@ +#define TYPE intmax_t +#define NAME strtoimax +#include "strtox.c" diff -puN /dev/null usr/klibc/strtok.c --- /dev/null +++ a/usr/klibc/strtok.c @@ -0,0 +1,15 @@ +/* + * strtok.c + */ + +#include + +char *strtok(char *s, const char *delim) +{ + static char *holder; + + if (s) + holder = s; + + return strsep(&holder, delim); +} diff -puN /dev/null usr/klibc/strtol.c --- /dev/null +++ a/usr/klibc/strtol.c @@ -0,0 +1,3 @@ +#define TYPE signed long +#define NAME strtol +#include "strtox.c" diff -puN /dev/null usr/klibc/strtoll.c --- /dev/null +++ a/usr/klibc/strtoll.c @@ -0,0 +1,3 @@ +#define TYPE signed long long +#define NAME strtoll +#include "strtox.c" diff -puN /dev/null usr/klibc/strtotimespec.c --- /dev/null +++ a/usr/klibc/strtotimespec.c @@ -0,0 +1,5 @@ +#define NAME strtotimespec +#define TIMEX struct timespec +#define FSEC tv_nsec +#define DECIMALS 9 +#include "strtotimex.c" diff -puN /dev/null usr/klibc/strtotimeval.c --- /dev/null +++ a/usr/klibc/strtotimeval.c @@ -0,0 +1,5 @@ +#define NAME strtotimeval +#define TIMEX struct timeval +#define FSEC tv_usec +#define DECIMALS 6 +#include "strtotimex.c" diff -puN /dev/null usr/klibc/strtotimex.c --- /dev/null +++ a/usr/klibc/strtotimex.c @@ -0,0 +1,39 @@ +/* + * strtotimex.c + * + * Nonstandard function which takes a string and converts it to a + * struct timespec/timeval. Returns a pointer to the first non-numeric + * character in the string. + * + */ + +#include +#include +#include +#include + +char *NAME(const char *str, TIMEX * ts) +{ + int n; + char *s, *s0; + __typeof__(ts->FSEC) fs; /* Fractional seconds */ + + ts->tv_sec = strntoumax(str, &s, 10, ~(size_t) 0); + fs = 0; + + if (*s == '.') { + s0 = s + 1; + + fs = strntoumax(s0, &s, 10, DECIMALS); + n = s - s0; + + while (isdigit(*s)) + s++; + + for (; n < DECIMALS; n++) + fs *= 10; + } + + ts->FSEC = fs; + return s; +} diff -puN /dev/null usr/klibc/strtoul.c --- /dev/null +++ a/usr/klibc/strtoul.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long +#define NAME strtoul +#include "strtox.c" diff -puN /dev/null usr/klibc/strtoull.c --- /dev/null +++ a/usr/klibc/strtoull.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long long +#define NAME strtoull +#include "strtox.c" diff -puN /dev/null usr/klibc/strtoumax.c --- /dev/null +++ a/usr/klibc/strtoumax.c @@ -0,0 +1,3 @@ +#define TYPE uintmax_t +#define NAME strtoumax +#include "strtox.c" diff -puN /dev/null usr/klibc/strtox.c --- /dev/null +++ a/usr/klibc/strtox.c @@ -0,0 +1,13 @@ +/* + * strtox.c + * + * strto...() functions, by macro definition + */ + +#include +#include + +TYPE NAME(const char *nptr, char **endptr, int base) +{ + return (TYPE) strntoumax(nptr, endptr, base, ~(size_t) 0); +} diff -puN /dev/null usr/klibc/strxspn.c --- /dev/null +++ a/usr/klibc/strxspn.c @@ -0,0 +1,29 @@ +/* + * strpbrk + */ + +#include +#include +#include +#include +#include "strxspn.h" + +size_t __strxspn(const char *s, const char *map, int parity) +{ + char matchmap[UCHAR_MAX + 1]; + size_t n = 0; + + /* Create bitmap */ + memset(matchmap, 0, sizeof matchmap); + while (*map) + matchmap[(unsigned char)*map++] = 1; + + /* Make sure the null character never matches */ + matchmap[0] = parity; + + /* Calculate span length */ + while (matchmap[(unsigned char)*s++] ^ parity) + n++; + + return n; +} diff -puN /dev/null usr/klibc/strxspn.h --- /dev/null +++ a/usr/klibc/strxspn.h @@ -0,0 +1,12 @@ +/* + * strxspn.h + */ + +#ifndef STRXSPN_H +#define STRXSPN_H + +#include + +extern size_t __strxspn(const char *s, const char *map, int parity); + +#endif diff -puN /dev/null usr/klibc/SYSCALLS.def --- /dev/null +++ a/usr/klibc/SYSCALLS.def @@ -0,0 +1,260 @@ +/* -*- c -*- + * + * This is a list of system calls we invoke "directly". These + * are generated into syscall stubs in their own files, so the + * linker can do its job properly. + * + * The full description of a line is: + * [<[?][!]arch,...>] type [sysname,...][@systype][::funcname](args); + * + * ? means only instantiate this system call if present in asm/unistd.h + */ + +#include +#include +#include + +/* + * Process-related syscalls + */ +void _exit,exit::_exit(int); + pid_t clone::__clone(unsigned long, void *); + pid_t clone::__clone2(unsigned long, void *, void *); +# if ! _KLIBC_NO_MMU + pid_t fork(); + pid_t fork@forkish(); +#endif +#if _KLIBC_REAL_VFORK +/* + * A lot of architectures need architecture-specific vfork + * stubs, due to the no-stack requirement. These are the + * architectures which do not. + */ + pid_t vfork(); + pid_t vfork@forkish(); +#endif + pid_t getpid(); + pid_t getxpid@dual0::getpid(); +int setpgid(pid_t, pid_t); +pid_t getpgid(pid_t); + pid_t getppid(); + pid_t getxpid@dual1::getppid(); +pid_t setsid(); +pid_t getsid(pid_t); +pid_t wait4(pid_t, int *, int, struct rusage *); +int execve(const char *, char * const *, char * const *); + int nice(int); + int getpriority(int, int); + int getpriority::__getpriority(int, int); +int setpriority(int, int, int); +int sched_setscheduler(pid_t, int, const struct sched_param *); +int sched_yield(); + +/* + * User and group IDs + */ +int setuid32,setuid::setuid(uid_t); +int setgid32,setgid::setgid(gid_t); + uid_t getuid32,getuid::getuid(); + uid_t getxuid@dual0::getuid(); + gid_t getgid32,getgid::getgid(); + gid_t getxgid@dual0::getgid(); + uid_t geteuid32,geteuid::geteuid(); + uid_t getxuid@dual1::geteuid(); + gid_t getegid32,getegid::getegid(); + gid_t getxgid@dual1::getegid(); +int getgroups32,getgroups::getgroups(int, gid_t *); +int setgroups32,setgroups::setgroups(size_t, const gid_t *); +int setreuid32,setreuid::setreuid(uid_t, uid_t); +int setregid32,setregid::setregid(gid_t, gid_t); +int setfsuid32,setfsuid::setfsuid(uid_t); +int setfsgid32,setfsgid::setfsgid(gid_t); +int setresuid32,setresuid::setresuid(int, uid_t, uid_t, uid_t); + +/* + * Filesystem-related system calls + */ +int mount(const char *, const char *, const char *, unsigned long, const void *); + int umount2(const char *, int); + int umount::umount2(const char *, int); + int pivot_root(const char *, const char *); +int sync(); +#ifdef __NR_statfs64 +int statfs64::__statfs64(const char *, size_t, struct statfs *); +#else +int statfs(const char *, struct statfs *); +#endif +#ifdef __NR_fstatfs64 +int fstatfs64::__fstatfs64(int, size_t, struct statfs *); +#else +int fstatfs(int, struct statfs *); +#endif +int swapon(const char *, int); +int swapoff(const char *); + +/* + * Inode-related system calls + */ +int access(const char *, int); + int faccessat(int, const char *, int); +int link(const char *, const char *); + int linkat(int, const char *, int, const char *); +int unlink(const char *); + int unlinkat(int, const char *); +int chdir(const char *); +int fchdir(int); +int rename(const char *, const char *); + int renameat(int, const char *, int, const char *); +int mknod(const char *, mode_t, dev_t); + int mknodat(int, const char *, const char *, mode_t, dev_t); +int chmod(const char *, mode_t); +int fchmod(int, mode_t); + int fchmodat(int, const char *, mode_t); +int mkdir(const char *, mode_t); + int mkdirat(int, const char *, const char *, mode_t); +int rmdir(const char *); + int pipe(int *); +mode_t umask(mode_t); +int chroot(const char *); +int symlink(const char *, const char *); + int symlinkat(const char *, int, const char *); +int readlink(const char *, char *, size_t); + int readlinkat(int, const char *, char *, int); + int stat64,stat::stat(const char *, struct stat *); + int lstat64,lstat::lstat(const char *, struct stat *); + int fstat64,fstat::fstat(int, struct stat *); + int stat::stat(const char *, struct stat *); + int lstat::lstat(const char *, struct stat *); + int fstat::fstat(int, struct stat *); +/* XXX: Is this right?! */ + int fstatat64,newstatat,fstatat::fstatat(int, const char *, struct stat *, int); +int getdents64,getdents::getdents(unsigned int, struct dirent *, unsigned int); +int chown32,chown::chown(const char *, uid_t, gid_t); +int fchown32,fchown::fchown(int, uid_t, gid_t); + int fchownat(int, const char *, uid_t, gid_t, int); +int lchown32,lchown::lchown(const char *, uid_t, gid_t); +int getcwd::__getcwd(char *, size_t); + int utime(const char *, const struct utimbuf *); + int utimes(const char *, const struct timeval *); + int futimesat(int, const char *, const struct timeval *); + int inotify_init(); + int inotify_add_watch(int, const char *, __u32); + int inotify_rm_watch(int, __u32); + +/* + * I/O operations + */ + int open::__open(const char *, int, mode_t); + int openat::__openat(int, const char *, int, mode_t); +<64> int open(const char *, int, mode_t); +ssize_t read(int, void *, size_t); +ssize_t write(int, const void *, size_t); +int close(int); +<64> off_t lseek(int, off_t, int); +<32> int _llseek::__llseek(int, unsigned long, unsigned long, off_t *, int); +int dup(int); +int dup2(int, int); + int fcntl64@varadic::fcntl(int, int, unsigned long); + int fcntl(int, int, unsigned long); + int fcntl64,fcntl::fcntl(int, int, unsigned long); +int ioctl(int, int, void *); +int flock(int, int); +int _newselect,select::select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +#if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG +int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *); +#elif defined(__NR_pselect7) +int pselect7::__pselect7(int, fd_set *, fd_set *, fd_set *, struct timespec *, const sigset_t *, size_t); +#elif defined(__NR_pselect6) +int pselect6::__pselect6(int, fd_set *, fd_set *, fd_set *, struct timespec *, const struct __pselect6 *); +#endif +int poll(struct pollfd *, nfds_t, long); + int ppoll::__ppoll(struct pollfd *, nfds_t, struct timespec *, const sigset_t *, size_t); +int fsync(int); +int fdatasync,fsync::fdatasync(int); +int readv(int, const struct iovec *, int); +int writev(int, const struct iovec *, int); +int ftruncate64,ftruncate::ftruncate(int, off_t); +ssize_t pread64,pread::pread(int, void *, size_t, off_t); +ssize_t pwrite64,pwrite::pwrite(int, void *, size_t, off_t); +int sync_file_range,fdatasync,fsync::sync_file_range(int, off_t, off_t, unsigned int); + int splice(int, off_t *, int, off_t *, size_t, unsigned int); + int tee(int, int, size_t, unsigned int); +ssize_t sendfile64,sendfile::sendfile(int, int, off_t *, size_t, off_t); + +/* + * Signal operations + * + * We really should get rid of the non-rt_* of these, but that takes + * sanitizing for all architectures, sigh. See . + */ +#if _KLIBC_USE_RT_SIG + int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t); + int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, void *, size_t); +int rt_sigsuspend::__rt_sigsuspend(const sigset_t *, size_t); +int rt_sigpending::__rt_sigpending(sigset_t *, size_t); +int rt_sigprocmask::__rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t); + void rt_sigreturn::__sigreturn(); +#else +int sigaction::__sigaction(int, const struct sigaction *, struct sigaction *); +int sigsuspend(const sigset_t *); +int sigpending(sigset_t *); +int sigprocmask(int, const sigset_t *, sigset_t *); +#endif +int kill(pid_t, int); + unsigned int alarm(unsigned int); +int getitimer(int, struct itimerval *); +int setitimer(int, const struct itimerval *, struct itimerval *); + +/* + * Time-related system calls + */ + time_t time(time_t *); +clock_t times(struct tms *); +int gettimeofday(struct timeval *, struct timezone *); +int settimeofday(const struct timeval *, const struct timezone *); +int nanosleep(const struct timespec *, struct timespec *); + int pause(); + +/* + * Memory + */ + void * brk::__brk(void *); +int munmap(void *, size_t); +void * mremap(void *, size_t, size_t, unsigned long); +int msync(const void *, size_t, int); +int mprotect(const void *, size_t, int); +# if _KLIBC_USE_MMAP2 + void * mmap2::__mmap2(void *, size_t, int, int, int, long); +# else + void * mmap(void *, size_t, int, int, int, long); +int mlockall(int); +int munlockall(); +int mlock(const void *, size_t); +int munlock(const void *, size_t); +#endif + +/* + * System stuff + */ +int uname(struct utsname *); +int setdomainname(const char *, size_t); +int sethostname(const char *, size_t); +long init_module(void *, unsigned long, const char *); +long delete_module(const char *, unsigned int); +int reboot::__reboot(int, int, int, void *); +int syslog::klogctl(int, char *, int); +int sysinfo(struct sysinfo *); + +/* + * Low-level I/O (generally architecture-specific); + */ + int iopl(int); + int ioperm(unsigned long, unsigned long, int); + int vm86(struct vm86_struct *); + +/* + * Most architectures have the socket interfaces using regular + * system calls. + */ + long socketcall::__socketcall(int, const unsigned long *); +#include "SOCKETCALLS.def" diff -puN /dev/null usr/klibc/syscalls/Kbuild --- /dev/null +++ a/usr/klibc/syscalls/Kbuild @@ -0,0 +1,94 @@ +# +# kbuild file for generating syscall stubs +# + +# Include automatically generated Makefile fragment. +# It contains definition of syscall-objs specifying name of all .o files +ifeq ($(clean),) +-include $(obj)/syscalls.mk +endif + +# Listing of all .o files +always := syscalls.list + + +##### +# Generate syscalls stubs +# Based on list in SYSCALLS.def generate stubs for sys calls. Actual arch code +# is defined in an arch specific perl file +targets += syscalls.mk +targets += syscalls.list +targets += SYSCALLS.i syscalls.nrs +targets += typesize.c typesize.o typesize.bin +targets += $(syscall-objs) + +# Side effect of running syscalls.pl +clean-files += $(objtree)/$(KLIBCINC)/klibc/havesyscall.h +clean-files += $(KLIBCINC)/klibc/havesyscall.h +# All the syscall stubs +clean-files += *.o *.S *.c *.list *.bin + +EXTRA_KLIBCCFLAGS := -I$(srctree)/$(src) + +quiet_cmd_makelist = LIST $@ + cmd_makelist = echo '$(filter-out FORCE,$^)' > $@ + +# Create list of all files +$(obj)/syscalls.list: $(call objectify,$(syscall-objs)) FORCE + $(call if_changed,makelist) + +# Generate assembler file (.i) +# We pass -ansi to keep cpp from define e.g. "i386" as well as "__i386__" +quiet_cmd_syscall.i = GEN $@ + cmd_syscall.i = $(KLIBCCC) $(klibccflags) -D__ASSEMBLY__ \ + -ansi -x c -E -o $@ $< +$(obj)/SYSCALLS.i: $(KLIBCSRC)/SYSCALLS.def FORCE + $(call if_changed_dep,syscall.i) + +# Get syscalls numbers +quiet_cmd_syscall.nrs = GEN $@ + cmd_syscall.nrs = $(KLIBCCC) $(klibccflags) -Wp,-dM -x c -E -o $@ $< +$(obj)/syscalls.nrs: $(KLIBCINC)/sys/syscall.h FORCE + $(call if_changed_dep,syscall.nrs) + +# Generate typesize.c +quiet_cmd_syscalsz = GEN $@ + cmd_syscalsz = mkdir -p $(KLIBCINC)/klibc/; \ + $(PERL) $(KLIBCSRC)/syscalls.pl -1 $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(KLIBCARCH) $(KLIBCBITSIZE) $(obj)/syscalls.nrs \ + $(obj) \ + $(KLIBCINC)/klibc/havesyscall.h \ + $(obj)/typesize.c > $@ \ + || ( rm -f $@ ; exit 1 ) + +$(obj)/typesize.c: $(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(src)/syscommon.h $(obj)/syscalls.nrs FORCE + $(call if_changed,syscalsz) + +# Convert typesize.o to typesize.bin +quiet_cmd_mkbin = OBJCOPY $@ + cmd_mkbin = $(KLIBCOBJCOPY) -O binary $< $@ + +$(obj)/typesize.bin: $(obj)/typesize.o FORCE + $(call if_changed,mkbin) + +# Generate $(KLIBINC)/klibc/havesyscall.h + makefile fragment +# Using sysstub.pl in arch dir generate all .S files +quiet_cmd_syscalls = GEN $@ + cmd_syscalls = mkdir -p $(KLIBCINC)/klibc/; \ + $(PERL) $(KLIBCSRC)/syscalls.pl -2 $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(KLIBCARCH) $(KLIBCBITSIZE) $(obj)/syscalls.nrs \ + $(obj) \ + $(KLIBCINC)/klibc/havesyscall.h \ + $(obj)/typesize.bin > $@ \ + || ( rm -f $@ ; exit 1 ) + +$(obj)/syscalls.mk: $(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(call objectify, $(syscall-objs:.o=.S)) \ + $(src)/syscommon.h $(obj)/syscalls.nrs \ + $(obj)/typesize.bin FORCE + $(call if_changed,syscalls) diff -puN /dev/null usr/klibc/syscalls.pl --- /dev/null +++ a/usr/klibc/syscalls.pl @@ -0,0 +1,286 @@ +#!/usr/bin/perl +# +# Script to parse the SYSCALLS file and generate appropriate +# stubs. +# +# Pass 1: generate the C array of sizes +# Pass 2: generate the syscall stubs and other output +# + +# +# Convert a string to a C array of characters, +# e.g. foo -> 'f','o','o','\0', +# +sub chararray($) { + use bytes; + + my($s) = @_; + my($i, $c); + my($a) = ''; + + for ($i = 0; $i < length($s); $i++) { + $c = substr($s, $i, 1); + if (ord($c) < 32 || ord($c) > 126) { + $a .= sprintf("0x%02x,", ord($c)); + } elsif ($c eq "\\" || $c eq "\'") { + $a .= "\'\\$c\',"; + } else { + $a .= "\'$c\',"; + } + } + + return $a; +} + +# +# This extracts an ASCIIZ string for the type and the additional +# information. This is open-coded, because unpack("Z*") apparently +# is broken in Perl 5.6.1. +# +sub get_one_type($) { + use bytes; + + my($typestr) = @_; + my $i, $c; + my $l = length($typestr); + + for ($i = 0; $i < $l-3; $i++) { + $c = substr($typestr, $i, 1); + if ($c eq "\0") { + return (substr($typestr, 0, $i), + unpack("CC", substr($typestr, $i+1, 2)), + substr($typestr, $i+3)); + } + } + + return (undef, undef, undef, undef); +} + +$v = $ENV{'KBUILD_VERBOSE'}; +$quiet = defined($v) && ($v == 0) ? 1 : undef; + +@args = (); +undef $pass; +for $arg ( @ARGV ) { + if ( $arg =~ /^-/ ) { + if ( $arg eq '-q' ) { + $quiet = 1; + } elsif ( $arg eq '-v' ) { + $quiet = 0; + } elsif ( $arg =~ /\-([0-9]+)$/ ) { + $pass = $1+0; + } else { + die "$0: Unknown option: $arg\n"; + } + } else { + push(@args, $arg); + } +} +($file, $sysstub, $arch, $bits, $unistd, $outputdir, + $havesyscall, $typesize) = @args; + +if (!$pass) { + die "$0: Need to specify pass\n"; +} + +$quiet = ($pass != 2) unless defined($quiet); + +require "$sysstub"; + +if (!open(UNISTD, "< $unistd\0")) { + die "$0: $unistd: $!\n"; +} + +while ( defined($line = ) ) { + chomp $line; + + if ( $line =~ /^\#\s*define\s+__NR_([A-Za-z0-9_]+)\s+(.*\S)\s*$/ ) { + $syscalls{$1} = $2; + print STDERR "SYSCALL FOUND: $1\n" unless ( $quiet ); + } +} +close(UNISTD); + +if ($pass == 2) { + use bytes; + + if (!open(TYPESIZE, "< $typesize\0")) { + die "$0: $typesize: $!\n"; + } + + binmode TYPESIZE; + + $len = -s TYPESIZE; + if (read(TYPESIZE, $typebin, $len) != $len) { + die "$0: $typesize: short read: $!\n"; + } + close(TYPESIZE); + + $ix = index($typebin, "\x7a\xc8\xdb\x4e\x97\xb4\x9c\x19"); + if ($ix < 0) { + die "$0: $typesize: magic number not found\n"; + } + + # Remove magic number and bytes before it + $typebin = substr($typebin, $ix+8); + + # Expand the types until a terminating null + %typesize = (); + while (1) { + my $n, $sz, $si; + ($n, $sz, $si, $typebin) = get_one_type($typebin); + last if (length($n) == 0); + $typesize{$n} = $sz; + $typesign{$n} = $si; + print STDERR "TYPE $n: size $sz, sign $si\n" unless ($quiet); + } +} else { + # List here any types which should be sized even if they never occur + # in any system calls at all. + %type_list = ('int' => 1, 'long' => 1, 'long long' => 1, + 'void *' => 1, + 'intptr_t' => 1, 'uintptr_t' => 1, + 'intmax_t' => 1, 'uintmax_t' => 1); +} + +if ($pass == 2) { + if (!open(HAVESYS, "> $havesyscall\0")) { + die "$0: $havesyscall: $!\n"; + } + + print HAVESYS "#ifndef _KLIBC_HAVESYSCALL_H\n"; + print HAVESYS "#define _KLIBC_HAVESYSCALL_H 1\n\n"; +} + +if (!open(FILE, "< $file\0")) { + die "$0: $file: $!\n"; +} + + +if ($pass == 2) { + print "syscall-objs := "; +} + + +while ( defined($line = ) ) { + chomp $line; + $line =~ s/\s*(|\#.*|\/\/.*)$//; # Strip comments and trailing blanks + next unless $line; + + if ( $line =~ /^\s*(\<[^\>]+\>\s+|)([A-Za-z0-9_\*\s]+)\s+([A-Za-z0-9_,]+)(|\@[A-Za-z0-9_]+)(|\:\:[A-Za-z0-9_]+)\s*\(([^\:\)]*)\)\s*\;$/ ) { + $archs = $1; + $type = $2; + $snames = $3; + $stype = $4; + $fname = $5; + $argv = $6; + + $doit = 1; + $maybe = 0; + if ( $archs ne '' ) { + die "$file:$.: Invalid architecture spec: <$archs>\n" + unless ( $archs =~ /^\<(|\?)(|\!)([^\>\!\?]*)\>/ ); + $maybe = $1 ne ''; + $not = $2 ne ''; + $list = $3; + + $doit = $not || ($list eq ''); + + @list = split(/,/, $list); + foreach $a ( @list ) { + if ( $a eq $arch || $a eq $bits ) { + $doit = !$not; + last; + } + } + } + next if ( ! $doit ); + + undef $sname; + foreach $sn ( split(/,/, $snames) ) { + if ( defined $syscalls{$sn} ) { + $sname = $sn; + last; + } + } + if ( !defined($sname) ) { + next if ( $maybe ); + die "$file:$.: Undefined system call: $snames\n"; + } + + $type =~ s/\s*$//; + $stype =~ s/^\@//; + + if ( $fname eq '' ) { + $fname = $sname; + } else { + $fname =~ s/^\:\://; + } + + $argv =~ s/^\s+//; + $argv =~ s/\s+$//; + + if ($argv eq 'void') { + @args = (); + } else { + @args = split(/\s*\,\s*/, $argv); + } + + if ($pass == 1) { + # Pass 1: Add the types to the type list + foreach $a (@args) { + $type_list{$a}++; + } + } else { + # Pass 2: make sure all types defined, and actually generate stubs + + foreach $a (@args) { + if (!defined($typesize{$a})) { + die "$0: $typesize: type name missing: $a\n"; + } + } + + print HAVESYS "#define _KLIBC_HAVE_SYSCALL_${fname} ${sname}\n"; + print " \\\n\t${fname}.o"; + make_sysstub($outputdir, $fname, $type, $sname, $stype, @args); + } + } else { + die "$file:$.: Could not parse input: \"$line\"\n"; + } +} + +if ($pass == 1) { + # Pass 1: generate typesize.c + if (!open(TYPESIZE, "> $typesize")) { + die "$0: cannot create file: $typesize: $!\n"; + } + + print TYPESIZE "#include \"syscommon.h\"\n"; + + # This compares -2 < 1 in the appropriate type, which is true for + # signed types and false for unsigned types. We use -2 and 1 since + # gcc complains about comparing unsigned types with zero, and might + # complain equally about -1 in the future. + # + # This test is valid (as in, doesn't cause the compiler to barf) + # for pointers as well as for integral types; if we ever add system + # calls which take any other kinds of types than that then this needs + # to be smarter. + print TYPESIZE "#define SIGNED(X) ((X)-2 < (X)1)\n"; + + print TYPESIZE "\n"; + print TYPESIZE "const unsigned char type_sizes[] = {\n"; + print TYPESIZE "\t0x7a,0xc8,0xdb,0x4e,0x97,0xb4,0x9c,0x19, /* magic */\n"; + foreach $t (sort(keys(%type_list))) { + print TYPESIZE "\t", chararray($t), "0, sizeof($t), SIGNED($t),\n"; + } + print TYPESIZE "\t0, 0,\n"; # End sentinel + print TYPESIZE "};\n"; + close(TYPESIZE); +} else { + # Pass 2: finalize output files + print "\n"; + + print HAVESYS "\n#endif\n"; + close(HAVESYS); +} diff -puN /dev/null usr/klibc/syscalls/syscommon.h --- /dev/null +++ a/usr/klibc/syscalls/syscommon.h @@ -0,0 +1,33 @@ +/* + * syscommon.h + * + * Common header file for system call stubs + */ + +#define __IN_SYS_COMMON +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __i386__ +# include +#endif diff -puN /dev/null usr/klibc/syslog.c --- /dev/null +++ a/usr/klibc/syslog.c @@ -0,0 +1,89 @@ +/* + * syslog.c + * + * Issue syslog messages via the kernel printk queue. + */ + +#include +#include +#include +#include +#include +#include + +/* Maximum size for a kernel message */ +#define BUFLEN 1024 + +/* Logging node */ +#define LOGDEV "/dev/kmsg" + +/* Max length of ID string */ +#define MAXID 31 /* MAXID+5 must be < BUFLEN */ + +int __syslog_fd = -1; +static char id[MAXID + 1]; +static int syslog_flags = 0; + +void openlog(const char *ident, int option, int facility) +{ + int fd; + + (void)option; + (void)facility; /* Unused */ + + if (__syslog_fd == -1) { + __syslog_fd = fd = open(LOGDEV, O_WRONLY); + if (fd == -1) + return; + fcntl(fd, F_SETFD, (long)FD_CLOEXEC); + } + + syslog_flags = option; + + strncpy(id, ident ? ident : "", MAXID); +} + +void vsyslog(int prio, const char *format, va_list ap) +{ + char buf[BUFLEN]; + int len; + int fd; + + if (__syslog_fd == -1) + openlog(NULL, 0, 0); + + buf[0] = '<'; + buf[1] = LOG_PRI(prio) + '0'; + buf[2] = '>'; + len = 3; + + if (syslog_flags & LOG_PID) + len += sprintf(buf + 3, "%s[%u]: ", id, getpid()); + else if (*id) + len += sprintf(buf + 3, "%s: ", id); + + len += vsnprintf(buf + len, BUFLEN - len, format, ap); + + if (len > BUFLEN - 1) + len = BUFLEN - 1; + if (buf[len - 1] != '\n') + buf[len++] = '\n'; + + fd = __syslog_fd; + if (fd == -1) + fd = 2; /* Failed to open log, write to stderr */ + + write(fd, buf, len); + + if (syslog_flags & LOG_PERROR) + _fwrite(buf + 3, len - 3, stderr); +} + +void syslog(int prio, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vsyslog(prio, format, ap); + va_end(ap); +} diff -puN /dev/null usr/klibc/system.c --- /dev/null +++ a/usr/klibc/system.c @@ -0,0 +1,61 @@ +/* + * system.c + * + * The system() function. If this turns out to actually be *used*, + * we may want to try to detect the very simple cases (no shell magic) + * and handle them internally, instead of requiring that /bin/sh be + * present. + */ + +#include +#include +#include +#include +#include + +int system(const char *string) +{ + pid_t pid; + struct sigaction ignore, old_int, old_quit; + sigset_t masked, oldmask; + static const char *argv[] = { "/bin/sh", "-c", NULL, NULL }; + int status; + + /* Block SIGCHLD and ignore SIGINT and SIGQUIT */ + /* Do this before the fork() to avoid races */ + + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + ignore.sa_flags = 0; + sigaction(SIGINT, &ignore, &old_int); + sigaction(SIGQUIT, &ignore, &old_quit); + + sigemptyset(&masked); + sigaddset(&masked, SIGCHLD); + sigprocmask(SIG_BLOCK, &masked, &oldmask); + + pid = fork(); + + if (pid < 0) + return -1; + else if (pid == 0) { + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + argv[2] = string; + + execve(argv[0], (char *const *)argv, (char *const *)environ); + _exit(127); + } + + /* else... */ + + waitpid(pid, &status, 0); + + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + return status; +} diff -puN /dev/null usr/klibc/sysv_signal.c --- /dev/null +++ a/usr/klibc/sysv_signal.c @@ -0,0 +1,11 @@ +/* + * sysv_signal.c + */ + +#include + +__sighandler_t sysv_signal(int signum, __sighandler_t handler) +{ + /* Linux/SysV signal() semantics */ + return __signal(signum, handler, SA_RESETHAND); +} diff -puN /dev/null usr/klibc/tests/environ.c --- /dev/null +++ a/usr/klibc/tests/environ.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(int argc, char *argv[], char *envp[]) +{ + int i; + + /* Verify envp == environ */ + printf("Verifying envp == environ... %s\n", + (envp == environ) ? "ok" : "ERROR"); + + /* Test argc/argv */ + printf("argc = %d, argv = %p\n", argc, argv); + for (i = 0; i < argc; i++) { + printf("argv[%2d] = %s\n", i, argv[i]); + } + + /* Test environ */ + for (i = 0; envp[i]; i++) + printf("%s\n", envp[i]); + + return 0; +} diff -puN /dev/null usr/klibc/tests/fcntl.c --- /dev/null +++ a/usr/klibc/tests/fcntl.c @@ -0,0 +1,50 @@ +/* + * Simple test of fcntl + */ + +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int fd = open(argv[0], O_RDONLY); + struct flock l; + long flags; + + (void)argc; + + if (fd < 0) { + perror("open"); + exit(1); + } + + /* Get the flags on this FD */ + + if ((flags = fcntl(fd, F_GETFL)) == -1) { + perror("F_GETFL"); + exit(1); + } + + if (flags != (O_RDONLY | O_LARGEFILE)) + fprintf(stderr, "flags = %#lx\n", flags); + + /* Set a lock on this FD */ + memset(&l, 0, sizeof l); + l.l_type = F_RDLCK; + l.l_whence = SEEK_SET; + l.l_start = 123; + l.l_len = 456; + + if (fcntl(fd, F_SETLK, &l) == -1) { + perror("F_SETLK"); + exit(1); + } + + /* Eventually, fork and try to conflict with this lock... */ + + return 0; +} diff -puN /dev/null usr/klibc/tests/getopttest.c --- /dev/null +++ a/usr/klibc/tests/getopttest.c @@ -0,0 +1,32 @@ +/* + * getopttest.c + * + * Simple test for getopt, set the environment variable GETOPTTEST + * to give the argument string to getopt() + */ + +#include +#include +#include + +int main(int argc, char *const *argv) +{ + const char *parser; + char showchar[] = "\'?\'"; + int c; + + parser = getenv("GETOPTTEST"); + if (!parser) + parser = "abzf:o:"; + + do { + c = getopt(argc, argv, parser); + showchar[1] = c; + printf + ("c = %s, optind = %d (%s), optarg = \"%s\", optopt = \'%c\'\n", + (c == EOF) ? "EOF" : showchar, optind, argv[optind], + optarg, optopt); + } while (c != -1); + + return 0; +} diff -puN /dev/null usr/klibc/tests/getpagesize.c --- /dev/null +++ a/usr/klibc/tests/getpagesize.c @@ -0,0 +1,10 @@ +#include +#include + +int main(void) +{ + printf("getpagesize() = %d\n" + "__getpageshift() = %d\n", getpagesize(), __getpageshift()); + + return 0; +} diff -puN /dev/null usr/klibc/tests/hello.c --- /dev/null +++ a/usr/klibc/tests/hello.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("Hello, World!\n"); + return 0; +} diff -puN /dev/null usr/klibc/tests/idtest.c --- /dev/null +++ a/usr/klibc/tests/idtest.c @@ -0,0 +1,14 @@ +#include +#include + +int main(void) +{ + printf("pid = %u\n", getpid()); + printf("ppid = %u\n", getppid()); + printf("uid = %u\n", getuid()); + printf("euid = %u\n", geteuid()); + printf("gid = %u\n", getgid()); + printf("egid = %u\n", getegid()); + sleep(10); + return 0; +} diff -puN /dev/null usr/klibc/tests/Kbuild --- /dev/null +++ a/usr/klibc/tests/Kbuild @@ -0,0 +1,47 @@ +# +# Kbuild file for all test files +# + +test-files := $(wildcard $(srctree)/$(src)/*.c) +test-files := $(notdir $(test-files)) + +# This particular file uses a bunch of formats gcc don't know of, in order +# to test the full range of our vsnprintf() function. This outputs a bunch +# of useless warnings unless we tell it not to. +KLIBCCFLAGS_testvsnp.o := -Wno-format + +static-y := $(test-files:.c=) +shared-y := $(addsuffix .shared, $(static-y)) + +environ.shared-y := environ.o +fcntl.shared-y := fcntl.o +getopttest.shared-y := getopttest.o +getpagesize.shared-y := getpagesize.o +hello.shared-y := hello.o +idtest.shared-y := idtest.o +malloctest.shared-y := malloctest.o +malloctest2.shared-y := malloctest2.o +memstrtest.shared-y := memstrtest.o +microhello.shared-y := microhello.o +minihello.shared-y := minihello.o +mmaptest.shared-y := mmaptest.o +nfs_no_rpc.shared-y := nfs_no_rpc.o +opentest.shared-y := opentest.o +pipetest.shared-y := pipetest.o +rtsig.shared-y := rtsig.o +setenvtest.shared-y := setenvtest.o +setjmptest.shared-y := setjmptest.o +sigint.shared-y := sigint.o +stat.shared-y := stat.o +statfs.shared-y := statfs.o +strlcpycat.shared-y := strlcpycat.o +strtoimax.shared-y := strtoimax.o +strtotime.shared-y := strtotime.o +testrand48.shared-y := testrand48.o +testvsnp.shared-y := testvsnp.o +vfork.shared-y := vfork.o + +# Cleaning +clean-files := $(static-y) $(shared-y) \ + $(addsuffix .g, $(static-y) $(shared-y)) \ + $(test-files:.c=.o) diff -puN /dev/null usr/klibc/tests/malloctest2.c --- /dev/null +++ a/usr/klibc/tests/malloctest2.c @@ -0,0 +1,62 @@ +#include +#include +#include + +#define NCYCLES 32768 +#define NSLOTS 4096 + +struct slot { + char *ptr; + size_t size; +}; + +struct slot s[NSLOTS]; + +int main(void) +{ + size_t sp, sq; + char *p, *ep, *q, *eq; + int r, i, j; + int ok; + int err = 0; + + for (r = 0; r < NCYCLES; r++) { + i = lrand48() % NSLOTS; + + if (s[i].ptr) { + free(s[i].ptr); + printf("Freed %8zu bytes at %p\n", s[i].size, + s[i].ptr); + s[i].ptr = NULL; + s[i].size = 0; + } else { + sp = lrand48(); /* 32-bit random number */ + sp >>= 12 + (lrand48() % 20); + + s[i].size = sp; + s[i].ptr = p = malloc(sp); + ep = p + sp; + ok = 1; + for (j = 0; j < NSLOTS; j++) { + q = s[j].ptr; + if (i != j && q) { + sq = s[j].size; + eq = q + sq; + + if ((p < q && ep > q) + || (p >= q && p < eq)) { + ok = 0; + err = 1; + break; + } + } + } + printf("Allocated %8zu bytes at %p, ok = %d\n", sp, p, + ok); + + if (p) + memset(p, 0xee, sp); /* Poison this memory */ + } + } + return err; +} diff -puN /dev/null usr/klibc/tests/malloctest.c --- /dev/null +++ a/usr/klibc/tests/malloctest.c @@ -0,0 +1,4146 @@ +#include +#include +#include + +#define NCYCLES 4096 + +int sizes[NCYCLES] = { + 11986, + 277806, + 2659, + 46, + 0, + 775553, + 1991, + 21, + 7638, + 250197, + 155828, + 5777, + 9, + 315006, + 900788, + 0, + 24893, + 119996, + 72299, + 171266, + 357, + 560, + 368, + 22952, + 54058, + 12638, + 39155, + 2738, + 217563, + 26853, + 47, + 75, + 1167, + 16917, + 1899, + 2905, + 9337, + 62243, + 14214, + 270523, + 4024, + 21, + 32, + 14892, + 625144, + 13, + 21700, + 8804, + 254147, + 0, + 6, + 836004, + 1718, + 2289, + 15554, + 412857, + 185097, + 806709, + 64, + 18602, + 17064, + 1779, + 78153, + 170600, + 199100, + 546528, + 0, + 21, + 20609, + 16514, + 548196, + 311446, + 53484, + 0, + 551, + 22225, + 24, + 153989, + 457309, + 526833, + 227979, + 757167, + 429560, + 0, + 835, + 1702, + 475275, + 798416, + 753, + 0, + 11126, + 145779, + 2006, + 0, + 8182, + 0, + 569432, + 9671, + 36, + 5523, + 407325, + 0, + 65, + 9293, + 0, + 6793, + 468701, + 73, + 0, + 186236, + 0, + 328405, + 125616, + 508013, + 380519, + 599518, + 83, + 151973, + 466906, + 9029, + 159725, + 1316, + 1, + 911532, + 1508, + 19050, + 972850, + 126, + 439377, + 29, + 37928, + 149628, + 54, + 130248, + 2, + 143, + 0, + 716873, + 3327, + 5, + 116131, + 5124, + 559621, + 2886, + 534, + 186432, + 441, + 7348, + 10331, + 1, + 260935, + 7, + 4370, + 405415, + 2, + 84518, + 1970, + 1, + 281910, + 46, + 274, + 2273, + 370565, + 4190, + 820641, + 577970, + 32809, + 974893, + 398067, + 380698, + 4, + 25978, + 153, + 882668, + 312365, + 9523, + 156421, + 0, + 268143, + 6, + 2, + 42987, + 212, + 12303, + 6723, + 1179, + 0, + 120924, + 3877, + 330421, + 310445, + 39264, + 8, + 85380, + 464716, + 0, + 33657, + 6285, + 0, + 4491, + 229, + 50, + 373197, + 6029, + 19, + 86884, + 243745, + 335656, + 90945, + 38973, + 572950, + 164129, + 0, + 3, + 17, + 13579, + 4448, + 47, + 3, + 132966, + 726249, + 498503, + 256, + 0, + 25841, + 0, + 7, + 945380, + 11872, + 69, + 3799, + 77223, + 1914, + 73, + 810968, + 10223, + 257918, + 184252, + 350, + 8101, + 725, + 9, + 2, + 2089, + 175, + 247, + 185964, + 36517, + 3723, + 313465, + 209, + 1300, + 128071, + 7425, + 2436, + 62, + 13753, + 9514, + 41, + 409141, + 46643, + 20866, + 15664, + 388548, + 84692, + 9549, + 610, + 7213, + 14, + 14930, + 244719, + 4748, + 41682, + 401098, + 102506, + 176535, + 0, + 5133, + 548, + 5234, + 56, + 11101, + 87638, + 336579, + 291705, + 640250, + 768165, + 370, + 2809, + 3, + 0, + 445122, + 47190, + 24885, + 143556, + 84, + 504726, + 610020, + 40355, + 902230, + 4360, + 1747, + 3496, + 489501, + 19, + 801601, + 62189, + 48, + 2645, + 320601, + 27304, + 17740, + 344, + 10, + 991, + 925503, + 0, + 315, + 251, + 3611, + 1756, + 683, + 165, + 380132, + 181101, + 453041, + 892056, + 67191, + 252592, + 32407, + 56242, + 8, + 297173, + 542903, + 830334, + 585236, + 422555, + 44769, + 0, + 68, + 4143, + 38754, + 73539, + 44579, + 94001, + 428537, + 38554, + 106612, + 0, + 182987, + 831731, + 3605, + 752851, + 52, + 72, + 120872, + 963754, + 31, + 764, + 240592, + 99101, + 328538, + 440325, + 12211, + 151282, + 353436, + 2991, + 40710, + 5212, + 5106, + 139122, + 148915, + 498505, + 1366, + 516, + 29190, + 17, + 224208, + 40, + 89, + 19190, + 8, + 25377, + 10029, + 720, + 97963, + 0, + 614, + 244567, + 2113, + 903675, + 8388, + 6, + 390705, + 325006, + 284272, + 108086, + 17, + 2628, + 952530, + 20474, + 898276, + 138661, + 3883, + 903, + 569993, + 376918, + 5849, + 103404, + 794499, + 35388, + 5, + 0, + 961626, + 27415, + 1927, + 92036, + 46241, + 35978, + 7426, + 399884, + 29490, + 252655, + 675971, + 3509, + 54170, + 170790, + 831341, + 134579, + 0, + 790422, + 35, + 930830, + 97394, + 20265, + 670, + 38497, + 1759, + 71209, + 93, + 736, + 11, + 886, + 1961, + 7, + 210607, + 62226, + 186736, + 1518, + 5, + 5, + 13, + 66989, + 442321, + 0, + 607939, + 11253, + 210875, + 495530, + 2, + 221136, + 377663, + 372, + 200658, + 18591, + 129783, + 803411, + 867506, + 757446, + 48836, + 34, + 200, + 114983, + 7287, + 22849, + 226669, + 13, + 0, + 20164, + 7828, + 39, + 49448, + 26740, + 185566, + 9927, + 36192, + 91068, + 338368, + 926, + 27746, + 534794, + 936132, + 2922, + 5, + 183162, + 256846, + 242551, + 134318, + 212959, + 167162, + 470, + 477045, + 532116, + 483794, + 733, + 5335, + 83074, + 4686, + 9567, + 1, + 195100, + 40354, + 87338, + 369, + 800, + 0, + 194504, + 469051, + 363532, + 850574, + 5085, + 167027, + 794511, + 124320, + 303231, + 132195, + 13225, + 46333, + 4313, + 89, + 799, + 51482, + 0, + 26, + 12659, + 1045, + 23621, + 0, + 74926, + 490979, + 6, + 3188, + 9448, + 174730, + 38982, + 102317, + 189621, + 853, + 29227, + 43374, + 423, + 420951, + 686, + 128, + 31291, + 0, + 402819, + 663143, + 55903, + 142, + 2, + 331584, + 197164, + 7, + 671983, + 53, + 5020, + 9782, + 123, + 743407, + 1276, + 1115, + 1169, + 122752, + 824690, + 292030, + 2094, + 144626, + 0, + 297278, + 440, + 742, + 95879, + 17682, + 10654, + 31, + 22183, + 746, + 0, + 0, + 11185, + 28, + 394987, + 36, + 474, + 243749, + 1431, + 56702, + 76, + 15619, + 33071, + 12181, + 158647, + 261786, + 1, + 119783, + 48816, + 6278, + 4121, + 61122, + 69, + 48790, + 345335, + 275917, + 964393, + 424, + 586433, + 20519, + 18156, + 756400, + 27736, + 458706, + 1, + 3286, + 929624, + 1883, + 2, + 1086, + 439501, + 552, + 157132, + 5565, + 105061, + 8199, + 23, + 178797, + 0, + 130644, + 1, + 6952, + 754, + 500, + 647683, + 0, + 959079, + 622561, + 1131, + 559783, + 6862, + 175420, + 408671, + 463461, + 55908, + 606496, + 169, + 49060, + 247, + 953, + 333030, + 0, + 23399, + 29193, + 9303, + 15, + 515402, + 34961, + 365856, + 633043, + 173, + 556089, + 1809, + 12215, + 14, + 316, + 20642, + 9, + 15, + 190391, + 951463, + 25059, + 13654, + 385040, + 4272, + 929033, + 208813, + 35166, + 42849, + 662648, + 254811, + 4230, + 812459, + 681, + 390168, + 5381, + 4662, + 173257, + 478863, + 103, + 89332, + 0, + 0, + 589484, + 19369, + 94, + 9, + 639917, + 1110, + 393, + 101040, + 911, + 152899, + 0, + 2, + 0, + 0, + 335691, + 43694, + 62273, + 200121, + 2250, + 621004, + 149918, + 41063, + 218229, + 0, + 497924, + 16832, + 587071, + 0, + 0, + 729918, + 2, + 808513, + 9417, + 718, + 0, + 2769, + 28704, + 1335, + 734726, + 219157, + 786230, + 981004, + 350788, + 884529, + 0, + 87872, + 34647, + 85469, + 4524, + 339838, + 38228, + 0, + 4151, + 1145, + 0, + 351, + 167956, + 810075, + 689, + 251212, + 583068, + 2929, + 189456, + 2089, + 48749, + 278952, + 77134, + 0, + 0, + 45595, + 281829, + 969602, + 43999, + 69824, + 856982, + 61732, + 336, + 25488, + 213, + 46683, + 1909, + 174097, + 57930, + 91466, + 828418, + 95740, + 378828, + 128065, + 68068, + 0, + 13312, + 26006, + 6760, + 51, + 276081, + 640068, + 634985, + 7131, + 784882, + 790126, + 628585, + 205824, + 764965, + 17793, + 3159, + 649924, + 0, + 37383, + 9919, + 353, + 0, + 149003, + 620629, + 95928, + 2560, + 504343, + 1000, + 32, + 43836, + 407031, + 207, + 800894, + 3222, + 51028, + 7, + 6, + 22010, + 0, + 21174, + 12893, + 824932, + 7305, + 70, + 624258, + 372139, + 21504, + 387996, + 418931, + 914268, + 576, + 0, + 0, + 618224, + 787516, + 133014, + 422, + 383124, + 656318, + 4420, + 6082, + 244813, + 38585, + 3200, + 1, + 2, + 11882, + 113, + 45581, + 13121, + 95475, + 807219, + 8195, + 995116, + 13, + 2146, + 369925, + 60103, + 25, + 125165, + 51300, + 4894, + 173261, + 74186, + 1044, + 122992, + 1243, + 21703, + 26294, + 197, + 333825, + 426872, + 719580, + 3598, + 106, + 0, + 9932, + 61509, + 146, + 721428, + 964781, + 319850, + 573802, + 7458, + 317889, + 0, + 133086, + 87836, + 60496, + 304249, + 1565, + 27, + 42, + 899324, + 189637, + 8648, + 104570, + 901598, + 447765, + 24, + 108, + 120127, + 828626, + 8, + 899514, + 28, + 13, + 7576, + 163390, + 1625, + 3023, + 155175, + 2, + 391, + 1, + 493073, + 398, + 210771, + 26266, + 287999, + 38255, + 249666, + 598202, + 119601, + 216933, + 91205, + 0, + 7247, + 77077, + 565383, + 29102, + 253641, + 48855, + 19722, + 463536, + 40182, + 65393, + 829444, + 598402, + 1590, + 798, + 467, + 834847, + 3007, + 13711, + 0, + 195, + 101662, + 255749, + 129201, + 11965, + 1781, + 13349, + 3100, + 718066, + 99, + 712450, + 888215, + 42503, + 43171, + 494946, + 0, + 2175, + 12387, + 25662, + 78, + 739030, + 0, + 19, + 427526, + 4275, + 5583, + 0, + 2447, + 132398, + 26437, + 3873, + 440035, + 21, + 6, + 35432, + 41523, + 7179, + 712703, + 428868, + 2793, + 6, + 286277, + 1882, + 95116, + 2959, + 86, + 115425, + 81386, + 59836, + 37, + 247598, + 34732, + 249, + 500110, + 5589, + 40319, + 575, + 12145, + 385829, + 565600, + 582150, + 92, + 223209, + 0, + 910, + 1048, + 47329, + 90944, + 235, + 8739, + 686685, + 1753, + 126, + 434, + 609477, + 25021, + 6610, + 52675, + 4, + 717846, + 150864, + 418583, + 17751, + 513794, + 181362, + 329556, + 10426, + 717019, + 457, + 616, + 388984, + 17, + 8338, + 59531, + 32, + 99565, + 376146, + 134578, + 966, + 0, + 0, + 174, + 2105, + 555, + 8990, + 298, + 169932, + 247281, + 240918, + 298655, + 158743, + 15994, + 95708, + 51, + 2985, + 4294, + 731934, + 185640, + 1483, + 87, + 742033, + 9, + 1345, + 3680, + 133530, + 9355, + 800111, + 28508, + 0, + 369, + 31681, + 24, + 8237, + 313380, + 4732, + 275423, + 951592, + 0, + 41381, + 225515, + 393004, + 526, + 187, + 19515, + 6006, + 28923, + 310151, + 2390, + 374, + 0, + 19142, + 72, + 114, + 193305, + 24035, + 397067, + 18, + 14839, + 3473, + 164, + 104622, + 378958, + 2218, + 0, + 89053, + 105183, + 312265, + 82146, + 147210, + 3419, + 5178, + 34948, + 46836, + 41319, + 842825, + 595972, + 0, + 249625, + 325, + 608, + 372328, + 119634, + 7504, + 920214, + 7302, + 444532, + 359213, + 27265, + 1755, + 48, + 126799, + 651270, + 818220, + 799493, + 724024, + 64047, + 73699, + 206999, + 209, + 1581, + 0, + 42937, + 301144, + 73416, + 0, + 242058, + 29660, + 3, + 34709, + 162719, + 2863, + 3992, + 5212, + 151814, + 3092, + 198001, + 44331, + 36, + 407, + 364771, + 1349, + 502772, + 214726, + 607, + 388583, + 137660, + 337124, + 13279, + 10549, + 943075, + 164068, + 19157, + 38443, + 26351, + 0, + 67167, + 735, + 46486, + 130305, + 232330, + 744, + 882337, + 2, + 69275, + 126354, + 9370, + 2845, + 299, + 38988, + 37834, + 0, + 306433, + 9139, + 237132, + 0, + 500, + 13462, + 373684, + 107453, + 381924, + 347915, + 4329, + 1668, + 3960, + 370661, + 3614, + 636048, + 0, + 487449, + 64925, + 333894, + 11, + 52192, + 531200, + 155554, + 461, + 1547, + 994361, + 11955, + 321056, + 37425, + 14249, + 69151, + 621862, + 174, + 79607, + 34, + 77577, + 13723, + 267550, + 13801, + 698, + 12, + 171556, + 57354, + 676845, + 0, + 24965, + 908955, + 570483, + 0, + 296387, + 983966, + 85012, + 130298, + 151946, + 384474, + 731455, + 150699, + 772, + 216131, + 346, + 130935, + 3472, + 18, + 426045, + 677262, + 808, + 17030, + 5188, + 0, + 491153, + 67299, + 19, + 60342, + 69, + 0, + 76478, + 95763, + 0, + 28778, + 147869, + 335927, + 27846, + 2163, + 22750, + 162, + 23, + 11391, + 469099, + 5852, + 63, + 0, + 0, + 22193, + 165, + 489007, + 9249, + 12477, + 2841, + 223532, + 13877, + 173, + 3570, + 45477, + 233073, + 23296, + 64377, + 4910, + 8, + 76246, + 411147, + 287411, + 10450, + 3667, + 1, + 500933, + 31363, + 257, + 1705, + 6036, + 49934, + 13738, + 13485, + 61608, + 561978, + 76493, + 16377, + 1817, + 0, + 235600, + 0, + 16347, + 680478, + 5115, + 895607, + 138270, + 369912, + 53110, + 0, + 647083, + 85, + 458681, + 163227, + 52767, + 196, + 267719, + 14047, + 147293, + 814457, + 174896, + 0, + 34138, + 36, + 21575, + 3, + 0, + 0, + 38391, + 2597, + 2, + 1433, + 3807, + 36476, + 287, + 141530, + 29389, + 495655, + 30014, + 0, + 550766, + 11958, + 348, + 226760, + 15, + 251353, + 675788, + 518308, + 215, + 81987, + 409862, + 559596, + 114283, + 4925, + 0, + 17, + 14221, + 0, + 162, + 766370, + 4898, + 998, + 493, + 138418, + 265159, + 12152, + 5229, + 1204, + 1814, + 432530, + 2889, + 144, + 1149, + 35886, + 636931, + 6640, + 1508, + 414118, + 858, + 20039, + 17398, + 3, + 5094, + 6, + 13996, + 6754, + 362, + 451487, + 11471, + 7896, + 330009, + 244269, + 99928, + 0, + 14311, + 9949, + 15251, + 283923, + 123754, + 188360, + 93902, + 854384, + 548001, + 531788, + 26298, + 328479, + 941, + 246535, + 106320, + 28769, + 440, + 4, + 61262, + 55615, + 170, + 989327, + 692534, + 8063, + 445842, + 4434, + 255349, + 117781, + 6, + 9249, + 136216, + 38165, + 307012, + 12, + 2341, + 18062, + 371882, + 662154, + 12623, + 176847, + 332220, + 590935, + 33682, + 0, + 121374, + 67, + 46841, + 495890, + 640, + 19, + 14737, + 11032, + 17, + 5993, + 302562, + 827710, + 165346, + 49607, + 87863, + 308513, + 735300, + 1914, + 2900, + 207308, + 9068, + 83494, + 179, + 417, + 41605, + 74681, + 652171, + 4013, + 29811, + 13966, + 8136, + 78, + 61182, + 674187, + 0, + 331121, + 0, + 18559, + 386, + 77, + 348439, + 975358, + 18, + 33700, + 47396, + 204751, + 2350, + 26503, + 0, + 83653, + 446, + 10844, + 485, + 9241, + 88347, + 232419, + 936900, + 43250, + 2, + 26112, + 811955, + 20723, + 102069, + 42255, + 8431, + 119508, + 4080, + 13565, + 12, + 46110, + 62096, + 638777, + 44025, + 152985, + 13362, + 3, + 12331, + 193337, + 56419, + 14593, + 3837, + 282314, + 403454, + 48589, + 135, + 18350, + 2160, + 90, + 918216, + 7083, + 105534, + 742826, + 399028, + 1470, + 23770, + 480, + 677884, + 340472, + 107406, + 0, + 5002, + 445, + 748948, + 534012, + 592464, + 6539, + 819632, + 3138, + 4, + 39397, + 229683, + 12204, + 2439, + 65131, + 817226, + 22596, + 0, + 1046, + 94638, + 0, + 95403, + 1230, + 790056, + 19976, + 43085, + 14251, + 139187, + 20232, + 693, + 3058, + 27654, + 65690, + 40948, + 15001, + 21089, + 14425, + 322459, + 13571, + 228154, + 536814, + 761221, + 28030, + 2322, + 921, + 1, + 1137, + 187815, + 8, + 34911, + 4527, + 15, + 46, + 78801, + 0, + 73605, + 44, + 28233, + 1370, + 73409, + 198159, + 66586, + 3, + 2576, + 15, + 35460, + 263237, + 44997, + 2873, + 240, + 1781, + 269, + 46, + 272778, + 28404, + 8232, + 417073, + 234591, + 9, + 720349, + 1176, + 16195, + 0, + 9705, + 0, + 14, + 947048, + 163, + 76288, + 1115, + 267020, + 3416, + 414217, + 441004, + 95131, + 765002, + 6196, + 9069, + 27017, + 137039, + 65247, + 266489, + 484945, + 187008, + 45405, + 5700, + 9, + 7751, + 12, + 294, + 3093, + 6350, + 103303, + 6045, + 252345, + 140207, + 22390, + 234867, + 443326, + 1, + 0, + 89972, + 8637, + 427150, + 22146, + 0, + 310432, + 390333, + 10461, + 1632, + 31403, + 908653, + 0, + 6543, + 163479, + 67608, + 195543, + 315889, + 822964, + 383536, + 954954, + 1619, + 241, + 96053, + 104556, + 767302, + 2469, + 12, + 164330, + 78, + 141, + 170519, + 268214, + 53338, + 48342, + 721, + 58980, + 4345, + 1, + 856265, + 87289, + 57219, + 775679, + 123992, + 695804, + 113025, + 832, + 117420, + 16634, + 352, + 24729, + 14973, + 25622, + 131290, + 0, + 22, + 87740, + 5917, + 533, + 2934, + 34261, + 9174, + 0, + 1656, + 764587, + 54652, + 35597, + 36389, + 577889, + 63957, + 26808, + 34556, + 56, + 15641, + 137, + 1, + 3, + 11724, + 197397, + 39027, + 87902, + 320, + 791479, + 7, + 487864, + 0, + 433, + 25733, + 6956, + 15407, + 312557, + 526302, + 383019, + 340215, + 96, + 276158, + 6493, + 135613, + 2000, + 1218, + 930, + 276808, + 273249, + 8896, + 397, + 735095, + 20648, + 2079, + 5349, + 205, + 356313, + 841954, + 8255, + 266874, + 0, + 965, + 287993, + 1549, + 207833, + 75, + 178180, + 39072, + 0, + 43254, + 3847, + 227, + 2712, + 161043, + 463264, + 74720, + 795789, + 12, + 6812, + 202804, + 29379, + 64241, + 132121, + 790622, + 493588, + 0, + 48, + 147352, + 925197, + 38149, + 18380, + 0, + 270280, + 633, + 3373, + 31294, + 7830, + 0, + 0, + 11371, + 56143, + 5393, + 74724, + 495109, + 0, + 18993, + 21524, + 0, + 53889, + 400509, + 204563, + 0, + 11625, + 9635, + 0, + 1678, + 12096, + 59, + 817112, + 10002, + 128209, + 11593, + 17313, + 15200, + 106796, + 261401, + 707077, + 0, + 314030, + 798591, + 14175, + 5668, + 2766, + 0, + 566, + 5543, + 24112, + 154482, + 5642, + 0, + 38410, + 3, + 4, + 700724, + 25024, + 5, + 407, + 564150, + 672, + 143, + 2049, + 574708, + 65858, + 213412, + 3797, + 511, + 30907, + 1212, + 765, + 2127, + 481, + 130048, + 113816, + 39861, + 153169, + 503378, + 523944, + 111, + 55083, + 698, + 275, + 3, + 3195, + 1657, + 0, + 317881, + 6672, + 543, + 153011, + 77240, + 9338, + 889850, + 29518, + 872485, + 181927, + 376086, + 266, + 409, + 4, + 14856, + 31943, + 2448, + 8, + 75, + 383097, + 294366, + 0, + 173084, + 753160, + 66457, + 725783, + 51, + 127651, + 1073, + 12598, + 140080, + 0, + 296375, + 581720, + 217346, + 8272, + 2051, + 185390, + 520645, + 1260, + 13873, + 168040, + 19690, + 103347, + 295011, + 548404, + 48, + 4, + 916417, + 1948, + 621365, + 263245, + 2792, + 86803, + 181193, + 558081, + 50907, + 442770, + 51448, + 340276, + 1346, + 607, + 459627, + 0, + 30, + 73298, + 15389, + 12264, + 2719, + 2936, + 143043, + 209970, + 0, + 42, + 6657, + 317419, + 0, + 32622, + 524000, + 0, + 310331, + 303778, + 268710, + 9, + 10410, + 25343, + 949506, + 784353, + 3861, + 46823, + 251292, + 75008, + 269798, + 87731, + 112813, + 571679, + 385, + 3, + 2811, + 36025, + 9243, + 935128, + 906, + 10688, + 25, + 86757, + 307, + 55, + 22, + 2, + 61, + 620426, + 484530, + 633806, + 0, + 1342, + 9293, + 992181, + 503, + 195433, + 46150, + 893091, + 3207, + 2865, + 72894, + 830299, + 355, + 327479, + 0, + 35573, + 3068, + 15699, + 31187, + 55378, + 416067, + 91721, + 159, + 0, + 255139, + 2104, + 19, + 606757, + 323, + 902659, + 365655, + 400, + 903, + 408, + 385, + 21774, + 701290, + 234426, + 17020, + 950, + 0, + 0, + 429, + 1245, + 405871, + 1097, + 280634, + 74, + 158233, + 1583, + 180333, + 42114, + 575973, + 539327, + 59252, + 121928, + 165, + 148501, + 55757, + 7494, + 127728, + 7832, + 68504, + 619770, + 70995, + 312816, + 7307, + 38265, + 46248, + 363304, + 269442, + 77112, + 448331, + 910442, + 474418, + 152752, + 752, + 104912, + 408492, + 691709, + 632381, + 48519, + 20524, + 344294, + 14670, + 0, + 21607, + 81162, + 181458, + 0, + 908322, + 7261, + 10888, + 58054, + 1788, + 970933, + 5925, + 121553, + 36152, + 588267, + 23615, + 1850, + 30728, + 3599, + 1319, + 6027, + 0, + 32141, + 984156, + 436781, + 15003, + 621407, + 9412, + 562911, + 189740, + 377895, + 656800, + 197, + 14413, + 99382, + 384, + 11480, + 0, + 86118, + 881961, + 1905, + 82061, + 4140, + 741153, + 26, + 687, + 12251, + 10945, + 209267, + 220602, + 135881, + 6, + 237945, + 158, + 5, + 76303, + 81344, + 986042, + 956063, + 30282, + 186055, + 357802, + 12492, + 577476, + 838, + 0, + 11, + 117602, + 0, + 187928, + 96860, + 4268, + 3478, + 818264, + 1649, + 17175, + 272, + 158951, + 440987, + 677594, + 14935, + 37953, + 0, + 198, + 160404, + 12, + 287803, + 2386, + 10, + 271663, + 319152, + 361322, + 68370, + 428, + 182707, + 387429, + 1152, + 360065, + 25218, + 2790, + 42228, + 13, + 110942, + 452491, + 1, + 665638, + 2308, + 1196, + 87306, + 66, + 219, + 0, + 130736, + 334, + 605, + 5979, + 2681, + 0, + 123463, + 11219, + 283681, + 19269, + 553, + 6217, + 130965, + 714409, + 242, + 674833, + 237581, + 133284, + 683, + 1758, + 278193, + 518726, + 44, + 420361, + 325228, + 14955, + 10, + 11994, + 64157, + 1937, + 20214, + 848, + 27804, + 151341, + 79236, + 316393, + 158883, + 1196, + 334, + 22797, + 185955, + 13857, + 397357, + 7948, + 6038, + 0, + 2621, + 16, + 155267, + 44809, + 9171, + 21328, + 12212, + 40200, + 2600, + 439, + 804014, + 10938, + 96135, + 43696, + 158715, + 4, + 284558, + 191, + 270254, + 7923, + 880603, + 21032, + 107700, + 172, + 700823, + 5613, + 78816, + 258290, + 214398, + 821856, + 295325, + 0, + 1, + 23559, + 63895, + 21249, + 717490, + 956952, + 944819, + 793, + 356, + 757716, + 111773, + 394826, + 25665, + 4358, + 640216, + 1152, + 37175, + 150192, + 106071, + 28992, + 67, + 1685, + 134242, + 2, + 102045, + 1457, + 419589, + 6789, + 677, + 94675, + 11300, + 2595, + 8, + 926535, + 265194, + 0, + 886048, + 246242, + 1494, + 191, + 169985, + 649765, + 0, + 201, + 1069, + 679163, + 16627, + 274639, + 84438, + 3, + 1301, + 247496, + 5879, + 710904, + 403652, + 958241, + 361, + 139732, + 6042, + 15985, + 2378, + 267031, + 223767, + 9656, + 241717, + 33863, + 14314, + 205697, + 1274, + 168000, + 621777, + 837913, + 89654, + 659829, + 69, + 503884, + 432717, + 70443, + 110891, + 19655, + 132432, + 620401, + 428, + 0, + 425662, + 0, + 0, + 0, + 194489, + 7601, + 26870, + 0, + 63, + 594, + 12278, + 582479, + 213723, + 424489, + 96446, + 990664, + 46966, + 44137, + 829810, + 104, + 19707, + 16, + 0, + 2499, + 167075, + 140972, + 249283, + 6620, + 68368, + 856414, + 9255, + 14315, + 0, + 11432, + 24329, + 216463, + 299556, + 818401, + 246607, + 697733, + 229, + 144, + 389394, + 664634, + 0, + 19393, + 657903, + 52912, + 952177, + 536931, + 187271, + 17687, + 970155, + 232571, + 234016, + 159980, + 13510, + 32952, + 0, + 0, + 24132, + 18806, + 15624, + 28364, + 472126, + 626978, + 599, + 112843, + 502933, + 915660, + 63920, + 0, + 84, + 10899, + 904823, + 126, + 469132, + 590052, + 195831, + 443113, + 294149, + 15944, + 2271, + 282974, + 211, + 0, + 22934, + 82283, + 49973, + 41707, + 87530, + 0, + 910528, + 0, + 36029, + 423337, + 817512, + 223671, + 27800, + 398847, + 198528, + 1, + 560679, + 518270, + 23033, + 501059, + 0, + 3909, + 272062, + 261581, + 187, + 52043, + 334, + 24354, + 3947, + 8549, + 37863, + 328851, + 963771, + 1, + 3930, + 82416, + 6, + 2943, + 122101, + 82577, + 85, + 89540, + 5135, + 109236, + 18297, + 1, + 177371, + 4541, + 769577, + 178, + 417, + 960566, + 33803, + 911651, + 248160, + 153725, + 43981, + 809174, + 116, + 486900, + 4842, + 148490, + 131534, + 4347, + 239949, + 984096, + 749756, + 429499, + 2794, + 78209, + 18812, + 21111, + 490, + 328042, + 12, + 132119, + 505103, + 353148, + 0, + 373656, + 951244, + 491, + 355778, + 30620, + 317, + 60175, + 220, + 214496, + 41249, + 5169, + 78367, + 506804, + 0, + 1368, + 407, + 295126, + 1288, + 86, + 97614, + 61640, + 244723, + 3, + 0, + 869827, + 527246, + 52, + 107036, + 240739, + 780281, + 113084, + 62009, + 740343, + 483201, + 8649, + 16419, + 1, + 801574, + 95524, + 326126, + 26912, + 877040, + 10262, + 5895, + 0, + 132633, + 59171, + 306347, + 702701, + 196245, + 12642, + 32723, + 24608, + 30287, + 45775, + 18281, + 7587, + 144532, + 5, + 35, + 99862, + 215127, + 170875, + 61461, + 77790, + 5, + 0, + 129358, + 0, + 105084, + 21399, + 42233, + 85397, + 480654, + 555988, + 89575, + 42346, + 20004, + 11102, + 21321, + 185, + 379267, + 849147, + 121514, + 3388, + 33662, + 12, + 164898, + 226, + 274, + 385003, + 365052, + 693376, + 41245, + 9010, + 41594, + 89835, + 10490, + 272, + 128437, + 0, + 122648, + 277, + 116505, + 38372, + 4, + 1376, + 0, + 46317, + 139368, + 36398, + 193899, + 30632, + 26371, + 7548, + 367643, + 954849, + 25889, + 36567, + 176, + 140631, + 4690, + 975031, + 80965, + 500471, + 8442, + 43, + 27758, + 301501, + 3797, + 80, + 384440, + 928477, + 4960, + 24566, + 33245, + 14638, + 228354, + 54347, + 861285, + 12841, + 2, + 157402, + 646747, + 53763, + 1, + 214732, + 49471, + 49757, + 998, + 201135, + 566, + 73512, + 194240, + 391773, + 21510, + 13, + 829894, + 783200, + 565329, + 2101, + 12, + 191043, + 1621, + 18443, + 279, + 294135, + 526503, + 729735, + 4639, + 444138, + 5835, + 12372, + 46362, + 1543, + 870907, + 83262, + 0, + 38331, + 95, + 1194, + 909, + 8053, + 453066, + 845561, + 411, + 3229, + 1, + 158, + 1431, + 835137, + 21774, + 7298, + 148388, + 224649, + 379318, + 520138, + 39781, + 172130, + 362634, + 487495, + 51957, + 158, + 1770, + 7, + 18010, + 1063, + 171484, + 19924, + 279867, + 469956, + 189785, + 0, + 814, + 60580, + 944349, + 18743, + 553235, + 0, + 95475, + 99, + 0, + 5, + 42623, + 178418, + 398940, + 5700, + 69023, + 5786, + 0, + 10531, + 551, + 86308, + 63451, + 32704, + 176903, + 0, + 251689, + 11589, + 25711, + 43437, + 1431, + 304, + 52965, + 34816, + 268688, + 47756, + 825323, + 122608, + 81246, + 69974, + 360515, + 99973, + 143015, + 5063, + 4499, + 34459, + 171982, + 677943, + 489082, + 257515, + 3765, + 5, + 7416, + 602206, + 74122, + 3, + 686204, + 5493, + 28901, + 11349, + 549668, + 257082, + 82000, + 17031, + 1517, + 7442, + 937160, + 722, + 0, + 72952, + 377192, + 438266, + 555, + 31436, + 284, + 56390, + 0, + 585856, + 27635, + 519344, + 126131, + 360273, + 845073, + 0, + 191965, + 55652, + 23, + 112773, + 639025, + 84749, + 0, + 330822, + 7173, + 126217, + 871, + 112112, + 0, + 664, + 530474, + 1, + 379564, + 172617, + 647308, + 0, + 356, + 17, + 84345, + 457, + 0, + 8, + 6, + 136602, + 634424, + 0, + 177298, + 100726, + 91661, + 383792, + 1665, + 43583, + 15775, + 4083, + 4277, + 345749, + 969599, + 65804, + 19327, + 0, + 352514, + 4225, + 9, + 103767, + 0, + 0, + 148436, + 850, + 33, + 2146, + 20153, + 50, + 9063, + 50329, + 348379, + 2569, + 83697, + 37073, + 715486, + 629, + 4753, + 442, + 259203, + 287223, + 48625, + 9, + 70184, + 45946, + 144947, + 0, + 60285, + 28640, + 7626, + 134159, + 33, + 12452, + 150566, + 348293, + 124426, + 353952, + 11, + 22, + 776742, + 29072, + 132168, + 254533, + 319957, + 1602, + 1659, + 209341, + 32847, + 92392, + 753005, + 1392, + 10271, + 28557, + 6717, + 941745, + 0, + 0, + 0, + 78645, + 45320, + 11193, + 1448, + 130626, + 377907, + 795535, + 24285, + 26094, + 266691, + 64449, + 77400, + 191410, + 1, + 1346, + 25224, + 489637, + 47052, + 248592, + 76689, + 0, + 7722, + 47285, + 3152, + 285577, + 0, + 149366, + 264346, + 1, + 208602, + 320459, + 131771, + 1421, + 350, + 723283, + 714934, + 0, + 566439, + 11656, + 34189, + 125484, + 943273, + 15, + 7789, + 0, + 7427, + 464278, + 680924, + 651102, + 87794, + 39640, + 838644, + 964500, + 1, + 1765, + 272604, + 10, + 837347, + 44845, + 130, + 163357, + 4150, + 403331, + 839132, + 44876, + 272792, + 592527, + 57225, + 128826, + 2915, + 2, + 3570, + 2410, + 199, + 171358, + 5931, + 53620, + 55299, + 1868, + 24123, + 165, + 346513, + 16527, + 133, + 517412, + 195700, + 730365, + 896209, + 152760, + 24577, + 65, + 8218, + 349642, + 901345, + 5127, + 5102, + 238318, + 955, + 631921, + 12218, + 55101, + 930381, + 219503, + 469237, + 132, + 16701, + 494, + 199729, + 0, + 32139, + 314, + 172, + 2947, + 106997, + 4871, + 236, + 6146, + 1843, + 128, + 0, + 254240, + 2964, + 14825, + 60624, + 2108, + 286953, + 654931, + 0, + 0, + 396587, + 19852, + 70311, + 363561, + 282, + 17966, + 924254, + 104173, + 130816, + 179096, + 105466, + 136, + 618261, + 358433, + 25587, + 49357, + 102, + 133746, + 620776, + 17084, + 406881, + 802675, + 349, + 69, + 8761, + 278482, + 16336, + 128, + 160096, + 25857, + 280, + 39639, + 726299, + 293905, + 4621, + 41, + 649, + 3655, + 269286, + 578026, + 0, + 11156, + 1, + 744858, + 531, + 48155, + 28435, + 7991, + 447, + 10201, + 379341, + 0, + 5773, + 0, + 295, + 228592, + 331155, + 104089, + 628069, + 29693, + 22, + 13, + 0, + 0, + 554349, + 6082, + 238, + 23, + 151873, + 805937, + 0, + 194076, + 6450, + 3, + 128322, + 69149, + 95511, + 86, + 844368, + 415964, + 51985, + 308686, + 553403, + 624943, + 365800, + 4, + 120263, + 91239, + 195248, + 58010, + 19, + 415112, + 136806, + 42, + 571848, + 55306, + 29454, + 3, + 144926, + 189, + 0, + 161943, + 592155, + 10930, + 279297, + 56932, + 957430, + 10244, + 190296, + 807209, + 781, + 1466, + 235055, + 33, + 196, + 58280, + 436, + 408649, + 221, + 711143, + 10495, + 2441, + 275720, + 2, + 15391, + 132107, + 102610, + 688549, + 237142, + 3041, + 14, + 308623, + 0, + 0, + 287, + 295147, + 61443, + 229, + 207, + 2051, + 64, + 13479, + 55656, + 570134, + 50387, + 225869, + 20615, + 258465, + 64932, + 112461, + 164521, + 907269, + 758563, + 22901, + 0, + 7944, + 48, + 154921, + 2784, + 548608, + 0, + 12524, + 142556, + 0, + 13882, + 507227, + 316598, + 987551, + 0, + 894687, + 1964, + 364, + 10316, + 440269, + 9, + 776723, + 72288, + 54604, + 185101, + 142, + 362, + 11679, + 77, + 79, + 529321, + 364, + 42387, + 0, + 570879, + 417503, + 604871, + 578806, + 1102, + 66584, + 615440, + 146744, + 19441, + 170478, + 144069, + 36170, + 145376, + 842283, + 193612, + 3, + 359429, + 368596, + 0, + 11064, + 7726, + 229410, + 63569, + 67402, + 91, + 203201, + 213513, + 0, + 704479, + 1325, + 0, + 385154, + 13, + 806763, + 197132, + 6183, + 45760, + 99377, + 0, + 972077, + 4043, + 195700, + 34229, + 0, + 154027, + 633, + 6, + 32142, + 0, + 29, + 620842, + 14099, + 495465, + 26937, + 0, + 0, + 432, + 227704, + 0, + 63, + 0, + 19, + 863491, + 20, + 1, + 160713, + 24607, + 85800, + 3566, + 37854, + 81913, + 121573, + 816, + 20, + 133253, + 692231, + 4869, + 255175, + 15028, + 9383, + 542877, + 4608, + 369610, + 243635, + 385285, + 391565, + 286009, + 0, + 61685, + 416318, + 208, + 67019, + 788416, + 88, + 165056, + 0, + 439589, + 160, + 105528, + 152, + 160624, + 865, + 390229, + 714086, + 6007, + 30229, + 481306, + 173266, + 1135, + 2266, + 8, + 59, + 104722, + 647885, + 579471, + 21309, + 230834, + 140278, + 31858, + 3288, + 36011, + 151387, + 594217, + 22439, + 418638, + 76859, + 29363, + 154809, + 275533, + 39, + 472996, + 22076, + 7481, + 155705, + 10406, + 214779, + 223, + 1312, + 16391, + 17203, + 55605, + 44579, + 69332, + 303, + 19217, + 26288, + 126212, + 316, + 98, + 114, + 37382, + 137591, + 439749, + 12972, + 54, + 154879, + 0, + 102680, + 7639, + 309119, + 263550, + 766, + 1124, + 56, + 686608, + 123767, + 518054, + 18, + 672385, + 3161, + 53791, + 26769, + 451670, + 61, + 148245, + 2713, + 96725, + 4794, + 33247, + 297946, + 33380, + 0, + 20034, + 5647, + 17227, + 76444, + 0, + 21011, + 675, + 13226, + 1027, + 990842, + 124459, + 34406, + 53, + 69540, + 134, + 0, + 168521, + 6, + 4075, + 1137, + 63740, + 220, + 10434, + 1171, + 28950, + 0, + 79680, + 993269, + 355622, + 15, + 0, + 1452, + 21667, + 22208, + 494484, + 33984, + 691308, + 10, + 693686, + 196, + 9, + 70676, + 157660, + 775, + 165, + 468432, + 1083, + 515154, + 778344, + 70241, + 42, + 40931, + 277125, + 43837, + 301881, + 1332, + 56712, + 9013, + 1299, + 7564, + 31092, + 1975, + 113517, + 833295, + 245021, + 36503, + 23586, + 149327, + 89175, + 10512, + 484348, + 187793, + 954609, + 53199, + 792175, + 126, + 12369, + 405, + 0, + 6614, + 322857, + 166, + 571874, + 60839, + 180975, + 146722, + 411565, + 1536, + 1, + 11, + 116230, + 60514, + 9003, + 2325, + 43763, + 63, + 355553, + 0, + 389876, + 14672, + 11526, + 160209, + 65, + 10283, + 966, + 10, + 58333, + 129920, + 2850, + 83346, + 0, + 14, + 295819, + 679550, + 143928, + 29489, + 82324, + 36558, + 267118, + 143313, + 90107, + 12789, + 951, + 0, + 187619, + 295317, + 82, + 41326, + 309682, + 907327, + 809358, + 324, + 139157, + 12, + 78366, + 671811, + 354, + 131, + 70525, + 35830, + 281018, + 91456, + 92523, + 54874, + 48273, + 2423, + 0, + 81, + 361314, + 374811, + 394758, + 15350, + 795, + 3, + 16779, + 796684, + 477556, + 73927, + 26643, + 119281, + 62692, + 17039, + 454778, + 952, + 48973, + 19529, + 151, + 239121, + 93509, + 254702, + 1307, + 10029, + 7973, + 546706, + 806644, + 680517, + 223, + 0, + 2, + 0, + 402421, + 619193, + 15685, + 2, + 939715, + 519198, + 0, + 444312, + 23204, + 35669, + 32467, + 0, + 799725, + 5883, + 2217, + 32292, + 355557, + 22179, + 1066, + 15704, + 610, + 37819, + 403626, + 83101, + 10989, + 311607, + 43394, + 72576, + 335450, + 85964, + 73734, + 105142, + 38292, + 0, + 181516, + 33959, + 611797, + 221838, + 5931, + 7666, + 1044, + 477173, + 13591, + 405, + 521, + 190653, + 184191, + 0, + 215, + 847195, + 22782, + 11912, + 27345, + 2572, + 0, + 566350, + 7, + 52302, + 26641, + 587826, + 127, + 2, + 44449, + 153198, + 14, + 926, + 285, + 0, + 938196, + 52255, + 9153, + 807, + 12548, + 358324, + 18521, + 104956, + 42738, + 116, + 135772, + 189554, + 38, + 54, + 36, + 89768, + 17170, + 75, + 34502, + 45489, + 172796, + 971810, + 16153, + 499280, + 1, + 879663, + 53830, + 186, + 539, + 242059, + 268, + 402, + 2732, + 68057, + 18463, + 198560, + 10068, + 591753, + 6116, + 699280, + 1, + 0, + 114258, + 277, + 149, + 283821, + 352561, + 88172, + 684476, + 3450, + 87, + 99936, + 3155, + 72983, + 31619, + 8832, + 58666, + 0, + 59023, + 306091, + 352150, + 255063, + 992708, + 23, + 4896, + 18165, + 424401, + 227613, + 5175, + 347, + 139846, + 11962, + 714, + 3501, + 82367, + 11110, + 10, + 12874, + 0, + 0, + 222712, + 169, + 123281, + 0, + 268149, + 101, + 17446, + 4262, + 489, + 0, + 30, + 0, + 277235, + 28, + 71, + 23, + 61219, + 953631, + 477548, + 662491, + 273, + 44787, + 4130, + 14483, + 470571, + 735977, + 406648, + 815898, + 5985, + 462696, + 937510, + 9, + 0, + 111727, + 93, + 331435, + 336402, + 78690, + 49, + 0, + 87422, + 1242, + 0, + 8783, + 8540, + 314, + 33411, + 805718, + 247, + 6870, + 523743, + 8323, + 612593, + 430, + 354048, + 264913, + 83, + 114063, + 202825, + 35202, + 32823, + 185554, + 85760, + 45159, + 5971, + 267733, + 4545, + 116, + 6910, + 24833, + 218, + 922362, + 221735, + 740, + 7112, + 31, + 15739, + 523589, + 4, + 95996, + 936, + 823951, + 0, + 88, + 160, + 375419, + 663627, + 3741, + 22896, + 114326, + 415962, + 880100, + 6222, + 18650, + 35524, + 195076, + 506, + 451640, + 541336, + 70903, + 3946, + 1, + 61765, + 1, + 2696, + 753129, + 289, + 225234, + 378692, + 1703, + 6751, + 1, + 820, + 7677, + 589, + 12412, + 317, + 69, + 226031, + 134523, + 318253, + 66677, + 111025, + 96, + 0, + 96, + 523528, + 1017, + 0, + 258740, + 420947, + 4600, + 400684, + 12174, + 11770, + 52, + 5959, + 82658, + 531787, + 202, + 548430, + 964, + 1054, + 34, + 96897, + 25445, + 47609, + 386052, + 97004, + 1935, + 30074, + 13458, + 494105, + 54, + 65575, + 594698, + 2340, + 20259, + 84, + 2774, + 534, + 972534, + 115057, + 0, + 11379, + 0, + 271, + 266305, + 132595, + 2, + 773561, + 52365, + 3585, + 351, + 148206, + 778964, + 149379, + 596, + 284914, + 2900, + 35596, + 1547, + 212027, + 8100, + 12248, + 3013, + 1814, + 183415, + 273633, + 15812, + 0, + 966680, + 14830, + 134309, + 0, + 416450, + 206611, + 816, + 82258, + 9873, + 3155, + 53485, + 779805, + 107690, + 254475, + 102504, + 72495, + 17301, + 472130, + 6895, + 245420, + 7299, + 110508, + 27776, + 246134, + 0, + 330853, + 0, + 271767, + 61886, + 24123, + 309681, + 58325, + 608865, + 20666, + 87349, + 229228, + 246, + 457768, + 5374, + 69643, + 148, + 618375, + 45236, + 352565, + 133904, + 152, + 10688, + 18, + 0, + 276036, + 493281, + 11156, + 12566, + 5762, + 113, + 24179, + 98, + 327, + 893, + 209180, + 140805, + 0, + 2341, + 66309, + 30305, + 630559, + 3682, + 152767, + 265822, + 142868, + 1535, + 728603, + 69081, + 353151, + 237995, + 1075, + 925071, + 86, + 6748, + 0, + 684186, + 735, + 13793, + 4790, + 73175, + 69677, + 367627, + 238650, + 303543, + 1, + 26059, + 21392, + 10, + 288609, + 0, + 76345, + 158496, + 7000, + 1865, + 20385, + 0, + 54213, + 9948, + 102667, + 6963, + 71, + 555744, + 5626, + 2512, + 1124, + 7171, + 628, + 29225, + 321687, + 61519, + 4, + 8352, + 9156, +}; + +char *pointers[NCYCLES]; + +int main(void) +{ + int r, i, j, sp, sq; + char *p, *q, *ep, *eq; + int ok; + int err = 0; + + for (r = 0; r < 4; r++) { + for (i = 0; i < NCYCLES; i++) { + pointers[i] = p = malloc(sp = sizes[i]); + ep = p + sp; + ok = 1; + for (j = 0; j < i; j++) { + q = pointers[j]; + sq = sizes[j]; + eq = q + sq; + + if ((p < q && ep > q) || (p >= q && p < eq)) { + ok = 0; + err = 1; + break; + } + } + printf("Allocated %6d bytes at %p, ok = %d\n", sp, p, + ok); + + if (p) + memset(p, 0xee, sp); /* Poison this memory */ + } + + for (i = 0; i < NCYCLES; i++) { + free(pointers[i]); + printf("Freed %6d bytes at %p\n", sizes[i], + pointers[i]); + } + } + + return err; +} diff -puN /dev/null usr/klibc/tests/memstrtest.c --- /dev/null +++ a/usr/klibc/tests/memstrtest.c @@ -0,0 +1,28 @@ +#include +#include +#include + +int main(void) +{ + unsigned char t1[256], t2[256]; + int i; + int r; + + for (i = 0; i < (int)sizeof(t1); i++) + t1[i] = t2[i] = (unsigned char)i; + + r = memcmp(t1, t2, sizeof(t1)); + printf("memcmp r = %d\n", r); + r = memcmp(t1, t2, sizeof(t1) / 2); + printf("memcmp r = %d\n", r); + t1[255] = 0; + r = memcmp(t1, t2, sizeof(t1)); + printf("memcmp r = %d\n", r); + + for (i = 0; i < (int)sizeof(t1); i++) + t1[i] = 0xaa; + memset(t2, 0xaa, sizeof(t2)); + r = memcmp(t1, t2, sizeof(t1)); + printf("memcmp r = %d\n", r); + return 0; +} diff -puN /dev/null usr/klibc/tests/microhello.c --- /dev/null +++ a/usr/klibc/tests/microhello.c @@ -0,0 +1,9 @@ +#include +#include + +int main(void) +{ + static const char hello[] = "Hello, World!\n"; + _fwrite(hello, sizeof hello - 1, stdout); + return 0; +} diff -puN /dev/null usr/klibc/tests/minihello.c --- /dev/null +++ a/usr/klibc/tests/minihello.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + fputs("Hello, World!\n", stdout); + return 0; +} diff -puN /dev/null usr/klibc/tests/mmaptest.c --- /dev/null +++ a/usr/klibc/tests/mmaptest.c @@ -0,0 +1,73 @@ +/* + * mmaptest.c + * + * Test some simple cases of mmap() + */ + +#include +#include +#include +#include +#include +#include + +static void make_test_file(int fd) +{ + unsigned long v; + FILE *f = fdopen(fd, "wb"); + + for (v = 0; v < 262144; v += sizeof(v)) + _fwrite(&v, sizeof(v), f); +} + +int main(int argc, char *argv[]) +{ + void *foo; + char *test_file = (argc > 1) ? argv[1] : "/tmp/mmaptest.tmp"; + int rv, fd; + + /* Important case, this is how we get memory for malloc() */ + errno = 0; + foo = mmap(NULL, 65536, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + + printf("mmap() returned %p, errno = %d\n", foo, errno); + if (foo == MAP_FAILED) + return 1; + + rv = munmap(foo, 65536); + printf("munmap() returned %d, errno = %d\n", rv, errno); + if (rv) + return 1; + + /* Create test file */ + fd = open(test_file, O_RDWR | O_CREAT | O_TRUNC, 0666); + if (fd < 0) { + perror(test_file); + return 1; + } + + make_test_file(fd); + + /* Map test file */ + foo = mmap(NULL, 65536, PROT_READ, MAP_SHARED, fd, 131072); + printf("mmap() returned %p, errno = %d\n", foo, errno); + if (foo == MAP_FAILED) + return 1; + + if (*(unsigned long *)foo != 131072) { + printf("mmap() with offset returned the wrong offset %ld!\n", + *(unsigned long *)foo); + return 1; + } + + if (munmap(foo, 65536)) { + printf("munmap() returned nonzero, errno = %d\n", errno); + return 1; + } + + close(fd); + unlink(test_file); + + return 0; +} diff -puN /dev/null usr/klibc/tests/opentest.c --- /dev/null +++ a/usr/klibc/tests/opentest.c @@ -0,0 +1,15 @@ +#include + +int main(void) +{ + char buffer[1024]; + FILE *f; + + f = fopen("/etc/passwd", "r"); + fgets(buffer, 1024, f); + fclose(f); + + printf("Line 1 = %s", buffer); + + return 0; +} diff -puN /dev/null usr/klibc/tests/pipetest.c --- /dev/null +++ a/usr/klibc/tests/pipetest.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + /* Size of message must be <= PIPE_BUF */ + const char msg[] = "Hello, World!"; + char buf[512]; + int rv; + int pfd[2]; + + if (pipe(pfd)) { + perror("pipe"); + return 1; + } + + if (write(pfd[1], msg, sizeof msg) != sizeof msg) { + perror("write"); + return 1; + } + + while ((rv = read(pfd[0], buf, sizeof buf)) < sizeof msg) { + if (rv == -1 && errno == EINTR) + continue; + perror("read"); + return 1; + } + + if (memcmp(msg, buf, sizeof msg)) { + fprintf(stderr, "Message miscompare!\n"); + return 1; + } + + return 0; +} diff -puN /dev/null usr/klibc/tests/rtsig.c --- /dev/null +++ a/usr/klibc/tests/rtsig.c @@ -0,0 +1,12 @@ +#include +#include + +int main(void) +{ +#ifdef SIGRTMIN + printf("sigrtmin = %d, sigrtmax = %d\n", SIGRTMIN, SIGRTMAX); +#else + printf("No realtime signals\n"); +#endif + return 0; +} diff -puN /dev/null usr/klibc/tests/setenvtest.c --- /dev/null +++ a/usr/klibc/tests/setenvtest.c @@ -0,0 +1,39 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + + /* Set SETENV */ + setenv("SETENV", "setenv", 1); + + /* Set PUTENV */ + putenv("PUTENV=putenv"); + + /* Print the results... */ + printf("SETENV = %s\n", getenv("SETENV")); + printf("PUTENV = %s\n", getenv("PUTENV")); + + /* Override tests */ + setenv("SETENV", "setenv_good", 1); + putenv("PUTENV=putenv_good"); + printf("SETENV = %s\n", getenv("SETENV")); + printf("PUTENV = %s\n", getenv("PUTENV")); + + /* Non-override test */ + setenv("SETENV", "setenv_bad", 0); + setenv("NEWENV", "newenv_good", 0); + printf("SETENV = %s\n", getenv("SETENV")); + printf("NEWENV = %s\n", getenv("NEWENV")); + + /* Undef test */ + unsetenv("SETENV"); + unsetenv("NEWENV"); + printf("SETENV = %s\n", getenv("SETENV")); + printf("NEWENV = %s\n", getenv("NEWENV")); + + return 0; +} diff -puN /dev/null usr/klibc/tests/setjmptest.c --- /dev/null +++ a/usr/klibc/tests/setjmptest.c @@ -0,0 +1,38 @@ +/* + * setjmptest.c + */ + +#include +#include + +static jmp_buf buf; + +void do_stuff(int v) +{ + printf("calling longjmp with %d... ", v + 1); + longjmp(buf, v + 1); +} + +void recurse(int ctr, int v) +{ + if (ctr--) { + recurse(ctr, v); + } else { + do_stuff(v); + } + + printf("ERROR!\n"); /* We should never get here... */ +} + +int main(void) +{ + int v; + + v = setjmp(buf); + printf("setjmp returned %d\n", v); + + if (v < 256) + recurse(v, v); + + return 0; +} diff -puN /dev/null usr/klibc/tests/sigint.c --- /dev/null +++ a/usr/klibc/tests/sigint.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +static sig_atomic_t counter = 0; + +static void sig_handler(int signum) +{ + static char msg[] = "Signal handler\n"; + + (void)signum; + + write(1, msg, sizeof msg - 1); + counter++; +} + +int main(int argc, char *argv[]) +{ + struct sigaction act, oact; + pid_t f; + + (void)argc; + + memset(&act, 0x00, sizeof(struct sigaction)); + act.sa_handler = sig_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + + /* oact is there for the benefit of strace() */ + sigaction(SIGINT, &act, &oact); + sigaction(SIGTERM, &act, &oact); + + f = fork(); + + if (f < 0) { + perror(argv[0]); + exit(255); + } else if (f > 0) { + sleep(5); + if (!counter) { + fprintf(stderr, "No signal received!\n"); + exit(1); + } else { + printf("Signal received OK\n"); + exit(0); + } + } else { + sleep(1); + kill(getppid(), SIGINT); + _exit(0); + } +} diff -puN /dev/null usr/klibc/tests/stat.c --- /dev/null +++ a/usr/klibc/tests/stat.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include + +static void do_stat(const char *path) +{ + struct stat st; + + if (stat(path, &st)) { + perror(path); + exit(1); + } + + printf("Path = %s\n" + " st_dev = %#jx (%u,%u)\n" + " st_ino = %ju\n" + " st_mode = %#jo\n" + " st_nlink = %ju\n" + " st_uid = %ju\n" + " st_gid = %ju\n" + " st_rdev = %#jx (%u,%u)\n" + " st_size = %ju\n" + " st_blksize = %ju\n" + " st_blocks = %ju\n", + path, + (uintmax_t) st.st_dev, major(st.st_dev), minor(st.st_dev), + (uintmax_t) st.st_ino, + (uintmax_t) st.st_mode, + (uintmax_t) st.st_nlink, + (uintmax_t) st.st_uid, + (uintmax_t) st.st_gid, + (uintmax_t) st.st_rdev, major(st.st_rdev), minor(st.st_rdev), + (uintmax_t) st.st_size, + (uintmax_t) st.st_blksize, (uintmax_t) st.st_blocks); + +#ifdef _STATBUF_ST_NSEC + printf(" st_atim = %jd.%09u\n" + " st.mtim = %jd.%09u\n" + " st.ctim = %jd.%09u\n", + (uintmax_t) st.st_atim.tv_sec, (unsigned int)st.st_atim.tv_nsec, + (uintmax_t) st.st_mtim.tv_sec, (unsigned int)st.st_mtim.tv_nsec, + (uintmax_t) st.st_ctim.tv_sec, (unsigned int)st.st_ctim.tv_nsec); +#else + printf(" st_atime = %jd\n" + " st.mtime = %jd\n" + " st.ctime = %jd\n", + (uintmax_t) st.st_atime, + (uintmax_t) st.st_mtime, (uintmax_t) st.st_ctime); +#endif +} + +int main(int argc, char *argv[]) +{ + int i; + + for (i = 1; i < argc; i++) + do_stat(argv[i]); + + return 0; +} diff -puN /dev/null usr/klibc/tests/statfs.c --- /dev/null +++ a/usr/klibc/tests/statfs.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +static void do_statfs(const char *path) +{ + struct statfs sfs; + + if (statfs(path, &sfs)) { + perror(path); + exit(1); + } + + printf("Path = %s\n" + " f_type = %#jx\n" + " f_bsize = %jd\n" + " f_blocks = %jd\n" + " f_bfree = %jd\n" + " f_bavail = %jd\n" + " f_files = %jd\n" + " f_ffree = %jd\n" + " f_namelen = %jd\n", + path, + (uintmax_t) sfs.f_type, + (intmax_t) sfs.f_bsize, + (intmax_t) sfs.f_blocks, + (intmax_t) sfs.f_bfree, + (intmax_t) sfs.f_bavail, + (intmax_t) sfs.f_files, + (intmax_t) sfs.f_ffree, (intmax_t) sfs.f_namelen); +} + +int main(int argc, char *argv[]) +{ + int i; + + for (i = 1; i < argc; i++) + do_statfs(argv[i]); + + return 0; +} diff -puN /dev/null usr/klibc/tests/strlcpycat.c --- /dev/null +++ a/usr/klibc/tests/strlcpycat.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include + +int main(void) +{ + char temp[8]; + size_t len; + + printf("strlcpy:\n"); + len = strlcpy(temp, "123", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "123") != 0) + goto error; + + len = strlcpy(temp, "", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "") != 0) + goto error; + + len = strlcpy(temp, "1234567890", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "1234567") != 0) + goto error; + + len = strlcpy(temp, "123", 1); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "") != 0) + goto error; + + len = strlcpy(temp, "1234567890", 1); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "") != 0) + goto error; + + len = strlcpy(temp, "123", 0); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "") != 0) + goto error; + + len = strlcpy(temp, "1234567890", 0); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "") != 0) + goto error; + + len = strlcpy(temp, "1234567", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "1234567") != 0) + goto error; + + len = strlcpy(temp, "12345678", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "1234567") != 0) + goto error; + + printf("\n"); + printf("strlcat:\n"); + strcpy(temp, ""); + len = strlcat(temp, "123", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "123") != 0) + goto error; + + strcpy(temp, "ABC"); + len = strlcat(temp, "", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "ABC") != 0) + goto error; + + strcpy(temp, ""); + len = strlcat(temp, "", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "") != 0) + goto error; + + strcpy(temp, "ABC"); + len = strlcat(temp, "123", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "ABC123") != 0) + goto error; + + strcpy(temp, "ABC"); + len = strlcat(temp, "1234567890", sizeof(temp)); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "ABC1234") != 0) + goto error; + + strcpy(temp, "ABC"); + len = strlcat(temp, "123", 5); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "ABC1") != 0) + goto error; + + strcpy(temp, "ABC"); + len = strlcat(temp, "123", 1); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "ABC") != 0) + goto error; + + strcpy(temp, "ABC"); + len = strlcat(temp, "123", 0); + printf("'%s'len:%zu strlen:%zu\n", temp, len, strlen(temp)); + if (strcmp(temp, "ABC") != 0) + goto error; + + exit(0); +error: + printf("unexpected result\n"); + exit(1); +} diff -puN /dev/null usr/klibc/tests/strtoimax.c --- /dev/null +++ a/usr/klibc/tests/strtoimax.c @@ -0,0 +1,23 @@ +/* + * strtoimaxtest.c + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int i; + char *ep; + intmax_t iv; + + for (i = 1; i < argc; i++) { + iv = strtoimax(argv[i], &ep, 0); + printf("strtoimax(\"%s\") = %jd\n", argv[i], iv); + if (*ep) + printf(" ep = \"%s\"\n", ep); + } + + return 0; +} diff -puN /dev/null usr/klibc/tests/strtotime.c --- /dev/null +++ a/usr/klibc/tests/strtotime.c @@ -0,0 +1,25 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + struct timeval tv; + struct timespec ts; + int i; + const char *rv, *rs; + + for (i = 1; i < argc; i++) { + rs = strtotimespec(argv[i], &ts); + rv = strtotimeval(argv[i], &tv); + printf("String: \"%s\"\n" + "Timespec: %ld.%09ld\n" + "Residual: \"%s\"\n" + "Timeval: %ld.%06ld\n" + "Residual: \"%s\"\n", + argv[i], + (long)ts.tv_sec, (long)ts.tv_nsec, rs, + (long)tv.tv_sec, (long)tv.tv_usec, rv); + } + + return 0; +} diff -puN /dev/null usr/klibc/tests/testrand48.c --- /dev/null +++ a/usr/klibc/tests/testrand48.c @@ -0,0 +1,19 @@ +#include +#include + +int main(void) +{ + unsigned short seed1[] = { 0x1234, 0x5678, 0x9abc }; + unsigned short *oldseed; + + oldseed = seed48(seed1); + printf("Initial seed: %#06x %#06x %#06x\n", + oldseed[0], oldseed[1], oldseed[2]); + + printf("lrand48() = %ld\n", lrand48()); + + seed48(seed1); + printf("mrand48() = %ld\n", mrand48()); + + return 1; +} diff -puN /dev/null usr/klibc/tests/testvsnp.c --- /dev/null +++ a/usr/klibc/tests/testvsnp.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int r, i; + char buffer[512]; + + r = snprintf(buffer, 512, "Hello, %d", 37); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'d", 37373737); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'x", 0xdeadbeef); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#X", 0xdeadbeef); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + /* Make sure overflow works correctly */ + memset(buffer, '\xff', 512); + r = snprintf(buffer, 16, "Hello, %'#llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + for (i = 16; i < 512; i++) + assert(buffer[i] == '\xff'); + + r = snprintf(buffer, 512, "Hello, %'#40.20llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#-40.20llo", 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llo", 40, 20, + 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llo", -40, 20, + 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llo", -40, -20, + 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %'#*.*llx", -40, -20, + 0123456701234567ULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %p", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %P", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %20p", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %-20p", &buffer); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 512, "Hello, %-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 20, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 15, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 3, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + /* This shouldn't change buffer in any way! */ + r = snprintf(buffer, 0, "Hello, %'-20p", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + for (i = -30; i <= 30; i++) { + r = snprintf(buffer, 40, "Hello, %'*p", i, NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), + r); + } + + r = snprintf(buffer, 40, "Hello, %'-20s", "String"); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'20s", "String"); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'020s", "String"); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'-20s", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'20s", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'020s", NULL); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'-20c", '*'); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'20c", '*'); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + r = snprintf(buffer, 40, "Hello, %'020c", '*'); + printf("buffer = \"%s\" (%d), r = %d\n", buffer, strlen(buffer), r); + + return 0; +} diff -puN /dev/null usr/klibc/tests/vfork.c --- /dev/null +++ a/usr/klibc/tests/vfork.c @@ -0,0 +1,45 @@ +/* + * usr/klibc/tests/vfork.c + * + * vfork is messy on most architectures. Do our best to test it out. + */ + +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + pid_t f, rv; + int status; + + f = vfork(); + + if (f == 0) { + printf("Child (%d)...\n", (int)getpid()); + _exit(123); + } else if (f > 0) { + int err = 0; + + printf("Parent (child = %d)\n", (int)f); + + rv = waitpid(f, &status, 0); + if (rv != f) { + printf("waitpid returned %d, errno = %d\n", + (int)rv, errno); + err++; + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 123) { + printf("Child process existed with wrong status %d\n", + status); + err++; + } + return err; + } else { + printf("vfork returned %d, errno = %d\n", + (int)f, errno); + return 127; + } +} diff -puN /dev/null usr/klibc/time.c --- /dev/null +++ a/usr/klibc/time.c @@ -0,0 +1,23 @@ +/* + * time.c + */ + +#include +#include +#include + +#ifndef __NR_time + +time_t time(time_t * t) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + if (t) + *t = (time_t) tv.tv_sec; + + return (time_t) tv.tv_sec; +} + +#endif diff -puN /dev/null usr/klibc/umount.c --- /dev/null +++ a/usr/klibc/umount.c @@ -0,0 +1,12 @@ +/* + * umount.c + * + * Single-argument form of umount + */ + +#include + +int umount(const char *dir) +{ + return umount2(dir, 0); +} diff -puN /dev/null usr/klibc/unsetenv.c --- /dev/null +++ a/usr/klibc/unsetenv.c @@ -0,0 +1,44 @@ +/* + * unsetenv.c + */ + +#include +#include +#include +#include +#include "env.h" + +int unsetenv(const char *name) +{ + size_t len; + char **p, *q; + const char *z; + + if (!name || !name[0]) { + errno = EINVAL; + return -1; + } + + len = 0; + for (z = name; *z; z++) { + len++; + if (*z == '=') { + errno = EINVAL; + return -1; + } + } + + if (!environ) + return 0; + + for (p = environ; (q = *p); p++) { + if (!strncmp(name, q, len) && q[len] == '=') + break; + } + + for (; (q = *p); p++) { + p[0] = p[1]; + } + + return 0; +} diff -puN /dev/null usr/klibc/usleep.c --- /dev/null +++ a/usr/klibc/usleep.c @@ -0,0 +1,15 @@ +/* + * usleep.c + */ + +#include +#include + +void usleep(unsigned long usec) +{ + struct timespec ts; + + ts.tv_sec = usec / 1000000UL; + ts.tv_nsec = (usec % 1000000UL) * 1000; + while (nanosleep(&ts, &ts) == -1 && errno == EINTR) ; +} diff -puN /dev/null usr/klibc/utime.c --- /dev/null +++ a/usr/klibc/utime.c @@ -0,0 +1,24 @@ +/* + * utime.c + */ + +#include +#include +#include +#include + +#ifndef __NR_utime + +int utime(const char *filename, const struct utimbuf *buf) +{ + struct timeval tvp[2]; + + tvp[0].tv_sec = buf->actime; + tvp[0].tv_usec = 0; + tvp[1].tv_sec = buf->modtime; + tvp[1].tv_usec = 0; + + return utimes(filename, tvp); +} + +#endif diff -puN /dev/null usr/klibc/vasprintf.c --- /dev/null +++ a/usr/klibc/vasprintf.c @@ -0,0 +1,25 @@ +/* + * vasprintf.c + */ + +#include +#include +#include + +int vasprintf(char **bufp, const char *format, va_list ap) +{ + va_list ap1; + int bytes; + char *p; + + va_copy(ap1, ap); + + bytes = vsnprintf(NULL, 0, format, ap1) + 1; + va_end(ap1); + + *bufp = p = malloc(bytes); + if (!p) + return -1; + + return vsnprintf(p, bytes, format, ap); +} diff -puN /dev/null usr/klibc/version --- /dev/null +++ a/usr/klibc/version @@ -0,0 +1 @@ +1.4.8 diff -puN /dev/null usr/klibc/vfork.c --- /dev/null +++ a/usr/klibc/vfork.c @@ -0,0 +1,13 @@ +/* + * vfork.c + * + * Emulate vfork() with fork() if necessary + */ + +#include +#include +#include + +#if !_KLIBC_NO_MMU && !_KLIBC_REAL_VFORK +__ALIAS(int, vfork, (void), fork) +#endif diff -puN /dev/null usr/klibc/vfprintf.c --- /dev/null +++ a/usr/klibc/vfprintf.c @@ -0,0 +1,26 @@ +/* + * vfprintf.c + */ + +#include +#include +#include +#include + +#define BUFFER_SIZE 32768 + +int vfprintf(FILE * file, const char *format, va_list ap) +{ + int rv; + char buffer[BUFFER_SIZE]; + + rv = vsnprintf(buffer, BUFFER_SIZE, format, ap); + + if (rv < 0) + return rv; + + if (rv > BUFFER_SIZE - 1) + rv = BUFFER_SIZE - 1; + + return _fwrite(buffer, rv, file); +} diff -puN /dev/null usr/klibc/vprintf.c --- /dev/null +++ a/usr/klibc/vprintf.c @@ -0,0 +1,11 @@ +/* + * vprintf.c + */ + +#include +#include + +int vprintf(const char *format, va_list ap) +{ + return vfprintf(stdout, format, ap); +} diff -puN /dev/null usr/klibc/vsnprintf.c --- /dev/null +++ a/usr/klibc/vsnprintf.c @@ -0,0 +1,488 @@ +/* + * vsnprintf.c + * + * vsnprintf(), from which the rest of the printf() + * family is built + */ + +#include +#include +#include +#include +#include +#include + +enum flags { + FL_ZERO = 0x01, /* Zero modifier */ + FL_MINUS = 0x02, /* Minus modifier */ + FL_PLUS = 0x04, /* Plus modifier */ + FL_TICK = 0x08, /* ' modifier */ + FL_SPACE = 0x10, /* Space modifier */ + FL_HASH = 0x20, /* # modifier */ + FL_SIGNED = 0x40, /* Number is signed */ + FL_UPPER = 0x80 /* Upper case digits */ +}; + +/* These may have to be adjusted on certain implementations */ +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2 +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +#define EMIT(x) ({ if (o nchars) { + while (width > nchars) { + EMIT(' '); + width--; + } + } + + /* Emit nondigits */ + if (minus) + EMIT('-'); + else if (flags & FL_PLUS) + EMIT('+'); + else if (flags & FL_SPACE) + EMIT(' '); + + if ((flags & FL_HASH) && base == 16) { + EMIT('0'); + EMIT((flags & FL_UPPER) ? 'X' : 'x'); + } + + /* Emit zero padding */ + if ((flags & (FL_MINUS | FL_ZERO)) == FL_ZERO && width > ndigits) { + while (width > nchars) { + EMIT('0'); + width--; + } + } + + /* Generate the number. This is done from right to left. */ + q += ndigits; /* Advance the pointer to end of number */ + o += ndigits; + qq = q; + oo = o; /* Temporary values */ + + b4tick = tickskip; + while (ndigits > 0) { + if (!b4tick--) { + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = '_'; + b4tick = tickskip - 1; + } + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = digits[val % base]; + val /= base; + } + + /* Emit late space padding */ + while ((flags & FL_MINUS) && width > nchars) { + EMIT(' '); + width--; + } + + return o; +} + +int vsnprintf(char *buffer, size_t n, const char *format, va_list ap) +{ + const char *p = format; + char ch; + char *q = buffer; + size_t o = 0; /* Number of characters output */ + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + int width = 0; + int prec = -1; + int base; + size_t sz; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_prec, /* Field precision */ + st_modifiers /* Length or conversion modifiers */ + } state = st_normal; + const char *sarg; /* %s string argument */ + char carg; /* %c char argument */ + int slen; /* String length */ + + while ((ch = *p++)) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = 0; + prec = -1; + } else { + EMIT(ch); + } + break; + + case st_flags: + switch (ch) { + case '-': + flags |= FL_MINUS; + break; + case '+': + flags |= FL_PLUS; + break; + case '\'': + flags |= FL_TICK; + break; + case ' ': + flags |= FL_SPACE; + break; + case '#': + flags |= FL_HASH; + break; + case '0': + flags |= FL_ZERO; + break; + default: + state = st_width; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else if (ch == '*') { + width = va_arg(ap, int); + if (width < 0) { + width = -width; + flags |= FL_MINUS; + } + } else if (ch == '.') { + prec = 0; /* Precision given */ + state = st_prec; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_prec: + if (ch >= '0' && ch <= '9') { + prec = prec * 10 + (ch - '0'); + } else if (ch == '*') { + prec = va_arg(ap, int); + if (prec < 0) + prec = -1; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank += 2; + break; + default: + /* Output modifiers - terminal sequences */ + + /* Next state will be normal */ + state = st_normal; + + /* Canonicalize rank */ + if (rank < MIN_RANK) + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + flags |= FL_UPPER; + /* fall through */ + case 'p': /* Pointer */ + base = 16; + prec = (CHAR_BIT*sizeof(void *)+3)/4; + flags |= FL_HASH; + val = (uintmax_t)(uintptr_t) + va_arg(ap, void *); + goto is_integer; + + case 'd': /* Signed decimal output */ + case 'i': + base = 10; + flags |= FL_SIGNED; + switch (rank) { + case rank_char: + /* Yes, all these casts are + needed... */ + val = (uintmax_t)(intmax_t) + (signed char) + va_arg(ap, signed int); + break; + case rank_short: + val = (uintmax_t)(intmax_t) + (signed short) + va_arg(ap, signed int); + break; + case rank_int: + val = (uintmax_t)(intmax_t) + va_arg(ap, signed int); + break; + case rank_long: + val = (uintmax_t)(intmax_t) + va_arg(ap, signed long); + break; + case rank_longlong: + val = (uintmax_t)(intmax_t) + va_arg(ap, + signed long long); + break; + } + goto is_integer; + case 'o': /* Octal */ + base = 8; + goto is_unsigned; + case 'u': /* Unsigned decimal */ + base = 10; + goto is_unsigned; + case 'X': /* Upper case hexadecimal */ + flags |= FL_UPPER; + /* fall through */ + case 'x': /* Hexadecimal */ + base = 16; + goto is_unsigned; + + is_unsigned: + switch (rank) { + case rank_char: + val = (uintmax_t) + (unsigned char) + va_arg(ap, unsigned + int); + break; + case rank_short: + val = (uintmax_t) + (unsigned short) + va_arg(ap, unsigned + int); + break; + case rank_int: + val = (uintmax_t) + va_arg(ap, unsigned + int); + break; + case rank_long: + val = (uintmax_t) + va_arg(ap, unsigned + long); + break; + case rank_longlong: + val = (uintmax_t) + va_arg(ap, unsigned + long long); + break; + } + /* fall through */ + + is_integer: + sz = format_int(q, (o < n) ? n - o : 0, + val, flags, base, + width, prec); + q += sz; + o += sz; + break; + + case 'c': /* Character */ + carg = (char)va_arg(ap, int); + sarg = &carg; + slen = 1; + goto is_string; + case 's': /* String */ + sarg = va_arg(ap, const char *); + sarg = sarg ? sarg : "(null)"; + slen = strlen(sarg); + goto is_string; + + is_string: + { + char sch; + int i; + + if (prec != -1 && slen > prec) + slen = prec; + + if (width > slen + && !(flags & FL_MINUS)) { + char pad = + (flags & FL_ZERO) ? + '0' : ' '; + while (width > slen) { + EMIT(pad); + width--; + } + } + for (i = slen; i; i--) { + sch = *sarg++; + EMIT(sch); + } + if (width > slen + && (flags & FL_MINUS)) { + while (width > slen) { + EMIT(' '); + width--; + } + } + } + break; + + case 'n': + { + /* Output the number of + characters written */ + + switch (rank) { + case rank_char: + *va_arg(ap, + signed char *) + = o; + break; + case rank_short: + *va_arg(ap, + signed short *) + = o; + break; + case rank_int: + *va_arg(ap, + signed int *) + = o; + break; + case rank_long: + *va_arg(ap, + signed long *) + = o; + break; + case rank_longlong: + *va_arg(ap, + signed long long *) + = o; + break; + } + } + break; + + default: /* Anything else, including % */ + EMIT(ch); + break; + } + } + } + } + + /* Null-terminate the string */ + if (o < n) + *q = '\0'; /* No overflow */ + else if (n > 0) + buffer[n - 1] = '\0'; /* Overflow - terminate at end of buffer */ + + return o; +} diff -puN /dev/null usr/klibc/vsprintf.c --- /dev/null +++ a/usr/klibc/vsprintf.c @@ -0,0 +1,11 @@ +/* + * vsprintf.c + */ + +#include +#include + +int vsprintf(char *buffer, const char *format, va_list ap) +{ + return vsnprintf(buffer, ~(size_t) 0, format, ap); +} diff -puN /dev/null usr/klibc/vsscanf.c --- /dev/null +++ a/usr/klibc/vsscanf.c @@ -0,0 +1,378 @@ +/* + * vsscanf.c + * + * vsscanf(), from which the rest of the scanf() + * family is built + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT*sizeof(long)) +#endif + +enum flags { + FL_SPLAT = 0x01, /* Drop the value, do not assign */ + FL_INV = 0x02, /* Character-set with inverse */ + FL_WIDTH = 0x04, /* Field width specified */ + FL_MINUS = 0x08, /* Negative number */ +}; + +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2, + rank_ptr = INT_MAX /* Special value used for pointers */ +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +enum bail { + bail_none = 0, /* No error condition */ + bail_eof, /* Hit EOF */ + bail_err /* Conversion mismatch */ +}; + +static inline const char *skipspace(const char *p) +{ + while (isspace((unsigned char)*p)) + p++; + return p; +} + +#undef set_bit +static inline void set_bit(unsigned long *bitmap, unsigned int bit) +{ + bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); +} + +#undef test_bit +static inline int test_bit(unsigned long *bitmap, unsigned int bit) +{ + return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1; +} + +int vsscanf(const char *buffer, const char *format, va_list ap) +{ + const char *p = format; + char ch; + const char *q = buffer; + const char *qq; + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + unsigned int width = UINT_MAX; + int base; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_modifiers, /* Length or conversion modifiers */ + st_match_init, /* Initial state of %[ sequence */ + st_match, /* Main state of %[ sequence */ + st_match_range, /* After - in a %[ sequence */ + } state = st_normal; + char *sarg = NULL; /* %s %c or %[ string argument */ + enum bail bail = bail_none; + int sign; + int converted = 0; /* Successful conversions */ + unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT]; + int matchinv = 0; /* Is match map inverted? */ + unsigned char range_start = 0; + + while ((ch = *p++) && !bail) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = UINT_MAX; + } else if (isspace((unsigned char)ch)) { + q = skipspace(q); + } else { + if (*q == ch) + q++; + else + bail = bail_err; /* Match failure */ + } + break; + + case st_flags: + switch (ch) { + case '*': + flags |= FL_SPLAT; + break; + case '0'...'9': + width = (ch - '0'); + state = st_width; + flags |= FL_WIDTH; + break; + default: + state = st_modifiers; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank = rank_longlong; /* long double/long long */ + break; + + default: + /* Output modifiers - terminal sequences */ + /* Next state will be normal */ + state = st_normal; + + /* Canonicalize rank */ + if (rank < MIN_RANK) + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + case 'p': /* Pointer */ + rank = rank_ptr; + base = 0; + sign = 0; + goto scan_int; + + case 'i': /* Base-independent integer */ + base = 0; + sign = 1; + goto scan_int; + + case 'd': /* Decimal integer */ + base = 10; + sign = 1; + goto scan_int; + + case 'o': /* Octal integer */ + base = 8; + sign = 0; + goto scan_int; + + case 'u': /* Unsigned decimal integer */ + base = 10; + sign = 0; + goto scan_int; + + case 'x': /* Hexadecimal integer */ + case 'X': + base = 16; + sign = 0; + goto scan_int; + + case 'n': /* # of characters consumed */ + val = (q - buffer); + goto set_integer; + + scan_int: + q = skipspace(q); + if (!*q) { + bail = bail_eof; + break; + } + val = + strntoumax(q, (char **)&qq, base, + width); + if (qq == q) { + bail = bail_err; + break; + } + q = qq; + converted++; + /* fall through */ + + set_integer: + if (!(flags & FL_SPLAT)) { + switch (rank) { + case rank_char: + *va_arg(ap, + unsigned char *) + = val; + break; + case rank_short: + *va_arg(ap, + unsigned short + *) = val; + break; + case rank_int: + *va_arg(ap, + unsigned int *) + = val; + break; + case rank_long: + *va_arg(ap, + unsigned long *) + = val; + break; + case rank_longlong: + *va_arg(ap, + unsigned long + long *) = val; + break; + case rank_ptr: + *va_arg(ap, void **) = + (void *) + (uintptr_t)val; + break; + } + } + break; + + case 'c': /* Character */ + /* Default width == 1 */ + width = (flags & FL_WIDTH) ? width : 1; + sarg = va_arg(ap, char *); + while (width--) { + if (!*q) { + bail = bail_eof; + break; + } + *sarg++ = *q++; + } + if (!bail) + converted++; + break; + + case 's': /* String */ + { + char *sp; + sp = sarg = va_arg(ap, char *); + while (width-- && *q + && + !isspace((unsigned char) + *q)) { + *sp++ = *q++; + } + if (sarg != sp) { + /* Terminate output */ + *sp = '\0'; + converted++; + } else { + bail = bail_eof; + } + } + break; + + case '[': /* Character range */ + sarg = va_arg(ap, char *); + state = st_match_init; + matchinv = 0; + memset(matchmap, 0, sizeof matchmap); + break; + + case '%': /* %% sequence */ + if (*q == '%') + q++; + else + bail = bail_err; + break; + + default: /* Anything else */ + /* Unknown sequence */ + bail = bail_err; + break; + } + } + break; + + case st_match_init: /* Initial state for %[ match */ + if (ch == '^' && !(flags & FL_INV)) { + matchinv = 1; + } else { + set_bit(matchmap, (unsigned char)ch); + state = st_match; + } + break; + + case st_match: /* Main state for %[ match */ + if (ch == ']') { + goto match_run; + } else if (ch == '-') { + range_start = (unsigned char)ch; + state = st_match_range; + } else { + set_bit(matchmap, (unsigned char)ch); + } + break; + + case st_match_range: /* %[ match after - */ + if (ch == ']') { + /* - was last character */ + set_bit(matchmap, (unsigned char)'-'); + goto match_run; + } else { + int i; + for (i = range_start; i < (unsigned char)ch; + i++) + set_bit(matchmap, i); + state = st_match; + } + break; + + match_run: /* Match expression finished */ + qq = q; + while (width && *q + && test_bit(matchmap, + (unsigned char)*q) ^ matchinv) { + *sarg++ = *q++; + } + if (q != qq) { + *sarg = '\0'; + converted++; + } else { + bail = *q ? bail_err : bail_eof; + } + break; + } + } + + if (bail == bail_eof && !converted) + converted = -1; /* Return EOF (-1) */ + + return converted; +} diff -puN /dev/null usr/klibc/wait3.c --- /dev/null +++ a/usr/klibc/wait3.c @@ -0,0 +1,12 @@ +/* + * wait3.c + */ + +#include +#include +#include + +pid_t wait3(int *status, int options, struct rusage * rusage) +{ + return wait4((pid_t) - 1, status, options, rusage); +} diff -puN /dev/null usr/klibc/wait.c --- /dev/null +++ a/usr/klibc/wait.c @@ -0,0 +1,12 @@ +/* + * wait.c + */ + +#include +#include +#include + +pid_t wait(int *status) +{ + return wait4((pid_t) - 1, status, 0, NULL); +} diff -puN /dev/null usr/klibc/waitpid.c --- /dev/null +++ a/usr/klibc/waitpid.c @@ -0,0 +1,12 @@ +/* + * waitpid.c + */ + +#include +#include +#include + +pid_t waitpid(pid_t pid, int *status, int options) +{ + return wait4(pid, status, options, NULL); +} diff -puN /dev/null usr/klibc/zlib/adler32.c --- /dev/null +++ a/usr/klibc/zlib/adler32.c @@ -0,0 +1,149 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff -puN /dev/null usr/klibc/zlib/algorithm.txt --- /dev/null +++ a/usr/klibc/zlib/algorithm.txt @@ -0,0 +1,209 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The key question is how to represent a Huffman code (or any prefix code) so +that you can decode fast. The most important characteristic is that shorter +codes are much more common than longer codes, so pay attention to decoding the +short codes fast, and let the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and then +to set that variable for the maximum speed. + +For inflate, which has 286 possible codes for the literal/length tree, the size +of the first table is nine bits. Also the distance trees have 30 possible +values, and the size of the first table is six bits. Note that for each of +those cases, the table ended up one bit longer than the ``average'' code +length, i.e. the code length of an approximately flat code which would be a +little more than eight bits for 286 symbols and a little less than five bits +for 30 symbols. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend two much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode as and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +http://www.ietf.org/rfc/rfc1951.txt diff -puN /dev/null usr/klibc/zlib/compress.c --- /dev/null +++ a/usr/klibc/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff -puN /dev/null usr/klibc/zlib/crc32.c --- /dev/null +++ a/usr/klibc/zlib/crc32.c @@ -0,0 +1,423 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff -puN /dev/null usr/klibc/zlib/crc32.h --- /dev/null +++ a/usr/klibc/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff -puN /dev/null usr/klibc/zlib/deflate.c --- /dev/null +++ a/usr/klibc/zlib/deflate.c @@ -0,0 +1,1736 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + /* %%% avoid this when Z_RLE */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff -puN /dev/null usr/klibc/zlib/deflate.h --- /dev/null +++ a/usr/klibc/zlib/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff -puN /dev/null usr/klibc/zlib/FAQ --- /dev/null +++ a/usr/klibc/zlib/FAQ @@ -0,0 +1,339 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://www.zlib.org which may have more recent information. +The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. + See the file win32/DLL_FAQ.txt in the zlib distribution. + Pointers to the precompiled DLL are found in the zlib web site at + http://www.zlib.org. + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm + * contrib/visual-basic.txt in the zlib distribution + * win32/DLL_FAQ.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR. + + Make sure that before the call of compress, the length of the compressed + buffer is equal to the total size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR. + + Before making the call, make sure that avail_in and avail_out are not + zero. When setting the parameter flush equal to Z_FINISH, also make sure + that avail_out is big enough to allow processing all pending input. + Note that a Z_BUF_ERROR is not fatal--another call to deflate() or + inflate() can be made with more input or output space. A Z_BUF_ERROR + may in fact be unavoidable depending on how the functions are used, since + it is not possible to tell whether or not there is more output pending + when strm.avail_out returns with zero. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h for the moment, and Francis S. Lin has converted it to a + web page zlib.html. Volunteers to transform this to Unix-style man pages, + please contact us (zlib@gzip.org). Examples of zlib usage are in the files + example.c and minigzip.c. + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple + package. zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of + zlib. Please try to reproduce the problem with a small program and send + the corresponding source to us at zlib@gzip.org . Do not send + multi-megabyte data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the contrib/delphi directory in the zlib distribution. + +11. Can zlib handle .zip archives? + + Not by itself, no. See the directory contrib/minizip in the zlib + distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + make clean + ./configure -s + make + +14. How do I install a shared zlib library on Unix? + + After the above, then: + + make install + + However, many flavors of Unix come with a shared zlib already installed. + Before going to the trouble of compiling a shared version of zlib and + trying to install it, you may want to check if it's already there! If you + can #include , it's there. The -lz option will probably link to it. + +15. I have a question about OttoPDF. + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site: Joel Hainley, jhainley@myndkryme.com. + +16. Can zlib decode Flate data in an Adobe PDF file? + + Yes. See http://www.fastio.com/ (ClibPDF), or http://www.pdflib.com/ . + To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ . + +17. Why am I getting this "register_frame_info not found" error on Solaris? + + After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib + generates an error such as: + + ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: + symbol __register_frame_info: referenced symbol not found + + The symbol __register_frame_info is not part of zlib, it is generated by + the C compiler (cc or gcc). You must recompile applications using zlib + which have this problem. This problem is specific to Solaris. See + http://www.sunfreeware.com for Solaris versions of zlib and applications + using zlib. + +18. Why does gzip give an error on a file I make with compress/deflate? + + The compress and deflate functions produce data in the zlib format, which + is different and incompatible with the gzip format. The gz* functions in + zlib on the other hand use the gzip format. Both the zlib and gzip + formats use the same compressed data format internally, but have different + headers and trailers around the compressed data. + +19. Ok, so why are there two different formats? + + The gzip format was designed to retain the directory information about + a single file, such as the name and last modification date. The zlib + format on the other hand was designed for in-memory and communication + channel applications, and has a much more compact header and trailer and + uses a faster integrity check than gzip. + +20. Well that's nice, but how do I make a gzip file in memory? + + You can request that deflate write the gzip format instead of the zlib + format using deflateInit2(). You can also request that inflate decode + the gzip format using inflateInit2(). Read zlib.h for more details. + +21. Is zlib thread-safe? + + Yes. However any library routines that zlib uses and any application- + provided memory allocation routines must also be thread-safe. zlib's gz* + functions use stdio library routines, and most of zlib's functions use the + library memory allocation routines by default. zlib's Init functions allow + for the application to provide custom memory allocation routines. + + Of course, you should only operate on any given zlib or gzip stream from a + single thread at a time. + +22. Can I use zlib in my commercial application? + + Yes. Please read the license in zlib.h. + +23. Is zlib under the GNU license? + + No. Please read the license in zlib.h. + +24. The license says that altered source versions must be "plainly marked". So + what exactly do I need to do to meet that requirement? + + You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In + particular, the final version number needs to be changed to "f", and an + identification string should be appended to ZLIB_VERSION. Version numbers + x.x.x.f are reserved for modifications to zlib by others than the zlib + maintainers. For example, if the version of the base zlib you are altering + is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and + ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also + update the version strings in deflate.c and inftrees.c. + + For altered source distributions, you should also note the origin and + nature of the changes in zlib.h, as well as in ChangeLog and README, along + with the dates of the alterations. The origin should include at least your + name (or your company's name), and an email address to contact for help or + issues with the library. + + Note that distributing a compiled zlib library along with zlib.h and + zconf.h is also a source distribution, and so you should change + ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes + in zlib.h as you would for a full source distribution. + +25. Will zlib work on a big-endian or little-endian architecture, and can I + exchange compressed data between them? + + Yes and yes. + +26. Will zlib work on a 64-bit machine? + + It should. It has been tested on 64-bit machines, and has no dependence + on any data types being limited to 32-bits in length. If you have any + difficulties, please provide a complete problem report to zlib@gzip.org + +27. Will zlib decompress data from the PKWare Data Compression Library? + + No. The PKWare DCL uses a completely different compressed data format + than does PKZIP and zlib. However, you can look in zlib's contrib/blast + directory for a possible solution to your problem. + +28. Can I access data randomly in a compressed stream? + + No, not without some preparation. If when compressing you periodically + use Z_FULL_FLUSH, carefully write all the pending data at those points, + and keep an index of those locations, then you can start decompression + at those points. You have to be careful to not use Z_FULL_FLUSH too + often, since it can significantly degrade compression. + +29. Does zlib work on MVS, OS/390, CICS, etc.? + + We don't know for sure. We have heard occasional reports of success on + these systems. If you do use it on one of these, please provide us with + a report, instructions, and patches that we can reference when we get + these questions. Thanks. + +30. Is there some simpler, easier to read version of inflate I can look at + to understand the deflate format? + + First off, you should read RFC 1951. Second, yes. Look in zlib's + contrib/puff directory. + +31. Does zlib infringe on any patents? + + As far as we know, no. In fact, that was originally the whole point behind + zlib. Look here for some more information: + + http://www.gzip.org/#faq11 + +32. Can zlib work with greater than 4 GB of data? + + Yes. inflate() and deflate() will process any amount of data correctly. + Each call of inflate() or deflate() is limited to input and output chunks + of the maximum value that can be stored in the compiler's "unsigned int" + type, but there is no limit to the number of chunks. Note however that the + strm.total_in and strm_total_out counters may be limited to 4 GB. These + counters are provided as a convenience and are not used internally by + inflate() or deflate(). The application can easily set up its own counters + updated after each call of inflate() or deflate() to count beyond 4 GB. + compress() and uncompress() may be limited to 4 GB, since they operate in a + single call. gzseek() and gztell() may be limited to 4 GB depending on how + zlib is compiled. See the zlibCompileFlags() function in zlib.h. + + The word "may" appears several times above since there is a 4 GB limit + only if the compiler's "long" type is 32 bits. If the compiler's "long" + type is 64 bits, then the limit is 16 exabytes. + +33. Does zlib have any security vulnerabilities? + + The only one that we are aware of is potentially in gzprintf(). If zlib + is compiled to use sprintf() or vsprintf(), then there is no protection + against a buffer overflow of a 4K string space, other than the caller of + gzprintf() assuring that the output will not exceed 4K. On the other + hand, if zlib is compiled to use snprintf() or vsnprintf(), which should + normally be the case, then there is no vulnerability. The ./configure + script will display warnings if an insecure variation of sprintf() will + be used by gzprintf(). Also the zlibCompileFlags() function will return + information on what variant of sprintf() is used by gzprintf(). + + If you don't have snprintf() or vsnprintf() and would like one, you can + find a portable implementation here: + + http://www.ijs.si/software/snprintf/ + + Note that you should be using the most recent version of zlib. Versions + 1.1.3 and before were subject to a double-free vulnerability. + +34. Is there a Java version of zlib? + + Probably what you want is to use zlib in Java. zlib is already included + as part of the Java SDK in the java.util.zip package. If you really want + a version of zlib written in the Java language, look on the zlib home + page for links: http://www.zlib.org/ + +35. I get this or that compiler or source-code scanner warning when I crank it + up to maximally-pedantic. Can't you guys write proper code? + + Many years ago, we gave up attempting to avoid warnings on every compiler + in the universe. It just got to be a waste of time, and some compilers + were downright silly. So now, we simply make sure that the code always + works. + +36. Valgrind (or some similar memory access checker) says that deflate is + performing a conditional jump that depends on an uninitialized value. + Isn't that a bug? + + No. That is intentional for performance reasons, and the output of + deflate is not affected. This only started showing up recently since + zlib 1.2.x uses malloc() by default for allocations, whereas earlier + versions used calloc(), which zeros out the allocated memory. + +37. Will zlib read the (insert any ancient or arcane format here) compressed + data format? + + Probably not. Look in the comp.compression FAQ for pointers to various + formats and associated software. + +38. How can I encrypt/decrypt zip files with zlib? + + zlib doesn't support encryption. The original PKZIP encryption is very weak + and can be broken with freely available programs. To get strong encryption, + use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. + For PKZIP compatible "encryption", look at http://www.info-zip.org/ + +39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? + + "gzip" is the gzip format, and "deflate" is the zlib format. They should + probably have called the second one "zlib" instead to avoid confusion + with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 + correctly points to the zlib specification in RFC 1950 for the "deflate" + transfer encoding, there have been reports of servers and browsers that + incorrectly produce or expect raw deflate data per the deflate + specficiation in RFC 1951, most notably Microsoft. So even though the + "deflate" transfer encoding using the zlib format would be the more + efficient approach (and in fact exactly what the zlib format was designed + for), using the "gzip" transfer encoding is probably more reliable due to + an unfortunate choice of name on the part of the HTTP 1.1 authors. + + Bottom line: use the gzip format for HTTP 1.1 encoding. + +40. Does zlib support the new "Deflate64" format introduced by PKWare? + + No. PKWare has apparently decided to keep that format proprietary, since + they have not documented it as they have previous compression formats. + In any case, the compression improvements are so modest compared to other + more modern approaches, that it's not worth the effort to implement. + +41. Can you please sign these lengthy legal documents and fax them back to us + so that we can use your software in our product? + + No. Go away. Shoo. diff -puN /dev/null usr/klibc/zlib/gzio.c --- /dev/null +++ a/usr/klibc/zlib/gzio.c @@ -0,0 +1,1029 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[46]; /* allow for up to 128-bit integers */ + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + /* klibc hack */ + if (errno) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + /* klibc hack */ + if (len == 0 && errno) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + start++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= + (uInt)fread(next_out, 1, s->stream.avail_out, s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (errno) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + if (len == s->stream.avail_out && + (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) + return -1; + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Returns 1 if reading and doing so transparently, otherwise zero. +*/ +int ZEXPORT gzdirect (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return 0; + return s->transparent; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + if (do_flush (file, Z_FINISH) != Z_OK) + return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +#ifdef STDC +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +/* =========================================================================== + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + /* klibc hack */ + /* clearerr(s->file); */ +} diff -puN /dev/null usr/klibc/zlib/INDEX --- /dev/null +++ a/usr/klibc/zlib/INDEX @@ -0,0 +1,51 @@ +ChangeLog history of changes +FAQ Frequently Asked Questions about zlib +INDEX this file +Makefile makefile for Unix (generated by configure) +Makefile.in makefile for Unix (template for configure) +README guess what +algorithm.txt description of the (de)compression algorithm +configure configure script for Unix +zconf.in.h template for zconf.h (used by configure) + +amiga/ makefiles for Amiga SAS C +as400/ makefiles for IBM AS/400 +msdos/ makefiles for MSDOS +old/ makefiles for various architectures and zlib documentation + files that have not yet been updated for zlib 1.2.x +projects/ projects for various Integrated Development Environments +qnx/ makefiles for QNX +win32/ makefiles for Windows + + zlib public header files (must be kept): +zconf.h +zlib.h + + private source files used to build the zlib library: +adler32.c +compress.c +crc32.c +crc32.h +deflate.c +deflate.h +gzio.c +infback.c +inffast.c +inffast.h +inffixed.h +inflate.c +inflate.h +inftrees.c +inftrees.h +trees.c +trees.h +uncompr.c +zutil.c +zutil.h + + source files for sample programs: +example.c +minigzip.c + + unsupported contribution by third parties +See contrib/README.contrib diff -puN /dev/null usr/klibc/zlib/infback.c --- /dev/null +++ a/usr/klibc/zlib/infback.c @@ -0,0 +1,623 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff -puN /dev/null usr/klibc/zlib/inffast.c --- /dev/null +++ a/usr/klibc/zlib/inffast.c @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff -puN /dev/null usr/klibc/zlib/inffast.h --- /dev/null +++ a/usr/klibc/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff -puN /dev/null usr/klibc/zlib/inffixed.h --- /dev/null +++ a/usr/klibc/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff -puN /dev/null usr/klibc/zlib/inflate.c --- /dev/null +++ a/usr/klibc/zlib/inflate.c @@ -0,0 +1,1368 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff -puN /dev/null usr/klibc/zlib/inflate.h --- /dev/null +++ a/usr/klibc/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff -puN /dev/null usr/klibc/zlib/inftrees.c --- /dev/null +++ a/usr/klibc/zlib/inftrees.c @@ -0,0 +1,329 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff -puN /dev/null usr/klibc/zlib/inftrees.h --- /dev/null +++ a/usr/klibc/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff -puN /dev/null usr/klibc/zlib/README --- /dev/null +++ a/usr/klibc/zlib/README @@ -0,0 +1,125 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.3 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install". For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.3 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff -puN /dev/null usr/klibc/zlib/trees.c --- /dev/null +++ a/usr/klibc/zlib/trees.c @@ -0,0 +1,1219 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2005 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local void set_data_type(s) + deflate_state *s; +{ + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff -puN /dev/null usr/klibc/zlib/trees.h --- /dev/null +++ a/usr/klibc/zlib/trees.h @@ -0,0 +1,127 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; diff -puN /dev/null usr/klibc/zlib/uncompr.c --- /dev/null +++ a/usr/klibc/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff -puN /dev/null usr/klibc/zlib/zconf.in.h --- /dev/null +++ a/usr/klibc/zlib/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.in.h,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff -puN /dev/null usr/klibc/zlib/zlib.3 --- /dev/null +++ a/usr/klibc/zlib/zlib.3 @@ -0,0 +1,159 @@ +.TH ZLIB 3 "18 July 2005" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms will be added later +and will have the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +(for example if an input file is mmap'ed), +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I example.c +and +.IR minigzip.c . +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source, +and are concerned primarily with bug fixes and portability enhancements. +.LP +A Java implementation of +.I zlib +is available in the Java Development Kit 1.1: +.IP +http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html +.LP +A Perl interface to +.IR zlib , +written by Paul Marquess (pmqs@cpan.org), +is available at CPAN (Comprehensive Perl Archive Network) sites, +including: +.IP +http://www.cpan.org/modules/by-module/Compress/ +.LP +A Python interface to +.IR zlib , +written by A.M. Kuchling (amk@magnet.com), +is available in Python 1.5 and later versions: +.IP +http://www.python.org/doc/lib/module-zlib.html +.LP +A +.I zlib +binding for +.IR tcl (1), +written by Andreas Kupries (a.kupries@westend.com), +is availlable at: +.IP +http://www.westend.com/~kupries/doc/trf/man/man.html +.LP +An experimental package to read and write files in .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/unzip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +web site. +.SH "SEE ALSO" +The +.I zlib +web site can be found at either of these locations: +.IP +http://www.zlib.org +.br +http://www.gzip.org/zlib/ +.LP +The data format used by the zlib library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://www.ietf.org/rfc/rfc1950.txt (concerning zlib format) +.br +http://www.ietf.org/rfc/rfc1951.txt (concerning deflate format) +.br +http://www.ietf.org/rfc/rfc1952.txt (concerning gzip format) +.LP +These documents are also available in other formats from: +.IP +ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html +.LP +Mark Nelson (markn@ieee.org) wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://dogma.net/markn/articles/zlibtool/zlibtool.htm +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://www.gzip.org/zlib/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS +Version 1.2.3 +Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org) +and Mark Adler (madler@alumni.caltech.edu). +.LP +This software is provided "as-is," +without any express or implied warranty. +In no event will the authors be held liable for any damages +arising from the use of this software. +See the distribution directory with respect to requirements +governing redistribution. +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff -puN /dev/null usr/klibc/zlib/zutil.c --- /dev/null +++ a/usr/klibc/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff -puN /dev/null usr/klibc/zlib/zutil.h --- /dev/null +++ a/usr/klibc/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2005/02/27 23:15:39 hpa Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff -puN usr/Makefile~git-klibc /dev/null --- a/usr/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# kbuild file for usr/ - including initramfs image -# - -klibcdirs:; - -# Generate builtin.o based on initramfs_data.o -obj-y := initramfs_data.o - -# initramfs_data.o contains the initramfs_data.cpio.gz image. -# The image is included using .incbin, a dependency which is not -# tracked automatically. -$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE - -##### -# Generate the initramfs cpio archive - -hostprogs-y := gen_init_cpio -initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh -ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \ - $(CONFIG_INITRAMFS_SOURCE),-d) -ramfs-args := \ - $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ - $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) - -# .initramfs_data.cpio.gz.d is used to identify all files included -# in initramfs and to detect if any files are added/removed. -# Removed files are identified by directory timestamp being updated -# The dependency list is generated by gen_initramfs.sh -l -ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),) - include $(obj)/.initramfs_data.cpio.gz.d -endif - -quiet_cmd_initfs = GEN $@ - cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) - -targets := initramfs_data.cpio.gz -$(deps_initramfs): klibcdirs -# We rebuild initramfs_data.cpio.gz if: -# 1) Any included file is newer then initramfs_data.cpio.gz -# 2) There are changes in which files are included (added or deleted) -# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz -# 4) arguments to gen_initramfs.sh changes -$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs - $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d - $(call if_changed,initfs) - diff -puN /dev/null usr/utils/cat.c --- /dev/null +++ a/usr/utils/cat.c @@ -0,0 +1,329 @@ +/* $NetBSD: cat.c,v 1.43 2004/01/04 03:31:28 jschauma Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Kevin Fall. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __COPYRIGHT +#define __COPYRIGHT(arg) +#endif +#ifndef __RCSID +#define __RCSID(arg) +#endif + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#ifndef __KLIBC__ +#include +#endif +#if !defined(lint) +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"); +#if 0 +static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; +#else +__RCSID("$NetBSD: cat.c,v 1.43 2004/01/04 03:31:28 jschauma Exp $"); +#endif +#endif /* not lint */ + +#include +#include + +#include +#ifndef __KLIBC__ +#include +#endif +#include +#include +#ifndef __KLIBC__ +#include +#endif +#include +#include +#include +#include + +int bflag, eflag, fflag, lflag, nflag, sflag, tflag, vflag; +int rval; +const char *filename; + +int main(int, char *[]); +void cook_args(char *argv[]); +void cook_buf(FILE *); +void raw_args(char *argv[]); +void raw_cat(int); + +int main(int argc, char *argv[]) +{ + int ch; + struct flock stdout_lock; + +#ifndef __KLIBC__ + setprogname(argv[0]); + (void)setlocale(LC_ALL, ""); +#endif + + while ((ch = getopt(argc, argv, "beflnstuv")) != -1) + switch (ch) { + case 'b': + bflag = nflag = 1; /* -b implies -n */ + break; + case 'e': + eflag = vflag = 1; /* -e implies -v */ + break; + case 'f': + fflag = 1; + break; + case 'l': + lflag = 1; + break; + case 'n': + nflag = 1; + break; + case 's': + sflag = 1; + break; + case 't': + tflag = vflag = 1; /* -t implies -v */ + break; + case 'u': +#ifndef __KLIBC__ + setbuf(stdout, NULL); +#endif + break; + case 'v': + vflag = 1; + break; + default: + case '?': + (void)fprintf(stderr, + "usage: cat [-beflnstuv] [-] [file ...]\n"); + exit(1); + /* NOTREACHED */ + } + argv += optind; + + if (lflag) { + stdout_lock.l_len = 0; + stdout_lock.l_start = 0; + stdout_lock.l_type = F_WRLCK; + stdout_lock.l_whence = SEEK_SET; + if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1) { + perror("fcntl"); + exit(1); + } + } + + if (bflag || eflag || nflag || sflag || tflag || vflag) + cook_args(argv); + else + raw_args(argv); + if (fclose(stdout)) { + perror("fclose"); + exit(1); + } + exit(rval); + /* NOTREACHED */ +} + +void cook_args(char **argv) +{ + FILE *fp; + + fp = stdin; + filename = "stdin"; + do { + if (*argv) { + if (!strcmp(*argv, "-")) + fp = stdin; + else if ((fp = fopen(*argv, + fflag ? "rf" : "r")) == NULL) { + perror("fopen"); + rval = 1; + ++argv; + continue; + } + filename = *argv++; + } + cook_buf(fp); + if (fp != stdin) + (void)fclose(fp); + } while (*argv); +} + +void cook_buf(FILE * fp) +{ + int ch, gobble, line, prev; + int stdout_err = 0; + + line = gobble = 0; + for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { + if (prev == '\n') { + if (ch == '\n') { + if (sflag) { + if (!gobble && putchar(ch) == EOF) + break; + gobble = 1; + continue; + } + if (nflag) { + if (!bflag) { + if (fprintf(stdout, + "%6d\t", + ++line) < 0) { + stdout_err++; + break; + } + } else if (eflag) { + if (fprintf(stdout, + "%6s\t", "") < 0) { + stdout_err++; + break; + } + } + } + } else if (nflag) { + if (fprintf(stdout, "%6d\t", ++line) < 0) { + stdout_err++; + break; + } + } + } + gobble = 0; + if (ch == '\n') { + if (eflag) + if (putchar('$') == EOF) + break; + } else if (ch == '\t') { + if (tflag) { + if (putchar('^') == EOF || putchar('I') == EOF) + break; + continue; + } + } else if (vflag) { + if (!isascii(ch)) { + if (putchar('M') == EOF || putchar('-') == EOF) + break; + ch = (ch) & 0x7f; + } + if (iscntrl(ch)) { + if (putchar('^') == EOF || + putchar(ch == '\177' ? '?' : + ch | 0100) == EOF) + break; + continue; + } + } + if (putchar(ch) == EOF) + break; + } + if (stdout_err) { + perror(filename); + rval = 1; + } +} + +void raw_args(char **argv) +{ + int fd; + + fd = fileno(stdin); + filename = "stdin"; + do { + if (*argv) { + if (!strcmp(*argv, "-")) + fd = fileno(stdin); + else if (fflag) { + struct stat st; + fd = open(*argv, O_RDONLY | O_NONBLOCK, 0); + if (fd < 0) + goto skip; + + if (fstat(fd, &st) == -1) { + close(fd); + goto skip; + } + if (!S_ISREG(st.st_mode)) { + close(fd); + errno = EINVAL; + goto skipnomsg; + } + } else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { + skip: + perror(*argv); + skipnomsg: + rval = 1; + ++argv; + continue; + } + filename = *argv++; + } + raw_cat(fd); + if (fd != fileno(stdin)) + (void)close(fd); + } while (*argv); +} + +void raw_cat(int rfd) +{ + static char *buf; + static char fb_buf[BUFSIZ]; + static size_t bsize; + + struct stat sbuf; + ssize_t nr, nw, off; + int wfd; + + wfd = fileno(stdout); + if (buf == NULL) { + if (fstat(wfd, &sbuf) == 0) { + bsize = sbuf.st_blksize > BUFSIZ ? + sbuf.st_blksize : BUFSIZ; + buf = malloc(bsize); + } + if (buf == NULL) { + buf = fb_buf; + bsize = BUFSIZ; + } + } + while ((nr = read(rfd, buf, bsize)) > 0) + for (off = 0; nr; nr -= nw, off += nw) + if ((nw = write(wfd, buf + off, (size_t) nr)) < 0) { + perror("write"); + exit(1); + } + if (nr < 0) { + fprintf(stderr, "%s: invalid length\n", filename); + rval = 1; + } +} diff -puN /dev/null usr/utils/chroot.c --- /dev/null +++ a/usr/utils/chroot.c @@ -0,0 +1,25 @@ +/* + * chroot.c, by rmk + */ +#include +#include + +int main(int argc, char *argv[], char *envp[]) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s newroot command...\n", argv[0]); + return 1; + } + + if (chroot(argv[1]) == -1) { + perror("chroot"); + return 1; + } + + if (execve(argv[2], argv + 2, envp) == -1) { + perror("execve"); + return 1; + } + + return 0; +} diff -puN /dev/null usr/utils/dd.c --- /dev/null +++ a/usr/utils/dd.c @@ -0,0 +1,533 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +static char *progname; + +struct option { + const char *opt; + char *str; + char *arg; +}; + +struct conv { + const char str[8]; + unsigned int set; + unsigned int exclude; +}; + +#define CONV_BLOCK (1<<0) +#define CONV_UNBLOCK (1<<1) + +#define CONV_LCASE (1<<2) +#define CONV_UCASE (1<<3) + +#define CONV_SWAB (1<<4) +#define CONV_NOERROR (1<<5) +#define CONV_NOTRUNC (1<<6) +#define CONV_SYNC (1<<7) + +static struct option options[] = { + {"bs", NULL, NULL}, +#define OPT_BS (&options[0]) + {"cbs", NULL, NULL}, +#define OPT_CBS (&options[1]) + {"conv", NULL, NULL}, +#define OPT_CONV (&options[2]) + {"count", NULL, NULL}, +#define OPT_COUNT (&options[3]) + {"ibs", NULL, NULL}, +#define OPT_IBS (&options[4]) + {"if", NULL, NULL}, +#define OPT_IF (&options[5]) + {"obs", NULL, NULL}, +#define OPT_OBS (&options[6]) + {"of", NULL, NULL}, +#define OPT_OF (&options[7]) + {"seek", NULL, NULL}, +#define OPT_SEEK (&options[8]) + {"skip", NULL, NULL} +#define OPT_SKIP (&options[9]) +}; + +static const struct conv conv_opts[] = { + {"block", CONV_BLOCK, CONV_UNBLOCK}, + {"unblock", CONV_UNBLOCK, CONV_BLOCK}, + {"lcase", CONV_LCASE, CONV_UCASE}, + {"ucase", CONV_UCASE, CONV_LCASE}, + {"swab", CONV_SWAB, 0}, + {"noerror", CONV_NOERROR, 0}, + {"notrunc", CONV_NOTRUNC, 0}, + {"sync", CONV_SYNC, 0}, +}; + +static size_t cbs; +static unsigned int conv; +static unsigned int count; +static size_t ibs = 512; +static size_t obs = 512; +static unsigned int seek; +static unsigned int skip; +static char *in_buf; +static char *out_buf; + +static size_t parse_bs(struct option *opt) +{ + unsigned long val, realval = 1; + char *str = opt->str; + int err = 0; + + do { + char *s = str; + val = strtoul(str, &str, 10); + if (s == str || (val == ULONG_MAX && errno == ERANGE)) { + err = 1; + break; + } + + /* + * This option may be followed by + * 'b', 'k' or 'x' + */ + if (*str == 'b') { + val *= 512; + str++; + } else if (*str == 'k') { + val *= 1024; + str++; + } + realval *= val; + if (*str != 'x') + break; + str++; + } while (1); + + if (*str != '\0') + err = 1; + + if (err) { + fprintf(stderr, "%s: bad operand `%s'\n", progname, opt->arg); + exit(1); + } + + return (size_t) realval; +} + +static unsigned int parse_num(struct option *opt) +{ + unsigned long val; + char *str = opt->str; + + val = strtoul(str, &str, 10); + if (str == opt->str || (val == ULONG_MAX && errno == ERANGE) || + val > UINT_MAX) { + fprintf(stderr, "%s: bad operand `%s'\n", progname, opt->arg); + exit(1); + } + + return (unsigned int)val; +} + +static int parse_options(int argc, char *argv[]) +{ + unsigned int i; + char *p, *s; + int arg; + + /* + * We cheat here; we don't parse the operand values + * themselves here. We merely split the operands + * up. This means that bs=foo bs=1 won't produce + * an error. + */ + for (arg = 1; arg < argc; arg++) { + unsigned int len; + + s = strchr(argv[arg], '='); + if (!s) + s = argv[arg]; /* don't recognise this arg */ + + len = s - argv[arg]; + for (i = 0; i < ARRAY_SIZE(options); i++) { + if (strncmp(options[i].opt, argv[arg], len) != 0) + continue; + + options[i].str = s + 1; + options[i].arg = argv[arg]; + break; + } + + if (i == ARRAY_SIZE(options)) { + fprintf(stderr, "%s: bad operand `%s'\n", + progname, argv[arg]); + return 1; + } + } + + /* + * Translate numeric operands. + */ + if (OPT_IBS->str) + ibs = parse_bs(OPT_IBS); + if (OPT_OBS->str) + obs = parse_bs(OPT_OBS); + if (OPT_CBS->str) + cbs = parse_bs(OPT_CBS); + if (OPT_COUNT->str) + count = parse_num(OPT_COUNT); + if (OPT_SEEK->str) + seek = parse_num(OPT_SEEK); + if (OPT_SKIP->str) + skip = parse_num(OPT_SKIP); + + /* + * If bs= is specified, it overrides ibs= and obs= + */ + if (OPT_BS->str) + ibs = obs = parse_bs(OPT_BS); + + /* + * And finally conv= + */ + if (OPT_CONV->str) { + p = OPT_CONV->str; + + while ((s = strsep(&p, ",")) != NULL) { + for (i = 0; i < ARRAY_SIZE(conv_opts); i++) { + if (strcmp(s, conv_opts[i].str) != 0) + continue; + conv &= ~conv_opts[i].exclude; + conv |= conv_opts[i].set; + break; + } + + if (i == ARRAY_SIZE(conv_opts)) { + fprintf(stderr, "%s: bad conversion `%s'\n", + progname, s); + return 1; + } + } + } + + if (conv & (CONV_BLOCK | CONV_UNBLOCK) && cbs == 0) { + fprintf(stderr, "%s: block/unblock conversion with zero cbs\n", + progname); + return 1; + } + + return 0; +} + +static int safe_read(int fd, void *buf, size_t size) +{ + int ret, count = 0; + char *p = buf; + + while (size) { + ret = read(fd, p, size); + + /* + * If we got EINTR, go again. + */ + if (ret == -1 && errno == EINTR) + continue; + + /* + * If we encountered an error condition + * or read 0 bytes (EOF) return what we + * have. + */ + if (ret == -1 || ret == 0) + return count ? count : ret; + + /* + * We read some bytes. + */ + count += ret; + size -= ret; + p += ret; + } + + return count; +} + +static int skip_blocks(int fd, void *buf, unsigned int blks, size_t size) +{ + unsigned int blk; + int ret = 0; + + /* + * Try to seek. + */ + for (blk = 0; blk < blks; blk++) { + ret = lseek(fd, size, SEEK_CUR); + if (ret == -1) + break; + } + + /* + * If we failed to seek, read instead. + * FIXME: we don't handle short reads here, or + * EINTR correctly. + */ + if (blk == 0 && ret == -1 && errno == ESPIPE) { + for (blk = 0; blk < blks; blk++) { + ret = safe_read(fd, buf, size); + if (ret != (int)size) + break; + } + } + + if (ret == -1) { + perror("seek/skip"); + return 1; + } + return 0; +} + +struct stats { + unsigned int in_full; + unsigned int in_partial; + unsigned int out_full; + unsigned int out_partial; + unsigned int truncated; +}; + +static int do_dd(int rd, int wr, struct stats *stats) +{ + unsigned int i; + int ret; + int fill_val = 0; + size_t out_size = 0; + size_t in_size; + char *buf; + + if (conv & (CONV_BLOCK | CONV_UNBLOCK)) + fill_val = ' '; + + while (!OPT_COUNT->str || count-- != 0) { + buf = in_buf; + + /* + * 1. read ibs-sized buffer + */ + in_size = ret = read(rd, in_buf, ibs); + if (ret == -1 || (ret == 0 && (conv & CONV_NOERROR) == 0)) + break; + + if (in_size == ibs) { + stats->in_full++; + } else { + stats->in_partial++; + + /* + * 2. zero (or append spaces) + */ + if (conv & CONV_SYNC) { + memset(in_buf + in_size, fill_val, + ibs - in_size); + in_size = ibs; + } + } + + /* + * 4. swab conversion. With an odd number of bytes, + * last byte does not get swapped. + */ + if (conv & CONV_SWAB) { + char c; + + for (i = 1; i < in_size; i += 2) { + c = in_buf[i - 1]; + in_buf[i - 1] = in_buf[i]; + in_buf[i] = c; + } + } + + /* + * 5. remaining conversions. + */ + if (conv & CONV_LCASE) + for (i = 0; i < in_size; i++) + in_buf[i] = tolower(in_buf[i]); + + if (conv & CONV_UCASE) + for (i = 0; i < in_size; i++) + in_buf[i] = toupper(in_buf[i]); + + /* block/unblock ? */ + + /* + * 6. Aggregate into obs sized buffers. + * If the in_size is obs-sized and we have no + * data waiting, just write "buf" to the output. + */ + if (out_size == 0 && in_size == obs) { + write(wr, buf, obs); + stats->out_full++; + } else { + /* + * We had data waiting, or we didn't have an + * obs-sized input block. We need to append + * the input data to the output buffer. + */ + unsigned int space; + char *in_ptr = in_buf; + + do { + space = obs - out_size; + if (space > in_size) + space = in_size; + + memcpy(out_buf + out_size, in_ptr, space); + out_size += space; + in_size -= space; + in_ptr += space; + + if (out_size == obs) { + write(wr, out_buf, obs); + stats->out_full++; + out_size = 0; + } + } while (out_size == 0 && in_size); + + if (in_size) { + memcpy(out_buf, in_ptr, in_size); + out_size = in_size; + } + } + } + + if (out_size) { + write(wr, out_buf, out_size); + stats->out_partial++; + } + + return 0; +} + +static sigjmp_buf jmp; + +static void sigint_handler(int sig) +{ + siglongjmp(jmp, -sig); +} + +static int dd(int rd_fd, int wr_fd, struct stats *stats) +{ + int ret; + + ret = sigsetjmp(jmp, 1); + if (ret == 0) { + sysv_signal(SIGINT, sigint_handler); + ret = do_dd(rd_fd, wr_fd, stats); + } + + sysv_signal(SIGINT, SIG_DFL); + return ret; +} + +int main(int argc, char *argv[]) +{ + struct stats stats; + int ret; + int rd_fd = 0, wr_fd = 1; + + progname = argv[0]; + + ret = parse_options(argc, argv); + if (ret) + return ret; + + if (conv & (CONV_BLOCK | CONV_UNBLOCK)) { + fprintf(stderr, "%s: block/unblock not implemented\n", + progname); + return 1; + } + + in_buf = malloc(ibs); + if (!in_buf) { + perror("malloc ibs"); + return 1; + } + + out_buf = malloc(obs); + if (!out_buf) { + perror("malloc obs"); + return 1; + } + + /* + * Open the input file, if specified. + */ + if (OPT_IF->str) { + rd_fd = open(OPT_IF->str, O_RDONLY); + if (rd_fd == -1) { + perror("open input file"); + return 1; + } + } + + /* + * Open the output file, if specified. + */ + if (OPT_OF->str) { + int flags = O_WRONLY|O_CREAT; + flags |= (conv & CONV_NOTRUNC) ? 0 : O_TRUNC; + wr_fd = open(OPT_OF->str, flags, 0666); + if (wr_fd == -1) { + perror("open output file"); + return 1; + } + } + + /* + * Skip obs-sized blocks of output file. + */ + if (OPT_SEEK->str && skip_blocks(wr_fd, out_buf, seek, obs)) + return 1; + + /* + * Skip ibs-sized blocks of input file. + */ + if (OPT_SKIP->str && skip_blocks(rd_fd, in_buf, skip, ibs)) + return 1; + + memset(&stats, 0, sizeof(stats)); + + /* + * Do the real work + */ + ret = dd(rd_fd, wr_fd, &stats); + + if (close(rd_fd) == -1) + perror(OPT_IF->str ? OPT_IF->str : "stdin"); + if (close(wr_fd) == -1) + perror(OPT_OF->str ? OPT_OF->str : "stdout"); + + fprintf(stderr, "%u+%u records in\n", stats.in_full, stats.in_partial); + fprintf(stderr, "%u+%u records out\n", + stats.out_full, stats.out_partial); + if (stats.truncated) + fprintf(stderr, "%u truncated record%s\n", + stats.truncated, stats.truncated == 1 ? "" : "s"); + + /* + * ret will be -SIGINT if we got a SIGINT. Raise + * the signal again to cause us to terminate with + * SIGINT status. + */ + if (ret == -SIGINT) + raise(SIGINT); + + return ret; +} diff -puN /dev/null usr/utils/false.c --- /dev/null +++ a/usr/utils/false.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 1; +} diff -puN /dev/null usr/utils/file_mode.c --- /dev/null +++ a/usr/utils/file_mode.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "file_mode.h" + +extern char *progname; + +mode_t parse_file_mode(char *arg, mode_t mode, mode_t sumask) +{ + char *clause; + + if (isdigit(*arg) && *arg < '8') { + unsigned long num; + + num = strtoul(arg, NULL, 8); + if ((num == ULONG_MAX && errno == ERANGE) || num > 07777) { + fprintf(stderr, "%s: invalid mode `%s'\n", progname, + arg); + exit(255); + } + return (mode_t) num; + } + + while ((clause = strsep(&arg, ",")) != NULL) { + mode_t who = 0; + int action; + char *p = clause; + + /* + * Parse the who list. Optional. + */ + while (1) { + switch (*p++) { + case 'u': + who |= S_IRWXU | S_ISUID; + continue; + case 'g': + who |= S_IRWXG | S_ISGID; + continue; + case 'o': + who |= S_IRWXO | S_ISVTX; + continue; + case 'a': + who = + S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | + S_ISGID | S_ISVTX; + continue; + } + /* undo the increment above */ + p--; + break; + } + + if (who == 0) + who = (~sumask) | S_ISVTX; + + /* + * Parse an action list. Must be at least one action. + */ + while (*p) { + mode_t perm = 0; + + /* + * Parse the action + */ + action = *p; + if (action == '+' || action == '-' || action == '=') + p++; + + /* + * Parse perm + */ + while (*p) { + switch (*p++) { + case 'r': + perm |= S_IRUSR | S_IRGRP | S_IROTH; + continue; + case 'w': + perm |= S_IWUSR | S_IWGRP | S_IWOTH; + continue; + case 'x': + perm |= S_IXUSR | S_IXGRP | S_IXOTH; + continue; + case 'X': + perm |= S_ISVTX; + continue; + case 's': + perm |= S_ISUID | S_ISGID; + continue; + case 'u': + perm = mode & S_IRWXU; + perm |= perm >> 3 | perm >> 6; + if (mode & S_ISUID) + perm |= S_ISGID; + continue; + case 'g': + perm = mode & S_IRWXG; + perm |= perm << 3 | perm >> 3; + if (mode & S_ISGID) + perm |= S_ISUID; + continue; + case 'o': + perm = mode & S_IRWXO; + perm |= perm << 6 | perm << 3; + continue; + } + /* undo the increment above */ + p--; + break; + } + + perm &= who; + + switch (action) { + case '+': + mode |= perm; + continue; + + case '-': + mode &= ~perm; + continue; + + case '=': + mode &= ~who; + mode |= perm; + continue; + } + + if (!action) + break; + fprintf(stderr, "%s: invalid mode `%s'\n", progname, + clause); + exit(255); + } + } + + return mode; +} diff -puN /dev/null usr/utils/file_mode.h --- /dev/null +++ a/usr/utils/file_mode.h @@ -0,0 +1 @@ +mode_t parse_file_mode(char *arg, mode_t mode, mode_t sumask); diff -puN /dev/null usr/utils/halt.c --- /dev/null +++ a/usr/utils/halt.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +static __noreturn usage(void) +{ + static char mesg[] = "Usage: {halt|reboot|poweroff} [-n]\n"; + write(2, mesg, sizeof(mesg) - 1); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int cmd = 0; /* initalize to shut gcc up */ + int do_sync = 1; + char *ptr, *ptr2; + + /* Which action (program name)? */ + ptr2 = ptr = argv[0]; + while (*ptr2) + if (*ptr2++ == '/') + ptr = ptr2; + if (*ptr == 'r') + cmd = LINUX_REBOOT_CMD_RESTART; + else if (*ptr == 'h') + cmd = LINUX_REBOOT_CMD_HALT; + else if (*ptr == 'p') + cmd = LINUX_REBOOT_CMD_POWER_OFF; + else + usage(); + + /* Walk options */ + while (*++argv && **argv == '-') + switch (*++*argv) { + case 'f': break; /* -f assumed */ + case 'n': do_sync = 0; break; + default: + usage(); + } + if (*argv) + usage(); /* any args == error */ + + if (do_sync) + sync(); + reboot(LINUX_REBOOT_CMD_CAD_OFF); /* Enable CTRL+ALT+DEL */ + if (!reboot(cmd)) { + /* Success. Currently, CMD_HALT returns, so stop the world */ + /* kill(-1, SIGSTOP); */ + kill(getpid(), SIGSTOP); + } + write(2, "failed.\n", 8); + return 1; +} diff -puN /dev/null usr/utils/insmod.c --- /dev/null +++ a/usr/utils/insmod.c @@ -0,0 +1,140 @@ +/* insmod.c: insert a module into the kernel. + Copyright (C) 2001 Rusty Russell. + Copyright (C) 2002 Rusty Russell, IBM Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define streq(a,b) (strcmp((a),(b)) == 0) + +/* This really needs to be in a header file... */ +extern long init_module(void *, unsigned long, const char *); + +static void print_usage(const char *progname) +{ + fprintf(stderr, "Usage: %s filename [args]\n", progname); + exit(1); +} + +/* We use error numbers in a loose translation... */ +static const char *moderror(int err) +{ + switch (err) { + case ENOEXEC: + return "Invalid module format"; + case ENOENT: + return "Unknown symbol in module"; + case ESRCH: + return "Module has wrong symbol version"; + case EINVAL: + return "Invalid parameters"; + default: + return strerror(err); + } +} + +static void *grab_file(const char *filename, unsigned long *size) +{ + unsigned int max = 16384; + int ret, fd; + void *buffer = malloc(max); + + if (streq(filename, "-")) + fd = dup(STDIN_FILENO); + else + fd = open(filename, O_RDONLY, 0); + + if (fd < 0) + return NULL; + + *size = 0; + while ((ret = read(fd, buffer + *size, max - *size)) > 0) { + *size += ret; + if (*size == max) + buffer = realloc(buffer, max *= 2); + } + if (ret < 0) { + free(buffer); + buffer = NULL; + } + close(fd); + return buffer; +} + +int main(int argc, char *argv[]) +{ + int i; + long int ret; + unsigned long len; + void *file; + char *filename, *options = strdup(""); + char *progname = argv[0]; + + if (argv[1] && (streq(argv[1], "--version") || streq(argv[1], "-V"))) { + puts("klibc insmod"); + exit(0); + } + + /* Ignore old options, for backwards compat. */ + while (argv[1] && (streq(argv[1], "-p") + || streq(argv[1], "-s") + || streq(argv[1], "-f"))) { + argv++; + argc--; + } + + filename = argv[1]; + if (!filename) + print_usage(progname); + + /* Rest is options */ + for (i = 2; i < argc; i++) { + options = realloc(options, + strlen(options) + 2 + strlen(argv[i]) + 2); + /* Spaces handled by "" pairs, but no way of escaping + quotes */ + if (strchr(argv[i], ' ')) + strcat(options, "\""); + strcat(options, argv[i]); + if (strchr(argv[i], ' ')) + strcat(options, "\""); + strcat(options, " "); + } + + file = grab_file(filename, &len); + if (!file) { + fprintf(stderr, "insmod: can't read '%s': %s\n", + filename, strerror(errno)); + exit(1); + } + + ret = init_module(file, len, options); + if (ret != 0) { + fprintf(stderr, "insmod: error inserting '%s': %li %s\n", + filename, ret, moderror(errno)); + exit(1); + } + exit(0); +} diff -puN /dev/null usr/utils/Kbuild --- /dev/null +++ a/usr/utils/Kbuild @@ -0,0 +1,62 @@ +# +# Kbuild file for klib utils +# + +progs := chroot dd mkdir mkfifo mknod mount pivot_root umount +progs += true false sleep ln nuke minips cat +progs += insmod uname halt + +static-y := $(addprefix static/, $(progs)) +shared-y := $(addprefix shared/, $(progs)) + +# The binary is placed in a subdir, so we need to tell kbuild this +static/chroot-y := chroot.o +shared/chroot-y := chroot.o +static/dd-y := dd.o +shared/dd-y := dd.o +static/mkdir-y := mkdir.o file_mode.o +shared/mkdir-y := mkdir.o file_mode.o +static/mkfifo-y := mkfifo.o file_mode.o +shared/mkfifo-y := mkfifo.o file_mode.o +static/mknod-y := mknod.o file_mode.o +shared/mknod-y := mknod.o file_mode.o +static/mount-y := mount_main.o mount_opts.o +shared/mount-y := mount_main.o mount_opts.o +static/pivot_root-y := pivot_root.o +shared/pivot_root-y := pivot_root.o +static/umount-y := umount.o +shared/umount-y := umount.o +static/true-y := true.o +shared/true-y := true.o +static/false-y := false.o +shared/false-y := false.o +static/sleep-y := sleep.o +shared/sleep-y := sleep.o +static/ln-y := ln.o +shared/ln-y := ln.o +static/nuke-y := nuke.o +shared/nuke-y := nuke.o +static/minips-y := minips.o +shared/minips-y := minips.o +static/cat-y := cat.o +shared/cat-y := cat.o +static/insmod-y := insmod.o +shared/insmod-y := insmod.o +static/uname-y := uname.o +shared/uname-y := uname.o +static/halt-y := halt.o +shared/halt-y := halt.o + +# Additionally linked targets +always := static/reboot static/poweroff shared/reboot shared/poweroff + +$(obj)/static/reboot $(obj)/static/poweroff: $(obj)/static/halt + $(call cmd,ln) +$(obj)/shared/reboot $(obj)/shared/poweroff: $(obj)/shared/halt + $(call cmd,ln) + +# Clean deletes the static and shared dir +clean-dirs := static shared + +# install only install the shared binaries +install-y := $(shared-y) shared/reboot shared/poweroff diff -puN /dev/null usr/utils/ln.c --- /dev/null +++ a/usr/utils/ln.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + int c, s, f; + char *p; + struct stat sb; + + s = f = 0; + do { + c = getopt(argc, argv, "sf"); + if (c == EOF) + break; + + switch (c) { + + case 's': + s = 1; + break; + case 'f': + f = 1; + break; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + argv[0], optopt); + return 1; + } + + } while (1); + + if (optind == argc) { + fprintf(stderr, "Usage: %s [-s] [-f] target link\n", argv[0]); + return 1; + } + + memset(&sb, 0, sizeof(struct stat)); + if (stat(argv[argc - 1], &sb) < 0 && argc - optind > 2) { + if (!(S_ISDIR(sb.st_mode))) { + fprintf(stderr, + "multiple targets and %s is not a directory\n", + argv[argc - 1]); + return 1; + } + } + + for (c = optind; c < argc - 1; c++) { + char target[PATH_MAX]; + + p = strrchr(argv[c], '/'); + p++; + + if (S_ISDIR(sb.st_mode)) + snprintf(target, PATH_MAX, "%s/%s", argv[argc - 1], p); + else + snprintf(target, PATH_MAX, "%s", argv[argc - 1]); + + if (f) + unlink(target); + + if (s) { + if (symlink(argv[c], target) == -1) + perror(target); + } else { + if (link(argv[c], target) == -1) + perror(target); + } + } + + return 0; +} diff -puN /dev/null usr/utils/minips.c --- /dev/null +++ a/usr/utils/minips.c @@ -0,0 +1,508 @@ +/* + * Copyright 1998 by Albert Cahalan; all rights reserved. + * This file may be used subject to the terms and conditions of the + * GNU Library General Public License Version 2, or any later version + * at your option, as published by the Free Software Foundation. + * 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 Library General Public License for more details. + */ + +/* This is a minimal /bin/ps, designed to be smaller than the old ps + * while still supporting some of the more important features of the + * new ps. (for total size, note that this ps does not need libproc) + * It is suitable for Linux-on-a-floppy systems only. + * + * Maintainers: do not compile or install for normal systems. + * Anyone needing this will want to tweak their compiler anyway. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* HZ */ + +static int P_euid; +static int P_pid; +static char P_cmd[16]; +static char P_state; +static int P_ppid, P_pgrp, P_session, P_tty, P_tpgid; +static unsigned long P_flags, P_min_flt, P_cmin_flt, P_maj_flt, P_cmaj_flt, + P_utime, P_stime; +static long P_cutime, P_cstime, P_priority, P_nice, P_timeout, P_it_real_value; +static unsigned long P_start_time, P_vsize; +static long P_rss; +static unsigned long P_rss_rlim, P_start_code, P_end_code, P_start_stack, + P_kstk_esp, P_kstk_eip; +static unsigned P_signal, P_blocked, P_sigignore, P_sigcatch; +static unsigned long P_wchan, P_nswap, P_cnswap; + +#if 0 +static int screen_cols = 80; +static int w_count; +#endif + +static int want_one_pid; +static const char *want_one_command; +static int select_notty; +static int select_all; + +static int ps_format; +static int old_h_option; + +/* we only pretend to support this */ +static int show_args; /* implicit with -f and all BSD options */ +static int bsd_c_option; /* this option overrides the above */ + +static int ps_argc; /* global argc */ +static char **ps_argv; /* global argv */ +static int thisarg; /* index into ps_argv */ +static char *flagptr; /* current location in ps_argv[thisarg] */ + +#ifndef HZ +#warning HZ not defined, assuming it is 100 +#define HZ 100 +#endif + +int page_shift; /* Page size as shift count */ + +static void usage(void) +{ + fprintf(stderr, + "-C select by command name (minimal ps only accepts one)\n" + "-p select by process ID (minimal ps only accepts one)\n" + "-e all processes (same as ax)\n" + "a all processes w/ tty, including other users\n" + "x processes w/o controlling ttys\n" + "-f full format\n" + "-j,j job control format\n" + "v virtual memory format\n" + "-l,l long format\n" + "u user-oriented format\n" + "-o user-defined format (limited support, only \"ps -o pid=\")\n" + "h no header\n" +/* + "-A all processes (same as ax)\n" + "c true command name\n" + "-w,w wide output\n" +*/ + ); + exit(1); +} + +/* + * Return the next argument, or call the usage function. + * This handles both: -oFOO -o FOO + */ +static const char *get_opt_arg(void) +{ + const char *ret; + ret = flagptr + 1; /* assume argument is part of ps_argv[thisarg] */ + if (*ret) + return ret; + if (++thisarg >= ps_argc) + usage(); /* there is nothing left */ + /* argument is the new ps_argv[thisarg] */ + ret = ps_argv[thisarg]; + if (!ret || !*ret) + usage(); + return ret; +} + +/* return the PID, or 0 if nothing good */ +static void parse_pid(const char *str) +{ + char *endp; + int num; + if (!str) + goto bad; + num = strtol(str, &endp, 0); + if (*endp != '\0') + goto bad; + if (num < 1) + goto bad; + if (want_one_pid) + goto bad; + want_one_pid = num; + return; + bad: + usage(); +} + +/***************** parse SysV options, including Unix98 *****************/ +static void parse_sysv_option(void) +{ + do { + switch (*flagptr) { + /**** selection ****/ + case 'C': /* end */ + if (want_one_command) + usage(); + want_one_command = get_opt_arg(); + return; /* can't have any more options */ + case 'p': /* end */ + parse_pid(get_opt_arg()); + return; /* can't have any more options */ + case 'A': + case 'e': + select_all++; + select_notty++; + case 'w': /* here for now, since the real one is not used */ + break; + /**** output format ****/ + case 'f': + show_args = 1; + /* FALL THROUGH */ + case 'j': + case 'l': + if (ps_format) + usage(); + ps_format = *flagptr; + break; + case 'o': /* end */ + /* We only support a limited form: "ps -o pid=" (yes, just "pid=") */ + if (strcmp(get_opt_arg(), "pid=")) + usage(); + if (ps_format) + usage(); + ps_format = 'o'; + old_h_option++; + return; /* can't have any more options */ + /**** other stuff ****/ +#if 0 + case 'w': + w_count++; + break; +#endif + default: + usage(); + } /* switch */ + } while (*++flagptr); +} + +/************************* parse BSD options **********************/ +static void parse_bsd_option(void) +{ + do { + switch (*flagptr) { + /**** selection ****/ + case 'a': + select_all++; + break; + case 'x': + select_notty++; + break; + case 'p': /* end */ + parse_pid(get_opt_arg()); + return; /* can't have any more options */ + /**** output format ****/ + case 'j': + case 'l': + case 'u': + case 'v': + if (ps_format) + usage(); + ps_format = 0x80 | *flagptr; /* use 0x80 to tell BSD from SysV */ + break; + /**** other stuff ****/ + case 'c': + bsd_c_option++; +#if 0 + break; +#endif + case 'w': +#if 0 + w_count++; +#endif + break; + case 'h': + old_h_option++; + break; + default: + usage(); + } /* switch */ + } while (*++flagptr); +} + +#if 0 +/* not used yet */ +static void choose_dimensions(void) +{ + struct winsize ws; + char *columns; + /* screen_cols is 80 by default */ + if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col > 30) + screen_cols = ws.ws_col; + columns = getenv("COLUMNS"); + if (columns && *columns) { + long t; + char *endptr; + t = strtol(columns, &endptr, 0); + if (!*endptr && (t > 30) && (t < (long)999999999)) + screen_cols = (int)t; + } + if (w_count && (screen_cols < 132)) + screen_cols = 132; + if (w_count > 1) + screen_cols = 999999999; +} +#endif + +static void arg_parse(int argc, char *argv[]) +{ + int sel = 0; /* to verify option sanity */ + ps_argc = argc; + ps_argv = argv; + thisarg = 0; + /**** iterate over the args ****/ + while (++thisarg < ps_argc) { + flagptr = ps_argv[thisarg]; + switch (*flagptr) { + case '0'...'9': + show_args = 1; + parse_pid(flagptr); + break; + case '-': + flagptr++; + parse_sysv_option(); + break; + default: + show_args = 1; + parse_bsd_option(); + break; + } + } + /**** sanity check and clean-up ****/ + if (want_one_pid) + sel++; + if (want_one_command) + sel++; + if (select_notty || select_all) + sel++; + if (sel > 1 || select_notty > 1 || select_all > 1 || bsd_c_option > 1 + || old_h_option > 1) + usage(); + if (bsd_c_option) + show_args = 0; +} + +/* return 1 if it works, or 0 for failure */ +static int stat2proc(int pid) +{ + char buf[800]; /* about 40 fields, 64-bit decimal is about 20 chars */ + int num; + int fd; + char *tmp; + struct stat sb; /* stat() used to get EUID */ + snprintf(buf, 32, "/proc/%d/stat", pid); + if ((fd = open(buf, O_RDONLY, 0)) == -1) + return 0; + num = read(fd, buf, sizeof buf - 1); + fstat(fd, &sb); + P_euid = sb.st_uid; + close(fd); + if (num < 80) + return 0; + buf[num] = '\0'; + tmp = strrchr(buf, ')'); /* split into "PID (cmd" and "" */ + *tmp = '\0'; /* replace trailing ')' with NUL */ + /* parse these two strings separately, skipping the leading "(". */ + memset(P_cmd, 0, sizeof P_cmd); /* clear */ + sscanf(buf, "%d (%15c", &P_pid, P_cmd); /* comm[16] in kernel */ + num = sscanf(tmp + 2, /* skip space after ')' too */ + "%c " "%d %d %d %d %d " "%lu %lu %lu %lu %lu %lu %lu " "%ld %ld %ld %ld %ld %ld " "%lu %lu " "%ld " "%lu %lu %lu %lu %lu %lu " "%u %u %u %u " /* no use for RT signals */ + "%lu %lu %lu", + &P_state, + &P_ppid, &P_pgrp, &P_session, &P_tty, &P_tpgid, + &P_flags, &P_min_flt, &P_cmin_flt, &P_maj_flt, &P_cmaj_flt, + &P_utime, &P_stime, &P_cutime, &P_cstime, &P_priority, + &P_nice, &P_timeout, &P_it_real_value, &P_start_time, + &P_vsize, &P_rss, &P_rss_rlim, &P_start_code, &P_end_code, + &P_start_stack, &P_kstk_esp, &P_kstk_eip, &P_signal, + &P_blocked, &P_sigignore, &P_sigcatch, &P_wchan, &P_nswap, + &P_cnswap); +/* fprintf(stderr, "stat2proc converted %d fields.\n",num); */ + P_vsize /= 1024; + P_rss <<= page_shift - 10; + if (num < 30) + return 0; + if (P_pid != pid) + return 0; + return 1; +} + +static const char *do_time(unsigned long t) +{ + int hh, mm, ss; + static char buf[32]; + int cnt = 0; + t /= HZ; + ss = t % 60; + t /= 60; + mm = t % 60; + t /= 60; + hh = t % 24; + t /= 24; + if (t) + cnt = snprintf(buf, sizeof buf, "%d-", (int)t); + snprintf(cnt + buf, sizeof(buf) - cnt, "%02d:%02d:%02d", hh, mm, ss); + return buf; +} + +static void print_proc(void) +{ + char tty[16]; + snprintf(tty, sizeof tty, "%3d,%-3d", (P_tty >> 8) & 0xff, + P_tty & 0xff); + switch (ps_format) { + case 0: + printf("%5d %s %s", P_pid, tty, do_time(P_utime + P_stime)); + break; + case 'o': + printf("%d\n", P_pid); + return; /* don't want the command */ + case 'l': + printf("%03x %c %5d %5d %5d - %3d %3d - " + "%5ld %06x %s %s", + (unsigned)P_flags & 0x777, P_state, P_euid, P_pid, + P_ppid, (int)P_priority, (int)P_nice, + P_vsize >> (page_shift - 10), + (unsigned)(P_wchan & 0xffffff), tty, + do_time(P_utime + P_stime) + ); + break; + case 'f': + printf("%5d %5d %5d - - %s %s", + P_euid, P_pid, P_ppid, tty, do_time(P_utime + P_stime) + ); + break; + case 'j': + printf("%5d %5d %5d %s %s", + P_pid, P_pgrp, P_session, tty, do_time(P_utime + P_stime) + ); + break; + case 'u' | 0x80: + printf("%5d %5d - - %5ld %5ld %s %c - %s", + P_euid, P_pid, P_vsize, P_rss, tty, P_state, + do_time(P_utime + P_stime) + ); + break; + case 'v' | 0x80: + printf("%5d %s %c %s %6d - - %5d -", + P_pid, tty, P_state, do_time(P_utime + P_stime), + (int)P_maj_flt, (int)P_rss); + break; + case 'j' | 0x80: + printf("%5d %5d %5d %5d %s %5d %c %5d %s", + P_ppid, P_pid, P_pgrp, P_session, tty, P_tpgid, P_state, + P_euid, do_time(P_utime + P_stime) + ); + break; + case 'l' | 0x80: + printf("%03x %5d %5d %5d %3d %3d " + "%5ld %4ld %06x %c %s %s", + (unsigned)P_flags & 0x777, P_euid, P_pid, P_ppid, + (int)P_priority, (int)P_nice, P_vsize, P_rss, + (unsigned)(P_wchan & 0xffffff), P_state, tty, + do_time(P_utime + P_stime) + ); + break; + default: + break; + } + if (show_args) + printf(" [%s]\n", P_cmd); + else + printf(" %s\n", P_cmd); +} + +int main(int argc, char *argv[]) +{ + arg_parse(argc, argv); + + page_shift = __getpageshift(); + +#if 0 + choose_dimensions(); +#endif + if (!old_h_option) { + const char *head; + switch (ps_format) { + default: /* can't happen */ + case 0: + head = " PID TTY TIME CMD"; + break; + case 'l': + head = + " F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD"; + break; + case 'f': + head = + " UID PID PPID C STIME TTY TIME CMD"; + break; + case 'j': + head = " PID PGID SID TTY TIME CMD"; + break; + case 'u' | 0x80: + head = + " UID PID %CPU %MEM VSZ RSS TTY S START TIME COMMAND"; + break; + case 'v' | 0x80: + head = + " PID TTY S TIME MAJFL TRS DRS RSS %MEM COMMAND"; + break; + case 'j' | 0x80: + head = + " PPID PID PGID SID TTY TPGID S UID TIME COMMAND"; + break; + case 'l' | 0x80: + head = + " F UID PID PPID PRI NI VSZ RSS WCHAN S TTY TIME COMMAND"; + break; + } + printf("%s\n", head); + } + if (want_one_pid) { + if (stat2proc(want_one_pid)) + print_proc(); + else + exit(1); + } else { + struct dirent *ent; /* dirent handle */ + DIR *dir; + int ouruid; + int found_a_proc; + found_a_proc = 0; + ouruid = getuid(); + dir = opendir("/proc"); + while ((ent = readdir(dir))) { + if (*ent->d_name < '0' || *ent->d_name > '9') + continue; + if (!stat2proc(atoi(ent->d_name))) + continue; + if (want_one_command) { + if (strcmp(want_one_command, P_cmd)) + continue; + } else { + if (!select_notty && P_tty == -1) + continue; + if (!select_all && P_euid != ouruid) + continue; + } + found_a_proc++; + print_proc(); + } + closedir(dir); + exit(!found_a_proc); + } + return 0; +} diff -puN /dev/null usr/utils/mkdir.c --- /dev/null +++ a/usr/utils/mkdir.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_mode.h" + +static mode_t leaf_mode, subdir_mode; +static int p_flag; + +char *progname; + +static int make_one_dir(char *dir, mode_t mode) +{ + struct stat stbuf; + + if (mkdir(dir, mode) == -1) { + int err = errno; + + /* + * Ignore the error if it all of the following + * are satisfied: + * - error was EEXIST + * - -p was specified + * - stat indicates that its a directory + */ + if (p_flag && errno == EEXIST && + stat(dir, &stbuf) == 0 && S_ISDIR(stbuf.st_mode)) + return 1; + errno = err; + fprintf(stderr, "%s: ", progname); + perror(dir); + return -1; + } + return 0; +} + +static int make_dir(char *dir) +{ + int ret; + + if (p_flag) { + char *s, *p; + + /* + * Recurse each directory, trying to make it + * as we go. Should we check to see if it + * exists, and if so if it's a directory + * before calling mkdir? + */ + s = dir; + while ((p = strchr(s, '/')) != NULL) { + /* + * Ignore the leading / + */ + if (p != dir) { + *p = '\0'; + + /* + * Make the intermediary directory. POSIX + * says that these directories are created + * with umask,u+wx + */ + if (make_one_dir(dir, subdir_mode) == -1) + return -1; + + *p = '/'; + } + s = p + 1; + } + } + + /* + * Make the final target. Only complain if the + * target already exists if -p was not specified. + * This is created with the asked for mode & ~umask + */ + ret = make_one_dir(dir, leaf_mode); + if (ret == -1) + return -1; + + /* + * We might not set all the permission bits. Do that + * here (but only if we did create it.) + */ + if (ret == 0 && chmod(dir, leaf_mode) == -1) { + int err_save = errno; + + /* + * We failed, remove the directory we created + */ + rmdir(dir); + errno = err_save; + fprintf(stderr, "%s: ", progname); + perror(dir); + return -1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int c, ret = 0; + mode_t saved_umask; + + progname = argv[0]; + + saved_umask = umask(0); + leaf_mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~saved_umask; + subdir_mode = (saved_umask ^ (S_IRWXU | S_IRWXG | S_IRWXO)) + | S_IWUSR | S_IXUSR; + + do { + c = getopt(argc, argv, "pm:"); + if (c == EOF) + break; + switch (c) { + case 'm': + leaf_mode = + parse_file_mode(optarg, leaf_mode, saved_umask); + break; + case 'p': + p_flag = 1; + break; + + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + progname, optopt); + exit(1); + } + } while (1); + + if (optind == argc) { + fprintf(stderr, "Usage: %s [-p] [-m mode] dir...\n", progname); + exit(1); + } + + while (optind < argc) { + if (make_dir(argv[optind])) + ret = 255; /* seems to be what gnu mkdir does */ + optind++; + } + + return ret; +} diff -puN /dev/null usr/utils/mkfifo.c --- /dev/null +++ a/usr/utils/mkfifo.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "file_mode.h" + +static mode_t leaf_mode; + +char *progname; + +static int make_fifo(char *dir) +{ + if (mkfifo(dir, leaf_mode)) { + /* + * We failed, remove the directory we created. + */ + fprintf(stderr, "%s: ", progname); + perror(dir); + return -1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int c, ret = 0; + mode_t saved_umask; + + progname = argv[0]; + + saved_umask = umask(0); + leaf_mode = + (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) & + ~saved_umask; + + do { + c = getopt(argc, argv, "m:"); + if (c == EOF) + break; + switch (c) { + case 'm': + leaf_mode = + parse_file_mode(optarg, leaf_mode, saved_umask); + break; + + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + progname, optopt); + exit(1); + } + } while (1); + + if (optind == argc) { + fprintf(stderr, "Usage: %s [-m mode] file...\n", progname); + exit(1); + } + + while (optind < argc) { + if (make_fifo(argv[optind])) + ret = 255; /* seems to be what gnu mkdir does */ + optind++; + } + + return ret; +} diff -puN /dev/null usr/utils/mknod.c --- /dev/null +++ a/usr/utils/mknod.c @@ -0,0 +1,58 @@ +#include +#include +#include + +char *progname; + +static __noreturn usage(void) +{ + fprintf(stderr, "Usage: %s name {b|c} major minor\n", progname); + exit(1); +} + +int main(int argc, char *argv[], char *envp[]) +{ + char *name = NULL, *endp; + unsigned int major, minor; + mode_t mode; + dev_t dev; + + progname = argv[0]; + if (argc != 5) + usage(); + + name = argv[1]; + if (!name) { + perror("device"); + usage(); + } + + mode = 0666; + if (argv[2][0] == 'c') + mode |= S_IFCHR; + else if (argv[2][0] == 'b') + mode |= S_IFBLK; + else { + perror("block or char devices."); + usage(); + } + + major = strtol(argv[3], &endp, 0); + if (*endp != '\0') { + perror("major."); + usage(); + } + minor = strtol(argv[4], &endp, 0); + if (*endp != '\0') { + perror("minor."); + usage(); + } + dev = makedev(major, minor); + + if (mknod(name, mode, dev) == -1) { + perror("mknod"); + exit(1); + } + + exit(0); +} diff -puN /dev/null usr/utils/mount_main.c --- /dev/null +++ a/usr/utils/mount_main.c @@ -0,0 +1,105 @@ +/* + * mount.c, by rmk + */ +#include +#include +#include +#include +#include +#include + +#include "mount_opts.h" + +char *progname; + +static struct extra_opts extra; +static unsigned long rwflag; + +static int +do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data) +{ + char *s; + int error = 0; + + while ((s = strsep(&type, ",")) != NULL) { + retry: + if (mount(dev, dir, s, rwflag, data) == -1) { + error = errno; + /* + * If the filesystem is not found, or the + * superblock is invalid, try the next. + */ + if (error == ENODEV || error == EINVAL) + continue; + + /* + * If we get EACCESS, and we're trying to + * mount readwrite and this isn't a remount, + * try read only. + */ + if (error == EACCES && + (rwflag & (MS_REMOUNT | MS_RDONLY)) == 0) { + rwflag |= MS_RDONLY; + goto retry; + } + break; + } + } + + if (error) { + errno = error; + perror("mount"); + return 255; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + char *type = NULL; + int c; + + progname = argv[0]; + rwflag = MS_VERBOSE; + + do { + c = getopt(argc, argv, "o:rt:w"); + if (c == EOF) + break; + switch (c) { + case 'o': + rwflag = parse_mount_options(optarg, rwflag, &extra); + break; + case 'r': + rwflag |= MS_RDONLY; + break; + case 't': + type = optarg; + break; + case 'w': + rwflag &= ~MS_RDONLY; + break; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + progname, optopt); + exit(1); + } + } while (1); + + /* + * If remount, bind or move was specified, then we don't + * have a "type" as such. Use the dummy "none" type. + */ + if (rwflag & MS_TYPE) + type = "none"; + + if (optind + 2 != argc || type == NULL) { + fprintf(stderr, "Usage: %s [-r] [-w] [-o options] [-t type] " + "device directory\n", progname); + exit(1); + } + + return do_mount(argv[optind], argv[optind + 1], type, rwflag, + extra.str); +} diff -puN /dev/null usr/utils/mount_opts.c --- /dev/null +++ a/usr/utils/mount_opts.c @@ -0,0 +1,94 @@ +/* + * mount_opts.c, by rmk + * + * Decode mount options. + */ +#include +#include +#include + +#include "mount_opts.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +static const struct mount_opts options[] = { + /* name mask set noset */ + {"async", MS_SYNCHRONOUS, 0, MS_SYNCHRONOUS}, + {"atime", MS_NOATIME, 0, MS_NOATIME}, + {"bind", MS_TYPE, MS_BIND, 0,}, + {"dev", MS_NODEV, 0, MS_NODEV}, + {"diratime", MS_NODIRATIME, 0, MS_NODIRATIME}, + {"dirsync", MS_DIRSYNC, MS_DIRSYNC, 0}, + {"exec", MS_NOEXEC, 0, MS_NOEXEC}, + {"move", MS_TYPE, MS_MOVE, 0}, + {"recurse", MS_REC, MS_REC, 0}, + {"remount", MS_TYPE, MS_REMOUNT, 0}, + {"ro", MS_RDONLY, MS_RDONLY, 0}, + {"rw", MS_RDONLY, 0, MS_RDONLY}, + {"suid", MS_NOSUID, 0, MS_NOSUID}, + {"sync", MS_SYNCHRONOUS, MS_SYNCHRONOUS, 0}, + {"verbose", MS_VERBOSE, MS_VERBOSE, 0}, +}; + +static void add_extra_option(struct extra_opts *extra, char *s) +{ + int len = strlen(s); + int newlen = extra->used_size + len; + + if (extra->str) + len++; /* +1 for ',' */ + + if (newlen >= extra->alloc_size) { + char *new; + + new = realloc(extra->str, newlen + 1); /* +1 for NUL */ + if (!new) + return; + + extra->str = new; + extra->end = extra->str + extra->used_size; + extra->alloc_size = newlen; + } + + if (extra->used_size) { + *extra->end = ','; + extra->end++; + } + strcpy(extra->end, s); + extra->used_size += len; + +} + +unsigned long +parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra) +{ + char *s; + + while ((s = strsep(&arg, ",")) != NULL) { + char *opt = s; + unsigned int i; + int res, no = s[0] == 'n' && s[1] == 'o'; + + if (no) + s += 2; + + for (i = 0, res = 1; i < ARRAY_SIZE(options); i++) { + res = strcmp(s, options[i].str); + + if (res == 0) { + rwflag &= ~options[i].rwmask; + if (no) + rwflag |= options[i].rwnoset; + else + rwflag |= options[i].rwset; + } + if (res <= 0) + break; + } + + if (res != 0 && s[0]) + add_extra_option(extra, opt); + } + + return rwflag; +} diff -puN /dev/null usr/utils/mount_opts.h --- /dev/null +++ a/usr/utils/mount_opts.h @@ -0,0 +1,21 @@ +struct mount_opts { + const char str[8]; + unsigned long rwmask; + unsigned long rwset; + unsigned long rwnoset; +}; + +struct extra_opts { + char *str; + char *end; + int used_size; + int alloc_size; +}; + +/* + * These options define the function of "mount(2)". + */ +#define MS_TYPE (MS_REMOUNT|MS_BIND|MS_MOVE) + +unsigned long +parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra); diff -puN /dev/null usr/utils/nuke.c --- /dev/null +++ a/usr/utils/nuke.c @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * nuke.c + * + * Simple program which does the same thing as rm -rf, except it takes + * no options and can therefore not get confused by filenames starting + * with -. Similarly, an empty list of inputs is assumed to mean don't + * do anything. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *program; + +static int nuke(const char *what); + +static int nuke_dirent(int len, const char *dir, const char *name) +{ + int bytes = len + strlen(name) + 2; + char path[bytes]; + int xlen; + + xlen = snprintf(path, bytes, "%s/%s", dir, name); + assert(xlen < bytes); + + return nuke(path); +} + +/* Wipe the contents of a directory, but not the directory itself */ +static int nuke_dir(const char *what) +{ + int len = strlen(what); + DIR *dir; + struct dirent *d; + int err = 0; + + if (!(dir = opendir(what))) { + /* EACCES means we can't read it. Might be empty and removable; + if not, the rmdir() in nuke() will trigger an error. */ + return (errno == EACCES) ? 0 : errno; + } + + while ((d = readdir(dir))) { + /* Skip . and .. */ + if (d->d_name[0] == '.' && + (d->d_name[1] == '\0' || + (d->d_name[1] == '.' && d->d_name[2] == '\0'))) + continue; + + err = nuke_dirent(len, what, d->d_name); + if (err) { + closedir(dir); + return err; + } + } + + closedir(dir); + + return 0; +} + +static int nuke(const char *what) +{ + int rv; + int err = 0; + + rv = unlink(what); + if (rv < 0) { + if (errno == EISDIR) { + /* It's a directory. */ + err = nuke_dir(what); + if (!err) + err = rmdir(what) ? errno : err; + } else { + err = errno; + } + } + + if (err) { + fprintf(stderr, "%s: %s: %s\n", program, what, strerror(err)); + return err; + } else { + return 0; + } +} + +int main(int argc, char *argv[]) +{ + int i; + int err = 0; + + program = argv[0]; + + for (i = 1; i < argc; i++) { + err = nuke(argv[i]); + if (err) + break; + } + + return !!err; +} diff -puN /dev/null usr/utils/pivot_root.c --- /dev/null +++ a/usr/utils/pivot_root.c @@ -0,0 +1,19 @@ +/* pivot_root.c - Change the root file system */ + +/* Written 2000 by Werner Almesberger */ + +#include +#include + +int main(int argc, const char **argv) +{ + if (argc != 3) { + fprintf(stderr, "Usage: %s new_root put_old\n", argv[0]); + return 1; + } + if (pivot_root(argv[1], argv[2]) < 0) { + perror("pivot_root"); + return 1; + } + return 0; +} diff -puN /dev/null usr/utils/sleep.c --- /dev/null +++ a/usr/utils/sleep.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + struct timespec ts; + char *p; + + if (argc != 2) + goto err; + + p = strtotimespec(argv[1], &ts); + if (*p) + goto err; + + while (nanosleep(&ts, &ts) == -1 && errno == EINTR) ; + + return 0; + + err: + fprintf(stderr, "Usage: %s seconds[.fraction]\n", argv[0]); + return 1; +} diff -puN /dev/null usr/utils/true.c --- /dev/null +++ a/usr/utils/true.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff -puN /dev/null usr/utils/umount.c --- /dev/null +++ a/usr/utils/umount.c @@ -0,0 +1,45 @@ +/* + * umount.c, by rmk + */ +#include +#include +#include +#include +#include +#include + +char *progname; + +int main(int argc, char *argv[]) +{ + int c, flag = 0; + + progname = argv[0]; + + do { + c = getopt(argc, argv, "f"); + if (c == EOF) + break; + switch (c) { + case 'f': + flag |= MNT_FORCE; + break; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + progname, optopt); + exit(1); + } + } while (1); + + if (optind + 1 != argc) { + fprintf(stderr, "Usage: %s [-f] mntpoint\n", progname); + return 1; + } + + if (umount2(argv[optind], flag) == -1) { + perror("umount2"); + return 255; + } + + return 0; +} diff -puN /dev/null usr/utils/uname.c --- /dev/null +++ a/usr/utils/uname.c @@ -0,0 +1,154 @@ +/* + * uname.c, by tlh + * + * The uname program for system information: kernel name, kernel + * release, kernel release, machine, processor, platform, os and + * hostname. + */ + +#include +#include +#include +#include +#include + +enum uname_fields { + UN_SYSNAME, + UN_NODENAME, + UN_RELEASE, + UN_VERSION, + UN_MACHINE, +#if NOT_IMPLEMENTED_PROCESSOR + UN_PROCESSOR, +#endif + UN_HARDWARE, +#if NOT_IMPLEMENTED_OS + UN_OS, +#endif + UN_NR_FIELDS +}; + +void usage(FILE * stream, const char *progname) +{ + fprintf(stream, + "Usage: %s [OPTION] . . .\n" + "Print system information, No options defaults to -s.\n" + "\n" + " -a print all the information in the same order as follows below\n" + " -s kernel name\n" + " -n network node name (hostname)\n" + " -r kernel release\n" + " -v kernel version\n" " -m machine hardware name\n" +#if NOT_IMPLEMENTED_PROCESSOR + " -p processor type\n" +#endif + " -i hardware platform\n" +#if NOT_IMPLEMENTED_OS + " -o operating system\n" +#endif + "\n" " -h help/usage\n" "\n", progname); +} + +char *make_hardware(const char *machine) +{ + char *hardware; + + if (!(hardware = strdup(machine))) { + fprintf(stderr, "strdup() failed: %s\n", strerror(errno)); + goto end; + } + if (strlen(hardware) == 4 + && hardware[0] == 'i' && hardware[2] == '8' && hardware[3] == '6') { + hardware[1] = '3'; + } + end: + return hardware; +} + +int main(int argc, char *argv[]) +{ + int ec = 1; + int opt; + int i; + int nr_pr; + struct utsname buf; + char *uname_fields[UN_NR_FIELDS] = { NULL }; + + if (-1 == uname(&buf)) { + fprintf(stderr, "uname() failure: %s\n", strerror(errno)); + goto end; + } + + if (1 == argc) + /* no options given - default to -s */ + uname_fields[UN_SYSNAME] = buf.sysname; + + while ((opt = getopt(argc, argv, "asnrvmpioh")) != -1) { + switch (opt) { + case 'a': + uname_fields[UN_SYSNAME] = buf.sysname; + uname_fields[UN_NODENAME] = buf.nodename; + uname_fields[UN_RELEASE] = buf.release; + uname_fields[UN_VERSION] = buf.version; + uname_fields[UN_MACHINE] = buf.machine; + uname_fields[UN_HARDWARE] = make_hardware(buf.machine); + if (!uname_fields[UN_HARDWARE]) + goto end; + break; + case 's': + uname_fields[UN_SYSNAME] = buf.sysname; + break; + case 'n': + uname_fields[UN_NODENAME] = buf.nodename; + break; + case 'r': + uname_fields[UN_RELEASE] = buf.release; + break; + case 'v': + uname_fields[UN_VERSION] = buf.version; + break; + case 'm': + uname_fields[UN_MACHINE] = buf.machine; + break; +#if NOT_IMPLEMENTED_PROCESSOR + case 'p': + break; +#endif + case 'i': + uname_fields[UN_HARDWARE] = make_hardware(buf.machine); + if (!uname_fields[UN_HARDWARE]) + goto end; + break; +#if NOT_IMPLEMENTED_OS + case 'o': + break; +#endif + case 'h': + usage(stdout, argv[0]); + ec = 0; + goto end; + break; + default: + usage(stderr, argv[0]); + goto end; + break; + } + } + + for (nr_pr = 0, i = UN_SYSNAME; i < UN_NR_FIELDS; i++) { + if (!uname_fields[i]) + continue; + if (nr_pr) + fputc(' ', stdout); + fputs(uname_fields[i], stdout); + nr_pr++; + } + fputc('\n', stdout); + + ec = 0; + + end: + if (uname_fields[UN_HARDWARE]) + free(uname_fields[UN_HARDWARE]); + return ec; +} _