klibc-2.0.7/0000755000175000017500000000000013546700422010701 5ustar benbenklibc-2.0.7/klibc.spec0000644000175000017500000000771713546700422012655 0ustar benbenSummary: A minimal libc subset for use with initramfs. Name: klibc Version: 2.0.7 Release: 1 License: BSD/GPL Group: Development/Libraries URL: https://www.zytor.com/mailman/listinfo/klibc Source: https://www.kernel.org/pub/linux/libs/klibc/2.0/klibc-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot BuildRequires: kernel >= 2.6.0, kernel-devel Packager: H. Peter Anvin Prefix: /usr Vendor: Starving Linux Artists %define klibcdir %{_prefix}/lib/klibc %define libdocdir %{_docdir}/%{name}-%{version}-%{release} %define bindocdir %{_docdir}/%{name}-utils-%{version}-%{release} %description %{name} is intended to be a minimalistic libc subset for use with initramfs. It is deliberately written for small size, minimal entanglement, and portability, not speed. %package devel Summary: Libraries and tools needed to compile applications against klibc. Group: Development/Libraries Requires: klibc = %{version}-%{release} %description devel This package contains the link libraries, header files, and gcc wrapper scripts needed to compile applications against klibc. %package utils Summary: Small utilities built with klibc. Group: Utilities/System Requires: klibc = %{version}-%{release} %description utils This package contains a collection of programs that are linked against klibc. These duplicate some of the functionality of a regular Linux toolset, but are typically much smaller than their full-function counterparts. They are intended for inclusion in initramfs images and embedded systems. %prep %setup -q cp -dRs /lib/modules/`uname -r`/build/ ./linux # Shouldn't need this when getting the build tree from /lib/modules # make -C linux defconfig ARCH=%{_target_cpu} # make -C linux prepare ARCH=%{_target_cpu} # Deal with braindamage in RedHat's kernel-source RPM rm -f linux/include/linux/config.h cat < linux/include/linux/config.h #ifndef _LINUX_CONFIG_H #define _LINUX_CONFIG_H #include #endif EOF mkdir -p %{buildroot} %build make %{_smp_mflags} \ KLIBCARCH=%{_target_cpu} prefix=%{_prefix} bindir=%{_bindir} \ INSTALLDIR=%{klibcdir} mandir=%{_mandir} INSTALLROOT=%{buildroot} %install rm -rf %{buildroot} make KLIBCARCH=%{_target_cpu} prefix=%{_prefix} bindir=%{_bindir} \ INSTALLDIR=%{klibcdir} mandir=%{_mandir} INSTALLROOT=%{buildroot} \ install # Make the .so file in /lib a hardlink (they will be expanded as two # files automatically if it crosses filesystems when extracted.) ln -f %{buildroot}%{klibcdir}/lib/klibc-*.so %{buildroot}/lib # Install the docs mkdir -p %{buildroot}%{bindocdir} %{buildroot}%{libdocdir} install -m 444 README %{buildroot}%{libdocdir} install -m 444 usr/klibc/README.klibc %{buildroot}%{libdocdir} install -m 444 usr/klibc/arch/README.klibc.arch %{buildroot}%{libdocdir} install -m 444 usr/gzip/COPYING %{buildroot}%{bindocdir}/COPYING.gzip install -m 444 usr/gzip/README %{buildroot}%{bindocdir}/README.gzip install -m 444 usr/kinit/ipconfig/README.ipconfig %{buildroot}%{bindocdir} install -m 444 usr/kinit/README %{buildroot}%{bindocdir}/README.kinit %clean rm -rf $RPM_BUILD_ROOT # # Note: libc.so and interp.o are technically -devel files, but # put them in this package until we can make really, really sure # the dependency system can avoid confusion. (In fact, it would be # good to eventually get them out of here, so that multiple runtimes # can be installed should it be necessary.) # %files %defattr(-,root,root,-) /lib/klibc-*.so %{klibcdir}/lib/*.so %{klibcdir}/lib/interp.o %files devel %defattr(-,root,root,-) %{klibcdir}/include %{klibcdir}/lib/*.a %{klibcdir}/lib/crt0.o %{_bindir}/klcc %doc %{_mandir}/man1/* %doc %{libdocdir}/* %files utils %defattr(-,root,root,-) %{klibcdir}/bin %doc %{bindocdir}/* %changelog * Tue Mar 1 2005 H. Peter Anvin - New "make install" scheme, klcc * Tue Jul 6 2004 H. Peter Anvin - Update to use kernel-source RPM for the kernel symlink. * Sat Nov 29 2003 Bryan O'Sullivan - - Initial build. klibc-2.0.7/usr/0000755000175000017500000000000013546663605011525 5ustar benbenklibc-2.0.7/usr/utils/0000755000175000017500000000000013546663605012665 5ustar benbenklibc-2.0.7/usr/utils/uname.c0000644000175000017500000000620313546663605014137 0ustar benben/* * 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 }; static 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); } static char *make_hardware(const char *machine) { char *hardware; hardware = strdup(machine); if (!hardware) { 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; } klibc-2.0.7/usr/utils/umount.c0000644000175000017500000000141413546663605014360 0ustar benben/* * by rmk */ #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, "fli"); if (c == EOF) break; switch (c) { case 'f': flag |= MNT_FORCE; break; case 'l': flag |= MNT_DETACH; break; case 'i': /* ignore for now; no support for umount helpers */ break; case '?': fprintf(stderr, "%s: invalid option -%c\n", progname, optopt); exit(1); } } while (1); if (optind + 1 != argc) { fprintf(stderr, "Usage: %s [-f] [-l] [-i] mntpoint\n", progname); return 1; } if (umount2(argv[optind], flag) == -1) { perror("umount2"); return 255; } return 0; } klibc-2.0.7/usr/utils/true.c0000644000175000017500000000003613546663605014007 0ustar benbenint main(void) { return 0; } klibc-2.0.7/usr/utils/sync.c0000644000175000017500000000007413546663605014006 0ustar benben#include int main(void) { sync(); return 0; } klibc-2.0.7/usr/utils/sleep.c0000644000175000017500000000057213546663605014145 0ustar benben#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; } klibc-2.0.7/usr/utils/readlink.c0000644000175000017500000000161613546663605014626 0ustar benben#include #include #include #include const char *progname; static __noreturn usage(void) { fprintf(stderr, "Usage: %s [-f] link...\n", progname); exit(1); } int main(int argc, char *argv[]) { int c, f_flag = 0; const char *name; char link_name[PATH_MAX]; int rv; progname = argv[0]; do { c = getopt(argc, argv, "f"); if (c == EOF) break; switch (c) { case 'f': f_flag = 1; break; case '?': fprintf(stderr, "%s: invalid option -%c\n", progname, optopt); usage(); } } while (1); if (optind == argc) usage(); argv += optind; while ((name = *argv++)) { if (f_flag) rv = realpath(name, link_name) ? strlen(link_name) : -1; else rv = readlink(name, link_name, sizeof link_name - 1); if (rv < 0) { perror(name); exit(1); } link_name[rv] = '\n'; _fwrite(link_name, rv+1, stdout); } return 0; } klibc-2.0.7/usr/utils/pivot_root.c0000644000175000017500000000053213546663605015235 0ustar benben/* 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; } klibc-2.0.7/usr/utils/nuke.c0000644000175000017500000000577313546663605014007 0ustar benben/* ----------------------------------------------------------------------- * * * 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. * * ----------------------------------------------------------------------- */ /* * 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 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; dir = opendir(what); if (!dir) { /* 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) rmdir(what); } } return 0; } int main(int argc, char *argv[]) { int i; program = argv[0]; for (i = 1; i < argc; i++) nuke(argv[i]); return 0; } klibc-2.0.7/usr/utils/mv.c0000644000175000017500000000220013546663605013445 0ustar benben#include #include #include #include #include #include #include int main(int argc, char *argv[]) { int c, f; char *p; struct stat sb; f = 0; do { c = getopt(argc, argv, "f"); if (c == EOF) break; switch (c) { 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 [-f] source dest\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 (rename(argv[c], target) == -1) perror(target); } return 0; } klibc-2.0.7/usr/utils/mount_opts.h0000644000175000017500000000074113546663605015247 0ustar benben#ifndef UTILS_MOUNT_OPTS_H #define UTILS_MOUNT_OPTS_H 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); #endif /* UTILS_MOUNT_OPTS_H */ klibc-2.0.7/usr/utils/mount_opts.c0000644000175000017500000000427613546663605015251 0ustar benben/* * 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}, {"nodev", MS_NODEV, MS_NODEV, 0}, {"noexec", MS_NOEXEC, MS_NOEXEC, 0}, {"nosuid", MS_NOSUID, MS_NOSUID, 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]) { if (!strcmp(opt, "defaults")) rwflag &= ~(MS_RDONLY|MS_NOSUID|MS_NODEV| MS_NOEXEC|MS_SYNCHRONOUS); else add_extra_option(extra, opt); } } return rwflag; } klibc-2.0.7/usr/utils/mount_main.c0000644000175000017500000000572013546663605015203 0ustar benben/* * by rmk */ #include #include #include #include #include #include #include #include "mount_opts.h" #define _PATH_MOUNTED "/etc/mtab" #define _PATH_PROC_MOUNTS "/proc/mounts" char *progname; static struct extra_opts extra; static unsigned long rwflag; static __noreturn usage(void) { fprintf(stderr, "Usage: %s [-r] [-w] [-o options] [-t type] [-f] [-i] " "[-n] device directory\n", progname); exit(1); } static __noreturn print_mount(char *type) { FILE *mfp; struct mntent *mnt; mfp = setmntent(_PATH_PROC_MOUNTS, "r"); if (!mfp) mfp = setmntent(_PATH_MOUNTED, "r"); if (!mfp) perror("setmntent"); while ((mnt = getmntent(mfp)) != NULL) { if (mnt->mnt_fsname && !strncmp(mnt->mnt_fsname, "no", 2)) continue; if (type && mnt->mnt_type && strcmp(type, mnt->mnt_type)) continue; printf("%s on %s", mnt->mnt_fsname, mnt->mnt_dir); if (mnt->mnt_type != NULL && *mnt->mnt_type != '\0') printf(" type %s", mnt->mnt_type); if (mnt->mnt_opts != NULL && *mnt->mnt_opts != '\0') printf(" (%s)", mnt->mnt_opts); printf("\n"); } endmntent(mfp); exit(0); } 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; } } else { error = 0; } 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, "fhino:rt:w"); if (c == EOF) break; switch (c) { case 'f': /* we can't edit /etc/mtab yet anyway; exit */ exit(0); case 'i': /* ignore for now; no support for mount helpers */ break; case 'h': usage(); case 'n': /* no mtab writing */ break; 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 (optind == argc) print_mount(type); /* * 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) usage(); return do_mount(argv[optind], argv[optind + 1], type, rwflag, extra.str); } klibc-2.0.7/usr/utils/mknod.c0000644000175000017500000000242013546663605014137 0ustar benben#include #include #include #include char *progname; static __noreturn usage(void) { fprintf(stderr, "Usage: %s [-m mode] name {b|c|p} major minor\n", progname); exit(1); } int main(int argc, char *argv[]) { char *name, *type, typec, *endp; unsigned int major_num, minor_num; mode_t mode, mode_set = 0; dev_t dev; progname = *argv++; if (argc == 1) usage(); if (argv[0][0] == '-' && argv[0][1] == 'm' && !argv[0][2]) { mode_set = strtoul(argv[1], &endp, 8); argv += 2; } name = *argv++; if (!name) usage(); type = *argv++; if (!type || !type[0] || type[1]) usage(); typec = type[0]; mode = 0; switch (typec) { case 'c': mode = S_IFCHR; break; case 'b': mode = S_IFBLK; break; case 'p': mode = S_IFIFO; break; default: usage(); } if (mode == S_IFIFO) { dev = 0; } else { if (!argv[0] || !argv[1]) usage(); major_num = strtol(*argv++, &endp, 0); if (*endp != '\0') usage(); minor_num = strtol(*argv++, &endp, 0); if (*endp != '\0') usage(); dev = makedev(major_num, minor_num); } if (*argv) usage(); if (mknod(name, mode|0666, dev) == -1) { perror("mknod"); exit(1); } if (mode_set && chmod(name, mode_set)) { perror("chmod"); exit(1); } exit(0); } klibc-2.0.7/usr/utils/mkfifo.c0000644000175000017500000000224013546663605014302 0ustar benben#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; } klibc-2.0.7/usr/utils/mkdir.c0000644000175000017500000000543513546663605014146 0ustar benben#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 __noreturn usage(void) { fprintf(stderr, "Usage: %s [-p] [-m mode] dir...\n", progname); exit(1); } 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); usage(); } } while (1); if (optind == argc) usage(); while (optind < argc) { if (make_dir(argv[optind])) ret = 255; /* seems to be what gnu mkdir does */ optind++; } return ret; } klibc-2.0.7/usr/utils/minips.c0000644000175000017500000003051613546663605014335 0ustar benben/* * 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 /* 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); fd = open(buf, O_RDONLY, 0); if (fd == -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"); if (!dir) exit(1); 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; } klibc-2.0.7/usr/utils/ls.c0000644000175000017500000001056713546663605013460 0ustar benben#include #include #include #include #include #include #include #define STAT_ISSET(mode, mask) (((mode) & mask) == mask) static size_t max_linksiz = 128; static int max_nlinks = 1; static int max_size = 1; static int max_uid = 1; static int max_gid = 1; static int max_min = 1; static int max_maj = 1; static void do_preformat(const struct stat *st) { int bytes; bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_nlink); if (bytes > max_nlinks) max_nlinks = bytes; bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_uid); if (bytes > max_uid) max_uid = bytes; bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_gid); if (bytes > max_gid) max_gid = bytes; if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { bytes = snprintf(NULL, 0, "%u", major(st->st_rdev)); if (bytes > max_maj) max_maj = bytes; bytes = snprintf(NULL, 0, "%u", minor(st->st_rdev)); if (bytes > max_min) max_min = bytes; max_size = max_maj + max_min + 1; } else { bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_size); if (bytes > max_size) max_size = bytes; } return; } static void do_stat(const struct stat *st, const char *path) { char *fmt, *link_name; int rc; switch (st->st_mode & S_IFMT) { case S_IFBLK: putchar('b'); break; case S_IFCHR: putchar('c'); break; case S_IFDIR: putchar('d'); break; case S_IFIFO: putchar('p'); break; case S_IFLNK: putchar('l'); break; case S_IFSOCK: putchar('s'); break; case S_IFREG: putchar('-'); break; default: putchar('?'); break; } putchar(STAT_ISSET(st->st_mode, S_IRUSR) ? 'r' : '-'); putchar(STAT_ISSET(st->st_mode, S_IWUSR) ? 'w' : '-'); !STAT_ISSET(st->st_mode, S_ISUID) ? putchar(STAT_ISSET(st->st_mode, S_IXUSR) ? 'x' : '-') : putchar('S'); putchar(STAT_ISSET(st->st_mode, S_IRGRP) ? 'r' : '-'); putchar(STAT_ISSET(st->st_mode, S_IWGRP) ? 'w' : '-'); !STAT_ISSET(st->st_mode, S_ISGID) ? putchar(STAT_ISSET(st->st_mode, S_IXGRP) ? 'x' : '-') : putchar('S'); putchar(STAT_ISSET(st->st_mode, S_IROTH) ? 'r' : '-'); putchar(STAT_ISSET(st->st_mode, S_IWOTH) ? 'w' : '-'); !STAT_ISSET(st->st_mode, S_ISVTX) ? putchar(STAT_ISSET(st->st_mode, S_IXOTH) ? 'x' : '-') : putchar(S_ISDIR(st->st_mode) ? 't' : 'T'); if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { rc = asprintf(&fmt, " %%%dju %%%dju %%%dju %%%du,%%%du %%s", max_nlinks, max_uid, max_gid, max_maj, max_min); if (rc == -1) { perror("asprintf"); exit(1); } fprintf(stdout, fmt, (uintmax_t) st->st_nlink, (uintmax_t) st->st_uid, (uintmax_t) st->st_gid, major(st->st_rdev), minor(st->st_rdev), path); } else { rc = asprintf(&fmt, " %%%dju %%%dju %%%dju %%%dju %%s", max_nlinks, max_uid, max_gid, max_size); if (rc == -1) { perror("asprintf"); exit(1); } fprintf(stdout, fmt, (uintmax_t) st->st_nlink, (uintmax_t) st->st_uid, (uintmax_t) st->st_gid, (uintmax_t) st->st_size, path); } free(fmt); if (S_ISLNK(st->st_mode)) { link_name = malloc(max_linksiz); if (link_name == NULL) { perror("malloc"); exit(1); } rc = readlink(path, link_name, max_linksiz); if (rc == -1) { free(link_name); perror("readlink"); exit(1); } link_name[rc] = '\0'; fprintf(stdout, " -> %s", link_name); free(link_name); } putchar('\n'); return; } static void do_dir(const char *path, int preformat) { DIR *dir; struct dirent *dent; struct stat st; if (chdir(path) == -1) { perror(path); exit(1); } dir = opendir(path); if (dir == NULL) { perror(path); exit(1); } while ((dent = readdir(dir)) != NULL) { if (lstat(dent->d_name, &st)) { perror(dent->d_name); exit(1); } (preformat) ? do_preformat(&st) : do_stat(&st, dent->d_name); } closedir(dir); } int main(int argc, char *argv[]) { int i; struct stat st; if (argc == 1) { do_dir(".", 1); do_dir(".", 0); return 0; } for (i = 1; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == 'h') { fprintf(stdout, "Usage: ls [-h] [FILE ...]\n"); return 0; } if (lstat(argv[i], &st)) { perror(argv[i]); exit(1); } S_ISDIR(st.st_mode) ? do_dir(argv[i], 1) : do_preformat(&st); } for (i = 1; i < argc; i++) { if (lstat(argv[i], &st)) { perror(argv[i]); exit(1); } S_ISDIR(st.st_mode) ? do_dir(argv[i], 0) : do_stat(&st, argv[i]); } return 0; } klibc-2.0.7/usr/utils/losetup.c0000644000175000017500000002514313546663605014531 0ustar benben/* Originally from Ted's losetup.c */ #define LOOPMAJOR 7 /* * losetup.c - setup and control loop devices */ #include #include #include #include #include #include #include #include #include #include #include #include #include "loop.h" extern int verbose; extern char *progname; extern char *xstrdup (const char *s); /* not: #include "sundries.h" */ extern void error (const char *fmt, ...); /* idem */ /* caller guarantees n > 0 */ void xstrncpy(char *dest, const char *src, size_t n) { strncpy(dest, src, n-1); dest[n-1] = 0; } static int loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info) { memset(info, 0, sizeof(*info)); info->lo_number = info64->lo_number; info->lo_device = info64->lo_device; info->lo_inode = info64->lo_inode; info->lo_rdevice = info64->lo_rdevice; info->lo_offset = info64->lo_offset; info->lo_encrypt_type = info64->lo_encrypt_type; info->lo_encrypt_key_size = info64->lo_encrypt_key_size; info->lo_flags = info64->lo_flags; info->lo_init[0] = info64->lo_init[0]; info->lo_init[1] = info64->lo_init[1]; if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI) memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE); else memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE); memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE); /* error in case values were truncated */ if (info->lo_device != info64->lo_device || info->lo_rdevice != info64->lo_rdevice || info->lo_inode != info64->lo_inode || info->lo_offset != info64->lo_offset) return -EOVERFLOW; return 0; } static int show_loop(char *device) { struct loop_info loopinfo; struct loop_info64 loopinfo64; int fd, errsv; if ((fd = open(device, O_RDONLY)) < 0) { int errsv = errno; fprintf(stderr, "loop: can't open device %s: %s\n", device, strerror (errsv)); return 2; } if (ioctl(fd, LOOP_GET_STATUS64, &loopinfo64) == 0) { loopinfo64.lo_file_name[LO_NAME_SIZE-2] = '*'; loopinfo64.lo_file_name[LO_NAME_SIZE-1] = 0; loopinfo64.lo_crypt_name[LO_NAME_SIZE-1] = 0; printf("%s: [%04llx]:%llu (%s)", device, loopinfo64.lo_device, loopinfo64.lo_inode, loopinfo64.lo_file_name); if (loopinfo64.lo_offset) printf(", offset %lld", loopinfo64.lo_offset); if (loopinfo64.lo_sizelimit) printf(", sizelimit %lld", loopinfo64.lo_sizelimit); if (loopinfo64.lo_encrypt_type || loopinfo64.lo_crypt_name[0]) { char *e = loopinfo64.lo_crypt_name; if (*e == 0 && loopinfo64.lo_encrypt_type == 1) e = "XOR"; printf(", encryption %s (type %d)", e, loopinfo64.lo_encrypt_type); } printf("\n"); close (fd); return 0; } if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) == 0) { printf ("%s: [%04x]:%ld (%s)", device, loopinfo.lo_device, loopinfo.lo_inode, loopinfo.lo_name); if (loopinfo.lo_offset) printf(", offset %d", loopinfo.lo_offset); if (loopinfo.lo_encrypt_type) printf(", encryption type %d\n", loopinfo.lo_encrypt_type); printf("\n"); close (fd); return 0; } errsv = errno; fprintf(stderr, "loop: can't get info on device %s: %s\n", device, strerror (errsv)); close (fd); return 1; } int is_loop_device (const char *device) { struct stat statbuf; return (stat(device, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) && major(statbuf.st_rdev) == LOOPMAJOR); } #define SIZE(a) (sizeof(a)/sizeof(a[0])) char * find_unused_loop_device (void) { /* Just creating a device, say in /tmp, is probably a bad idea - people might have problems with backup or so. So, we just try /dev/loop[0-7]. */ char dev[20]; char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" }; int i, j, fd, somedev = 0, someloop = 0, permission = 0; struct stat statbuf; struct loop_info loopinfo; for (j = 0; j < SIZE(loop_formats); j++) { for(i = 0; i < 256; i++) { sprintf(dev, loop_formats[j], i); if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { somedev++; fd = open (dev, O_RDONLY); if (fd >= 0) { if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0) someloop++; /* in use */ else if (errno == ENXIO) { close (fd); return xstrdup(dev);/* probably free */ } close (fd); } else if (errno == EACCES) permission++; continue;/* continue trying as long as devices exist */ } break; } } if (!somedev) error("%s: could not find any device /dev/loop#", progname); else if (!someloop && permission) error("%s: no permission to look at /dev/loop#", progname); else if (!someloop) error( "%s: Could not find any loop device. Maybe this kernel " "does not know\n" " about the loop device? (If so, recompile or " "`modprobe loop'.)", progname); else error("%s: could not find any free loop device", progname); return 0; } /* * A function to read the passphrase either from the terminal or from * an open file descriptor. */ static char * xgetpass(int pfd, const char *prompt) { char *pass; int buflen, i; pass = NULL; buflen = 0; for (i=0; ; i++) { if (i >= buflen-1) { /* we're running out of space in the buffer. * Make it bigger: */ char *tmppass = pass; buflen += 128; pass = realloc(tmppass, buflen); if (pass == NULL) { /* realloc failed. Stop reading. */ error("Out of memory while reading passphrase"); pass = tmppass; /* the old buffer hasn't changed */ break; } } if (read(pfd, pass+i, 1) != 1 || pass[i] == '\n' || pass[i] == 0) break; } if (pass == NULL) return ""; pass[i] = 0; return pass; } static int digits_only(const char *s) { while (*s) if (!isdigit(*s++)) return 0; return 1; } int set_loop(const char *device, const char *file, unsigned long long offset, const char *encryption, int pfd, int *loopro) { struct loop_info64 loopinfo64; int fd, ffd, mode, i; char *pass; mode = (*loopro ? O_RDONLY : O_RDWR); if ((ffd = open(file, mode)) < 0) { if (!*loopro && errno == EROFS) ffd = open(file, mode = O_RDONLY); if (ffd < 0) { perror(file); return 1; } } if ((fd = open(device, mode)) < 0) { perror (device); return 1; } *loopro = (mode == O_RDONLY); memset(&loopinfo64, 0, sizeof(loopinfo64)); xstrncpy(loopinfo64.lo_file_name, file, LO_NAME_SIZE); if (encryption && *encryption) { if (digits_only(encryption)) { loopinfo64.lo_encrypt_type = atoi(encryption); } else { loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI; snprintf(loopinfo64.lo_crypt_name, LO_NAME_SIZE, "%s", encryption); } } loopinfo64.lo_offset = offset; switch (loopinfo64.lo_encrypt_type) { case LO_CRYPT_NONE: loopinfo64.lo_encrypt_key_size = 0; break; case LO_CRYPT_XOR: pass = xgetpass(pfd, "Password: "); goto gotpass; default: pass = xgetpass(pfd, "Password: "); gotpass: memset(loopinfo64.lo_encrypt_key, 0, LO_KEY_SIZE); xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); memset(pass, 0, strlen(pass)); loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE; } if (ioctl(fd, LOOP_SET_FD, (void *)(size_t)ffd) < 0) { perror("ioctl: LOOP_SET_FD"); return 1; } close (ffd); i = ioctl(fd, LOOP_SET_STATUS64, &loopinfo64); if (i) { struct loop_info loopinfo; int errsv = errno; i = loop_info64_to_old(&loopinfo64, &loopinfo); if (i) { errno = errsv; perror("ioctl: LOOP_SET_STATUS64"); } else { i = ioctl(fd, LOOP_SET_STATUS, &loopinfo); if (i) perror("ioctl: LOOP_SET_STATUS"); } memset(&loopinfo, 0, sizeof(loopinfo)); } memset(&loopinfo64, 0, sizeof(loopinfo64)); if (i) { ioctl (fd, LOOP_CLR_FD, 0); close (fd); return 1; } close (fd); if (verbose > 1) printf("set_loop(%s,%s,%llu): success\n", device, file, offset); return 0; } int del_loop (const char *device) { int fd; if ((fd = open (device, O_RDONLY)) < 0) { int errsv = errno; fprintf(stderr, "loop: can't delete device %s: %s\n", device, strerror (errsv)); return 1; } if (ioctl (fd, LOOP_CLR_FD, 0) < 0) { perror ("ioctl: LOOP_CLR_FD"); close (fd); return 1; } close (fd); if (verbose > 1) printf("del_loop(%s): success\n", device); return 0; } int verbose = 0; char *progname; static void usage(FILE *f) { fprintf(f, "usage:\n\ %s loop_device # give info\n\ %s -d loop_device # delete\n\ %s -f # find unused\n\ %s -h # this help\n\ %s [-e encryption] [-o offset] {-f|loop_device} file # setup\n", progname, progname, progname, progname, progname); exit(f == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } char * xstrdup (const char *s) { char *t; if (s == NULL) return NULL; t = strdup (s); if (t == NULL) { fprintf(stderr, "not enough memory"); exit(1); } return t; } void error (const char *fmt, ...) { va_list args; va_start (args, fmt); vfprintf (stderr, fmt, args); va_end (args); fprintf (stderr, "\n"); } int main(int argc, char **argv) { char *p, *offset, *encryption, *passfd, *device, *file; int delete, find, c; int res = 0; int ro = 0; int pfd = -1; unsigned long long off; delete = find = 0; off = 0; offset = encryption = passfd = NULL; progname = argv[0]; if ((p = strrchr(progname, '/')) != NULL) progname = p+1; while ((c = getopt(argc, argv, "de:E:fho:p:v")) != -1) { switch (c) { case 'd': delete = 1; break; case 'E': case 'e': encryption = optarg; break; case 'f': find = 1; break; case 'h': usage(stdout); break; case 'o': offset = optarg; break; case 'p': passfd = optarg; break; case 'v': verbose = 1; break; default: usage(stderr); } } if (argc == 1) { usage(stderr); } else if (delete) { if (argc != optind+1 || encryption || offset || find) usage(stderr); } else if (find) { if (argc < optind || argc > optind+1) usage(stderr); } else { if (argc < optind+1 || argc > optind+2) usage(stderr); } if (find) { device = find_unused_loop_device(); if (device == NULL) return -1; if (verbose) printf("Loop device is %s\n", device); if (argc == optind) { printf("%s\n", device); return 0; } file = argv[optind]; } else { device = argv[optind]; if (argc == optind+1) file = NULL; else file = argv[optind+1]; } if (delete) res = del_loop(device); else if (file == NULL) res = show_loop(device); else { if (offset && sscanf(offset, "%llu", &off) != 1) usage(stderr); if (passfd && sscanf(passfd, "%d", &pfd) != 1) usage(stderr); res = set_loop(device, file, off, encryption, pfd, &ro); } return res; } klibc-2.0.7/usr/utils/loop.h0000644000175000017500000000236113546663605014011 0ustar benben#define LO_CRYPT_NONE 0 #define LO_CRYPT_XOR 1 #define LO_CRYPT_DES 2 #define LO_CRYPT_CRYPTOAPI 18 #define LOOP_SET_FD 0x4C00 #define LOOP_CLR_FD 0x4C01 #define LOOP_SET_STATUS 0x4C02 #define LOOP_GET_STATUS 0x4C03 #define LOOP_SET_STATUS64 0x4C04 #define LOOP_GET_STATUS64 0x4C05 #define LO_NAME_SIZE 64 #define LO_KEY_SIZE 32 struct loop_info { int lo_number; dev_t lo_device; unsigned long lo_inode; dev_t lo_rdevice; int lo_offset; int lo_encrypt_type; int lo_encrypt_key_size; int lo_flags; char lo_name[LO_NAME_SIZE]; unsigned char lo_encrypt_key[LO_KEY_SIZE]; unsigned long lo_init[2]; char reserved[4]; }; /* * Where to get __u8, __u32, __u64? Let us use unsigned char/int/long long * and get punished when someone comes with 128-bit long longs. */ struct loop_info64 { unsigned long long lo_device; unsigned long long lo_inode; unsigned long long lo_rdevice; unsigned long long lo_offset; unsigned long long lo_sizelimit; /* bytes, 0 == max available */ unsigned int lo_number; unsigned int lo_encrypt_type; unsigned int lo_encrypt_key_size; unsigned int lo_flags; char lo_file_name[LO_NAME_SIZE]; char lo_crypt_name[LO_NAME_SIZE]; char lo_encrypt_key[LO_KEY_SIZE]; unsigned long long lo_init[2]; }; klibc-2.0.7/usr/utils/ln.c0000644000175000017500000000240213546663605013440 0ustar benben#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; } klibc-2.0.7/usr/utils/kill.c0000644000175000017500000000072013546663605013763 0ustar benben#include #include #include #include char *progname; static __noreturn usage(void) { fprintf(stderr, "Usage: %s pid\n", progname); exit(1); } int main(int argc, char *argv[]) { long pid; char *endp; progname = argv[0]; if (argc != 2) usage(); pid = strtol(argv[1], &endp, 10); if (*endp != '\0') { perror("pid"); usage(); } if (kill(pid, SIGTERM) == -1) { perror("kill"); exit(-1); } exit(0); } klibc-2.0.7/usr/utils/halt.c0000644000175000017500000000251113546663605013760 0ustar benben#include #include #include #include #include static __noreturn usage(void) { static char mesg[] = "Usage: {halt|reboot|poweroff} [-n] [reboot-arg]\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; char *reboot_arg = NULL; /* 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) if (**argv == '-') { switch (*++*argv) { case 'f': break; /* -f assumed */ case 'n': do_sync = 0; break; default: usage(); } } else if (cmd == LINUX_REBOOT_CMD_RESTART) { reboot_arg = *argv; cmd = LINUX_REBOOT_CMD_RESTART2; } else { usage(); /* args, not reboot == error */ } if (do_sync) sync(); reboot(LINUX_REBOOT_CMD_CAD_OFF, NULL); /* Enable CTRL+ALT+DEL */ if (!reboot(cmd, reboot_arg)) { /* Success. Currently, CMD_HALT returns, so stop the world */ /* kill(-1, SIGSTOP); */ kill(getpid(), SIGSTOP); } write(2, "failed.\n", 8); return 1; } klibc-2.0.7/usr/utils/file_mode.h0000644000175000017500000000022413546663605014757 0ustar benben#ifndef UTILS_FILE_MODE_H #define UTILS_FILE_MODE_H mode_t parse_file_mode(char *arg, mode_t mode, mode_t sumask); #endif /* UTILS_FILE_MODE_H */ klibc-2.0.7/usr/utils/file_mode.c0000644000175000017500000000467413546663605014767 0ustar benben#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; } klibc-2.0.7/usr/utils/false.c0000644000175000017500000000003613546663605014122 0ustar benbenint main(void) { return 1; } klibc-2.0.7/usr/utils/dmesg.c0000644000175000017500000000227113546663605014132 0ustar benben#include #include #include #include #include static void usage(char *name) { fprintf(stderr, "usage: %s [-c]\n", name); } int main(int argc, char *argv[]) { char *buf = NULL; const char *p; int c; int bufsz = 0; int cmd = 3; /* Read all messages remaining in the ring buffer */ int len = 0; int opt; int newline; while ((opt = getopt(argc, argv, "c")) != -1) { switch (opt) { /* Read and clear all messages remaining in the ring buffer */ case 'c': cmd = 4; break; case '?': default: usage(argv[0]); exit(1); } } if (!bufsz) { len = klogctl(10, NULL, 0); /* Get size of log buffer */ if (len > 0) bufsz = len; } if (bufsz) { int sz = bufsz + 8; buf = (char *)malloc(sz); len = klogctl(cmd, buf, sz); } if (len < 0) { perror("klogctl"); exit(1); } newline = 1; p = buf; while ((c = *p)) { switch (c) { case '\n': newline = 1; putchar(c); p++; break; case '<': if (newline && isdigit(p[1]) && p[2] == '>') { p += 3; break; } /* else fall through */ default: newline = 0; putchar(c); p++; } } if (!newline) putchar('\n'); return 0; } klibc-2.0.7/usr/utils/dd.c0000644000175000017500000002371313546663605013426 0ustar benben#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"); close(rd_fd); return 1; } } /* * Skip obs-sized blocks of output file. */ if (OPT_SEEK->str && skip_blocks(wr_fd, out_buf, seek, obs)) { close(rd_fd); close(wr_fd); return 1; } /* * Skip ibs-sized blocks of input file. */ if (OPT_SKIP->str && skip_blocks(rd_fd, in_buf, skip, ibs)) { close(rd_fd); close(wr_fd); 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; } klibc-2.0.7/usr/utils/cpio.c0000644000175000017500000007600513546663605013773 0ustar benben/* copyin.c - extract or list a cpio archive Copyright (C) 1990,1991,1992,2001,2002,2003,2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include # ifndef DIRECTORY_SEPARATOR # define DIRECTORY_SEPARATOR '/' # endif # ifndef ISSLASH # define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) # endif /* Return 1 if an array of N objects, each of size S, cannot exist due to size arithmetic overflow. S must be positive and N must be nonnegative. This is a macro, not an inline function, so that it works correctly even when SIZE_MAX < N. By gnulib convention, SIZE_MAX represents overflow in size calculations, so the conservative dividend to use here is SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. However, malloc (SIZE_MAX) fails on all known hosts where sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for exactly-SIZE_MAX allocations on such hosts; this avoids a test and branch when S is known to be 1. */ # define xalloc_oversized(n, s) \ ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) #define DISK_IO_BLOCK_SIZE (512) char *progname = NULL; /* If true, print a . for each file processed. (-V) */ char dot_flag = false; /* Input and output buffers. */ char *input_buffer, *output_buffer; /* The size of the input buffer. */ long input_buffer_size; /* Current locations in `input_buffer' and `output_buffer'. */ char *in_buff, *out_buff; /* Current number of bytes stored at `input_buff' and `output_buff'. */ long input_size, output_size; /* Block size value, initially 512. -B sets to 5120. */ int io_block_size = 512; struct new_cpio_header { unsigned short c_magic; union { struct { unsigned long c_ino; unsigned long c_mode; unsigned long c_uid; unsigned long c_gid; unsigned long c_nlink; unsigned long c_mtime; unsigned long c_filesize; long c_dev_maj; long c_dev_min; long c_rdev_maj; long c_rdev_min; unsigned long c_namesize; unsigned long c_chksum; }; unsigned long c_hdr[13]; }; char *c_name; char *c_tar_linkname; }; /* Total number of bytes read and written for all files. * Now that many tape drives hold more than 4Gb we need more than 32 * bits to hold input_bytes and output_bytes. */ long long input_bytes, output_bytes; /* Allocate N bytes of memory dynamically, with error checking. */ static void *xmalloc(size_t n) { void *p; if (xalloc_oversized(n, 1) || (!(p = malloc(n)) && n != 0)) { fprintf(stderr, "%s: memory exhausted\n", progname); exit(1); } return p; /* return xnmalloc_inline (n, 1); */ } /* Clone STRING. */ static char *xstrdup(char const *string) { size_t s = strlen(string) + 1; return memcpy(xmalloc(s), string, s); /* return xmemdup_inline (string, strlen (string) + 1); */ } /* Copy NUM_BYTES of buffer `in_buff' into IN_BUF. `in_buff' may be partly full. When `in_buff' is exhausted, refill it from file descriptor IN_DES. */ static void tape_fill_input_buffer(int in_des, int num_bytes) { in_buff = input_buffer; num_bytes = (num_bytes < io_block_size) ? num_bytes : io_block_size; input_size = read(in_des, input_buffer, num_bytes); if (input_size < 0) { fprintf(stderr, "%s: read error: %s\n", progname, strerror(errno)); exit(1); } if (input_size == 0) { fprintf(stderr, "%s: premature end of file\n", progname); exit(1); } input_bytes += input_size; } /* Write `output_size' bytes of `output_buffer' to file descriptor OUT_DES and reset `output_size' and `out_buff'. If `swapping_halfwords' or `swapping_bytes' is set, do the appropriate swapping first. Our callers have to make sure to only set these flags if `output_size' is appropriate (a multiple of 4 for `swapping_halfwords', 2 for `swapping_bytes'). The fact that DISK_IO_BLOCK_SIZE must always be a multiple of 4 helps us (and our callers) insure this. */ static void disk_empty_output_buffer(int out_des) { int bytes_written; bytes_written = write(out_des, output_buffer, output_size); if (bytes_written != output_size) { fprintf(stderr, "%s: write error: %s\n", progname, strerror(errno)); exit(1); } output_bytes += output_size; out_buff = output_buffer; output_size = 0; } /* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full. When `out_buff' fills up, flush it to file descriptor OUT_DES. */ static void disk_buffered_write(char *in_buf, int out_des, long num_bytes) { register long bytes_left = num_bytes; /* Bytes needing to be copied. */ register long space_left; /* Room left in output buffer. */ while (bytes_left > 0) { space_left = DISK_IO_BLOCK_SIZE - output_size; if (space_left == 0) disk_empty_output_buffer(out_des); else { if (bytes_left < space_left) space_left = bytes_left; memmove(out_buff, in_buf, (unsigned)space_left); out_buff += space_left; output_size += space_left; in_buf += space_left; bytes_left -= space_left; } } } /* Copy a file using the input and output buffers, which may start out partly full. After the copy, the files are not closed nor the last block flushed to output, and the input buffer may still be partly full. If `crc_i_flag' is set, add each byte to `crc'. IN_DES is the file descriptor for input; OUT_DES is the file descriptor for output; NUM_BYTES is the number of bytes to copy. */ static void copy_files_tape_to_disk(int in_des, int out_des, long num_bytes) { long size; while (num_bytes > 0) { if (input_size == 0) tape_fill_input_buffer(in_des, io_block_size); size = (input_size < num_bytes) ? input_size : num_bytes; disk_buffered_write(in_buff, out_des, size); num_bytes -= size; input_size -= size; in_buff += size; } } /* if IN_BUF is NULL, Skip the next NUM_BYTES bytes of file descriptor IN_DES. */ static void tape_buffered_read(char *in_buf, int in_des, long num_bytes) { register long bytes_left = num_bytes; /* Bytes needing to be copied. */ register long space_left; /* Bytes to copy from input buffer. */ while (bytes_left > 0) { if (input_size == 0) tape_fill_input_buffer(in_des, io_block_size); if (bytes_left < input_size) space_left = bytes_left; else space_left = input_size; if (in_buf != NULL) { memmove(in_buf, in_buff, (unsigned)space_left); in_buf += space_left; } in_buff += space_left; input_size -= space_left; bytes_left -= space_left; } } /* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */ #define tape_toss_input(in_des,num_bytes) \ (tape_buffered_read(NULL,(in_des),(num_bytes))) struct deferment { struct deferment *next; struct new_cpio_header header; }; static struct deferment *create_deferment(struct new_cpio_header *file_hdr) { struct deferment *d; d = (struct deferment *)xmalloc(sizeof(struct deferment)); d->header = *file_hdr; d->header.c_name = (char *)xmalloc(strlen(file_hdr->c_name) + 1); strcpy(d->header.c_name, file_hdr->c_name); return d; } static void free_deferment(struct deferment *d) { free(d->header.c_name); free(d); } static int link_to_name(char *link_name, char *link_target) { int res = link(link_target, link_name); return res; } struct inode_val { unsigned long inode; unsigned long major_num; unsigned long minor_num; char *file_name; }; /* Inode hash table. Allocated by first call to add_inode. */ static struct inode_val **hash_table = NULL; /* Size of current hash table. Initial size is 47. (47 = 2*22 + 3) */ static int hash_size = 22; /* Number of elements in current hash table. */ static int hash_num; /* Do the hash insert. Used in normal inserts and resizing the hash table. It is guaranteed that there is room to insert the item. NEW_VALUE is the pointer to the previously allocated inode, file name association record. */ static void hash_insert(struct inode_val *new_value) { int start; /* Home position for the value. */ int temp; /* Used for rehashing. */ /* Hash function is node number modulo the table size. */ start = new_value->inode % hash_size; /* Do the initial look into the table. */ if (hash_table[start] == NULL) { hash_table[start] = new_value; return; } /* If we get to here, the home position is full with a different inode record. Do a linear search for the first NULL pointer and insert the new item there. */ temp = (start + 1) % hash_size; while (hash_table[temp] != NULL) temp = (temp + 1) % hash_size; /* Insert at the NULL. */ hash_table[temp] = new_value; } /* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */ static void add_inode(unsigned long node_num, char *file_name, unsigned long major_num, unsigned long minor_num) { struct inode_val *temp; /* Create new inode record. */ temp = (struct inode_val *)xmalloc(sizeof(struct inode_val)); temp->inode = node_num; temp->major_num = major_num; temp->minor_num = minor_num; temp->file_name = xstrdup(file_name); /* Do we have to increase the size of (or initially allocate) the hash table? */ if (hash_num == hash_size || hash_table == NULL) { struct inode_val **old_table; /* Pointer to old table. */ int i; /* Index for re-insert loop. */ /* Save old table. */ old_table = hash_table; if (old_table == NULL) hash_num = 0; /* Calculate new size of table and allocate it. Sequence of table sizes is 47, 97, 197, 397, 797, 1597, 3197, 6397 ... where 3197 and most of the sizes after 6397 are not prime. The other numbers listed are prime. */ hash_size = 2 * hash_size + 3; hash_table = (struct inode_val **) xmalloc(hash_size * sizeof(struct inode_val *)); memset(hash_table, 0, hash_size * sizeof(struct inode_val *)); /* Insert the values from the old table into the new table. */ for (i = 0; i < hash_num; i++) hash_insert(old_table[i]); free(old_table); } /* Insert the new record and increment the count of elements in the hash table. */ hash_insert(temp); hash_num++; } static char *find_inode_file(unsigned long node_num, unsigned long major_num, unsigned long minor_num) { int start; /* Initial hash location. */ int temp; /* Rehash search variable. */ if (hash_table != NULL) { /* Hash function is node number modulo the table size. */ start = node_num % hash_size; /* Initial look into the table. */ if (hash_table[start] == NULL) return NULL; if (hash_table[start]->inode == node_num && hash_table[start]->major_num == major_num && hash_table[start]->minor_num == minor_num) return hash_table[start]->file_name; /* The home position is full with a different inode record. Do a linear search terminated by a NULL pointer. */ for (temp = (start + 1) % hash_size; hash_table[temp] != NULL && temp != start; temp = (temp + 1) % hash_size) { if (hash_table[temp]->inode == node_num && hash_table[start]->major_num == major_num && hash_table[start]->minor_num == minor_num) return hash_table[temp]->file_name; } } return NULL; } /* Try and create a hard link from FILE_NAME to another file with the given major/minor device number and inode. If no other file with the same major/minor/inode numbers is known, add this file to the list of known files and associated major/minor/inode numbers and return -1. If another file with the same major/minor/inode numbers is found, try and create another link to it using link_to_name, and return 0 for success and -1 for failure. */ static int link_to_maj_min_ino(char *file_name, int st_dev_maj, int st_dev_min, int st_ino) { int link_res; char *link_name; link_res = -1; /* Is the file a link to a previously copied file? */ link_name = find_inode_file(st_ino, st_dev_maj, st_dev_min); if (link_name == NULL) add_inode(st_ino, file_name, st_dev_maj, st_dev_min); else link_res = link_to_name(file_name, link_name); return link_res; } static void copyin_regular_file(struct new_cpio_header *file_hdr, int in_file_des); static void warn_junk_bytes(long bytes_skipped) { fprintf(stderr, "%s: warning: skipped %ld byte(s) of junk\n", progname, bytes_skipped); } /* Skip the padding on IN_FILE_DES after a header or file, up to the next header. The number of bytes skipped is based on OFFSET -- the current offset from the last start of a header (or file) -- and the current header type. */ static void tape_skip_padding(int in_file_des, int offset) { int pad; pad = (4 - (offset % 4)) % 4; if (pad != 0) tape_toss_input(in_file_des, pad); } static int try_existing_file(struct new_cpio_header *file_hdr, int in_file_des, int *existing_dir) { struct stat file_stat; *existing_dir = false; if (lstat(file_hdr->c_name, &file_stat) == 0) { if (S_ISDIR(file_stat.st_mode) && ((file_hdr->c_mode & S_IFMT) == S_IFDIR)) { /* If there is already a directory there that we are trying to create, don't complain about it. */ *existing_dir = true; return 0; } else if (S_ISDIR(file_stat.st_mode) ? rmdir(file_hdr->c_name) : unlink(file_hdr->c_name)) { fprintf(stderr, "%s: cannot remove current %s: %s\n", progname, file_hdr->c_name, strerror(errno)); tape_toss_input(in_file_des, file_hdr->c_filesize); tape_skip_padding(in_file_des, file_hdr->c_filesize); return -1; /* Go to the next file. */ } } return 0; } /* The newc and crc formats store multiply linked copies of the same file in the archive only once. The actual data is attached to the last link in the archive, and the other links all have a filesize of 0. When a file in the archive has multiple links and a filesize of 0, its data is probably "attatched" to another file in the archive, so we can't create it right away. We have to "defer" creating it until we have created the file that has the data "attatched" to it. We keep a list of the "defered" links on deferments. */ struct deferment *deferments = NULL; /* Add a file header to the deferments list. For now they all just go on one list, although we could optimize this if necessary. */ static void defer_copyin(struct new_cpio_header *file_hdr) { struct deferment *d; d = create_deferment(file_hdr); d->next = deferments; deferments = d; return; } /* We just created a file that (probably) has some other links to it which have been defered. Go through all of the links on the deferments list and create any which are links to this file. */ static void create_defered_links(struct new_cpio_header *file_hdr) { struct deferment *d; struct deferment *d_prev; int ino; int maj; int min; int link_res; ino = file_hdr->c_ino; maj = file_hdr->c_dev_maj; min = file_hdr->c_dev_min; d = deferments; d_prev = NULL; while (d != NULL) { if ((d->header.c_ino == ino) && (d->header.c_dev_maj == maj) && (d->header.c_dev_min == min)) { struct deferment *d_free; link_res = link_to_name(d->header.c_name, file_hdr->c_name); if (link_res < 0) { fprintf(stderr, "%s: cannot link %s to %s: %s\n", progname, d->header.c_name, file_hdr->c_name, strerror(errno)); } if (d_prev != NULL) d_prev->next = d->next; else deferments = d->next; d_free = d; d = d->next; free_deferment(d_free); } else { d_prev = d; d = d->next; } } } /* If we had a multiply linked file that really was empty then we would have defered all of its links, since we never found any with data "attached", and they will still be on the deferment list even when we are done reading the whole archive. Write out all of these empty links that are still on the deferments list. */ static void create_final_defers(void) { struct deferment *d; int link_res; int out_file_des; struct utimbuf times; /* For setting file times. */ /* Initialize this in case it has members we don't know to set. */ memset(×, 0, sizeof(struct utimbuf)); for (d = deferments; d != NULL; d = d->next) { /* Debian hack: A line, which could cause an endless loop, was removed (97/1/2). It was reported by Ronald F. Guilmette to the upstream maintainers. -BEM */ /* Debian hack: This was reported by Horst Knobloch. This bug has been reported to "bug-gnu-utils@prep.ai.mit.edu". (99/1/6) -BEM */ link_res = link_to_maj_min_ino(d->header.c_name, d->header.c_dev_maj, d->header.c_dev_min, d->header.c_ino); if (link_res == 0) { continue; } out_file_des = open(d->header.c_name, O_CREAT | O_WRONLY, 0600); if (out_file_des < 0) { fprintf(stderr, "%s: open %s: %s\n", progname, d->header.c_name, strerror(errno)); continue; } /* File is now copied; set attributes. */ if ((fchown(out_file_des, d->header.c_uid, d->header.c_gid) < 0) && errno != EPERM) fprintf(stderr, "%s: fchown %s: %s\n", progname, d->header.c_name, strerror(errno)); /* chown may have turned off some permissions we wanted. */ if (fchmod(out_file_des, (int)d->header.c_mode) < 0) fprintf(stderr, "%s: fchmod %s: %s\n", progname, d->header.c_name, strerror(errno)); if (close(out_file_des) < 0) fprintf(stderr, "%s: close %s: %s\n", progname, d->header.c_name, strerror(errno)); } } static void copyin_regular_file(struct new_cpio_header *file_hdr, int in_file_des) { int out_file_des; /* Output file descriptor. */ /* Can the current file be linked to a previously copied file? */ if (file_hdr->c_nlink > 1) { int link_res; if (file_hdr->c_filesize == 0) { /* The newc and crc formats store multiply linked copies of the same file in the archive only once. The actual data is attached to the last link in the archive, and the other links all have a filesize of 0. Since this file has multiple links and a filesize of 0, its data is probably attatched to another file in the archive. Save the link, and process it later when we get the actual data. We can't just create it with length 0 and add the data later, in case the file is readonly. We still lose if its parent directory is readonly (and we aren't running as root), but there's nothing we can do about that. */ defer_copyin(file_hdr); tape_toss_input(in_file_des, file_hdr->c_filesize); tape_skip_padding(in_file_des, file_hdr->c_filesize); return; } /* If the file has data (filesize != 0), then presumably any other links have already been defer_copyin'ed(), but GNU cpio version 2.0-2.2 didn't do that, so we still have to check for links here (and also in case the archive was created and later appeneded to). */ /* Debian hack: (97/1/2) This was reported by Ronald F. Guilmette to the upstream maintainers. -BEM */ link_res = link_to_maj_min_ino(file_hdr->c_name, file_hdr->c_dev_maj, file_hdr->c_dev_min, file_hdr->c_ino); if (link_res == 0) { tape_toss_input(in_file_des, file_hdr->c_filesize); tape_skip_padding(in_file_des, file_hdr->c_filesize); return; } } /* If not linked, copy the contents of the file. */ out_file_des = open(file_hdr->c_name, O_CREAT | O_WRONLY, 0600); if (out_file_des < 0) { fprintf(stderr, "%s: open %s: %s\n", progname, file_hdr->c_name, strerror(errno)); tape_toss_input(in_file_des, file_hdr->c_filesize); tape_skip_padding(in_file_des, file_hdr->c_filesize); return; } copy_files_tape_to_disk(in_file_des, out_file_des, file_hdr->c_filesize); disk_empty_output_buffer(out_file_des); if (close(out_file_des) < 0) fprintf(stderr, "%s: close %s: %s\n", progname, file_hdr->c_name, strerror(errno)); /* File is now copied; set attributes. */ if ((chown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0) && errno != EPERM) fprintf(stderr, "%s: chown %s: %s\n", progname, file_hdr->c_name, strerror(errno)); /* chown may have turned off some permissions we wanted. */ if (chmod(file_hdr->c_name, (int)file_hdr->c_mode) < 0) fprintf(stderr, "%s: chmod %s: %s\n", progname, file_hdr->c_name, strerror(errno)); tape_skip_padding(in_file_des, file_hdr->c_filesize); if (file_hdr->c_nlink > 1) { /* (see comment above for how the newc and crc formats store multiple links). Now that we have the data for this file, create any other links to it which we defered. */ create_defered_links(file_hdr); } } /* In general, we can't use the builtin `basename' function if available, since it has different meanings in different environments. In some environments the builtin `basename' modifies its argument. Return the address of the last file name component of NAME. If NAME has no file name components because it is all slashes, return NAME if it is empty, the address of its last slash otherwise. */ static char *base_name(char const *name) { char const *base = name; char const *p; for (p = base; *p; p++) { if (ISSLASH(*p)) { /* Treat multiple adjacent slashes like a single slash. */ do p++; while (ISSLASH(*p)); /* If the file name ends in slash, use the trailing slash as the basename if no non-slashes have been found. */ if (!*p) { if (ISSLASH(*base)) base = p - 1; break; } /* *P is a non-slash preceded by a slash. */ base = p; } } return (char *)base; } /* Return the length of of the basename NAME. Typically NAME is the value returned by base_name. Act like strlen (NAME), except omit redundant trailing slashes. */ static size_t base_len(char const *name) { size_t len; for (len = strlen(name); 1 < len && ISSLASH(name[len - 1]); len--) continue; return len; } /* Remove trailing slashes from PATH. Return true if a trailing slash was removed. This is useful when using filename completion from a shell that adds a "/" after directory names (such as tcsh and bash), because the Unix rename and rmdir system calls return an "Invalid argument" error when given a path that ends in "/" (except for the root directory). */ static bool strip_trailing_slashes(char *path) { char *base = base_name(path); char *base_lim = base + base_len(base); bool had_slash = (*base_lim != '\0'); *base_lim = '\0'; return had_slash; } static void copyin_directory(struct new_cpio_header *file_hdr, int existing_dir) { int res; /* Result of various function calls. */ /* Strip any trailing `/'s off the filename; tar puts them on. We might as well do it here in case anybody else does too, since they cause strange things to happen. */ strip_trailing_slashes(file_hdr->c_name); /* Ignore the current directory. It must already exist, and we don't want to change its permission, ownership or time. */ if (file_hdr->c_name[0] == '.' && file_hdr->c_name[1] == '\0') { return; } if (!existing_dir) { res = mkdir(file_hdr->c_name, file_hdr->c_mode); } else res = 0; if (res < 0) { /* In some odd cases where the file_hdr->c_name includes `.', the directory may have actually been created by create_all_directories(), so the mkdir will fail because the directory exists. If that's the case, don't complain about it. */ struct stat file_stat; if ((errno != EEXIST) || (lstat(file_hdr->c_name, &file_stat) != 0) || !(S_ISDIR(file_stat.st_mode))) { fprintf(stderr, "%s: lstat %s: %s\n", progname, file_hdr->c_name, strerror(errno)); return; } } if ((chown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0) && errno != EPERM) fprintf(stderr, "%s: chown %s: %s\n", progname, file_hdr->c_name, strerror(errno)); /* chown may have turned off some permissions we wanted. */ if (chmod(file_hdr->c_name, (int)file_hdr->c_mode) < 0) fprintf(stderr, "%s: chmod %s: %s\n", progname, file_hdr->c_name, strerror(errno)); } static void copyin_device(struct new_cpio_header *file_hdr) { int res; /* Result of various function calls. */ if (file_hdr->c_nlink > 1) { int link_res; /* Debian hack: This was reported by Horst Knobloch. This bug has been reported to "bug-gnu-utils@prep.ai.mit.edu". (99/1/6) -BEM */ link_res = link_to_maj_min_ino(file_hdr->c_name, file_hdr->c_dev_maj, file_hdr->c_dev_min, file_hdr->c_ino); if (link_res == 0) { return; } } res = mknod(file_hdr->c_name, file_hdr->c_mode, makedev(file_hdr->c_rdev_maj, file_hdr->c_rdev_min)); if (res < 0) { fprintf(stderr, "%s: mknod %s: %s\n", progname, file_hdr->c_name, strerror(errno)); return; } if ((chown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0) && errno != EPERM) fprintf(stderr, "%s: chown %s: %s\n", progname, file_hdr->c_name, strerror(errno)); /* chown may have turned off some permissions we wanted. */ if (chmod(file_hdr->c_name, file_hdr->c_mode) < 0) fprintf(stderr, "%s: chmod %s: %s\n", progname, file_hdr->c_name, strerror(errno)); } static void copyin_link(struct new_cpio_header *file_hdr, int in_file_des) { char *link_name = NULL; /* Name of hard and symbolic links. */ int res; /* Result of various function calls. */ link_name = (char *)xmalloc((unsigned int)file_hdr->c_filesize + 1); link_name[file_hdr->c_filesize] = '\0'; tape_buffered_read(link_name, in_file_des, file_hdr->c_filesize); tape_skip_padding(in_file_des, file_hdr->c_filesize); res = symlink(link_name, file_hdr->c_name); if (res < 0) { fprintf(stderr, "%s: symlink %s: %s\n", progname, file_hdr->c_name, strerror(errno)); free(link_name); return; } if ((lchown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0) && errno != EPERM) { fprintf(stderr, "%s: lchown %s: %s\n", progname, file_hdr->c_name, strerror(errno)); } free(link_name); } static void copyin_file(struct new_cpio_header *file_hdr, int in_file_des) { int existing_dir; if (try_existing_file(file_hdr, in_file_des, &existing_dir) < 0) return; /* Do the real copy or link. */ switch (file_hdr->c_mode & S_IFMT) { case S_IFREG: copyin_regular_file(file_hdr, in_file_des); break; case S_IFDIR: copyin_directory(file_hdr, existing_dir); break; case S_IFCHR: case S_IFBLK: case S_IFSOCK: case S_IFIFO: copyin_device(file_hdr); break; case S_IFLNK: copyin_link(file_hdr, in_file_des); break; default: fprintf(stderr, "%s: %s: unknown file type\n", progname, file_hdr->c_name); tape_toss_input(in_file_des, file_hdr->c_filesize); tape_skip_padding(in_file_des, file_hdr->c_filesize); } } /* Fill in FILE_HDR by reading a new-format ASCII format cpio header from file descriptor IN_DES, except for the magic number, which is already filled in. */ static void read_in_new_ascii(struct new_cpio_header *file_hdr, int in_des) { char ascii_header[13*8], *ah, hexbuf[9]; int i; tape_buffered_read(ascii_header, in_des, 13*8); ah = ascii_header; hexbuf[8] = '\0'; for (i = 0; i < 13; i++) { memcpy(hexbuf, ah, 8); file_hdr->c_hdr[i] = strtoul(hexbuf, NULL, 16); ah += 8; } /* Read file name from input. */ free(file_hdr->c_name); file_hdr->c_name = (char *)xmalloc(file_hdr->c_namesize); tape_buffered_read(file_hdr->c_name, in_des, (long)file_hdr->c_namesize); /* In SVR4 ASCII format, the amount of space allocated for the header is rounded up to the next long-word, so we might need to drop 1-3 bytes. */ tape_skip_padding(in_des, file_hdr->c_namesize + 110); } /* Return 16-bit integer I with the bytes swapped. */ #define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff)) /* Read the header, including the name of the file, from file descriptor IN_DES into FILE_HDR. */ static void read_in_header(struct new_cpio_header *file_hdr, int in_des) { long bytes_skipped = 0; /* Bytes of junk found before magic number. */ /* Search for a valid magic number. */ file_hdr->c_tar_linkname = NULL; tape_buffered_read((char *)file_hdr, in_des, 6L); while (1) { if (!strncmp((char *)file_hdr, "070702", 6) || !strncmp((char *)file_hdr, "070701", 6)) { if (bytes_skipped > 0) warn_junk_bytes(bytes_skipped); read_in_new_ascii(file_hdr, in_des); break; } bytes_skipped++; memmove((char *)file_hdr, (char *)file_hdr + 1, 5); tape_buffered_read((char *)file_hdr + 5, in_des, 1L); } } /* Read the collection from standard input and create files in the file system. */ static void process_copy_in(void) { char done = false; /* True if trailer reached. */ struct new_cpio_header file_hdr; /* Output header information. */ int in_file_des; /* Input file descriptor. */ /* Initialize the copy in. */ file_hdr.c_name = NULL; /* only from stdin */ in_file_des = 0; /* While there is more input in the collection, process the input. */ while (!done) { /* Start processing the next file by reading the header. */ read_in_header(&file_hdr, in_file_des); /* Is this the header for the TRAILER file? */ if (strcmp("TRAILER!!!", file_hdr.c_name) == 0) { done = true; break; } /* Copy the input file into the directory structure. */ copyin_file(&file_hdr, in_file_des); if (dot_flag) fputc('.', stderr); } if (dot_flag) fputc('\n', stderr); create_final_defers(); } /* Initialize the input and output buffers to their proper size and initialize all variables associated with the input and output buffers. */ static void initialize_buffers(void) { int in_buf_size, out_buf_size; /* Make sure the input buffer can always hold 2 blocks and that it is big enough to hold 1 tar record (512 bytes) even if it is not aligned on a block boundary. The extra buffer space is needed by process_copyin and peek_in_buf to automatically figure out what kind of archive it is reading. */ if (io_block_size >= 512) in_buf_size = 2 * io_block_size; else in_buf_size = 1024; out_buf_size = DISK_IO_BLOCK_SIZE; input_buffer = (char *)xmalloc(in_buf_size); in_buff = input_buffer; input_buffer_size = in_buf_size; input_size = 0; input_bytes = 0; output_buffer = (char *)xmalloc(out_buf_size); out_buff = output_buffer; output_size = 0; output_bytes = 0; } int main(int argc, char *argv[]) { int c; int extract_flag = false; progname = argv[0]; do { c = getopt(argc, argv, "iV"); if (c == EOF) break; switch (c) { case 'V': dot_flag = true; break; case 'i': extract_flag = true; break; case '?': fprintf(stderr, "%s: not implemented or invalid option -%c\n", progname, optopt); exit(1); } } while (1); if (extract_flag) { initialize_buffers(); process_copy_in(); } else { fprintf(stderr, "Usage: %s [-V] -i [< archive]\n", progname); exit(1); } return 0; } klibc-2.0.7/usr/utils/chroot.c0000644000175000017500000000064013546663605014327 0ustar benben/* * 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 (chdir("/") == -1) { perror("chdir"); return 1; } if (execvp(argv[2], argv + 2) == -1) { perror("execvp"); return 1; } return 0; } klibc-2.0.7/usr/utils/cat.c0000644000175000017500000001512413546663605013603 0ustar benben/* $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 !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 #include #include #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; 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': /* unimplemented */ 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; } } klibc-2.0.7/usr/utils/Kbuild0000644000175000017500000000500513546663605014022 0ustar benben# # Kbuild file for klib utils # progs := chroot dd mkdir mkfifo mknod mount pivot_root umount progs += true false sleep ln mv nuke minips cat ls losetup progs += uname halt kill readlink cpio sync dmesg 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/dmesg-y := dmesg.o shared/dmesg-y := dmesg.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/ls-y := ls.o shared/ls-y := ls.o static/mv-y := mv.o shared/mv-y := mv.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/uname-y := uname.o shared/uname-y := uname.o static/halt-y := halt.o shared/halt-y := halt.o static/kill-y := kill.o shared/kill-y := kill.o static/readlink-y := readlink.o shared/readlink-y := readlink.o static/cpio-y := cpio.o shared/cpio-y := cpio.o static/sync-y := sync.o shared/sync-y := sync.o static/losetup-y := losetup.o shared/losetup-y := losetup.o # Additionally linked targets always := static/reboot static/poweroff ifdef KLIBCSHAREDFLAGS always += shared/reboot shared/poweroff endif $(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 the shared binaries by preference ifdef KLIBCSHAREDFLAGS install-y := $(shared-y) shared/reboot shared/poweroff else install-y := $(static-y) static/reboot static/poweroff endif klibc-2.0.7/usr/klibc/0000755000175000017500000000000013546663605012611 5ustar benbenklibc-2.0.7/usr/klibc/zlib/0000755000175000017500000000000013546663605013551 5ustar benbenklibc-2.0.7/usr/klibc/zlib/zutil.h0000644000175000017500000001536713546663605015105 0ustar benben/* 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 */ klibc-2.0.7/usr/klibc/zlib/zutil.c0000644000175000017500000001601413546663605015066 0ustar benben/* 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 */ klibc-2.0.7/usr/klibc/zlib/zlib.30000644000175000017500000001060613546663605014600 0ustar benben.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 klibc-2.0.7/usr/klibc/zlib/zconf.in.h0000644000175000017500000002256713546663605015462 0ustar benben/* 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 */ klibc-2.0.7/usr/klibc/zlib/uncompr.c0000644000175000017500000000412513546663605015402 0ustar benben/* 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; } klibc-2.0.7/usr/klibc/zlib/trees.h0000644000175000017500000002037313546663605015051 0ustar benben/* 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 }; klibc-2.0.7/usr/klibc/zlib/trees.c0000644000175000017500000012604713546663605015051 0ustar benben/* 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++); } } klibc-2.0.7/usr/klibc/zlib/inftrees.h0000644000175000017500000000450513546663605015545 0ustar benben/* 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)); klibc-2.0.7/usr/klibc/zlib/inftrees.c0000644000175000017500000003267413546663605015550 0ustar benben/* 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; } klibc-2.0.7/usr/klibc/zlib/inflate.h0000644000175000017500000001343413546663605015351 0ustar benben/* 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 */ }; klibc-2.0.7/usr/klibc/zlib/inflate.c0000644000175000017500000013752113546663605015350 0ustar benben/* 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; } klibc-2.0.7/usr/klibc/zlib/inffixed.h0000644000175000017500000001430713546663605015523 0ustar benben /* 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} }; klibc-2.0.7/usr/klibc/zlib/inffast.h0000644000175000017500000000062713546663605015361 0ustar benben/* 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)); klibc-2.0.7/usr/klibc/zlib/inffast.c0000644000175000017500000003043013546663605015347 0ustar benben/* 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 */ klibc-2.0.7/usr/klibc/zlib/infback.c0000644000175000017500000005322413546663605015320 0ustar benben/* 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; } klibc-2.0.7/usr/klibc/zlib/gzio.c0000644000175000017500000007471713546663605014705 0ustar benben/* 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); */ } klibc-2.0.7/usr/klibc/zlib/deflate.h0000644000175000017500000002760013546663605015333 0ustar benben/* 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 */ klibc-2.0.7/usr/klibc/zlib/deflate.c0000644000175000017500000017532113546663605015332 0ustar benben/* 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 klibc-2.0.7/usr/klibc/zlib/crc32.h0000644000175000017500000007355013546663605014650 0ustar benben/* 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 } }; klibc-2.0.7/usr/klibc/zlib/crc32.c0000644000175000017500000003161113546663605014633 0ustar benben/* 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; } klibc-2.0.7/usr/klibc/zlib/compress.c0000644000175000017500000000475013546663605015556 0ustar benben/* 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; } klibc-2.0.7/usr/klibc/zlib/algorithm.txt0000644000175000017500000002217013546663605016302 0ustar benben1. 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 klibc-2.0.7/usr/klibc/zlib/adler32.c0000644000175000017500000001077513546663605015163 0ustar benben/* 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); } klibc-2.0.7/usr/klibc/zlib/README0000644000175000017500000001310013546663605014424 0ustar benbenZLIB 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. klibc-2.0.7/usr/klibc/zlib/Kbuild0000644000175000017500000000032613546663605014707 0ustar benben# zlib klib-y := adler32.o compress.o crc32.o gzio.o klib-y += uncompr.o deflate.o trees.o zutil.o klib-y += inflate.o infback.o inftrees.o inffast.o # zlib specific flag EXTRA_KLIBCCFLAGS := -DDYNAMIC_CRC_TABLE klibc-2.0.7/usr/klibc/zlib/INDEX0000644000175000017500000000244613546663605014351 0ustar benbenChangeLog 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 klibc-2.0.7/usr/klibc/zlib/FAQ0000644000175000017500000003535013546663605014111 0ustar benben 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. klibc-2.0.7/usr/klibc/zalloc.c0000644000175000017500000000025513546663605014243 0ustar benben/* * zalloc.c */ #include #include void *zalloc(size_t size) { void *ptr; ptr = malloc(size); if (ptr) memset(ptr, 0, size); return ptr; } klibc-2.0.7/usr/klibc/waitpid.c0000644000175000017500000000027713546663605014424 0ustar benben/* * waitpid.c */ #include #include #include pid_t waitpid(pid_t pid, int *status, int options) { return wait4(pid, status, options, NULL); } klibc-2.0.7/usr/klibc/wait3.c0000644000175000017500000000032213546663605014001 0ustar benben/* * wait3.c */ #include #include #include pid_t wait3(int *status, int options, struct rusage * rusage) { return wait4((pid_t) - 1, status, options, rusage); } klibc-2.0.7/usr/klibc/wait.c0000644000175000017500000000023513546663605013721 0ustar benben/* * wait.c */ #include #include #include pid_t wait(int *status) { return wait4((pid_t) - 1, status, 0, NULL); } klibc-2.0.7/usr/klibc/vsscanf.c0000644000175000017500000001757313546663605014435 0ustar benben/* * 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; unsigned char uc; 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 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; goto scan_int; case 'i': /* Base-independent integer */ base = 0; goto scan_int; case 'd': /* Decimal integer */ base = 10; goto scan_int; case 'o': /* Octal integer */ base = 8; goto scan_int; case 'u': /* Unsigned decimal integer */ base = 10; goto scan_int; case 'x': /* Hexadecimal integer */ case 'X': base = 16; 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; if (!(flags & FL_SPLAT)) 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; if (flags & FL_SPLAT) { while (width--) { if (!*q) { bail = bail_eof; break; } } } else { sarg = va_arg(ap, char *); while (width--) { if (!*q) { bail = bail_eof; break; } *sarg++ = *q++; } if (!bail) converted++; } break; case 's': /* String */ uc = 1; /* Anything nonzero */ if (flags & FL_SPLAT) { while (width-- && (uc = *q) && !isspace(uc)) { q++; } } else { char *sp; sp = sarg = va_arg(ap, char *); while (width-- && (uc = *q) && !isspace(uc)) { *sp++ = uc; q++; } if (sarg != sp) { /* Terminate output */ *sp = '\0'; converted++; } } if (!uc) bail = bail_eof; break; case '[': /* Character range */ sarg = (flags & FL_SPLAT) ? NULL : 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; uc = 1; /* Anything nonzero */ while (width && (uc = *q) && test_bit(matchmap, uc)^matchinv) { if (sarg) *sarg++ = uc; q++; } if (q != qq && sarg) { *sarg = '\0'; converted++; } else { bail = bail_err; } if (!uc) bail = bail_eof; break; } } if (bail == bail_eof && !converted) converted = -1; /* Return EOF (-1) */ return converted; } klibc-2.0.7/usr/klibc/vsprintf.c0000644000175000017500000000026113546663605014627 0ustar benben/* * vsprintf.c */ #include #include int vsprintf(char *buffer, const char *format, va_list ap) { return vsnprintf(buffer, ~(size_t) 0, format, ap); } klibc-2.0.7/usr/klibc/vsnprintf.c0000644000175000017500000002332513546663605015013 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/vprintf.c0000644000175000017500000000022313546663605014442 0ustar benben/* * vprintf.c */ #include #include int vprintf(const char *format, va_list ap) { return vfprintf(stdout, format, ap); } klibc-2.0.7/usr/klibc/vfprintf.c0000644000175000017500000000061113546663605014611 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/vfork.c0000644000175000017500000000034413546663605014105 0ustar benben/* * vfork.c * * Emulate vfork() with fork() if necessary */ #include #include #include #if !_KLIBC_NO_MMU && !_KLIBC_REAL_VFORK int vfork(void) { return fork(); } #endif klibc-2.0.7/usr/klibc/version0000644000175000017500000000000613546663605014215 0ustar benben2.0.7 klibc-2.0.7/usr/klibc/vasprintf.c0000644000175000017500000000054413546663605014774 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/utimes.c0000644000175000017500000000053613546663605014267 0ustar benben#include #include #include #include #ifndef __NR_utimes int utimes(const char *file, const struct timeval tvp[2]) { struct timespec ts[2]; if (tvp) { ts->tv_sec = tvp->tv_sec; ts->tv_nsec = tvp->tv_usec * 1000; } return utimensat(AT_FDCWD, file, &ts[0], 0); } #endif /* __NR_utimes */ klibc-2.0.7/usr/klibc/utime.c0000644000175000017500000000055013546663605014100 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/usleep.c0000644000175000017500000000043313546663605014252 0ustar benben/* * usleep.c */ #include #include #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) ; } klibc-2.0.7/usr/klibc/userdb/0000755000175000017500000000000013546663605014075 5ustar benbenklibc-2.0.7/usr/klibc/userdb/userdb.h0000644000175000017500000000043013546663605015527 0ustar benben/* * userdb.h * * Common header file */ #ifndef USERDB_H #define USERDB_H #include #include #include #include #include extern const struct passwd __root_user; extern const struct group __root_group; #endif /* USERDB_H */ klibc-2.0.7/usr/klibc/userdb/root_user.c0000644000175000017500000000037613546663605016270 0ustar benben/* * root_user.c * */ #include "userdb.h" #include const struct passwd __root_user = { .pw_name = "root", .pw_passwd = "", .pw_uid = 0, .pw_gid = 0, .pw_gecos = "root", .pw_dir = "/", .pw_shell = _PATH_BSHELL }; klibc-2.0.7/usr/klibc/userdb/root_group.c0000644000175000017500000000024013546663605016434 0ustar benben/* * root_group.c */ #include "userdb.h" const struct group __root_group = { .gr_name = "root", .gr_passwd = "", .gr_gid = 0, .gr_mem = NULL }; klibc-2.0.7/usr/klibc/userdb/getpwuid.c0000644000175000017500000000033713546663605016074 0ustar benben/* * getpwuid.c * * Dummy getpwuid() to support udev */ #include #include "userdb.h" struct passwd *getpwuid(uid_t uid) { if (!uid) return (struct passwd *)&__root_user; errno = ENOENT; return NULL; } klibc-2.0.7/usr/klibc/userdb/getpwnam.c0000644000175000017500000000036713546663605016071 0ustar benben/* * getpwnam.c * * Dummy getpwnam() to support udev */ #include #include "userdb.h" struct passwd *getpwnam(const char *name) { if (!strcmp(name, "root")) return (struct passwd *)&__root_user; errno = ENOENT; return NULL; } klibc-2.0.7/usr/klibc/userdb/getgrnam.c0000644000175000017500000000036513546663605016051 0ustar benben/* * getgrnam.c * * Dummy getgrnam() to support udev */ #include #include "userdb.h" struct group *getgrnam(const char *name) { if (!strcmp(name, "root")) return (struct group *)&__root_group; errno = ENOENT; return NULL; } klibc-2.0.7/usr/klibc/userdb/getgrgid.c0000644000175000017500000000033513546663605016036 0ustar benben/* * getgrgid.c * * Dummy getgrgid() to support udev */ #include #include "userdb.h" struct group *getgrgid(gid_t gid) { if (!gid) return (struct group *)&__root_group; errno = ENOENT; return NULL; } klibc-2.0.7/usr/klibc/unsetenv.c0000644000175000017500000000104213546663605014621 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/unlink.c0000644000175000017500000000027713546663605014263 0ustar benben#include #include #include #ifndef __NR_unlink int unlink(const char *pathname) { return unlinkat(AT_FDCWD, pathname, 0); } #endif /* __NR_unlink */ klibc-2.0.7/usr/klibc/umount.c0000644000175000017500000000021213546663605014277 0ustar benben/* * umount.c * * Single-argument form of umount */ #include int umount(const char *dir) { return umount2(dir, 0); } klibc-2.0.7/usr/klibc/time.c0000644000175000017500000000037313546663605013716 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/tests/0000755000175000017500000000000013546663605013753 5ustar benbenklibc-2.0.7/usr/klibc/tests/vfork.c0000644000175000017500000000151113546663605015244 0ustar benben/* * 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; } } klibc-2.0.7/usr/klibc/tests/testvsnp.c0000644000175000017500000001041713546663605016010 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/testrand48.c0000644000175000017500000000056013546663605016120 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/strtotime.c0000644000175000017500000000102713546663605016151 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/strtoimax.c0000644000175000017500000000052213546663605016150 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/tests/strlcpycat.c0000644000175000017500000000557213546663605016320 0ustar benben#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); } klibc-2.0.7/usr/klibc/tests/stdio.c0000644000175000017500000000230613546663605015242 0ustar benben#include #include #include #include #include #include #include #include #define TEST_WORDS (1024*1024) int main(void) { FILE *f; int i, n; uint32_t *buf1, *buf2, *p; printf("Hello, World!\nHello again"); printf(" - and some more - "); printf("and some more\n"); buf1 = mmap(NULL, 2*4*TEST_WORDS, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0, 0); if (buf1 == MAP_FAILED) { perror("mmap"); return 1; } buf2 = buf1 + TEST_WORDS; p = buf1; for (i = 0; i < TEST_WORDS; i++) *p++ = htonl(i); f = fopen("test.out", "w+b"); if (!f) { perror("fopen"); return 1; } for (i = 2; i < TEST_WORDS; i += (i >> 1)) { n = fwrite(buf1, 4, i, f); if (n != i) { perror("fwrite"); return 1; } } fprintf(f, "Writing to the file...\n"); fprintf(f, "Writing to the file "); fprintf(f, "some more\n"); fseek(f, 0, SEEK_SET); for (i = 2; i < TEST_WORDS; i += (i >> 1)) { n = fread(buf2, 4, i, f); if (n != i) { perror("fread"); return 1; } if (memcmp(buf1, buf2, i*4)) { fprintf(stderr, "memory mismatch error, i = %d\n", i); return 1; } } fclose(f); return 0; } klibc-2.0.7/usr/klibc/tests/statfs.c0000644000175000017500000000151013546663605015420 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/stat.c0000644000175000017500000000323213546663605015072 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/sscanf.c0000644000175000017500000000125013546663605015372 0ustar benben#include int main() { int ret, err = 0, e1, e2; const char a1[] = "3.0", a2[] = "-12,1000"; /* int tests */ ret = sscanf(a1, "%1d", &e1); if (ret != 1) { printf("Error wrong sscanf int return %d.\n", ret); err++; } if (e1 != 3) { printf("Error wrong sscanf int reading %d.\n", e1); err++; } ret = sscanf(a2, "%3d,%4d", &e1, &e2); if (ret != 2) { printf("Error wrong sscanf int return %d.\n", ret); err++; } if (e1 != -12) { printf("Error wrong sscanf int reading %d.\n", e1); err++; } if (e2 != 1000) { printf("Error wrong sscanf int reading %d.\n", e2); err++; } /* XXX: add more int tests */ if (err) return err; return 0; } klibc-2.0.7/usr/klibc/tests/socket.c0000644000175000017500000000043713546663605015413 0ustar benben#include #include #include #include int main(int argc, char *argv[]) { int ret; ret = socket(AF_INET, SOCK_DGRAM, 0); if (ret == -1) { fprintf(stderr, "klibc: socket(AF_INET): %s\n", strerror(errno)); return 1; } return 0; } klibc-2.0.7/usr/klibc/tests/sigint.c0000644000175000017500000000216313546663605015416 0ustar benben#include #include #include #include static sig_atomic_t counter = 0; static void sig_handler(int signum) { static const 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; sigset_t set; (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); sigemptyset(&set); sigaddset(&set, SIGINT); sigprocmask(SIG_BLOCK, &set, NULL); f = fork(); if (f < 0) { perror(argv[0]); exit(255); } else if (f > 0) { sleep(3); if (counter) { fprintf(stderr, "Signal received while masked!\n"); exit(1); } sigprocmask(SIG_UNBLOCK, &set, NULL); sleep(3); 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); } } klibc-2.0.7/usr/klibc/tests/sig-nodefer.c0000644000175000017500000000170213546663605016321 0ustar benben/* * Expected output of ./sig-nodefer: * SIGUSR2: blocked * SIGTERM: blocked */ #include #include #include #include #include #include #include void handler(int signum) { sigset_t mask; sigprocmask(SIG_BLOCK, NULL, &mask); printf("SIGUSR2: %s\n", sigismember(&mask, SIGUSR2) ? "blocked" : "not blocked"); printf("SIGTERM: %s\n", sigismember(&mask, SIGTERM) ? "blocked" : "not blocked"); } int main(int argc, char **argv) { pid_t pid; pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } else if (!pid) { struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = handler; act.sa_flags = SA_NODEFER; sigaddset(&act.sa_mask, SIGUSR2); sigaddset(&act.sa_mask, SIGTERM); sigaction(SIGUSR1, &act, NULL); pause(); } else { int status; sleep(3); kill(pid, SIGUSR1); waitpid(pid, &status, 0); } return 0; } klibc-2.0.7/usr/klibc/tests/setjmptest.c0000644000175000017500000000070013546663605016316 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/tests/setenvtest.c0000644000175000017500000000153713546663605016331 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/select.c0000644000175000017500000000206113546663605015375 0ustar benben/* * Simple test of select() */ #include #include #include #include #include #include int main(int argc, char *argv[]) { int fdn, fdz, pfd[2], rv; fd_set readset; struct timeval timeout; int err = 0; /* We can always read from /dev/zero; open a pipe that is never ready for a "never readable" file descriptor */ fdz = open("/dev/zero", O_RDONLY); pipe(pfd); fdn = pfd[0]; FD_ZERO(&readset); FD_SET(fdn, &readset); timeout.tv_sec = 0; timeout.tv_usec = 100000; rv = select(FD_SETSIZE, &readset, NULL, NULL, &timeout); if (rv != 0) { fprintf(stderr, "select with timeout failed (rv = %d, errno = %s)\n", rv, strerror(errno)); err++; } FD_ZERO(&readset); FD_SET(fdn, &readset); FD_SET(fdz, &readset); rv = select(FD_SETSIZE, &readset, NULL, NULL, &timeout); if (rv != 1 || !FD_ISSET(fdz, &readset) || FD_ISSET(fdn, &readset)) { fprintf(stderr, "select with /dev/zero failed (rv = %d, errno = %s)\n", rv, strerror(errno)); err++; } return err; } klibc-2.0.7/usr/klibc/tests/rtsig.c0000644000175000017500000000030413546663605015244 0ustar benben#include #include int main(void) { #ifdef SIGRTMIN printf("sigrtmin = %d, sigrtmax = %d\n", SIGRTMIN, SIGRTMAX); #else printf("No realtime signals\n"); #endif return 0; } klibc-2.0.7/usr/klibc/tests/pipetest.c0000644000175000017500000000120613546663605015753 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/opentest.c0000644000175000017500000000027013546663605015757 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/mmaptest.c0000644000175000017500000000266513546663605015762 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/tests/minihello.c0000644000175000017500000000012513546663605016075 0ustar benben#include int main(void) { fputs("Hello, World!\n", stdout); return 0; } klibc-2.0.7/usr/klibc/tests/microhello.c0000644000175000017500000000024113546663605016251 0ustar benben#include #include int main(void) { static const char hello[] = "Hello, World!\n"; _fwrite(hello, sizeof hello - 1, stdout); return 0; } klibc-2.0.7/usr/klibc/tests/memstrtest.c0000644000175000017500000000110113546663605016317 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/malloctest2.c0000644000175000017500000000201313546663605016344 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/malloctest.c0000644000175000017500000007513413546663605016300 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/lseek.c0000644000175000017500000000040513546663605015221 0ustar benben#include #include #include #include int main(void) { int fd = open("test.out", O_RDWR|O_CREAT|O_TRUNC, 0666); off_t rv; rv = lseek(fd, 123456789012ULL, SEEK_SET); printf("seek to: %lld\n", rv); return 0; } klibc-2.0.7/usr/klibc/tests/idtest.c0000644000175000017500000000044713546663605015420 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/hello.c0000644000175000017500000000011613546663605015220 0ustar benben#include int main(void) { printf("Hello, World!\n"); return 0; } klibc-2.0.7/usr/klibc/tests/getpagesize.c0000644000175000017500000000025613546663605016431 0ustar benben#include #include int main(void) { printf("getpagesize() = %d\n" "__getpageshift() = %d\n", getpagesize(), __getpageshift()); return 0; } klibc-2.0.7/usr/klibc/tests/getopttest.c0000644000175000017500000000115513546663605016323 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/tests/getoptlong.c0000644000175000017500000000225513546663605016305 0ustar benben/* * getoptlong.c * * Simple test for getopt_long, set the environment variable GETOPTTEST * to give the argument string to getopt() */ #include #include #include #include static int foo = 0; static const struct option long_options[] = { { "first", 1, NULL, 'f' }, { "second", 0, NULL, 's' }, { "third", 2, NULL, '3' }, { "fourth", 0, NULL, 4 }, { "set-foo", 0, &foo, 1 }, { NULL, 0, NULL, 0 } }; int main(int argc, char *const *argv) { const char *parser; const char *showchar; char one_char[] = "\'?\'"; char num_buf[16]; int c; int longindex; parser = getenv("GETOPTTEST"); if (!parser) parser = "abzf:o:"; do { c = getopt_long(argc, argv, parser, long_options, &longindex); if (c == EOF) { showchar = "EOF"; } else if (c >= 32 && c <= 126) { one_char[1] = c; showchar = one_char; } else { snprintf(num_buf, sizeof num_buf, "%d", c); showchar = num_buf; } printf("c = %s, optind = %d (\"%s\"), optarg = \"%s\", " "optopt = \'%c\', foo = %d, longindex = %d\n", showchar, optind, argv[optind], optarg, optopt, foo, longindex); } while (c != -1); return 0; } klibc-2.0.7/usr/klibc/tests/fnmatch.c0000644000175000017500000000037713546663605015546 0ustar benben#include #include #include int main(int argc, char *argv[]) { int flags = atoi(argv[3]); int match = fnmatch(argv[1], argv[2], flags); printf("\"%s\" matches \"%s\": %d\n", argv[1], argv[2], match); return match; } klibc-2.0.7/usr/klibc/tests/fcntl.c0000644000175000017500000000143113546663605015224 0ustar benben/* * Simple test of fcntl */ #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 */ flags = fcntl(fd, F_GETFL); if (flags == -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... */ close(fd); return 0; } klibc-2.0.7/usr/klibc/tests/environ.c0000644000175000017500000000072313546663605015601 0ustar benben#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; } klibc-2.0.7/usr/klibc/tests/Kbuild0000644000175000017500000000322313546663605015110 0ustar benben# # 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 fnmatch.shared-y := fnmatch.o getopttest.shared-y := getopttest.o getoptlong.shared-y := getoptlong.o getpagesize.shared-y := getpagesize.o hello.shared-y := hello.o idtest.shared-y := idtest.o lseek.shared-y := lseek.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 select.shared-y := select.o setenvtest.shared-y := setenvtest.o setjmptest.shared-y := setjmptest.o sigint.shared-y := sigint.o sig-nodefer.shared-y := sig-nodefer.o socket.shared-y := socket.o sscanf.shared-y := sscanf.o stat.shared-y := stat.o statfs.shared-y := statfs.o stdio.shared-y := stdio.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) klibc-2.0.7/usr/klibc/sysv_signal.c0000644000175000017500000000030713546663605015316 0ustar benben/* * sysv_signal.c */ #include __sighandler_t sysv_signal(int signum, __sighandler_t handler) { /* Linux/SysV signal() semantics */ return __signal(signum, handler, SA_RESETHAND); } klibc-2.0.7/usr/klibc/system.c0000644000175000017500000000250513546663605014303 0ustar benben/* * 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 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; } klibc-2.0.7/usr/klibc/syslog.c0000644000175000017500000000310513546663605014274 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/syscalls/0000755000175000017500000000000013546663605014446 5ustar benbenklibc-2.0.7/usr/klibc/syscalls/syscommon.h0000644000175000017500000000117313546663605016650 0ustar benben/* * 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 #include #ifdef __i386__ # include #endif klibc-2.0.7/usr/klibc/syscalls/Kbuild0000644000175000017500000000754713546663605015620 0ustar benben# # 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 := klib.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 += klib.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)/klib.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) $(srctree)/$(KLIBCSRC)/syscalls.pl \ -1 $(obj)/SYSCALLS.i \ $(srctree)/$(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: $(srctree)/$(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \ $(srctree)/$(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) $(srctree)/$(KLIBCSRC)/syscalls.pl -2 $(obj)/SYSCALLS.i \ $(srctree)/$(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: $(srctree)/$(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \ $(srctree)/$(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) PHONY += FORCE klibc-2.0.7/usr/klibc/syscalls/.gitignore0000644000175000017500000000010013546663605016425 0ustar benben*.S SYSCALLS.i syscalls.mk syscalls.nrs typesize.bin typesize.c klibc-2.0.7/usr/klibc/syscalls.pl0000644000175000017500000001467313546663605015016 0ustar benben#!/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); } klibc-2.0.7/usr/klibc/symlink.c0000644000175000017500000000033313546663605014442 0ustar benben#include #include #include #ifndef __NR_symlink int symlink(const char *oldpath, const char *newpath) { return symlinkat(oldpath, AT_FDCWD, newpath); } #endif /* __NR_symlink */ klibc-2.0.7/usr/klibc/strxspn.h0000644000175000017500000000023413546663605014502 0ustar benben/* * strxspn.h */ #ifndef STRXSPN_H #define STRXSPN_H #include extern size_t __strxspn(const char *s, const char *map, int parity); #endif klibc-2.0.7/usr/klibc/strxspn.c0000644000175000017500000000100713546663605014474 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strtox.c0000644000175000017500000000037013546663605014320 0ustar benben/* * strtox.c * * strto...() functions, by macro definition */ #include #include #include TYPE NAME(const char *nptr, char **endptr, int base) { return (TYPE) strntoumax(nptr, endptr, base, ~(size_t) 0); } klibc-2.0.7/usr/klibc/strtoumax.c0000644000175000017500000000010213546663605015014 0ustar benben#define TYPE uintmax_t #define NAME strtoumax #include "strtox.c" klibc-2.0.7/usr/klibc/strtoull.c0000644000175000017500000000011213546663605014637 0ustar benben#define TYPE unsigned long long #define NAME strtoull #include "strtox.c" klibc-2.0.7/usr/klibc/strtoul.c0000644000175000017500000000010413546663605014464 0ustar benben#define TYPE unsigned long #define NAME strtoul #include "strtox.c" klibc-2.0.7/usr/klibc/strtotimex.c0000644000175000017500000000123713546663605015202 0ustar benben/* * 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 #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; } klibc-2.0.7/usr/klibc/strtotimeval.c0000644000175000017500000000017213546663605015512 0ustar benben#define NAME strtotimeval #define TIMEX struct timeval #define FSEC tv_usec #define DECIMALS 6 #include "strtotimex.c" klibc-2.0.7/usr/klibc/strtotimespec.c0000644000175000017500000000017413546663605015664 0ustar benben#define NAME strtotimespec #define TIMEX struct timespec #define FSEC tv_nsec #define DECIMALS 9 #include "strtotimex.c" klibc-2.0.7/usr/klibc/strtoll.c0000644000175000017500000000010713546663605014456 0ustar benben#define TYPE signed long long #define NAME strtoll #include "strtox.c" klibc-2.0.7/usr/klibc/strtol.c0000644000175000017500000000010113546663605014274 0ustar benben#define TYPE signed long #define NAME strtol #include "strtox.c" klibc-2.0.7/usr/klibc/strtok_r.c0000644000175000017500000000025713546663605014630 0ustar benben#include char *strtok_r(char *s, const char *delim, char **holder) { if (s) *holder = s; do { s = strsep(holder, delim); } while (s && !*s); return s; } klibc-2.0.7/usr/klibc/strtok.c0000644000175000017500000000022213546663605014277 0ustar benben/* * strtok.c */ #include char *strtok(char *s, const char *delim) { static char *holder; return strtok_r(s, delim, &holder); } klibc-2.0.7/usr/klibc/strtoimax.c0000644000175000017500000000010113546663605014777 0ustar benben#define TYPE intmax_t #define NAME strtoimax #include "strtox.c" klibc-2.0.7/usr/klibc/strstr.c0000644000175000017500000000027113546663605014316 0ustar benben/* * strstr.c */ #include char *strstr(const char *haystack, const char *needle) { return (char *)memmem(haystack, strlen(haystack), needle, strlen(needle)); } klibc-2.0.7/usr/klibc/strspn.c0000644000175000017500000000022313546663605014303 0ustar benben/* * strspn */ #include #include "strxspn.h" size_t strspn(const char *s, const char *accept) { return __strxspn(s, accept, 0); } klibc-2.0.7/usr/klibc/strsignal.c0000644000175000017500000000066213546663605014767 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strsep.c0000644000175000017500000000034013546663605014272 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strrchr.c0000644000175000017500000000042413546663605014444 0ustar benben/* * 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) klibc-2.0.7/usr/klibc/strpbrk.c0000644000175000017500000000030413546663605014441 0ustar benben/* * strpbrk */ #include #include "strxspn.h" char *strpbrk(const char *s, const char *accept) { const char *ss = s + __strxspn(s, accept, 1); return *ss ? (char *)ss : NULL; } klibc-2.0.7/usr/klibc/strntoumax.c0000644000175000017500000000234513546663605015205 0ustar benben/* * strntoumax.c * * The strntoumax() function and associated */ #include #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; } klibc-2.0.7/usr/klibc/strntoimax.c0000644000175000017500000000033113546663605015162 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/strnlen.c0000644000175000017500000000046313546663605014445 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strndup.c0000644000175000017500000000034213546663605014453 0ustar benben/* * strndup.c */ #include #include char *strndup(const char *s, size_t n) { size_t l = strnlen(s, n); char *d = malloc(l + 1); if (!d) return NULL; memcpy(d, s, l); d[l] = '\0'; return d; } klibc-2.0.7/usr/klibc/strncpy.c0000644000175000017500000000047413546663605014464 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strncmp.c0000644000175000017500000000051613546663605014445 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strncat.c0000644000175000017500000000042713546663605014436 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strncasecmp.c0000644000175000017500000000076513546663605015307 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strlen.c0000644000175000017500000000020413546663605014260 0ustar benben/* * strlen() */ #include size_t strlen(const char *s) { const char *ss = s; while (*ss) ss++; return ss - s; } klibc-2.0.7/usr/klibc/strlcpy.c0000644000175000017500000000056513546663605014463 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strlcat.c0000644000175000017500000000062613546663605014435 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strerror.c0000644000175000017500000000106613546663605014642 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strdup.c0000644000175000017500000000026313546663605014277 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strcspn.c0000644000175000017500000000022513546663605014450 0ustar benben/* * strcspn */ #include #include "strxspn.h" size_t strcspn(const char *s, const char *reject) { return __strxspn(s, reject, 1); } klibc-2.0.7/usr/klibc/strcpy.c0000644000175000017500000000031513546663605014300 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strcmp.c0000644000175000017500000000050013546663605014260 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/strchr.c0000644000175000017500000000036313546663605014264 0ustar benben/* * 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) klibc-2.0.7/usr/klibc/strcat.c0000644000175000017500000000020413546663605014251 0ustar benben/* * strcat.c */ #include char *strcat(char *dst, const char *src) { strcpy(strchr(dst, '\0'), src); return dst; } klibc-2.0.7/usr/klibc/strcasecmp.c0000644000175000017500000000074713546663605015131 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/stdio/0000755000175000017500000000000013546663605013733 5ustar benbenklibc-2.0.7/usr/klibc/stdio/ungetc.c0000644000175000017500000000033113546663605015361 0ustar benben/* * ungetc.c */ #include "stdioint.h" int ungetc(int c, FILE *file) { struct _IO_file_pvt *f = stdio_pvt(file); if (f->obytes || f->data <= f->buf) return EOF; *(--f->data) = c; f->ibytes++; return c; } klibc-2.0.7/usr/klibc/stdio/stdioint.h0000644000175000017500000000170113546663605015740 0ustar benben/* * stdioint.h * * stdio internals */ #ifndef USR_KLIBC_STDIO_STDIOINT_H #define USR_KLIBC_STDIO_STDIOINT_H #include #include #include #include #include #include /* Actual FILE structure */ struct _IO_file_pvt { struct _IO_file pub; /* Data exported to inlines */ struct _IO_file_pvt *prev, *next; char *buf; /* Buffer */ char *data; /* Location of input data in buffer */ unsigned int ibytes; /* Input data bytes in buffer */ unsigned int obytes; /* Output data bytes in buffer */ unsigned int bufsiz; /* Total size of buffer */ enum _IO_bufmode bufmode; /* Type of buffering */ }; #define stdio_pvt(x) container_of(x, struct _IO_file_pvt, pub) /* Assign this much extra to the input buffer in case of ungetc() */ #define _IO_UNGET_SLOP 32 __extern int __fflush(struct _IO_file_pvt *); __extern struct _IO_file_pvt __stdio_headnode; #endif /* USR_KLIBC_STDIO_STDIOINT_H */ klibc-2.0.7/usr/klibc/stdio/rewind.c0000644000175000017500000000016713546663605015373 0ustar benben#include #include void rewind(FILE *f) { if (!fseek(f, 0, SEEK_SET)) f->_IO_error = false; } klibc-2.0.7/usr/klibc/stdio/fwrite.c0000644000175000017500000000327413546663605015405 0ustar benben/* * fwrite.c */ #include #include "stdioint.h" static size_t fwrite_noflush(const void *buf, size_t count, struct _IO_file_pvt *f) { size_t bytes = 0; size_t nb; const char *p = buf; ssize_t rv; while (count) { if (f->ibytes || f->obytes >= f->bufsiz || (f->obytes && count >= f->bufsiz)) if (__fflush(f)) break; if (count >= f->bufsiz) { /* * The write is large, so bypass * buffering entirely. */ rv = write(f->pub._IO_fileno, p, count); if (rv == -1) { if (errno == EINTR || errno == EAGAIN) continue; f->pub._IO_error = true; break; } else if (rv == 0) { /* EOF on output? */ f->pub._IO_eof = true; break; } p += rv; bytes += rv; count -= rv; } else { nb = f->bufsiz - f->obytes; nb = (count < nb) ? count : nb; if (nb) { memcpy(f->buf+f->obytes, p, nb); p += nb; f->obytes += nb; count -= nb; bytes += nb; } } } return bytes; } size_t _fwrite(const void *buf, size_t count, FILE *file) { struct _IO_file_pvt *f = stdio_pvt(file); size_t bytes = 0; size_t pf_len, pu_len; const char *p = buf; const char *q; /* We divide the data into two chunks, flushed (pf) and unflushed (pu) depending on buffering mode and contents. */ switch (f->bufmode) { case _IOFBF: pf_len = 0; break; case _IOLBF: q = memrchr(p, '\n', count); pf_len = q ? q - p + 1 : 0; break; case _IONBF: default: pf_len = count; break; } if (pf_len) { bytes = fwrite_noflush(p, pf_len, f); p += bytes; if (__fflush(f) || bytes != pf_len) return bytes; } pu_len = count - pf_len; if (pu_len) bytes += fwrite_noflush(p, pu_len, f); return bytes; } klibc-2.0.7/usr/klibc/stdio/ftell.c0000644000175000017500000000033213546663605015203 0ustar benben#include "stdioint.h" off_t ftell(FILE *file) { struct _IO_file_pvt *f = stdio_pvt(file); off_t pos = lseek(f->pub._IO_fileno, 0, SEEK_CUR); if (pos >= 0) pos += (int)f->obytes - (int)f->ibytes; return pos; } klibc-2.0.7/usr/klibc/stdio/fseek.c0000644000175000017500000000066413546663605015202 0ustar benben/* * fseek.c */ #include "stdioint.h" __extern int fseek(FILE *file, off_t where, int whence) { struct _IO_file_pvt *f = stdio_pvt(file); off_t rv; if (f->obytes) if (__fflush(f)) return -1; if (whence == SEEK_CUR) where -= f->ibytes; rv = lseek(f->pub._IO_fileno, where, whence); if (__likely(rv >= 0)) { f->pub._IO_eof = false; f->ibytes = 0; return 0; } else { f->pub._IO_error = true; return -1; } } klibc-2.0.7/usr/klibc/stdio/fread.c0000644000175000017500000000241213546663605015157 0ustar benben/* * fread.c */ #include #include #include "stdioint.h" size_t _fread(void *buf, size_t count, FILE *file) { struct _IO_file_pvt *f = stdio_pvt(file); size_t bytes = 0; size_t nb; char *p = buf; char *rdptr; ssize_t rv; bool bypass; if (!count) return 0; if (f->obytes) /* User error! */ __fflush(f); while (count) { while (f->ibytes == 0) { /* * The buffer is empty, we have to read */ bypass = (count >= f->bufsiz); if (bypass) { /* Large read, bypass buffer */ rdptr = p; nb = count; } else { rdptr = f->buf + _IO_UNGET_SLOP; nb = f->bufsiz; } rv = read(f->pub._IO_fileno, rdptr, nb); if (rv == -1) { if (errno == EINTR || errno == EAGAIN) continue; f->pub._IO_error = true; return bytes; } else if (rv == 0) { f->pub._IO_eof = true; return bytes; } if (bypass) { p += rv; bytes += rv; count -= rv; } else { f->ibytes = rv; f->data = rdptr; } if (!count) return bytes; } /* If we get here, the buffer is non-empty */ nb = f->ibytes; nb = (count < nb) ? count : nb; if (nb) { memcpy(p, f->data, nb); p += nb; bytes += nb; count -= nb; f->data += nb; f->ibytes -= nb; } } return bytes; } klibc-2.0.7/usr/klibc/stdio/fopen.c0000644000175000017500000000152413546663605015210 0ustar benben/* * fopen.c */ #include "stdioint.h" static int __parse_open_mode(const char *mode) { int rwflags = O_RDONLY; int crflags = 0; int eflags = 0; while (*mode) { switch (*mode++) { case 'r': rwflags = O_RDONLY; crflags = 0; break; case 'w': rwflags = O_WRONLY; crflags = O_CREAT | O_TRUNC; break; case 'a': rwflags = O_WRONLY; crflags = O_CREAT | O_APPEND; break; case 'e': eflags |= O_CLOEXEC; break; case 'x': eflags |= O_EXCL; break; case '+': rwflags = O_RDWR; break; } } return rwflags | crflags | eflags; } FILE *fopen(const char *file, const char *mode) { int flags = __parse_open_mode(mode); int fd, err; FILE *f; fd = open(file, flags, 0666); if (fd < 0) return NULL; f = fdopen(fd, mode); if (!f) { err = errno; close(fd); errno = err; } return f; } klibc-2.0.7/usr/klibc/stdio/fileno.c0000644000175000017500000000014513546663605015353 0ustar benben#define __NO_STDIO_INLINES #include "stdioint.h" int fileno(FILE *__f) { return __f->_IO_fileno; } klibc-2.0.7/usr/klibc/stdio/fgetc.c0000644000175000017500000000041713546663605015171 0ustar benben/* * fgetc.c */ #include "stdioint.h" int fgetc(FILE *file) { struct _IO_file_pvt *f = stdio_pvt(file); unsigned char ch; if (__likely(f->ibytes)) { f->ibytes--; return (unsigned char) *f->data++; } else { return _fread(&ch, 1, file) == 1 ? ch : EOF; } } klibc-2.0.7/usr/klibc/stdio/fflush.c0000644000175000017500000000162313546663605015370 0ustar benben/* * fflush.c */ #include "stdioint.h" int __fflush(struct _IO_file_pvt *f) { ssize_t rv; char *p; /* * Flush any unused input data. If there is input data, there * won't be any output data. */ if (__unlikely(f->ibytes)) return fseek(&f->pub, 0, SEEK_CUR); p = f->buf; while (f->obytes) { rv = write(f->pub._IO_fileno, p, f->obytes); if (rv == -1) { if (errno == EINTR || errno == EAGAIN) continue; f->pub._IO_error = true; return EOF; } else if (rv == 0) { /* EOF on output? */ f->pub._IO_eof = true; return EOF; } p += rv; f->obytes -= rv; } return 0; } int fflush(FILE *file) { struct _IO_file_pvt *f; if (__likely(file)) { f = stdio_pvt(file); return __fflush(f); } else { int err = 0; for (f = __stdio_headnode.next; f != &__stdio_headnode; f = f->next) { if (f->obytes) err |= __fflush(f); } return err; } } klibc-2.0.7/usr/klibc/stdio/ferror.c0000644000175000017500000000014413546663605015375 0ustar benben#define __NO_STDIO_INLINES #include "stdioint.h" int ferror(FILE *__f) { return __f->_IO_error; } klibc-2.0.7/usr/klibc/stdio/feof.c0000644000175000017500000000014013546663605015011 0ustar benben#define __NO_STDIO_INLINES #include "stdioint.h" int feof(FILE *__f) { return __f->_IO_eof; } klibc-2.0.7/usr/klibc/stdio/fdopen.c0000644000175000017500000000202413546663605015350 0ustar benben/* * fdopen.c * * Common code between fopen(), fdopen() and the standard descriptors. */ #include "stdioint.h" FILE *stdin, *stdout, *stderr; /* Doubly-linked list of all stdio structures */ struct _IO_file_pvt __stdio_headnode = { .prev = &__stdio_headnode, .next = &__stdio_headnode, }; FILE *fdopen(int fd, const char *mode) { struct _IO_file_pvt *f; const size_t bufoffs = (sizeof *f + 4*sizeof(void *) - 1) & ~(4*sizeof(void *) - 1); (void)mode; f = zalloc(bufoffs + BUFSIZ + _IO_UNGET_SLOP); if (!f) goto err; f->data = f->buf = (char *)f + bufoffs; f->pub._IO_fileno = fd; f->bufsiz = BUFSIZ; f->bufmode = isatty(fd) ? _IOLBF : _IOFBF; /* Insert into linked list */ f->prev = &__stdio_headnode; f->next = __stdio_headnode.next; f->next->prev = f; __stdio_headnode.next = f; return &f->pub; err: if (f) free(f); errno = ENOMEM; return NULL; } void __libc_init_stdio(void) { stdin = fdopen(0, NULL); stdout = fdopen(1, NULL); stderr = fdopen(2, NULL); stdio_pvt(stderr)->bufmode = _IONBF; } klibc-2.0.7/usr/klibc/stdio/fclose.c0000644000175000017500000000042613546663605015354 0ustar benben/* * fclose.c */ #include "stdioint.h" int fclose(FILE *file) { struct _IO_file_pvt *f = stdio_pvt(file); int rv; fflush(file); rv = close(f->pub._IO_fileno); /* Remove from linked list */ f->next->prev = f->prev; f->prev->next = f->next; free(f); return rv; } klibc-2.0.7/usr/klibc/statfs.c0000644000175000017500000000050013546663605014254 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/stat.c0000644000175000017500000000036313546663605013732 0ustar benben#include #include #include #include #include #ifndef __NR_stat int stat(const char *path, struct stat *buf) { return fstatat(AT_FDCWD, path, buf, 0); } #endif /* __NR_stat */ klibc-2.0.7/usr/klibc/sscanf.c0000644000175000017500000000031113546663605014225 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/srand48.c0000644000175000017500000000045713546663605014246 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/sprintf.c0000644000175000017500000000035613546663605014446 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/socketcalls/0000755000175000017500000000000013546663605015120 5ustar benbenklibc-2.0.7/usr/klibc/socketcalls/socketcommon.h0000644000175000017500000000042213546663605017770 0ustar benben/* * socketcommon.h * * Common header file for socketcall stubs */ #define __IN_SYS_COMMON #include #include #include #include #include #include #include #include klibc-2.0.7/usr/klibc/socketcalls/Kbuild0000644000175000017500000000327413546663605016263 0ustar benben# # 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 := klib.list ##### # Generate socket calls stubs # Based on input from SOCKETCALLS.def generate socket call stubs targets := klib.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)/klib.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) $(srctree)/$(KLIBCSRC)/socketcalls.pl \ $(obj)/SOCKETCALLS.i \ $(KLIBCARCH) $(obj) > $@ \ || ( rm -f $@ ; exit 1 ) $(obj)/socketcalls.mk: $(srctree)/$(KLIBCSRC)/socketcalls.pl \ $(obj)/SOCKETCALLS.i \ $(src)/socketcommon.h $(call cmd,socketcalls) PHONY += FORCE klibc-2.0.7/usr/klibc/socketcalls/.gitignore0000644000175000017500000000004513546663605017107 0ustar benben*.S *.c SOCKETCALLS.i socketcalls.mk klibc-2.0.7/usr/klibc/socketcalls.pl0000644000175000017500000000353513546663605015463 0ustar benben#!/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"; 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 "#if _KLIBC_SYS_SOCKETCALL\n"; print OUT "# define DO_THIS_SOCKETCALL\n"; print OUT "#else\n"; print OUT "# if !defined(__NR_${name})"; if ($name eq 'accept') { print OUT " && !defined(__NR_accept4)"; } print OUT "\n# define DO_THIS_SOCKETCALL\n"; print OUT "# endif\n"; print OUT "#endif\n\n"; print OUT "#if defined(DO_THIS_SOCKETCALL) && defined(SYS_\U${name}\E)\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"; klibc-2.0.7/usr/klibc/snprintf.c0000644000175000017500000000033313546663605014617 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/sleep.c0000644000175000017500000000046313546663605014070 0ustar benben/* * sleep.c */ #include #include #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; } klibc-2.0.7/usr/klibc/sigsuspend.c0000644000175000017500000000123113546663605015136 0ustar benben/* * sigsuspend.c */ #include #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); } #else extern int __sigsuspend_s(sigset_t); extern int __sigsuspend_xxs(int, int, sigset_t); int sigsuspend(const sigset_t *maskp) { #ifdef _KLIBC_HAVE_SYSCALL___sigsuspend_s return __sigsuspend_s(*maskp); #elif defined(_KLIBC_HAVE_SYSCALL___sigsuspend_xxs) return __sigsuspend_xxs(0, 0, *maskp); #else # error "Unknown sigsuspend implementation" #endif } #endif klibc-2.0.7/usr/klibc/sigprocmask.c0000644000175000017500000000051613546663605015301 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/sigpending.c0000644000175000017500000000041013546663605015077 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/siglongjmp.c0000644000175000017500000000051013546663605015122 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/siglist.c0000644000175000017500000000425213546663605014436 0ustar benben/* * 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 }; klibc-2.0.7/usr/klibc/sigaction.c0000644000175000017500000000300113546663605014727 0ustar benben/* * 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); #elif defined(__alpha__) __extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t, void *); #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)); } # elif defined(__alpha__) rv = __rt_sigaction(sig, act, oact, sizeof(sigset_t), NULL); # 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; } klibc-2.0.7/usr/klibc/sigabbrev.c0000644000175000017500000000351613546663605014726 0ustar benben/* * 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 }; klibc-2.0.7/usr/klibc/shm_unlink.c0000644000175000017500000000053413546663605015126 0ustar benben/* * shm_unlink.c * * POSIX shared memory support */ #include #include #include #include #include int shm_unlink(const char *path) { int len = strlen(path); char *pathbuf = alloca(len+10); memcpy(pathbuf, "/dev/shm/", 9); memcpy(pathbuf+9, path, len+1); return unlink(path); } klibc-2.0.7/usr/klibc/shm_open.c0000644000175000017500000000060513546663605014566 0ustar benben/* * shm_open.c * * POSIX shared memory support */ #include #include #include #include #include int shm_open(const char *path, int oflag, mode_t mode) { int len = strlen(path); char *pathbuf = alloca(len+10); memcpy(pathbuf, "/dev/shm/", 9); memcpy(pathbuf+9, path, len+1); return open(path, oflag, mode|O_CLOEXEC); } klibc-2.0.7/usr/klibc/sha1hash.c0000644000175000017500000002333313546663605014461 0ustar benben/* 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; } klibc-2.0.7/usr/klibc/setpgrp.c0000644000175000017500000000012713546663605014441 0ustar benben/* * setpgrp.c */ #include int setpgrp(void) { return setpgid(0, 0); } klibc-2.0.7/usr/klibc/setmntent.c0000644000175000017500000000020313546663605014771 0ustar benben#include #include FILE *setmntent(const char *filename, const char *type) { return fopen(filename, type); } klibc-2.0.7/usr/klibc/seteuid.c0000644000175000017500000000014213546663605014414 0ustar benben/* * seteuid.c */ #include int seteuid(uid_t euid) { return setreuid(-1, euid); } klibc-2.0.7/usr/klibc/setenv.c0000644000175000017500000000107313546663605014262 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/setegid.c0000644000175000017500000000014213546663605014376 0ustar benben/* * setegid.c */ #include int setegid(gid_t egid) { return setregid(-1, egid); } klibc-2.0.7/usr/klibc/send.c0000644000175000017500000000026113546663605013705 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/select.c0000644000175000017500000000132413546663605014234 0ustar benben#include #include #include #include #include #if !defined(__NR_select) && !defined(__NR__newselect) struct __pselect6; __extern int __pselect6(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const struct __pselect6 *); int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { int result; struct timespec ts; if (timeout) { ts.tv_sec = timeout->tv_sec; ts.tv_nsec = timeout->tv_usec * 1000; } result = __pselect6(nfds, readfds, writefds, exceptfds, &ts, NULL); if (timeout) { timeout->tv_sec = ts.tv_sec; timeout->tv_usec = ts.tv_nsec / 1000; } return result; } #endif klibc-2.0.7/usr/klibc/seed48.c0000644000175000017500000000051613546663605014053 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/scandir.c0000644000175000017500000000237513546663605014407 0ustar benben/* * scandir.c: scandir */ #include #include #include #include int scandir(const char *dirp, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) { struct dirent **nl = NULL, **next_nl; struct dirent *dirent; size_t count = 0; size_t allocated = 0; DIR *dir; dir = opendir(dirp); if (!dir) return -1; while (1) { dirent = readdir(dir); if (!dirent) break; if (!filter || filter(dirent)) { struct dirent *copy; copy = malloc(sizeof(*copy)); if (!copy) goto cleanup_fail; memcpy(copy, dirent, sizeof(*copy)); /* Extend the array if needed */ if (count == allocated) { if (allocated == 0) allocated = 15; /* ~1 page worth */ else allocated *= 2; next_nl = realloc(nl, allocated); if (!next_nl) { free(copy); goto cleanup_fail; } nl = next_nl; } nl[count++] = copy; } } qsort(nl, count, sizeof(struct dirent *), (int (*)(const void *, const void *))compar); closedir(dir); *namelist = nl; return count; cleanup_fail: while (count) { dirent = nl[--count]; free(dirent); } free(nl); closedir(dir); errno = ENOMEM; return -1; } klibc-2.0.7/usr/klibc/sbrk.c0000644000175000017500000000164213546663605013721 0ustar benben/* 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 */ klibc-2.0.7/usr/klibc/rmdir.c0000644000175000017500000000030613546663605014071 0ustar benben#include #include #include #ifndef __NR_rmdir int rmdir(const char *pathname) { return unlinkat(AT_FDCWD, pathname, AT_REMOVEDIR); } #endif /* __NR_rmdir */ klibc-2.0.7/usr/klibc/renameat.c0000644000175000017500000000036313546663605014553 0ustar benben#include #include #ifndef __NR_renameat int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { return renameat2(olddirfd, oldpath, newdirfd, newpath, 0); } #endif /* __NR_renameat */ klibc-2.0.7/usr/klibc/rename.c0000644000175000017500000000031313546663605014221 0ustar benben#include #include #ifndef __NR_rename int rename(const char *oldpath, const char *newpath) { return renameat2(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0); } #endif /* __NR_rename */ klibc-2.0.7/usr/klibc/remove.c0000644000175000017500000000033713546663605014255 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/recv.c0000644000175000017500000000025513546663605013716 0ustar benben/* * recv.c */ #include #include int recv(int s, void *buf, size_t len, unsigned int flags) { return recvfrom(s, buf, len, flags, NULL, 0); } klibc-2.0.7/usr/klibc/reboot.c0000644000175000017500000000053413546663605014251 0ustar benben/* * reboot.c */ #include #include #include /* This provides two-argument reboot function (glibc flag plus reboot argument). The full four-argument system call is available as __reboot(). */ int reboot(int flag, void *arg) { return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, flag, arg); } klibc-2.0.7/usr/klibc/realpath.c0000644000175000017500000000212313546663605014553 0ustar benben#include #include #include #include #include #include /* * Note that this requires name to refer to an existing file. This is * correct according to POSIX. However, BSD and GNU implementations * also allow name to refer to a non-existing file in an existing * directory. */ char *realpath(const char *name, char *resolved_name) { static const char proc_fd_prefix[] = "/proc/self/fd/"; char proc_fd_name[sizeof(proc_fd_prefix) + sizeof(int) * 3]; int allocated = 0; int fd; ssize_t len; /* Open for path lookup only */ fd = open(name, O_PATH); if (fd < 0) return NULL; if (!resolved_name) { resolved_name = malloc(PATH_MAX); if (!resolved_name) goto out_close; allocated = 1; } /* Use procfs to read back the resolved name */ sprintf(proc_fd_name, "%s%d", proc_fd_prefix, fd); len = readlink(proc_fd_name, resolved_name, PATH_MAX - 1); if (len < 0) { if (allocated) free(resolved_name); resolved_name = NULL; } else { resolved_name[len] = 0; } out_close: close(fd); return resolved_name; } klibc-2.0.7/usr/klibc/realloc.c0000644000175000017500000000174113546663605014401 0ustar benben/* * 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 following block 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; } } klibc-2.0.7/usr/klibc/readlink.c0000644000175000017500000000034213546663605014545 0ustar benben#include #include #include #ifndef __NR_readlink int readlink(const char *path, char *buf, size_t bufsiz) { return readlinkat(AT_FDCWD, path, buf, bufsiz); } #endif /* __NR_readlink */ klibc-2.0.7/usr/klibc/readdir.c0000644000175000017500000000172713546663605014376 0ustar benben/* * readdir.c: opendir/readdir/closedir */ #include #include #include #include #define __KLIBC_DIRENT_INTERNALS #include DIR *fdopendir(int fd) { DIR *dp = zalloc(sizeof(DIR)); if (!dp) return NULL; dp->__fd = fd; return dp; } DIR *opendir(const char *name) { int fd, err; DIR *dp; fd = open(name, O_DIRECTORY | O_RDONLY); if (fd < 0) return NULL; dp = fdopendir(fd); if (!dp) { err = errno; close(fd); errno = err; } 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; } klibc-2.0.7/usr/klibc/raise.c0000644000175000017500000000016613546663605014063 0ustar benben/* * raise.c */ #include #include int raise(int signal) { return kill(getpid(), signal); } klibc-2.0.7/usr/klibc/qsort.c0000644000175000017500000000144013546663605014124 0ustar benben/* * 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 #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; if (!nmemb) return; 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); } klibc-2.0.7/usr/klibc/pwrite.c0000644000175000017500000000115413546663605014270 0ustar benben/* * pwrite.c * * Some architectures need to wrap the system call */ #include #include #include #if defined(__hppa__) #if _BITSIZE == 32 extern ssize_t __pwrite(int, const void *, size_t, unsigned int, unsigned int); #else extern ssize_t __pwrite(int, const void *, size_t, off_t); #endif size_t pwrite(int fd, void *buf, size_t count, off_t offset) { #if _BITSIZE == 32 unsigned int hi = offset >> 32; unsigned int lo = (unsigned int) offset; return __pwrite(fd, buf, count, __LONG_LONG_PAIR(hi, lo)); #else return __pwrite(fd, buf, count, offset); #endif } #endif klibc-2.0.7/usr/klibc/puts.c0000644000175000017500000000021513546663605013746 0ustar benben/* * puts.c */ #include int puts(const char *s) { if (fputs(s, stdout) < 0) return -1; return _fwrite("\n", 1, stdout); } klibc-2.0.7/usr/klibc/putenv.c0000644000175000017500000000064113546663605014277 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/putchar.c0000644000175000017500000000025613546663605014426 0ustar benben/* * putchar.c * * - gcc wants this */ #include #undef putchar /* Defined as a macro */ int putchar(int); int putchar(int c) { return fputc(c, stdout); } klibc-2.0.7/usr/klibc/pty.c0000644000175000017500000000101013546663605013561 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/pselect.c0000644000175000017500000000207513546663605014420 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/printf.c0000644000175000017500000000035213546663605014257 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/pread.c0000644000175000017500000000113013546663605014043 0ustar benben/* * pread.c * * Some architectures need to wrap the system call */ #include #include #include #if defined(__hppa__) #if _BITSIZE == 32 extern size_t __pread(int, void *, size_t, unsigned int, unsigned int); #else extern size_t __pread(int, void *, size_t, off_t); #endif size_t pread(int fd, void *buf, size_t count, off_t offset) { #if _BITSIZE == 32 unsigned int hi = offset >> 32; unsigned int lo = (unsigned int) offset; return __pread(fd, buf, count, __LONG_LONG_PAIR(hi, lo)); #else return __pread(fd, buf, count, offset); #endif } #endif klibc-2.0.7/usr/klibc/ppoll.c0000644000175000017500000000055113546663605014104 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/poll.c0000644000175000017500000000065213546663605013726 0ustar benben#include #include #include #ifndef __NR_poll int poll(struct pollfd *fds, nfds_t nfds, long timeout) { struct timespec timeout_ts; struct timespec *timeout_ts_p = NULL; if (timeout >= 0) { timeout_ts.tv_sec = timeout / 1000; timeout_ts.tv_nsec = (timeout % 1000) * 1000000; timeout_ts_p = &timeout_ts; } return ppoll(fds, nfds, timeout_ts_p, 0); } #endif /* __NR_poll */ klibc-2.0.7/usr/klibc/pipe.c0000644000175000017500000000022013546663605013704 0ustar benben#include #include #ifndef __NR_pipe int pipe(int pipefd[2]) { return pipe2(pipefd, 0); } #endif /* __NR_pipe */ klibc-2.0.7/usr/klibc/perror.c0000644000175000017500000000025413546663605014267 0ustar benben/* * perror.c */ #include #include #include void perror(const char *s) { int e = errno; fprintf(stderr, "%s: %s\n", s, strerror(e)); } klibc-2.0.7/usr/klibc/pause.c0000644000175000017500000000030613546663605014071 0ustar benben/* * pause.c */ #include #include #include #include #ifndef __NR_pause int pause(void) { return select(0, NULL, NULL, NULL, NULL); } #endif klibc-2.0.7/usr/klibc/openat.c0000644000175000017500000000100013546663605014232 0ustar benben/* * 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(__m68k__) && 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 klibc-2.0.7/usr/klibc/open.c0000644000175000017500000000175013546663605013721 0ustar benben/* * 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. * * For 64 bit systems without the open syscall, pass straight * through into openat. */ #define _KLIBC_IN_OPEN_C #include #include #include #include #ifndef __NR_open #if _BITSIZE == 32 extern int __openat(int, const char *, int, mode_t); int open(const char *pathname, int flags, mode_t mode) { return __openat(AT_FDCWD, pathname, flags | O_LARGEFILE, mode); } #else __extern int openat(int, const char *, int, ...); int open(const char *pathname, int flags, mode_t mode) { return openat(AT_FDCWD, pathname, flags, mode); } #endif /* _BITSIZE == 32 */ #elif _BITSIZE == 32 && !defined(__i386__) && !defined(__m68k__) 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 /* __NR_open */ klibc-2.0.7/usr/klibc/onexit.c0000644000175000017500000000046413546663605014267 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/nullenv.c0000644000175000017500000000014513546663605014440 0ustar benben/* * nullenv.c */ #include #include "env.h" char * const __null_environ[] = { NULL }; klibc-2.0.7/usr/klibc/nrand48.c0000644000175000017500000000023013546663605014226 0ustar benben/* * nrand48.c */ #include #include long nrand48(unsigned short xsubi[3]) { return (long)((uint32_t) jrand48(xsubi) >> 1); } klibc-2.0.7/usr/klibc/nice.c0000644000175000017500000000040613546663605013673 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/mrand48.c0000644000175000017500000000027613546663605014237 0ustar benben/* * mrand48.c */ #include #include unsigned short __rand48_seed[3]; /* Common with lrand48.c, srand48.c */ long mrand48(void) { return jrand48(__rand48_seed); } klibc-2.0.7/usr/klibc/mmap.c0000644000175000017500000000164013546663605013710 0ustar benben/* * 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_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 klibc-2.0.7/usr/klibc/mknod.c0000644000175000017500000000041113546663605014061 0ustar benben#include #include #include #include #include #ifndef __NR_mknod int mknod(const char *pathname, mode_t mode, dev_t dev) { return mknodat(AT_FDCWD, pathname, mode, dev); } #endif /* __NR_mknod */ klibc-2.0.7/usr/klibc/mkdir.c0000644000175000017500000000036713546663605014071 0ustar benben#include #include #include #include #include #ifndef __NR_mkdir int mkdir(const char *pathname, mode_t mode) { return mkdirat(AT_FDCWD, pathname, mode); } #endif /* __NR_mkdir */ klibc-2.0.7/usr/klibc/memswap.c0000644000175000017500000000045313546663605014430 0ustar benben/* * 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++; } } klibc-2.0.7/usr/klibc/memset.c0000644000175000017500000000113213546663605014244 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/memrchr.c0000644000175000017500000000041413546663605014411 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/memmove.c0000644000175000017500000000102713546663605014422 0ustar benben/* * 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; cld" : "+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; } klibc-2.0.7/usr/klibc/memmem.c0000644000175000017500000000156213546663605014236 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/memcpy.c0000644000175000017500000000106013546663605014244 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/memcmp.c0000644000175000017500000000035013546663605014231 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/memchr.c0000644000175000017500000000035313546663605014231 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/memccpy.c0000644000175000017500000000046513546663605014417 0ustar benben/* * 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 */ } klibc-2.0.7/usr/klibc/malloc.h0000644000175000017500000000172313546663605014234 0ustar benben/* * 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; 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; }; /* * Internal variable used by brk/sbrk */ extern char *__current_brk; klibc-2.0.7/usr/klibc/malloc.c0000644000175000017500000001562713546663605014237 0ustar benben/* * malloc.c * * Very simple linked-list based malloc()/free(). */ #include #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. */ static struct free_arena_header __malloc_head = { { ARENA_TYPE_HEAD, 0, &__malloc_head, &__malloc_head, }, &__malloc_head, &__malloc_head }; static inline void mark_block_dead(struct free_arena_header *ah) { #ifdef DEBUG_MALLOC ah->a.type = ARENA_TYPE_DEAD; #endif } static inline void remove_from_main_chain(struct free_arena_header *ah) { struct free_arena_header *ap, *an; mark_block_dead(ah); ap = ah->a.prev; an = ah->a.next; ap->a.next = an; an->a.prev = ap; } static inline void remove_from_free_chain(struct free_arena_header *ah) { struct free_arena_header *ap, *an; ap = ah->prev_free; an = ah->next_free; ap->next_free = an; an->prev_free = ap; } static inline void remove_from_chains(struct free_arena_header *ah) { remove_from_free_chain(ah); remove_from_main_chain(ah); } static void *__malloc_from_block(struct free_arena_header *fp, size_t size) { size_t fsize; struct free_arena_header *nfp, *na, *fpn, *fpp; 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 = fpn = fp->next_free; nfp->prev_free = fpp = fp->prev_free; fpn->prev_free = nfp; fpp->next_free = nfp; } else { fp->a.type = ARENA_TYPE_USED; /* Allocate the whole block */ remove_from_free_chain(fp); } 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; mark_block_dead(ah); 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 */ remove_from_chains(nah); } /* 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 /* Merge into adjacent free blocks */ ah = __free_block(ah); /* See if it makes sense to return memory to the system */ #if _KLIBC_MALLOC_USES_SBRK if (ah->a.size >= _KLIBC_MALLOC_CHUNK_SIZE && (char *)ah + ah->a.size == __current_brk) { remove_from_chains(ah); brk(ah); } #else { size_t page_size = getpagesize(); size_t page_mask = page_size - 1; size_t head_portion = -(size_t)ah & page_mask; size_t tail_portion = ((size_t)ah + ah->a.size) & page_mask; size_t adj_size; /* Careful here... an individual chunk of memory must have a minimum size if it exists at all, so if either the head or the tail is below the minimum, then extend that chunk by a page. */ if (head_portion && head_portion < 2*sizeof(struct arena_header)) head_portion += page_size; if (tail_portion && tail_portion < 2*sizeof(struct arena_header)) tail_portion += page_size; adj_size = ah->a.size - head_portion - tail_portion; /* Worth it? This is written the way it is to guard against overflows... */ if (ah->a.size >= head_portion+tail_portion+ _KLIBC_MALLOC_CHUNK_SIZE) { struct free_arena_header *tah, *tan, *tap; if (tail_portion) { /* Make a new header, and insert into chains immediately after the current block */ tah = (struct free_arena_header *) ((char *)ah + head_portion + adj_size); tah->a.type = ARENA_TYPE_FREE; tah->a.size = tail_portion; tah->a.next = tan = ah->a.next; tan->a.prev = tah; tah->a.prev = ah; ah->a.next = tah; tah->prev_free = tap = ah->prev_free; tap->next_free = tah; tah->next_free = ah; ah->prev_free = tah; } if (head_portion) ah->a.size = head_portion; else remove_from_chains(ah); munmap((char *)ah + head_portion, adj_size); } } #endif } klibc-2.0.7/usr/klibc/makeerrlist.pl0000644000175000017500000000454213546663605015475 0ustar benben#!/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"; } klibc-2.0.7/usr/klibc/lstat.c0000644000175000017500000000041213546663605014101 0ustar benben#include #include #include #include #include #ifndef __NR_lstat int lstat(const char *path, struct stat *buf) { return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW); } #endif /* __NR_lstat */ klibc-2.0.7/usr/klibc/lseek.c0000644000175000017500000000131513546663605014060 0ustar benben/* * lseek.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) { unsigned long long ullo = offset; off_t result; int rv; rv = __llseek(fd, (unsigned long)(ullo >> 32), (unsigned long)ullo, &result, whence); return rv ? (off_t)-1 : result; } #endif klibc-2.0.7/usr/klibc/lrand48.c0000644000175000017500000000031613546663605014231 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/link.c0000644000175000017500000000033513546663605013713 0ustar benben#include #include #include #ifndef __NR_link int link(const char *oldpath, const char *newpath) { return linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0); } #endif /* __NR_link */ klibc-2.0.7/usr/klibc/libgcc/0000755000175000017500000000000013546663605014034 5ustar benbenklibc-2.0.7/usr/klibc/libgcc/__umodsi3.c0000644000175000017500000000040113546663605016054 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__umoddi3.c0000644000175000017500000000041313546663605016040 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__udivsi3.c0000644000175000017500000000035213546663605016064 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/libgcc/__udivmodsi4.c0000644000175000017500000000074313546663605016571 0ustar benben#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; } klibc-2.0.7/usr/klibc/libgcc/__udivmoddi4.c0000644000175000017500000000074313546663605016552 0ustar benben#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; } klibc-2.0.7/usr/klibc/libgcc/__udivdi3.c0000644000175000017500000000036413546663605016050 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/libgcc/__modsi3.c0000644000175000017500000000061613546663605015677 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__moddi3.c0000644000175000017500000000063013546663605015654 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__lshrdi3.c0000644000175000017500000000053713546663605016053 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__divsi3.c0000644000175000017500000000060013546663605015673 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__divdi3.c0000644000175000017500000000061213546663605015657 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__clzsi2.c0000644000175000017500000000062213546663605015704 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__ashrdi3.c0000644000175000017500000000060413546663605016033 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libgcc/__ashldi3.c0000644000175000017500000000053713546663605016032 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/libc_init.c0000644000175000017500000000534413546663605014717 0ustar benben/* * 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 #include #include "atexit.h" #if _KLIBC_HAS_ARCHINIT # include "klibc/archinit.h" #else # define __libc_archinit() ((void)0) #endif /* 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 { unsigned long type; unsigned long v; }; extern void __libc_init_stdio(void); unsigned long __auxval[_AUXVAL_MAX]; __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) { if (auxentry->type < _AUXVAL_MAX) __auxval[auxentry->type] = auxentry->v; auxentry++; } #if SHARED MAIN = (main_t) __auxval[AT_ENTRY]; #endif __page_size = page_size = __auxval[AT_PAGESZ]; #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; #if _KLIBC_HAS_ARCHINIT __libc_archinit(); #endif __libc_init_stdio(); environ = envp; exit(MAIN(argc, argv, envp)); } klibc-2.0.7/usr/klibc/lchown.c0000644000175000017500000000036013546663605014246 0ustar benben#include #include #include #ifndef __NR_lchown int lchown(const char *path, uid_t owner, gid_t group) { return fchownat(AT_FDCWD, path, owner, group, AT_SYMLINK_NOFOLLOW); } #endif /* __NR_lchown */ klibc-2.0.7/usr/klibc/jrand48.c0000644000175000017500000000077513546663605014240 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/isatty.c0000644000175000017500000000036413546663605014275 0ustar benben/* * isatty.c */ #include #include #include int isatty(int fd) { struct termios dummy; /* All ttys support TIOCGPGRP */ /* except /dev/console which needs TCGETS */ return !ioctl(fd, TCGETS, &dummy); } klibc-2.0.7/usr/klibc/interp.S0000644000175000017500000000045413546663605014241 0ustar benben# # 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 klibc-2.0.7/usr/klibc/inet/0000755000175000017500000000000013546663605013550 5ustar benbenklibc-2.0.7/usr/klibc/inet/inet_pton.c0000644000175000017500000000256513546663605015723 0ustar benben/* * 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; } } klibc-2.0.7/usr/klibc/inet/inet_ntop.c0000644000175000017500000000170313546663605015714 0ustar benben/* * inet/inet_ntop.c */ #include #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; } klibc-2.0.7/usr/klibc/inet/inet_ntoa.c0000644000175000017500000000043213546663605015673 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/inet/inet_aton.c0000644000175000017500000000054613546663605015701 0ustar benben/* * 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; } } klibc-2.0.7/usr/klibc/inet/inet_addr.c0000644000175000017500000000030613546663605015644 0ustar benben/* * 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 ? a.s_addr : INADDR_NONE; } klibc-2.0.7/usr/klibc/inet/bindresvport.c0000644000175000017500000000151113546663605016433 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/globals.c0000644000175000017500000000020313546663605014373 0ustar benben/* * globals.c * * These have to be defined somewhere... */ #include #include int errno; char **environ; klibc-2.0.7/usr/klibc/getpriority.c0000644000175000017500000000066213546663605015342 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/getpgrp.c0000644000175000017500000000012613546663605014424 0ustar benben/* * getpgrp.c */ #include pid_t getpgrp(void) { return getpgid(0); } klibc-2.0.7/usr/klibc/getopt_long.c0000644000175000017500000000623013546663605015277 0ustar benben/* * getopt.c * * getopt_long(), or at least a common subset thereof: * * - Option reordering is not supported * - -W foo is not supported * - First optstring character "-" not supported. */ #include #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; static inline const char *option_matches(const char *arg_str, const char *opt_name) { while (*arg_str != '\0' && *arg_str != '=') { if (*arg_str++ != *opt_name++) return NULL; } if (*opt_name) return NULL; return arg_str; } int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longindex) { 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] == '-') { const struct option *lo; const char *opt_end = NULL; optind++; /* Either it's a long option, or it's -- */ if (!carg[2]) { /* It's -- */ return -1; } for (lo = longopts; lo->name; lo++) { if ((opt_end = option_matches(carg+2, lo->name))) break; } if (!opt_end) return '?'; if (longindex) *longindex = lo-longopts; if (*opt_end == '=') { if (lo->has_arg) optarg = (char *)opt_end+1; else return '?'; } else if (lo->has_arg == 1) { if (!(optarg = argv[optind])) return '?'; optind++; } if (lo->flag) { *lo->flag = lo->val; return 0; } else { return lo->val; } } 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 '?'; } } klibc-2.0.7/usr/klibc/getopt.c0000644000175000017500000000416713546663605014267 0ustar benben/* * 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 '?'; } } klibc-2.0.7/usr/klibc/getmntent.c0000644000175000017500000000227013546663605014763 0ustar benben#include #include #include #include #define BUFLEN 1024 struct mntent *getmntent_r(FILE *fp, struct mntent *mntbuf, char *buf, int buflen) { char *line = NULL, *saveptr = NULL; const char *sep = " \t\n"; if (!fp || !mntbuf || !buf) return NULL; while ((line = fgets(buf, buflen, fp)) != NULL) { if (buf[0] == '#' || buf[0] == '\n') continue; break; } if (!line) return NULL; mntbuf->mnt_fsname = strtok_r(buf, sep, &saveptr); if (!mntbuf->mnt_fsname) return NULL; mntbuf->mnt_dir = strtok_r(NULL, sep, &saveptr); if (!mntbuf->mnt_fsname) return NULL; mntbuf->mnt_type = strtok_r(NULL, sep, &saveptr); if (!mntbuf->mnt_type) return NULL; mntbuf->mnt_opts = strtok_r(NULL, sep, &saveptr); if (!mntbuf->mnt_opts) mntbuf->mnt_opts = ""; line = strtok_r(NULL, sep, &saveptr); mntbuf->mnt_freq = !line ? 0 : atoi(line); line = strtok_r(NULL, sep, &saveptr); mntbuf->mnt_passno = !line ? 0 : atoi(line); return mntbuf; } struct mntent *getmntent(FILE *fp) { static char *buf = NULL; static struct mntent mntbuf; buf = malloc(BUFLEN); if (!buf) perror("malloc"); return getmntent_r(fp, &mntbuf, buf, BUFLEN); } klibc-2.0.7/usr/klibc/gethostname.c0000644000175000017500000000047713546663605015303 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/getenv.c0000644000175000017500000000050013546663605014240 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/getdomainname.c0000644000175000017500000000050713546663605015567 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/getcwd.c0000644000175000017500000000041613546663605014233 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/fwrite2.c0000644000175000017500000000035513546663605014342 0ustar benben/* * fwrite2.c * * The actual fwrite() function as a non-inline */ #define __NO_STDIO_INLINES #include size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * f) { return _fwrite(ptr, size * nmemb, f) / size; } klibc-2.0.7/usr/klibc/fstatfs.c0000644000175000017500000000046113546663605014430 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/fread2.c0000644000175000017500000000034313546663605014120 0ustar benben/* * fread2.c * * The actual fread() function as a non-inline */ #define __NO_STDIO_INLINES #include size_t fread(void *ptr, size_t size, size_t nmemb, FILE * f) { return _fread(ptr, size * nmemb, f) / size; } klibc-2.0.7/usr/klibc/fputs.c0000644000175000017500000000043413546663605014117 0ustar benben/* * 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); } klibc-2.0.7/usr/klibc/fputc.c0000644000175000017500000000030313546663605014072 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/fprintf.c0000644000175000017500000000036713546663605014433 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/fork.c0000644000175000017500000000055413546663605013722 0ustar benben/* * 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 */ klibc-2.0.7/usr/klibc/fnmatch.c0000644000175000017500000000242313546663605014376 0ustar benben/* * fnmatch.c * * Original implementation by Kay Sievers, modified by H. Peter Anvin. */ #include int fnmatch(const char *p, const char *s, int flags) { if (flags & FNM_PATHNAME && *s == '/') return (*p != '/') || fnmatch(p+1, s+1, flags); if (flags & FNM_PERIOD && *s == '.') return (*p != '.') || fnmatch(p+1, s+1, flags); flags &= ~FNM_PERIOD; /* Only applies at beginning */ if (!(flags & FNM_NOESCAPE) && *p == '\\') { p++; return (*p != *s) || fnmatch(p+1, s+1, flags); } if (*s == '\0') { while (*p == '*') p++; return (*p != '\0'); } switch (*p) { case '[': { int not = 0; p++; if (*p == '!') { not = 1; p++; } while ((*p != '\0') && (*p != ']')) { int match = 0; if (p[1] == '-') { if ((*s >= *p) && (*s <= p[2])) match = 1; p += 3; } else { match = (*p == *s); p++; } if (match ^ not) { while ((*p != '\0') && (*p != ']')) p++; if (*p == ']') return fnmatch(p+1, s+1, flags); } } } break; case '*': if (fnmatch(p, s+1, flags)) return fnmatch(p+1, s, flags); return 0; case '\0': if (*s == '\0') { return 0; } break; default: if ((*p == *s) || (*p == '?')) return fnmatch(p+1, s+1, flags); break; } return 1; } klibc-2.0.7/usr/klibc/fgets.c0000644000175000017500000000041313546663605014063 0ustar benben/* * fgets.c */ #include char *fgets(char *s, int n, FILE *f) { int ch; char *p = s; while (n > 1) { ch = getc(f); if (ch == EOF) { s = NULL; break; } *p++ = ch; n--; if (ch == '\n') break; } if (n) *p = '\0'; return s; } klibc-2.0.7/usr/klibc/exit.c0000644000175000017500000000123013546663605013722 0ustar benben/* * exit.c * * exit(), including the handling of the atexit chain. */ #include #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... */ fflush(NULL); _exit(rv); } klibc-2.0.7/usr/klibc/execvpe.c0000644000175000017500000000364013546663605014417 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/execvp.c0000644000175000017500000000020313546663605014242 0ustar benben/* * execvp.c */ #include int execvp(const char *path, char *const *argv) { return execvpe(path, argv, environ); } klibc-2.0.7/usr/klibc/execv.c0000644000175000017500000000020013546663605014057 0ustar benben/* * execv.c */ #include int execv(const char *path, char *const *argv) { return execve(path, argv, environ); } klibc-2.0.7/usr/klibc/execlpe.c0000644000175000017500000000014013546663605014375 0ustar benben/* * execlpe.c */ #define NAME execlpe #define EXEC_P 1 #define EXEC_E 1 #include "exec_l.c" klibc-2.0.7/usr/klibc/execlp.c0000644000175000017500000000013613546663605014235 0ustar benben/* * execlp.c */ #define NAME execlp #define EXEC_P 1 #define EXEC_E 0 #include "exec_l.c" klibc-2.0.7/usr/klibc/execle.c0000644000175000017500000000013613546663605014222 0ustar benben/* * execle.c */ #define NAME execle #define EXEC_P 0 #define EXEC_E 1 #include "exec_l.c" klibc-2.0.7/usr/klibc/execl.c0000644000175000017500000000013413546663605014053 0ustar benben/* * execl.c */ #define NAME execl #define EXEC_P 0 #define EXEC_E 0 #include "exec_l.c" klibc-2.0.7/usr/klibc/exec_l.c0000644000175000017500000000176313546663605014223 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/env.h0000644000175000017500000000036313546663605013554 0ustar benben#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 klibc-2.0.7/usr/klibc/endmntent.c0000644000175000017500000000014613546663605014752 0ustar benben#include #include int endmntent(FILE *fp) { if (fp) fclose(fp); return 1; } klibc-2.0.7/usr/klibc/dup2.c0000644000175000017500000000022113546663605013622 0ustar benben#include #include #ifndef __NR_dup2 int dup2(int fd, int fd2) { return dup3(fd, fd2, 0); } #endif /* __NR_dup2 */ klibc-2.0.7/usr/klibc/daemon.c0000644000175000017500000000075713546663605014231 0ustar benben/* * 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(); } klibc-2.0.7/usr/klibc/ctypes.c0000644000175000017500000003030413546663605014264 0ustar benben/* * 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 */ }; klibc-2.0.7/usr/klibc/ctype/0000755000175000017500000000000013546663605013735 5ustar benbenklibc-2.0.7/usr/klibc/ctype/toupper.c0000644000175000017500000000005213546663605015574 0ustar benben#include "ctypefunc.h" CTYPEFUNC(toupper) klibc-2.0.7/usr/klibc/ctype/tolower.c0000644000175000017500000000005213546663605015571 0ustar benben#include "ctypefunc.h" CTYPEFUNC(tolower) klibc-2.0.7/usr/klibc/ctype/isxdigit.c0000644000175000017500000000005313546663605015723 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isxdigit) klibc-2.0.7/usr/klibc/ctype/isupper.c0000644000175000017500000000005213546663605015565 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isupper) klibc-2.0.7/usr/klibc/ctype/isspace.c0000644000175000017500000000005213546663605015525 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isspace) klibc-2.0.7/usr/klibc/ctype/ispunct.c0000644000175000017500000000005213546663605015563 0ustar benben#include "ctypefunc.h" CTYPEFUNC(ispunct) klibc-2.0.7/usr/klibc/ctype/isprint.c0000644000175000017500000000005213546663605015566 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isprint) klibc-2.0.7/usr/klibc/ctype/islower.c0000644000175000017500000000005213546663605015562 0ustar benben#include "ctypefunc.h" CTYPEFUNC(islower) klibc-2.0.7/usr/klibc/ctype/isgraph.c0000644000175000017500000000005213546663605015533 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isgraph) klibc-2.0.7/usr/klibc/ctype/isdigit.c0000644000175000017500000000005213546663605015532 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isdigit) klibc-2.0.7/usr/klibc/ctype/iscntrl.c0000644000175000017500000000005213546663605015554 0ustar benben#include "ctypefunc.h" CTYPEFUNC(iscntrl) klibc-2.0.7/usr/klibc/ctype/isblank.c0000644000175000017500000000005213546663605015521 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isblank) klibc-2.0.7/usr/klibc/ctype/isascii.c0000644000175000017500000000005213546663605015522 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isascii) klibc-2.0.7/usr/klibc/ctype/isalpha.c0000644000175000017500000000005213546663605015517 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isalpha) klibc-2.0.7/usr/klibc/ctype/isalnum.c0000644000175000017500000000005213546663605015546 0ustar benben#include "ctypefunc.h" CTYPEFUNC(isalnum) klibc-2.0.7/usr/klibc/ctype/ctypefunc.h0000644000175000017500000000031613546663605016106 0ustar benben/* * 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); \ } klibc-2.0.7/usr/klibc/creat.c0000644000175000017500000000030113546663605014045 0ustar benben/* * creat.c */ #include #include #include int creat(const char *pathname, mode_t mode) { return open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); } klibc-2.0.7/usr/klibc/closelog.c0000644000175000017500000000030613546663605014563 0ustar benben/* * closelog.c */ #include #include extern int __syslog_fd; void closelog(void) { int logfd = __syslog_fd; if (logfd != -1) { close(logfd); __syslog_fd = -1; } } klibc-2.0.7/usr/klibc/clearenv.c0000644000175000017500000000042113546663605014551 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/chown.c0000644000175000017500000000033513546663605014074 0ustar benben#include #include #include #ifndef __NR_chown int chown(const char *path, uid_t owner, gid_t group) { return fchownat(AT_FDCWD, path, owner, group, 0); } #endif /* __NR_chown */ klibc-2.0.7/usr/klibc/chmod.c0000644000175000017500000000034013546663605014044 0ustar benben#include #include #include #include #ifndef __NR_chmod int chmod(const char *path, mode_t mode) { return fchmodat(AT_FDCWD, path, mode, 0); } #endif /* __NR_chmod */ klibc-2.0.7/usr/klibc/calloc.c0000644000175000017500000000030213546663605014205 0ustar benben/* * calloc.c */ #include #include /* FIXME: This should look for multiplication overflow */ void *calloc(size_t nmemb, size_t size) { return zalloc(nmemb * size); } klibc-2.0.7/usr/klibc/bzero.c0000644000175000017500000000011513546663605014073 0ustar benben#include void bzero(void *dst, size_t n) { memset(dst, 0, n); } klibc-2.0.7/usr/klibc/bsearch.c0000644000175000017500000000070213546663605014363 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/bsd_signal.c0000644000175000017500000000042013546663605015056 0ustar benben/* * bsd_signal.c */ #include __sighandler_t bsd_signal(int signum, __sighandler_t handler) { /* BSD signal() semantics */ return __signal(signum, handler, SA_RESTART); } __sighandler_t signal(int signum, __sighandler_t handler) __alias("bsd_signal"); klibc-2.0.7/usr/klibc/brk.c0000644000175000017500000000103513546663605013532 0ustar benben/* brk.c - Change data segment size */ /* Written 2000 by Werner Almesberger */ #include #include #include #include "malloc.h" #if !_KLIBC_NO_MMU /* uClinux doesn't have brk() */ char *__current_brk; /* * 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; } #endif klibc-2.0.7/usr/klibc/atox.c0000644000175000017500000000031713546663605013731 0ustar benben/* * atox.c * * atoi(), atol(), atoll() */ #include #include #include TYPE NAME(const char *nptr) { return (TYPE) strntoumax(nptr, (char **)NULL, 10, ~(size_t) 0); } klibc-2.0.7/usr/klibc/atoll.c0000644000175000017500000000007413546663605014071 0ustar benben#define TYPE long long #define NAME atoll #include "atox.c" klibc-2.0.7/usr/klibc/atol.c0000644000175000017500000000006613546663605013716 0ustar benben#define TYPE long #define NAME atol #include "atox.c" klibc-2.0.7/usr/klibc/atoi.c0000644000175000017500000000006513546663605013712 0ustar benben#define TYPE int #define NAME atoi #include "atox.c" klibc-2.0.7/usr/klibc/atexit.h0000644000175000017500000000042213546663605014256 0ustar benben/* * 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 */ klibc-2.0.7/usr/klibc/atexit.c0000644000175000017500000000020113546663605014244 0ustar benben/* * atexit.c */ #include int atexit(void (*fctn) (void)) { return on_exit((void (*)(int, void *))fctn, NULL); } klibc-2.0.7/usr/klibc/assert.c0000644000175000017500000000042013546663605014252 0ustar benben/* * 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(); } klibc-2.0.7/usr/klibc/asprintf.c0000644000175000017500000000036413546663605014606 0ustar benben/* * asprintf.c */ #include #include #include int asprintf(char **bufp, const char *format, ...) { va_list ap; int rv; va_start(ap, format); rv = vasprintf(bufp, format, ap); va_end(ap); return rv; } klibc-2.0.7/usr/klibc/arch/0000755000175000017500000000000013546663605013526 5ustar benbenklibc-2.0.7/usr/klibc/arch/x86_64/0000755000175000017500000000000013546663605014464 5ustar benbenklibc-2.0.7/usr/klibc/arch/x86_64/vfork.S0000644000175000017500000000062513546663605015742 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/x86_64/sysstub.ph0000644000175000017500000000111013546663605016522 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/x86_64/syscall.S0000644000175000017500000000106013546663605016257 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/x86_64/sigreturn.S0000644000175000017500000000032413546663605016631 0ustar benben/* * arch/x86_64/sigreturn.S */ #include .text .align 4 .globl __sigreturn .type __sigreturn,@function __sigreturn: movl $__NR_rt_sigreturn,%eax syscall .size __sigreturn,.-__sigreturn klibc-2.0.7/usr/klibc/arch/x86_64/setjmp.S0000644000175000017500000000164413546663605016117 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/x86_64/crt0.S0000644000175000017500000000067013546663605015463 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/x86_64/MCONFIG0000644000175000017500000000251513546663605015474 0ustar benben# -*- 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 KLIBCOPTFLAGS += -Os -fomit-frame-pointer -mno-sse \ -falign-functions=1 -falign-jumps=1 -falign-loops=1 ifeq ($(DEBUG),y) KLIBCOPTFLAGS += -g else KLIBCOPTFLAGS += -fno-asynchronous-unwind-tables 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 # # binutils now uses max-page-size=0x200000 by default, which pushes # klibc.so data over the 4 MB mark, overlapping the executable. # The old default was max-page-size=0x100000, but that also results # in a broken layout with binutils 2.30. Since there's no # architectural page size betwen 4 KB and 2MB, set it to 4 KB. KLIBCSHAREDFLAGS = -Ttext-segment 0x00200000 -z max-page-size=0x1000 klibc-2.0.7/usr/klibc/arch/x86_64/Kbuild0000644000175000017500000000020513546663605015616 0ustar benben# -*- makefile -*- # # klibc files for x86_64 always := crt0.o targets := crt0.o klib-y := setjmp.o syscall.o sigreturn.o vfork.o klibc-2.0.7/usr/klibc/arch/sparc64/0000755000175000017500000000000013546663605015010 5ustar benbenklibc-2.0.7/usr/klibc/arch/sparc64/sysstub.ph0000644000175000017500000000112113546663605017050 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/sparc64/sysfork.S0000644000175000017500000000102213546663605016627 0ustar benben/* * 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 */ #include .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 PIC_PROLOGUE(%g1,%g4) SET(errno,%g1,%g4) st %o0, [%g4] retl mov -1, %o0 1: retl nop klibc-2.0.7/usr/klibc/arch/sparc64/syscall.S0000644000175000017500000000052313546663605016606 0ustar benben/* * arch/sparc64/syscall.S * * Common system-call stub; %g1 already set to syscall number */ #include .globl __syscall_common .type __syscall_common,#function .align 4 __syscall_common: t 0x6d bcc %xcc, 1f PIC_PROLOGUE(%g1,%g4) SET(errno,%g1,%g4) st %o0,[%g4] 1: retl movcs %xcc, -1, %o0 klibc-2.0.7/usr/klibc/arch/sparc64/setjmp.S0000644000175000017500000000174013546663605016440 0ustar benben! ! 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 klibc-2.0.7/usr/klibc/arch/sparc64/pipe.S0000644000175000017500000000072013546663605016070 0ustar benben/* * arch/sparc64/pipe.S * * The pipe system call are special on sparc[64]: * they return the two file descriptors in %o0 and %o1. */ #include #include .globl pipe .type pipe,#function .align 4 pipe: mov __NR_pipe, %g1 or %o0, 0, %g4 t 0x6d bcc %xcc, 1f nop PIC_PROLOGUE(%g1,%g4) SET(errno,%g1,%g4) st %o0,[%g4] retl mov -1, %o0 1: st %o0,[%g4] st %o1,[%g4+4] retl mov 0, %o0 .size pipe,.-pipe klibc-2.0.7/usr/klibc/arch/sparc64/crt0.S0000644000175000017500000000006713546663605016007 0ustar benben#define TARGET_PTR_SIZE 64 #include "../sparc/crt0i.S" klibc-2.0.7/usr/klibc/arch/sparc64/MCONFIG0000644000175000017500000000125713546663605016022 0ustar benben# -*- 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-segment 0x80000000 klibc-2.0.7/usr/klibc/arch/sparc64/Kbuild0000644000175000017500000000016213546663605016144 0ustar benben# # klibc files for sparc64 # klib-y := pipe.o setjmp.o syscall.o sysfork.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/sparc/0000755000175000017500000000000013546663605014636 5ustar benbenklibc-2.0.7/usr/klibc/arch/sparc/umul.S0000644000175000017500000001477313546663605015760 0ustar benben/* $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 klibc-2.0.7/usr/klibc/arch/sparc/sysstub.ph0000644000175000017500000000112113546663605016676 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/sparc/sysfork.S0000644000175000017500000000100113546663605016452 0ustar benben/* * 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 */ #include .globl __syscall_forkish .type __syscall_forkish,#function .align 4 __syscall_forkish: t 0x10 sub %o1, 1, %o1 bcc,a 1f and %o0, %o1, %o0 PIC_PROLOGUE(%g1,%g4) SET(errno,%g1,%g4) st %o0,[%g4] mov -1, %o0 1: retl nop klibc-2.0.7/usr/klibc/arch/sparc/syscall.S0000644000175000017500000000051013546663605016430 0ustar benben/* * arch/sparc/syscall.S * * Common system-call stub; %g1 already set to syscall number */ #include .globl __syscall_common .type __syscall_common,#function .align 4 __syscall_common: t 0x10 bcc 1f PIC_PROLOGUE(%g1,%g4) SET(errno,%g1,%g4) st %o0,[%g4] mov -1, %o0 1: retl nop klibc-2.0.7/usr/klibc/arch/sparc/smul.S0000644000175000017500000001226613546663605015751 0ustar benben/* $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 klibc-2.0.7/usr/klibc/arch/sparc/setjmp.S0000644000175000017500000000150713546663605016267 0ustar benben! ! 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 klibc-2.0.7/usr/klibc/arch/sparc/pipe.S0000644000175000017500000000071013546663605015715 0ustar benben/* * arch/sparc/pipe.S * * The pipe system call are special on sparc[64]: * they return the two file descriptors in %o0 and %o1. */ #include #include .globl pipe .type pipe,#function .align 4 pipe: mov __NR_pipe, %g1 or %o0, 0, %g4 t 0x10 bcc 1f nop PIC_PROLOGUE(%g1,%g4) SET(errno,%g1,%g4) st %o0,[%g4] retl mov -1, %o0 1: st %o0,[%g4] st %o1,[%g4+4] retl mov 0, %o0 .size pipe,.-pipe klibc-2.0.7/usr/klibc/arch/sparc/divrem.m40000644000175000017500000001757013546663605016400 0ustar benben/* * 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') klibc-2.0.7/usr/klibc/arch/sparc/crt0i.S0000644000175000017500000000510313546663605016002 0ustar benben! 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 klibc-2.0.7/usr/klibc/arch/sparc/crt0.S0000644000175000017500000000005613546663605015633 0ustar benben#define TARGET_PTR_SIZE 32 #include "crt0i.S" klibc-2.0.7/usr/klibc/arch/sparc/__muldi3.S0000644000175000017500000000065113546663605016457 0ustar benben .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 klibc-2.0.7/usr/klibc/arch/sparc/MCONFIG0000644000175000017500000000120413546663605015640 0ustar benben# -*- 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-segment 0x40000000 klibc-2.0.7/usr/klibc/arch/sparc/Kbuild0000644000175000017500000000210613546663605015772 0ustar benben# # klibc files for sparc # always := crt0.o targets := crt0.o m4-targets := sdiv.o srem.o udiv.o urem.o klib-y := $(m4-targets) smul.o umul.o __muldi3.o klib-y += setjmp.o pipe.o syscall.o sysfork.o klib-y += ../../libgcc/__ashldi3.o ../../libgcc/__ashrdi3.o klib-y += ../../libgcc/__lshrdi3.o ../../libgcc/__divdi3.o klib-y += ../../libgcc/__moddi3.o ../../libgcc/__udivdi3.o klib-y += ../../libgcc/__umoddi3.o ../../libgcc/__udivmoddi4.o klib-y += ../../libgcc/__clzsi2.o $(obj)/sdiv.S: m4 := define(NAME,\`.div')define(OP,\`div')define(S,\`true') $(obj)/srem.S: m4 := define(NAME,\`.rem')define(OP,\`rem')define(S,\`true') $(obj)/udiv.S: m4 := define(NAME,\`.udiv')define(OP,\`div')define(S,\`false') $(obj)/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)): $(obj)/%.o : $(obj)/%.S # build .S from .m4 $(addprefix $(obj)/,$(m4-targets:.o=.S)): $(src)/divrem.m4 $(call if_changed,m4) klibc-2.0.7/usr/klibc/arch/sh/0000755000175000017500000000000013546663605014140 5ustar benbenklibc-2.0.7/usr/klibc/arch/sh/sysstub.ph0000644000175000017500000000212513546663605016205 0ustar benben# -*- 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 "\t.import __syscall_common\n"; print OUT "${fname}:\n"; print OUT "\t mov.l\t1f, r3\n"; print OUT "\t jmp\t\@r3\n"; print OUT "#if __NR_${sname} >= 128\n"; print OUT "\t mov.l\t2f, 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 "\t.align\t2\n"; print OUT "\t.import\t__syscall_common\n"; print OUT "1:\t.long\t__syscall_common\n"; print OUT "#if __NR_${sname} >= 128\n"; print OUT "2:\t.long\t__NR_${sname}\n"; print OUT "#endif\n"; close(OUT); } 1; klibc-2.0.7/usr/klibc/arch/sh/syscall.S0000644000175000017500000000116313546663605015737 0ustar benben/* * 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 r0. */ .section ".text.syscall","ax" .align 2 .globl __syscall_common .type __syscall_common,@function __syscall_common: mov.l @(0,sp),r0 mov.l @(4,sp),r1 trapa #0x15 mov.l 1f,r1 cmp/hs r0,r1 bt/s 3f neg r0,r1 mov.l 2f,r2 mov.l r1,@r2 rts mov #-1,r0 3: rts nop .align 2 1: .long -4096 /* Errno limit */ 2: .long errno .size __syscall_common,.-__syscall_common klibc-2.0.7/usr/klibc/arch/sh/setjmp.S0000644000175000017500000000142113546663605015564 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/sh/pipe.S0000644000175000017500000000076313546663605015227 0ustar benben/* * arch/sh/pipe.S * * The pipe system call is special on sh: it returns * the two file descriptors in r0 and r1. */ #include .section ".text.syscall","ax" .align 2 .globl pipe .type pipe,@function pipe: mov #__NR_pipe, r3 trapa #0x10 mov.l 1f,r2 cmp/hs r0,r2 bt/s 3f neg r0,r2 mov.l 2f,r3 mov.l r2,@r3 rts mov #-1,r0 3: mov.l r0, @r4 mov.l r1, @(4, r4) rts mov #0,r0 .align 2 1: .long -4096 /* Errno limit */ 2: .long errno .size pipe,.-pipe klibc-2.0.7/usr/klibc/arch/sh/crt0.S0000644000175000017500000000055713546663605015143 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/sh/MCONFIG0000644000175000017500000000104513546663605015145 0ustar benben# -*- 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. # 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-segment 0x00200000 klibc-2.0.7/usr/klibc/arch/sh/Kbuild0000644000175000017500000000014313546663605015273 0ustar benben# # klibc files for sh # klib-y := pipe.o setjmp.o syscall.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/s390/0000755000175000017500000000000013546663605014224 5ustar benbenklibc-2.0.7/usr/klibc/arch/s390/sysstub.ph0000644000175000017500000000201413546663605016266 0ustar benben# -*- perl -*- # # arch/s390/sysstub.ph # # Script to generate system call stubs # sub make_sysstub($$$$$@) { my($outputdir, $fname, $type, $sname, $stype, @args) = @_; my($t); my($r, $llregs) = (0, ($typesize{'void *'} == 8) ? 1 : 2); foreach $t (@args) { $r += ($typesize{$t} == 8) ? $llregs : 1; } open(OUT, '>', "${outputdir}/${fname}.S"); print OUT < .type ${fname},\@function .globl ${fname} ${fname}: .if ${r} > 6 .print "System call with more than six parameters not supported yet." .err .endif .if ${r} == 6 #ifndef __s390x__ st %r7,56(%r15) l %r7,96(%r15) #else stg %r7,80(%r15) lg %r7,160(%r15) #endif .endif .if __NR_${sname} < 256 svc __NR_${sname} .else la %r1,__NR_${sname} svc 0 .endif .if ${r} == 6 #ifndef __s390x__ l %r7,56(%r15) #else lg %r7,160(%r15) #endif .endif #ifndef __s390x__ bras %r3,1f .long __syscall_common 1: l %r3,0(%r3) br %r3 #else brasl %r3,__syscall_common #endif .size ${fname},.-${fname} EOF close(OUT); } 1; klibc-2.0.7/usr/klibc/arch/s390/syscall.c0000644000175000017500000000046413546663605016046 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/arch/s390/setjmp.S0000644000175000017500000000216513546663605015656 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/s390/mmap.c0000644000175000017500000000313313546663605015322 0ustar benben#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 = { .addr = (unsigned long)addr, .len = (unsigned long)len, .prot = (unsigned long)prot, .flags = (unsigned long)flags, .fd = (unsigned long)fd, .offset = (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 = { .addr = (unsigned long)addr, .len = (unsigned long)len, .prot = (unsigned long)prot, .flags = (unsigned long)flags, .fd = (unsigned long)fd, .offset = (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__ */ klibc-2.0.7/usr/klibc/arch/s390/crt0.S0000644000175000017500000000075013546663605015222 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/s390/MCONFIG0000644000175000017500000000071713546663605015236 0ustar benben# -*- 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-segment 0x40000000 klibc-2.0.7/usr/klibc/arch/s390/Kbuild0000644000175000017500000000072213546663605015362 0ustar benben# # klibc files for s390 # always := crt0.o targets := crt0.o ifneq ("$(KLIBCARCH)", "s390x") klib-y := setjmp.o mmap.o syscall.o klib-y += ../../libgcc/__clzsi2.o ../../libgcc/__ashldi3.o klib-y += ../../libgcc/__ashrdi3.o ../../libgcc/__lshrdi3.o klib-y += ../../libgcc/__divdi3.o ../../libgcc/__moddi3.o klib-y += ../../libgcc/__udivdi3.o ../../libgcc/__umoddi3.o klib-y += ../../libgcc/__udivmoddi4.o else klib-y := setjmp.o mmap.o syscall.o endif klibc-2.0.7/usr/klibc/arch/riscv64/0000755000175000017500000000000013546663605015026 5ustar benbenklibc-2.0.7/usr/klibc/arch/riscv64/sysstub.ph0000644000175000017500000000124713546663605017077 0ustar benben# -*- perl -*- # # arch/riscv/sysstub.ph # # Script to generate system call stubs # # On RISC-V, most system calls follow the standard convention, with the # system call number in x17 (a7) and the return value in x10 (a0). 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 "\n"; print OUT "ENTRY(${fname})\n"; print OUT "\tli\ta7, __NR_${sname}\n"; print OUT "\tj\t__syscall_${stype}\n"; print OUT "END(${fname})\n"; close(OUT); } 1; klibc-2.0.7/usr/klibc/arch/riscv64/syscall.S0000644000175000017500000000032113546663605016620 0ustar benben#include #include ENTRY(__syscall_common) scall li t0, -4096 bleu a0, t0, 1f neg a0, a0 lui t0, %hi(errno) sw a0, %lo(errno)(t0) li a0, -1 1: jr ra END(__syscall_common) klibc-2.0.7/usr/klibc/arch/riscv64/setjmp.S0000644000175000017500000000132313546663605016453 0ustar benben/* * arch/riscv64/setjmp.S * * setjmp/longjmp for the RISC-V (RV64) architecture * * The jmp_buf is assumed to contain the following, in order: * pc (ra) * s0..s11 * sp */ #include ENTRY(setjmp) sd ra, 0(a0) sd s0, 8(a0) sd s1, 16(a0) sd s2, 24(a0) sd s3, 32(a0) sd s4, 40(a0) sd s5, 48(a0) sd s6, 56(a0) sd s7, 64(a0) sd s8, 72(a0) sd s9, 80(a0) sd s10, 88(a0) sd s11, 96(a0) sd sp, 104(a0) mv a0, zero jr ra END(setjmp) ENTRY(longjmp) ld ra, 0(a0) ld s0, 8(a0) ld s1, 16(a0) ld s2, 24(a0) ld s3, 32(a0) ld s4, 40(a0) ld s5, 48(a0) ld s6, 56(a0) ld s7, 64(a0) ld s8, 72(a0) ld s9, 80(a0) ld s10, 88(a0) ld s11, 96(a0) ld sp, 104(a0) mv a0, a1 jr ra END(longjmp) klibc-2.0.7/usr/klibc/arch/riscv64/crt0.S0000644000175000017500000000064113546663605016023 0ustar benben# # arch/riscv64/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 ENTRY(_start) .option push .option norelax lla gp, __global_pointer$ .option pop mv a0, sp # Pointer to ELF entry structure mv a1, zero # No onexit pointer jal __libc_init END(_start) klibc-2.0.7/usr/klibc/arch/riscv64/MCONFIG0000644000175000017500000000107213546663605016033 0ustar benben# -*- makefile -*- # # arch/riscv64/MCONFIG # # Special rules for this architecture. Note that this is actually # included from the main Makefile, and that pathnames should be # accordingly. # # We should get klibc.so and the executables to agree on what gp # should be. For now, disable gp-relative addressing. KLIBCLDFLAGS = --no-relax KLIBCOPTFLAGS += -Os -fomit-frame-pointer ifeq ($(DEBUG),y) KLIBCOPTFLAGS += -g endif KLIBCBITSIZE = 64 # Normal binaries start at 64 KB, so start the libary at 2 MB. KLIBCSHAREDFLAGS =-Ttext-segment 0x00200000 klibc-2.0.7/usr/klibc/arch/riscv64/Kbuild0000644000175000017500000000016213546663605016162 0ustar benben# -*- makefile -*- # # klibc files for riscv64 always := crt0.o targets := crt0.o klib-y := setjmp.o syscall.o klibc-2.0.7/usr/klibc/arch/ppc64/0000755000175000017500000000000013546663605014462 5ustar benbenklibc-2.0.7/usr/klibc/arch/ppc64/sysstub.ph0000644000175000017500000000140213546663605016524 0ustar benben# -*- 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 < .text .balign 4 .globl ${fname} #if _CALL_ELF == 2 .type ${fname},\@function ${fname}: 0: addis 2,12,(.TOC.-0b)\@ha addi 2,2,(.TOC.-0b)\@l .localentry ${fname},.-${fname} #else .section ".opd","aw" .balign 8 ${fname}: .quad .${fname}, .TOC.\@tocbase, 0 .previous .type .${fname},\@function .globl .${fname} .${fname}: #endif li 0, __NR_${sname} sc bnslr b __syscall_error #if _CALL_ELF == 2 .size ${fname},.-${fname} #else .size ${fname},.-.${fname} #endif EOF close(OUT); } 1; klibc-2.0.7/usr/klibc/arch/ppc64/syscall.c0000644000175000017500000000040613546663605016300 0ustar benben/* * 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; } klibc-2.0.7/usr/klibc/arch/ppc64/setjmp.S0000644000175000017500000000362613546663605016117 0ustar benben# # arch/ppc64/setjmp.S # # Basic setjmp/longjmp implementation # .text .balign 4 .globl setjmp #if _CALL_ELF == 2 .type setjmp,@function setjmp: #else .section ".opd","aw" .balign 8 setjmp: .quad .setjmp, .TOC.@tocbase, 0 .previous .type .setjmp,@function .globl .setjmp .setjmp: #endif 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 */ #if _CALL_ELF == 2 .size setjmp,.-setjmp #else .size setjmp,.-.setjmp #endif .text .balign 4 .globl longjmp #if _CALL_ELF == 2 .type longjmp,@function longjmp: #else .section ".opd","aw" .balign 8 longjmp: .quad .longjmp, .TOC.@tocbase, 0 .previous .type .longjmp,@function .globl .longjmp .longjmp: #endif 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 */ #if _CALL_ELF == 2 .size longjmp,.-longjmp #else .size longjmp,.-.longjmp #endif klibc-2.0.7/usr/klibc/arch/ppc64/crt0.S0000644000175000017500000000114313546663605015455 0ustar benben# # arch/ppc64/crt0.S # # void _start(void) # { # /* Divine up argc, argv, and envp */ # environ = envp; # exit(main(argc, argv, envp)); # } # .text .balign 4 .globl _start #if _CALL_ELF == 2 .type _start,@function _start: #else .section ".opd","aw" .balign 8 _start: .quad ._start, .TOC.@tocbase, 0 .previous .type ._start,@function ._start: #endif #if _CALL_ELF == 2 0: addis 2,12,.TOC.-0b@ha addi 2,2,.TOC.-0b@l #endif stdu %r1,-32(%r1) addi %r3,%r1,32 li %r4,0 /* fini (unused) */ b __libc_init nop #if _CALL_ELF == 2 .size _start,.-_start #else .size _start,.-._start #endif klibc-2.0.7/usr/klibc/arch/ppc64/MCONFIG0000644000175000017500000000140413546663605015466 0ustar benben# -*- 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 KLIBCARCHREQFLAGS += $(call cc-option, -mcall-aixdesc, ) KLIBCARCHREQFLAGS += $(call cc-option, -mcmodel=small, ) 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 # 256-16 MB - normal binaries start at 256 MB, and jumps are limited # to +/- 16 MB KLIBCSHAREDFLAGS = -Ttext-segment 0x0f000000 # The asm include files live in asm-powerpc KLIBCASMARCH = powerpc klibc-2.0.7/usr/klibc/arch/ppc64/Kbuild0000644000175000017500000000013713546663605015620 0ustar benben# # klibc files for ppc64 # klib-y := setjmp.o syscall.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/ppc/0000755000175000017500000000000013546663605014310 5ustar benbenklibc-2.0.7/usr/klibc/arch/ppc/sysstub.ph0000644000175000017500000000112413546663605016353 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/ppc/syscall.S0000644000175000017500000000040513546663605016105 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/ppc/setjmp.S0000644000175000017500000000220313546663605015733 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/ppc/crt0.S0000644000175000017500000000071213546663605015304 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/ppc/MCONFIG0000644000175000017500000000136313546663605015320 0ustar benben# -*- 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-segment 0x0f800000 # The asm include files live in asm-powerpc KLIBCASMARCH = powerpc klibc-2.0.7/usr/klibc/arch/ppc/Kbuild0000644000175000017500000000040113546663605015440 0ustar benben# # klibc files for ppc # klib-y := setjmp.o syscall.o klib-y += ../../libgcc/__divdi3.o ../../libgcc/__moddi3.o klib-y += ../../libgcc/__udivdi3.o ../../libgcc/__umoddi3.o klib-y += ../../libgcc/__udivmoddi4.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/parisc/0000755000175000017500000000000013546663605015007 5ustar benbenklibc-2.0.7/usr/klibc/arch/parisc/vfork.S0000644000175000017500000000122313546663605016260 0ustar benben/* * arch/parisc/vfork.S, "vfork() me harder. ugh." -- kyle * * %rp contains whence we came, * %rp is saved and restored across the syscall, thankfully. * */ .text .align 64 ; cache-width aligned .globl vfork .type vfork,@function vfork: /* pid_t vfork(void) */ ldi 113,%r20 ble 0x100(%sr2, %r0) ; jump to gateway page nop 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: bv %r0(%rp) ; jump back nop .size vfork,.-vfork klibc-2.0.7/usr/klibc/arch/parisc/sysstub.ph0000644000175000017500000000130513546663605017053 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/parisc/syscall.S0000644000175000017500000000151513546663605016607 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/parisc/setjmp.S0000644000175000017500000000427113546663605016441 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/parisc/crt0.S0000644000175000017500000000117013546663605016002 0ustar benben .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 klibc-2.0.7/usr/klibc/arch/parisc/MCONFIG0000644000175000017500000000045413546663605016017 0ustar benben# -*- 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-segment 0x40001000 klibc-2.0.7/usr/klibc/arch/parisc/Kbuild0000644000175000017500000000015013546663605016140 0ustar benben# # klibc files for parisc # klib-y := setjmp.o syscall.o vfork.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/mips64/0000755000175000017500000000000013546663605014650 5ustar benbenklibc-2.0.7/usr/klibc/arch/mips64/sysstub.ph0000644000175000017500000000141313546663605016714 0ustar benben# -*- perl -*- # # arch/mips64/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 "\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; klibc-2.0.7/usr/klibc/arch/mips64/setjmp.S0000644000175000017500000000121213546663605016272 0ustar benben# # arch/mips64/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 # #include LEAF(setjmp) sd s0, 0(a0) sd s1, 8(a0) sd s2, 16(a0) sd s3, 24(a0) sd s4, 32(a0) sd s5, 40(a0) sd s6, 48(a0) sd s7, 56(a0) sd gp, 64(a0) sd sp, 72(a0) sd s8, 80(a0) sd ra, 88(a0) move v0, zero jr ra END(setjmp) LEAF(longjmp) ld s0, 0(a0) ld s1, 8(a0) ld s2, 16(a0) ld s3, 24(a0) ld s4, 32(a0) ld s5, 40(a0) ld s6, 48(a0) ld s7, 56(a0) ld gp, 64(a0) ld sp, 72(a0) ld s8, 80(a0) ld ra, 88(a0) move v0, a1 jr ra END(longjmp) klibc-2.0.7/usr/klibc/arch/mips64/crt0.S0000644000175000017500000000070613546663605015647 0ustar benben# # arch/mips64/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, 0, ra) move a0, sp # Pointer to ELF entry structure move a1, v0 # Kernel-provided atexit() pointer and sp, -16 # Align stack to 16 bytes jal __libc_init teq zero, zero # Crash if we return END(__start) klibc-2.0.7/usr/klibc/arch/mips64/MCONFIG0000644000175000017500000000155113546663605015657 0ustar benben# -*- 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. # KLIBCARCHREQFLAGS = -fno-pic -mno-abicalls -G 0 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 # 4862 MB - normal binaries start at 4608 MB. Non-PIC jumps usually # use the JAL instruction which requires a destination within the same # 256M aligned region. Since we can't put ourselves below the normal # load address, use the very top of the 256M region (minus 2MB) # # Use -Ttext-segment so that the special .MIPS* sections are moved as well. KLIBCSHAREDFLAGS = -Ttext-segment 0x12FE00000 klibc-2.0.7/usr/klibc/arch/mips64/Kbuild0000644000175000017500000000065113546663605016007 0ustar benben# # klibc files for mips64 # klib-y := ../mips/pipe.o ../mips/vfork.o setjmp.o ../mips/syscall.o klib-y += ../../libgcc/__clzsi2.o ../../libgcc/__ashldi3.o klib-y += ../../libgcc/__ashrdi3.o ../../libgcc/__lshrdi3.o klib-y += ../../libgcc/__divdi3.o ../../libgcc/__moddi3.o klib-y += ../../libgcc/__udivdi3.o ../../libgcc/__umoddi3.o klib-y += ../../libgcc/__udivmoddi4.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/mips/0000755000175000017500000000000013546663605014476 5ustar benbenklibc-2.0.7/usr/klibc/arch/mips/vfork.S0000644000175000017500000000040713546663605015752 0ustar benben#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) klibc-2.0.7/usr/klibc/arch/mips/sysstub.ph0000644000175000017500000000141113546663605016540 0ustar benben# -*- 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 "\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; klibc-2.0.7/usr/klibc/arch/mips/syscall.S0000644000175000017500000000055413546663605016300 0ustar benben#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) klibc-2.0.7/usr/klibc/arch/mips/setjmp.S0000644000175000017500000000120613546663605016123 0ustar benben# # 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 # #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) 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) move v0,a1 jr ra END(longjmp) klibc-2.0.7/usr/klibc/arch/mips/pipe.S0000644000175000017500000000030013546663605015550 0ustar benben#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) klibc-2.0.7/usr/klibc/arch/mips/crt0.S0000644000175000017500000000076713546663605015504 0ustar benben# # 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, 0, ra) move a0, sp # Pointer to ELF entry structure move a1, v0 # Kernel-provided atexit() pointer and sp, -8 # Align stack to 8 bytes subu sp, 16 # Allocate 16 bytes for function call jal __libc_init teq zero, zero # Crash if we return END(__start) klibc-2.0.7/usr/klibc/arch/mips/MCONFIG0000644000175000017500000000120513546663605015501 0ustar benben# -*- 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 # 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 # # Use -Ttext-segment so that the special .MIPS* sections are moved as well. KLIBCSHAREDFLAGS = -Ttext-segment 0x00200000 klibc-2.0.7/usr/klibc/arch/mips/Kbuild0000644000175000017500000000061713546663605015637 0ustar benben# # klibc files for mips # klib-y := pipe.o vfork.o setjmp.o syscall.o klib-y += ../../libgcc/__clzsi2.o ../../libgcc/__ashldi3.o klib-y += ../../libgcc/__ashrdi3.o ../../libgcc/__lshrdi3.o klib-y += ../../libgcc/__divdi3.o ../../libgcc/__moddi3.o klib-y += ../../libgcc/__udivdi3.o ../../libgcc/__umoddi3.o klib-y += ../../libgcc/__udivmoddi4.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/m68k/0000755000175000017500000000000013546663605014313 5ustar benbenklibc-2.0.7/usr/klibc/arch/m68k/vfork.S0000644000175000017500000000071013546663605015564 0ustar benben# # 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) /* restore stack */ /* fallthrough into common code from syscall.S */ bra __syscall_checkandout .size vfork, .-vfork klibc-2.0.7/usr/klibc/arch/m68k/sysstub.ph0000644000175000017500000000113413546663605016357 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/m68k/syscall.S0000644000175000017500000000307213546663605016113 0ustar benben/* * 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: /* * According to eglibc, separate moves are faster than movem; * speed is important and this code is not duplicated anyway, * so we do the same here. We use %a1 as scratch register for * saving; syscall arguments are to be in %d1 to %d5 and %a0. */ move.l 24(%sp), %a0 /* orig.sp+24: arg 6 */ move.l %d5, -(%sp) /* push d5 (callee saved) */ move.l 24(%sp), %d5 /* orig.sp+20: arg 5 */ move.l %d4, -(%sp) /* push d4 (callee saved) */ move.l 24(%sp), %d4 /* orig.sp+16: arg 4 */ move.l %d3, -(%sp) /* push d3 (callee saved) */ move.l 24(%sp), %d3 /* orig.sp+12: arg 3 */ move.l %d2, %a1 /* save d2 (callee saved) in a1 */ move.l 20(%sp), %d2 /* orig.sp+8: arg 2 */ move.l 16(%sp), %d1 /* orig.sp+4: arg 1 */ trap #0 move.l %a1, %d2 /* restore d2 from a1 (scratch) */ move.l (%sp)+, %d3 /* pop d3..d5, see above */ move.l (%sp)+, %d4 move.l (%sp)+, %d5 /* syscall is done, result in %d0, registers are restored */ .globl __syscall_checkandout __syscall_checkandout: /* now check for error */ cmp.l #-4095, %d0 bcs.l 1f /* jump if _not_ error */ /* prepare for error return */ neg.l %d0 move.l %d0, (errno) move.l #-1, %d0 /* fallthrough into common return path */ 1: /* copy return value to %a0 for syscalls returning pointers */ move.l %d0, %a0 rts .size __syscall_common,.-__syscall_common klibc-2.0.7/usr/klibc/arch/m68k/setjmp.S0000644000175000017500000000152713546663605015746 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/m68k/openat.S0000644000175000017500000000102513546663605015723 0ustar benben/* * arch/m68k/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 0400000 #ifdef __NR_openat /* Don't build if kernel headers too old */ .globl openat .type openat,@function openat: or.l # O_LARGEFILE, 12(%sp) move.l # __NR_openat, %d0 br __syscall_common .size openat,.-openat #endif klibc-2.0.7/usr/klibc/arch/m68k/open.S0000644000175000017500000000067313546663605015406 0ustar benben/* * arch/m68k/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 0400000 .globl open .type open,@function open: or.l # O_LARGEFILE, 8(%sp) move.l # __NR_open, %d0 br __syscall_common .size open,.-open klibc-2.0.7/usr/klibc/arch/m68k/crt0.S0000644000175000017500000000106713546663605015313 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/m68k/MCONFIG0000644000175000017500000000122413546663605015317 0ustar benben# -*- 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 # 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-segment 0xb0000000 klibc-2.0.7/usr/klibc/arch/m68k/Kbuild0000644000175000017500000000020013546663605015440 0ustar benben# # klibc files for m68k # klib-y := setjmp.o syscall.o vfork.o klib-y += open.o openat.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/ia64/0000755000175000017500000000000013546663605014271 5ustar benbenklibc-2.0.7/usr/klibc/arch/ia64/vfork.S0000644000175000017500000000155213546663605015547 0ustar benben/* * ia64 specific vfork syscall * * Written By: Martin Hicks * */ /* This syscall is a special case of the clone syscall */ #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 klibc-2.0.7/usr/klibc/arch/ia64/sysstub.ph0000644000175000017500000000140513546663605016336 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/ia64/syscall.S0000644000175000017500000000041513546663605016067 0ustar benben# # arch/ia64/syscall.S # #include .text .align 32 .proc __syscall_error .globl __syscall_error __syscall_error: movl r2 = errno ;; st4 [r2] = r8 mov r8 = -1 br.ret.sptk.many b0 .size __syscall_error, .-__syscall_error .endp __syscall_error klibc-2.0.7/usr/klibc/arch/ia64/setjmp.S0000644000175000017500000002126213546663605015722 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/ia64/pipe.S0000644000175000017500000000057513546663605015361 0ustar benben#include .align 32 .proc pipe .global pipe pipe: alloc r16 = ar.pfs, 1, 0, 8, 0 mov r33 = r32 mov r15=__NR_pipe ;; break 0x100000 // Do the syscall ;; cmp.ne p6, p7 = -1, r10 mov r15 = r0 ;; (p6) st4 [r32] = r8, 4 (p7) movl r14 = errno (p7) addl r15 = -1, r0 ;; (p6) st4 [r32] = r9 (p7) st4 [r14] = r8 mov r8 = r15 br.ret.sptk.many b0 .endp pipe klibc-2.0.7/usr/klibc/arch/ia64/klibc.ld0000644000175000017500000002364513546663605015710 0ustar benben/* Linker script for klibc.so. Whilst we can control text-segment for klibc.so to not collide, the data segment is not controllable and hard-coded to start at 0x6000000000000000 for position-dependent outputs, rather than simply following on from the text segment like position-independent output or other architectures. */ /* Copyright (C) 2014-2018 Free Software Foundation, Inc. Copying and distribution of this script, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. */ ENTRY(_start) SECTIONS { /* Read-only sections, merged into text segment: */ /* Dynamic linker is normally placed in the 0x20..0 segment along with any mmap'ed shared libraries. */ . = SEGMENT_START("text-segment", 0x2000000000000000) + SIZEOF_HEADERS; .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } .hash : { *(.hash) } .gnu.hash : { *(.gnu.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.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) *(.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.*) PROVIDE_HIDDEN (__rel_iplt_start = .); *(.rel.iplt) PROVIDE_HIDDEN (__rel_iplt_end = .); } .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.*) PROVIDE_HIDDEN (__rela_iplt_start = .); *(.rela.iplt) PROVIDE_HIDDEN (__rela_iplt_end = .); } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .rela.IA_64.pltoff : { *(.rela.IA_64.pltoff) } .init : { KEEP (*(SORT_NONE(.init))) } =0x00300000010070000002000001000400 .plt : { *(.plt) } .iplt : { *(.iplt) } .text : { *(.text.unlikely .text.*_unlikely .text.unlikely.*) *(.text.exit .text.exit.*) *(.text.startup .text.startup.*) *(.text.hot .text.hot.*) *(.text .stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } =0x00300000010070000002000001000400 .fini : { KEEP (*(SORT_NONE(.fini))) } =0x00300000010070000002000001000400 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.*) } .opd : { *(.opd) } .IA_64.unwind_info : { KEEP(*(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*)) } .IA_64.unwind : { KEEP(*(.IA_64.unwind* .gnu.linkonce.ia64unw.*)) } .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } /* These sections are generated by the Sun/Oracle C++ compiler. */ .exception_ranges : ONLY_IF_RO { *(.exception_ranges .exception_ranges*) } /* 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(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); /* Exception handling */ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } /* Thread Local Storage sections */ .tdata : { PROVIDE_HIDDEN (__tdata_start = .); *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); } .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); } .jcr : { KEEP (*(.jcr)) } .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } .dynamic : { *(.dynamic) } .data : { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } .data1 : { *(.data1) } .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)) KEEP (*crtbegin?.o(.ctors)) /* We don't want to include the .ctor section 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 *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } .dtors : { KEEP (*crtbegin.o(.dtors)) KEEP (*crtbegin?.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } .IA_64.pltoff : { *(.IA_64.pltoff) } /* 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.*) } _edata = .; PROVIDE (edata = .); . = .; __bss_start = .; .sbss : { *(.dynsbss) *(.sbss .sbss.* .gnu.linkonce.sb.*) *(.scommon) } .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. FIXME: Why do we need it? When there is no .bss section, we don't pad the .data section. */ . = ALIGN(. != 0 ? 64 / 8 : 1); } . = ALIGN(64 / 8); . = SEGMENT_START("ldata-segment", .); . = ALIGN(64 / 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_line.* .debug_line_end ) } .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) } /* DWARF 3 */ .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } /* DWARF Extension. */ .debug_macro 0 : { *(.debug_macro) } .debug_addr 0 : { *(.debug_addr) } .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } } klibc-2.0.7/usr/klibc/arch/ia64/crt0.S0000644000175000017500000000052513546663605015267 0ustar benben #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 */ .body br.call.sptk.few rp = __libc_init ;; break 0 /* break miserably if we ever return */ .endp _start klibc-2.0.7/usr/klibc/arch/ia64/MCONFIG0000644000175000017500000000047613546663605015305 0ustar benben# -*- 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. # KLIBCARCHREQFLAGS = -mno-pic KLIBCOPTFLAGS += -Os KLIBCBITSIZE = 64 KLIBCSHAREDFLAGS = -T $(src)/arch/$(KLIBCARCH)/klibc.ld klibc-2.0.7/usr/klibc/arch/ia64/Kbuild0000644000175000017500000000055413546663605015432 0ustar benben# # klibc files for ia64 # klib-y := vfork.o setjmp.o pipe.o syscall.o klib-y += ../../libgcc/__divdi3.o ../../libgcc/__divsi3.o klib-y += ../../libgcc/__udivdi3.o ../../libgcc/__udivsi3.o klib-y += ../../libgcc/__umodsi3.o ../../libgcc/__umoddi3.o klib-y += ../../libgcc/__udivmodsi4.o ../../libgcc/__udivmoddi4.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/i386/0000755000175000017500000000000013546663605014217 5ustar benbenklibc-2.0.7/usr/klibc/arch/i386/vfork.S0000644000175000017500000000103713546663605015473 0ustar benben# # 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. # # We *MUST* use int $0x80, because calling the vdso would screw up # our stack handling. # #include .text .align 4 .globl vfork .type vfork, @function vfork: popl %edx /* Return address */ movl $__NR_vfork, %eax int $0x80 /* DO NOT call the vdso here! */ pushl %edx cmpl $-4095, %eax jae 1f ret 1: negl %eax movl %eax, errno orl $-1, %eax ret klibc-2.0.7/usr/klibc/arch/i386/varsyscall.S0000644000175000017500000000121113546663605016521 0ustar benben/* * 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+24)(%esp) #define SYSNO ARG(-2) .text .align 4 .globl __syscall_varadic .type __syscall_varadic,@function __syscall_varadic: pushl %ebx pushl %esi pushl %edi pushl %ebp movl SYSNO,%eax 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 klibc-2.0.7/usr/klibc/arch/i386/sysstub.ph0000644000175000017500000000112513546663605016263 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/i386/syscall.S0000644000175000017500000000245213546663605016020 0ustar benben/* * 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)+24)(%esp) #define SYSNO ARG(-2) .text .align 4 .globl __syscall_common .type __syscall_common,@function __syscall_common: pushl %ebx pushl %esi pushl %edi pushl %ebp #ifdef _REGPARM xchgl %ecx,%edx movl %eax,%ebx movl SYSNO,%eax movl ARG(0),%esi movl ARG(1),%edi movl ARG(2),%ebp #else movl SYSNO,%eax 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: call *__syscall_entry cmpl $-4095,%eax popl %ebp popl %edi popl %esi popl %ebx popl %edx # Drop system call number 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 .align 4 __syscall_int80: int $0x80 ret .type __syscall_int80,@function .size __syscall_int80,.-__syscall_int80 .data .align 4 .globl __syscall_entry __syscall_entry: .long __syscall_int80 .size __syscall_entry,.-__syscall_entry klibc-2.0.7/usr/klibc/arch/i386/setjmp.S0000644000175000017500000000170313546663605015646 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/i386/openat.S0000644000175000017500000000102213546663605015624 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/i386/open.S0000644000175000017500000000104513546663605015304 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/i386/libgcc/0000755000175000017500000000000013546663605015442 5ustar benbenklibc-2.0.7/usr/klibc/arch/i386/libgcc/__negdi2.S0000644000175000017500000000040613546663605017234 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/i386/libgcc/__muldi3.S0000644000175000017500000000077613546663605017273 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/i386/libgcc/__lshrdi3.S0000644000175000017500000000056213546663605017437 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/i386/libgcc/__ashrdi3.S0000644000175000017500000000054613546663605017426 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/i386/libgcc/__ashldi3.S0000644000175000017500000000056213546663605017416 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/i386/crt0.S0000644000175000017500000000131613546663605015214 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/i386/MCONFIG0000644000175000017500000000200213546663605015216 0ustar benben# -*- 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-segment 0x06000000 klibc-2.0.7/usr/klibc/arch/i386/Kbuild0000644000175000017500000000066313546663605015361 0ustar benben# # klibc .o files for i386 # klib-y := setjmp.o syscall.o varsyscall.o klib-y += open.o openat.o vfork.o klib-y += libgcc/__ashldi3.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o klib-y += libgcc/__muldi3.o libgcc/__negdi2.o klib-y += ../../libgcc/__divdi3.o klib-y += ../../libgcc/__moddi3.o klib-y += ../../libgcc/__udivdi3.o klib-y += ../../libgcc/__umoddi3.o klib-y += ../../libgcc/__udivmoddi4.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/cris/0000755000175000017500000000000013546663605014466 5ustar benbenklibc-2.0.7/usr/klibc/arch/cris/vfork.S0000644000175000017500000000102313546663605015735 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/cris/sysstub.ph0000644000175000017500000000137713546663605016543 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/cris/syscall.S0000644000175000017500000000112613546663605016264 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/cris/setjmp.S0000644000175000017500000000112213546663605016110 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/cris/divide.c0000644000175000017500000000256513546663605016106 0ustar benben#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; } klibc-2.0.7/usr/klibc/arch/cris/crt0.S0000644000175000017500000000104013546663605015455 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/cris/__negdi2.S0000644000175000017500000000061113546663605016256 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/arch/cris/MCONFIG0000644000175000017500000000167013546663605015477 0ustar benben# -*- 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 klibc-2.0.7/usr/klibc/arch/cris/Kbuild0000644000175000017500000000147113546663605015626 0ustar benben# # klibc files fora cris # always := crt0.o targets := crt0.o klib-y += __negdi2.o setjmp.o syscall.o vfork.o klib-y += ../../libgcc/__divdi3.o ../../libgcc/__moddi3.o klib-y += ../../libgcc/__udivdi3.o ../../libgcc/__umoddi3.o klib-y += ../../libgcc/__udivmoddi4.o # Divide support klib-y := __Umod.o __Udiv.o __Mod.o __Div.o quiet_cmd_cc-div = DIV-CC $@ cmd_cc-div = $(KLIBCC) $(klibccflags) -c -o $@ $< $(obj)/__Umod.o: $(src)/divide.c KLIBCCFLAGS___Umod.o := -DSIGNED=0 -DREM=1 -DBITS=32 -DNAME=__Umod $(obj)/__Udiv.o: $(src)/divide.c KLIBCCFLAGS___Udiv.o := -DSIGNED=0 -DREM=0 -DBITS=32 -DNAME=__Udiv $(obj)/__Mod.o: $(src)/divide.c KLIBCCFLAGS___Mod.o := -DSIGNED=1 -DREM=1 -DBITS=32 -DNAME=__Mod $(obj)/__Div.o: $(src)/divide.c KLIBCCFLAGS___Div.o := -DSIGNED=1 -DREM=0 -DBITS=32 -DNAME=__Div klibc-2.0.7/usr/klibc/arch/arm64/0000755000175000017500000000000013546663605014457 5ustar benbenklibc-2.0.7/usr/klibc/arch/arm64/vfork.S0000644000175000017500000000134313546663605015733 0ustar benben/* * arch/arm64/vfork.S * * vfork - a system call which must not use the stack. */ #include .type vfork,#function .globl vfork .balign 8 vfork: /* Prepare for the system call */ /* 1. Push the function pointer and argument location on to the child process stack */ /* 2. Gather the Flags */ /* New sp is already in x1. */ mov x0, #0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ mov x1, sp mov w8,__NR_clone svc 0 cmp x0, #0x0 b.ge 2f neg x0, x0 ldr x8, 1f str x0, [x8] mov x0, #-1 2: ret 1: .dword errno .size vfork,.-vfork klibc-2.0.7/usr/klibc/arch/arm64/sysstub.ph0000644000175000017500000000113113546663605016520 0ustar benben# -*- perl -*- # # arch/arm64/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 " .text\n"; print OUT " .type ${fname}, #function\n"; print OUT " .globl ${fname}\n"; print OUT " .balign 8\n"; print OUT "${fname}:\n"; print OUT " mov w8,__NR_${sname}\n"; print OUT " svc 0\n"; print OUT " b __syscall_common\n"; print OUT " .size ${fname},.-${fname}\n"; } 1; klibc-2.0.7/usr/klibc/arch/arm64/syscall.S0000644000175000017500000000066313546663605016262 0ustar benben/* * arch/arm64/syscall.S * * System call common handling - if the return * value from the system call is negative, then * extract the magnitude and return it as errno and * return -1, if the return value is 0 that is * success case. */ .type __syscall_common,#function .globl __syscall_common .balign 8 __syscall_common: cmp x0, #0x0 b.ge 2f neg x0, x0 ldr x8, 1f str x0, [x8] mov x0, #-1 2: ret 1: .dword errno klibc-2.0.7/usr/klibc/arch/arm64/setjmp.S0000644000175000017500000000144013546663605016104 0ustar benben# # arch/arm64/setjmp.S # # setjmp/longjmp for arm64 # # we specify -mgeneral-regs-only as a build flag thus do not need to # save d8-d15 .text .balign 8 .globl setjmp .type setjmp, #function setjmp: mov x1, sp stp x19, x20, [x0, #0] stp x21, x22, [x0, #16] stp x23, x24, [x0, #32] stp x25, x26, [x0, #48] stp x27, x28, [x0, #64] stp x29, x30, [x0, #80] str x1, [x0, #96] mov x0, #0 /* set the return value of setjmp */ br x30 .size setjmp,.-setjmp .text .balign 8 .globl longjmp .type longjmp, #function longjmp: ldp x19, x20, [x0, #0] ldp x21, x22, [x0, #16] ldp x23, x24, [x0, #32] ldp x25, x26, [x0, #48] ldp x27, x28, [x0, #64] ldp x29, x30, [x0, #80] ldr x2, [x0, #96] mov sp, x2 mov x0, x1 cbnz x1, 1f mov x0, #1 1: br x30 .size longjmp,.-longjmp klibc-2.0.7/usr/klibc/arch/arm64/crt0.S0000644000175000017500000000034513546663605015455 0ustar benben# # arch/arm64/crt0.S # # void _start(void) # { # __libc_init(elf_structure, atexit_ptr); # } # .text .balign 8 .type _start,#function .globl _start _start: mov x0, sp mov x1, #0 bl __libc_init .size _start,.-_start klibc-2.0.7/usr/klibc/arch/arm64/MCONFIG0000644000175000017500000000131613546663605015465 0ustar benben# -*- makefile -*- # # arch/arm64/MCONFIG # # Special rules for this architecture. Note that this is actually # included from the main Makefile, and that pathnames should be # accordingly. # CPU_ARCH ?= armv8-a CPU_TUNE ?= generic KLIBCOPTFLAGS += -g -Os -march=$(CPU_ARCH) -mtune=$(CPU_TUNE) KLIBCBITSIZE = 64 KLIBCREQFLAGS += -fno-exceptions -mgeneral-regs-only # 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 # On arm64, binaries are normally loaded at 4MB. Place klibc.so # a little before that at 2MB to prevent overlap. KLIBCSHAREDFLAGS = -Ttext-segment 0x0200000 klibc-2.0.7/usr/klibc/arch/arm64/Kbuild0000644000175000017500000000014513546663605015614 0ustar benben # klibc files for arm64 # klib-y := setjmp.o syscall.o vfork.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/arm/0000755000175000017500000000000013546663605014305 5ustar benbenklibc-2.0.7/usr/klibc/arch/arm/vfork.S0000644000175000017500000000132313546663605015557 0ustar benben/* * arch/arm/vfork.S * * vfork - nasty system call which must not use the stack. */ #include #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] BX(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: BX(lr) .balign 4 2: .word -4095 3: .word errno #endif klibc-2.0.7/usr/klibc/arch/arm/sysstub.ph0000644000175000017500000000270113546663605016352 0ustar benben# -*- 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 ${fname},.-${fname}\n"; } 1; klibc-2.0.7/usr/klibc/arch/arm/syscall.S0000644000175000017500000000170113546663605016102 0ustar benben/* * 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] #ifdef __ARM_EABI__ ldmfd sp!,{r4,r5,r7,pc} #else ldmfd sp!,{r4,r5,pc} #endif .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 klibc-2.0.7/usr/klibc/arch/arm/setjmp.S0000644000175000017500000000264413546663605015741 0ustar benben# # arch/arm/setjmp.S # # setjmp/longjmp for the ARM architecture # #include #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 BX(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} movs r0, r1 moveq r0, #1 BX(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 r2, r0 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} /* Do not trash r4 .. r7 */ ldmia r2!, {r3, r4, r5, r6, r7} mov r0, #0 BX(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: BX(r3) .size longjmp,.-longjmp #endif /* __thumb__ */ klibc-2.0.7/usr/klibc/arch/arm/crt0.S0000644000175000017500000000041113546663605015275 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/arm/aeabi_nonsense.S0000644000175000017500000000034313546663605017402 0ustar benben .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: klibc-2.0.7/usr/klibc/arch/arm/__muldi3.c0000644000175000017500000000043213546663605016143 0ustar benben#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; } klibc-2.0.7/usr/klibc/arch/arm/MCONFIG0000644000175000017500000000175113546663605015316 0ustar benben# -*- 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 main KLIBCREQFLAGS += -mabi=aapcs-linux KLIBCSHAREDFLAGS = -Ttext-segment 0x380000 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-segment 0x01800000 ifeq ($(CONFIG_AEABI),y) KLIBCREQFLAGS += -mabi=aapcs-linux -mno-thumb-interwork else KLIBCREQFLAGS += -mabi=apcs-gnu -mno-thumb-interwork endif endif klibc-2.0.7/usr/klibc/arch/arm/Kbuild0000644000175000017500000000053013546663605015440 0ustar benben# # klibc files for arm # klib-y := setjmp.o syscall.o vfork.o aeabi_nonsense.o klib-y += ../../libgcc/__udivmodsi4.o ../../libgcc/__divdi3.o klib-y += ../../libgcc/__moddi3.o ../../libgcc/__udivdi3.o klib-y += ../../libgcc/__umoddi3.o ../../libgcc/__udivmoddi4.o klib-y += ../../libgcc/__clzsi2.o always := crt0.o targets := crt0.o klibc-2.0.7/usr/klibc/arch/alpha/0000755000175000017500000000000013546663605014613 5ustar benbenklibc-2.0.7/usr/klibc/arch/alpha/sysstub.ph0000644000175000017500000000205613546663605016663 0ustar benben# -*- 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; klibc-2.0.7/usr/klibc/arch/alpha/sysdual.S0000644000175000017500000000104613546663605016424 0ustar benben# # 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 beq a3, 1f br pv, 2f # pv <- pc 2: ldgp gp, 0(pv) lda a1, errno stl v0, 0(a1) lda a4, -1(zero) 1: mov a4, v0 ret zero,(ra),1 .size __syscall_dual1,.-__syscall_dual1 .end __syscall_dual1 klibc-2.0.7/usr/klibc/arch/alpha/syscall.S0000644000175000017500000000060713546663605016414 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/alpha/setjmp.S0000644000175000017500000000216413546663605016244 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/alpha/pipe.S0000644000175000017500000000107713546663605015701 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/alpha/divide.c0000644000175000017500000000173513546663605016231 0ustar benben#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; } klibc-2.0.7/usr/klibc/arch/alpha/crt0.S0000644000175000017500000000047013546663605015610 0ustar benben# # 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 klibc-2.0.7/usr/klibc/arch/alpha/README-gcc0000644000175000017500000000145613546663605016233 0ustar benben 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) klibc-2.0.7/usr/klibc/arch/alpha/MCONFIG0000644000175000017500000000067713546663605015632 0ustar benben# -*- 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-segment 0x1c0000000 klibc-2.0.7/usr/klibc/arch/alpha/Kbuild0000644000175000017500000000377713546663605015766 0ustar benben# -*- 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. # always := crt0.o targets := crt0.o klib-y := pipe.o setjmp.o syscall.o sysdual.o # 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 div-objs := __divqu.o __remqu.o __divq.o __remq.o div-objs += __divlu.o __remlu.o __divl.o __reml.o klib-y += $(div-objs) 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)/,$(div-objs:.o=.S)): $(obj)/%.S: $(obj)/%.ss $(call if_changed,regswap) quiet_cmd_genss = DIV-CC $@ cmd_genss = $(CC) $(DIVCFLAGS) $(FILE_CFLAGS) \ $(call flags,KLIBCCPPFLAGS) \ -DNAME=$(basename $(notdir $@)) -S -o $@ $< $(obj)/%.ss: $(obj)/divide.c $(call if_changed,genss) $(obj)/__divqu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=0 -DBITS=64 $(obj)/__remqu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=1 -DBITS=64 $(obj)/__divq.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=0 -DBITS=64 $(obj)/__remq.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=1 -DBITS=64 $(obj)/__divlu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=0 -DBITS=32 $(obj)/__remlu.ss: FILE_CFLAGS := -DSIGNED=0 -DREM=1 -DBITS=32 $(obj)/__divl.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=0 -DBITS=32 $(obj)/__reml.ss: FILE_CFLAGS := -DSIGNED=1 -DREM=1 -DBITS=32 targets += $(div-objs:.o=.S) $(div-objs:.o=.ss) klibc-2.0.7/usr/klibc/arch/README.klibc.arch0000644000175000017500000000546213546663605016414 0ustar benbenTo 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. klibc-2.0.7/usr/klibc/alphasort.c0000644000175000017500000000027413546663605014755 0ustar benben/* * alphasort.c: alphasort */ #include #include int alphasort(const struct dirent **a, const struct dirent **b) { return strcmp((*a)->d_name, (*b)->d_name); } klibc-2.0.7/usr/klibc/alarm.c0000644000175000017500000000063113546663605014051 0ustar benben/* * 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 klibc-2.0.7/usr/klibc/access.c0000644000175000017500000000032013546663605014211 0ustar benben#include #include #include #ifndef __NR_access int access(const char *pathname, int mode) { return faccessat(AT_FDCWD, pathname, mode, 0); } #endif /* __NR_access */ klibc-2.0.7/usr/klibc/accept.c0000644000175000017500000000046213546663605014216 0ustar benben/* * accept.c * * Some architectures need to wrap the system call */ #include #if !_KLIBC_SYS_SOCKETCALL && defined(__NR_accept4) && !defined(__NR_accept) int accept(int socket, struct sockaddr *address, socklen_t *addr_len) { return accept4(socket, address, addr_len, 0); } #endif klibc-2.0.7/usr/klibc/abort.c0000644000175000017500000000041613546663605014065 0ustar benben/* * 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 */ } klibc-2.0.7/usr/klibc/__static_init.c0000644000175000017500000000005013546663605015560 0ustar benben#define SHARED 0 #include "libc_init.c" klibc-2.0.7/usr/klibc/__signal.c0000644000175000017500000000052613546663605014533 0ustar benben/* * __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; } } klibc-2.0.7/usr/klibc/__shared_init.c0000644000175000017500000000005013546663605015537 0ustar benben#define SHARED 1 #include "libc_init.c" klibc-2.0.7/usr/klibc/__put_env.c0000644000175000017500000000276313546663605014743 0ustar benben/* * __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; } klibc-2.0.7/usr/klibc/SYSCALLS.def0000644000175000017500000002553013546663605014533 0ustar benben/* -*- 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 getrusage(int, struct rusage *); int sched_setscheduler(pid_t, int, const struct sched_param *); int sched_setaffinity(pid_t, unsigned int, unsigned long *); int sched_getaffinity(pid_t, unsigned int, unsigned long *); int sched_yield(); int prctl@varadic(int, unsigned long, unsigned long, unsigned long, unsigned long); int prctl(int, unsigned long, unsigned long, unsigned long, unsigned long); /* * 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); /* * POSIX Capabilities */ int capget(cap_user_header_t, cap_user_data_t); int capset(cap_user_header_t, cap_user_data_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); int link(const char *, const char *); int linkat(int, const char *, int, const char *, int); int unlink(const char *); int unlinkat(int, const char *, int); int chdir(const char *); int fchdir(int); int rename(const char *, const char *); int renameat(int, const char *, int, const char *); int renameat2(int, const char *, int, const char *, unsigned int); int mknod(const char *, mode_t, dev_t); int mknodat(int, 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); int mkdir(const char *, mode_t); int mkdirat(int, const char *, mode_t); int rmdir(const char *); int pipe(int *); int pipe2(int *, 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,newfstatat,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 utimensat(int, const char *, const struct timespec *, int); 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); int open(const char *, int, mode_t); <64> int openat(int, 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 dup3(int, 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); 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_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t, void *); 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 sigpending(sigset_t *); int sigprocmask(int, const sigset_t *, sigset_t *); /* * There is no single calling convention for the old sigsuspend. * If your architecture is not listed here, building klibc shall * rather fail than use a broken calling convention. * You better switch to RT signals on those architectures: * blackfin h8300 microblaze mips. * * The arguments other than the sigset_t are assumed ignored. */ int sigsuspend::__sigsuspend_s(sigset_t); int sigsuspend::__sigsuspend_xxs(int, int, 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 *); long kexec_load(void *, unsigned long, struct kexec_segment *, unsigned long); /* * 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 *); #if ! _KLIBC_SYS_SOCKETCALL #include "SOCKETCALLS.def" #endif klibc-2.0.7/usr/klibc/SOCKETCALLS.def0000644000175000017500000000200213546663605015032 0ustar benben/* -*- 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, const struct sockaddr *, int); int connect(int, const struct sockaddr *, socklen_t); int listen(int, int); int accept(int, struct sockaddr *, socklen_t *); int accept4(int, struct sockaddr *, socklen_t *, int); 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); klibc-2.0.7/usr/klibc/README.klibc0000644000175000017500000001037513546663605014562 0ustar benbenIntroduction ============ This is klibc, what is intended to be a minimalistic libc subset for use with initramfs. It is deliberately written for small size, minimal entanglement, and portability, not speed. It is definitely a work in progress, and a lot of things are still missing. Building ======== The build procedure is not very polished yet, but for a native build with the default configuration it should be simple: 1. In a recent Linux kernel source directory, run: make headers_install INSTALL_HDR_PATH=/linux 2. In the klibc source directory, run: make Cross-compiling --------------- If you're cross-compiling, you need to set KLIBCARCH to the appropriate architecture, and set CROSS_COMPILE to your toolchain prefix, on the "make" command line 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. Out-of-tree builds ------------------ It is possible to use a separate build directory so that build products are not created in source directories. To do this, create the build directory and in that directory run: make -f /Makefile KBUILD_SRC= Build configuration ------------------- The build configuration is defined in a ".config" file in the build directory. If this file does not already exist, it is created as a copy of the "defconfig" source file. The configuration variables are: * CONFIG_KLIBC_ERRLIST (bool): Include standard error strings for strerror(). If disabled, strerror() returns the error number as a string. * CONFIG_KLIBC_ZLIB (bool): Include zlib decompression functions. If disabled, kinit can only load uncompressed ramdisk images. * CONFIG_KLIBC_ZIP (bool): Include compression support in the gzip command. * CONFIG_DEBUG_INFO (bool): Install all executables and the shared library with debug information and build IDs included. If disabled, the executables and shared library are stripped when installed. For arm only: * CONFIG_KLIBC_THUMB (bool): Compile all code to Thumb instructions, which should reduce code size slightly. If disabled, regular ARM instructions are used. * CONFIG_AEABI (bool): Compile ARM code to use the ARM EABI and the "new" system call ABI. If both CONFIG_KLIBC_THUMB and CONFIG_AEABI are disabled, the GNU APCS and the old system call ABI are used. For i386 only: * CONFIG_REGPARM (bool): Optimise function calls by passing the first 3 function parameters in registers. Building without kernel source ------------------------------ If you already have a copy of the current kernel UAPI headers, you don't need the kernel source as well. You can either: 1. Copy or link to the UAPI headers so that they appear under the "linux/include" subdirectory. 2. Set the KLIBCKERNELSRC variable on the "make" command line to point to the *parent* of the UAPI headers directory. Architecture support ==================== The following is the last known status of various architectures: alpha: Mostly working arm-thumb: Working arm: Working arm64: Working avr32: Not yet ported cris: Working h8300: Not yet ported i386: Working ia64: Mostly working m68k: Working mips: Working mips64: Working parisc: Working parisc64: Not yet ported ppc: Working ppc64: Working s390: Working s390x: Working sh: Working sh64: Not yet ported sparc: Working sparc64: Working 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. Testing ======= Try the test programs in the tests/ directory. They should run... Contact ======= Contact the klibc mailing list: https://www.zytor.com/mailman/listinfo/klibc ... for more info. -hpa klibc-2.0.7/usr/klibc/LICENSE0000644000175000017500000000723613546663605013626 0ustar benbenThis 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. klibc-2.0.7/usr/klibc/Kbuild0000644000175000017500000001522313546663605013751 0ustar benben# # Kbuild file for klibc # # Tell that we are building klibc export klibc-build := y # Generate syscall stubs klib-y += syscalls/ # Generate socket calls stubs klib-y += socketcalls/ # zlib, if configured klib-$(CONFIG_KLIBC_ZLIB) += zlib/ # arch specific .o files klib-y += arch/$(KLIBCARCHDIR)/ klib-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 \ creat.o open.o openat.o \ fread2.o fwrite2.o fgets.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 \ pread.o pwrite.o \ brk.o sbrk.o malloc.o realloc.o zalloc.o calloc.o \ mmap.o shm_open.o shm_unlink.o \ memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \ memmove.o memchr.o memrchr.o bzero.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 \ strtok_r.o \ fnmatch.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 getopt_long.o readdir.o scandir.o alphasort.o remove.o \ syslog.o closelog.o pty.o isatty.o reboot.o \ time.o utime.o lseek.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 \ accept.o send.o recv.o \ access.o chmod.o chown.o dup2.o mknod.o poll.o rename.o renameat.o \ stat.o \ lchown.o link.o rmdir.o unlink.o utimes.o lstat.o mkdir.o \ readlink.o realpath.o select.o symlink.o pipe.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 \ userdb/getgrgid.o userdb/getgrnam.o userdb/getpwnam.o \ userdb/getpwuid.o userdb/root_group.o userdb/root_user.o \ setmntent.o endmntent.o getmntent.o \ stdio/fclose.o stdio/fopen.o stdio/fdopen.o \ stdio/fread.o stdio/fwrite.o stdio/fflush.o \ stdio/ungetc.o stdio/fgetc.o \ stdio/fseek.o stdio/ftell.o stdio/rewind.o \ stdio/fileno.o stdio/feof.o stdio/ferror.o klib-$(CONFIG_KLIBC_ERRLIST) += errlist.o ifeq ($(CONFIG_KLIBC_ERRLIST),y) KLIBCCFLAGS_strerror.o += -DWITH_ERRLIST endif # sigsuspend.c includes generated by syscalls/ # build, so require that to build first $(obj)/sigsuspend.o: $(obj)/syscalls/klib.list ##### # Shared definitions LIBC := libc.a SOLIB := libc.so SOHASH := klibc.so CRT0 := arch/$(KLIBCARCHDIR)/crt0.o INTERP_O := interp.o always := $(LIBC) ifdef KLIBCSHAREDFLAGS always += $(SOLIB) $(SOHASH) $(INTERP_O) endif LIBC := $(call objectify,$(LIBC)) SOLIB := $(call objectify,$(SOLIB)) SOHASH := $(call objectify,$(SOHASH)) CRT0 := $(call objectify,$(CRT0)) INTERP_O := $(call objectify,$(INTERP_O)) SOLIBHASH = $(shell cat $(SOLIB).hash) ##### # Readable errormessages extracted from src.. targets += errlist.c quiet_cmd_errlist = GEN $@ cmd_errlist = $(PERL) $< $(call flags,KLIBCCPPFLAGS) -errlist > $@ \ || rm -f $@ $(obj)/errlist.c: $(srctree)/$(src)/makeerrlist.pl $(call cmd,errlist) # all .o files for all dirs klib-o-files = $(shell cat $(obj)/klib.list \ $(addsuffix /klib.list, $(klib-dirs))) ###### # Build static library: libc.a targets += libc.a __static_init.o quiet_cmd_libc = KLIBCAR $@ cmd_libc = rm -f $@; \ $(call klibc-ar,cq,Dcq) $@ \ $(call objectify,__static_init.o) $(klib-o-files); \ $(KLIBCRANLIB) $@ $(LIBC): $(call objectify,__static_init.o) $(obj)/klib.list 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 \ $(CRT0) \ $(call objectify,__shared_init.o) \ $(klib-o-files) \ $(KLIBCLIBGCC) \ --end-group $(SOLIB): $(call objectify,__shared_init.o) $(obj)/klib.list 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) $@; \ chmod a+x $@; \ 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, $(LIBC) $(CRT0), \ $(shell $(install-data) $(f) \ $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib)) ifdef KLIBCSHAREDFLAGS $(Q)$(foreach f, $(SOLIB) $(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) endif klibc-2.0.7/usr/klibc/CAVEATS0000644000175000017500000000307213546663605013624 0ustar benben ------------------------------------------------- Please note the following caveats when 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: -------------------------- signal() now defaults to bsd_signal(). klibc-2.0.7/usr/klibc/.gitignore0000644000175000017500000000017713546663605014606 0ustar benbenerrlist.c .interp.o.d klibc*.so klib.list .klib.list.cmd libc.a libc.so libc.so.hash sha1hash tests/* !tests/Kbuild !tests/*.c klibc-2.0.7/usr/kinit/0000755000175000017500000000000013546663605012643 5ustar benbenklibc-2.0.7/usr/kinit/xpio.h0000644000175000017500000000034013546663605013770 0ustar benben/* * 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 */ klibc-2.0.7/usr/kinit/xpio.c0000644000175000017500000000137613546663605013775 0ustar benben/* * Looping versions of pread() and pwrite() */ #include #include #include #include "xpio.h" 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; } klibc-2.0.7/usr/kinit/run-init/0000755000175000017500000000000013546663605014410 5ustar benbenklibc-2.0.7/usr/kinit/run-init/runinitlib.c0000644000175000017500000001336013546663605016736 0ustar benben/* ----------------------------------------------------------------------- * * * 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(realroot, consoledev, drop_caps, persist_initramfs, 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; * - Drops comma-separated list of capabilities; * - 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 "run-init.h" #include "capabilities.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 *drop_caps, bool dry_run, bool persist_initramfs, 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"; /* 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... */ if (!dry_run) { if (!persist_initramfs) { /* 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"; /* Drop capabilities */ if (drop_capabilities(drop_caps) < 0) return "dropping capabilities"; /* Open /dev/console */ if ((confd = open(console, O_RDWR)) < 0) return "opening console"; if (!dry_run) { dup2(confd, 0); dup2(confd, 1); dup2(confd, 2); } close(confd); if (!dry_run) { /* Spawn init */ execv(init, initargs); return init; /* Failed to spawn init */ } else { if (stat(init, &ist)) return init; if (!S_ISREG(ist.st_mode) || !(ist.st_mode & S_IXUGO)) { errno = EACCES; return init; } return NULL; /* Success */ } } klibc-2.0.7/usr/kinit/run-init/run-init.h0000644000175000017500000000307313546663605016331 0ustar benben/* ----------------------------------------------------------------------- * * * 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. * * ----------------------------------------------------------------------- */ #ifndef RUN_INIT_H #define RUN_INIT_H #include const char *run_init(const char *realroot, const char *console, const char *drop_caps, bool dry_run, bool persist_initramfs, const char *init, char **initargs); #endif klibc-2.0.7/usr/kinit/run-init/run-init.c0000644000175000017500000000653313546663605016330 0ustar benben/* ----------------------------------------------------------------------- * * * 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. * * ----------------------------------------------------------------------- */ /* * Usage: exec run-init [-d caps] [-c /dev/console] [-n] [-p] /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: * * 1. Delete all files in the initramfs; * 2. Remounts /real-root onto the root filesystem; * 3. Drops comma-separated list of capabilities; * 4. Chroots; * 5. Opens /dev/console; * 6. Spawns the specified init program (with arguments.) * * With the -p option, it skips step 1 in order to allow the initramfs to * be persisted into the running system. * * With the -n option, it skips steps 1, 2 and 6 and can be used to check * whether the given root and init are likely to work. */ #include #include #include #include #include #include #include "run-init.h" static const char *program; static void __attribute__ ((noreturn)) usage(void) { fprintf(stderr, "Usage: exec %s [-d caps] [-c consoledev] [-n] [-p] /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; const char *drop_caps = NULL; bool dry_run = false; bool persist_initramfs = false; char **initargs; /* Variables... */ int o; /* Parse the command line */ program = argv[0]; while ((o = getopt(argc, argv, "c:d:pn")) != -1) { if (o == 'c') { console = optarg; } else if (o == 'd') { drop_caps = optarg; } else if (o == 'n') { dry_run = true; } else if (o == 'p') { persist_initramfs = true; } else { usage(); } } if (argc - optind < 2) usage(); realroot = argv[optind]; init = argv[optind + 1]; initargs = argv + optind + 1; error = run_init(realroot, console, drop_caps, dry_run, persist_initramfs, init, initargs); if (error) { fprintf(stderr, "%s: %s: %s\n", program, error, strerror(errno)); return 1; } else { /* Must have been a dry run */ return 0; } } klibc-2.0.7/usr/kinit/run-init/Kbuild0000644000175000017500000000154013546663605015545 0ustar benben# # 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) # force run-init to not have an executable stack (to keep READ_IMPLIES_EXEC # personality(2) flag from getting set and passed to init). EXTRA_KLIBCLDFLAGS += -z noexecstack # Additional include paths files KLIBCCFLAGS += -I$(srctree)/$(src)/.. # .o files used to built executables static/run-init-y := $(objs) static/run-init-lib := ../lib.a shared/run-init-y := $(objs) shared/run-init-lib := ../lib.a # Cleaning clean-dirs := static shared # install binary ifdef KLIBCSHAREDFLAGS install-y := $(shared-y) else install-y := $(static-y) endif klibc-2.0.7/usr/kinit/resume/0000755000175000017500000000000013546663605014143 5ustar benbenklibc-2.0.7/usr/kinit/resume/resumelib.c0000644000175000017500000000472613546663605016307 0ustar benben/* * Handle resume from suspend-to-disk */ #include #include #include #include #include #include #include #include "kinit.h" #include "do_mounts.h" #include "resume.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; unsigned long long resume_offset; resume_arg = get_arg(argc, argv, "resume="); resume_file = resume_arg ? resume_arg : resume_file; /* No resume device specified */ if (!resume_file[0]) return 0; resume_arg = get_arg(argc, argv, "resume_offset="); resume_offset = resume_arg ? strtoull(resume_arg, NULL, 0) : 0ULL; /* Fix: we either should consider reverting the device back to ordinary swap, or (better) put that code into swapon */ /* Noresume requested */ if (get_flag(argc, argv, "noresume")) return 0; return resume(resume_file, resume_offset); } int resume(const char *resume_file, unsigned long long resume_offset) { dev_t resume_device; int attr_fd = -1; char attr_value[64]; int len; 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 ((attr_fd = open("/sys/power/resume_offset", O_WRONLY)) < 0) goto fail_offset; len = snprintf(attr_value, sizeof attr_value, "%llu", resume_offset); /* This should never happen */ if (len >= sizeof attr_value) goto fail_offset; if (write(attr_fd, attr_value, len) != len) goto fail_offset; close(attr_fd); if ((attr_fd = open("/sys/power/resume", O_WRONLY)) < 0) goto fail_r; len = snprintf(attr_value, sizeof attr_value, "%u:%u", major(resume_device), minor(resume_device)); /* This should never happen */ if (len >= sizeof attr_value) goto fail_r; dprintf("kinit: trying to resume from %s\n", resume_file); if (write(attr_fd, attr_value, len) != len) goto fail_r; /* Okay, what are we still doing alive... */ failure: if (attr_fd >= 0) close(attr_fd); dprintf("kinit: No resume image, doing normal boot...\n"); return -1; fail_offset: fprintf(stderr, "Cannot write /sys/power/resume_offset " "(no software suspend kernel support, or old kernel version?)\n"); goto failure; fail_r: fprintf(stderr, "Cannot write /sys/power/resume " "(no software suspend kernel support?)\n"); goto failure; } klibc-2.0.7/usr/kinit/resume/resume.h0000644000175000017500000000025013546663605015611 0ustar benben#ifndef RESUME_H #define RESUME_H int do_resume(int argc, char *argv[]); int resume(const char *resume_file, unsigned long long resume_offset); #endif /* RESUME_H */ klibc-2.0.7/usr/kinit/resume/resume.c0000644000175000017500000000063313546663605015611 0ustar benben/* * Handle resume from suspend-to-disk */ #include #include #include "resume.h" char *progname; static __noreturn usage(void) { fprintf(stderr, "Usage: %s /dev/ [offset]\n", progname); exit(1); } int main(int argc, char *argv[]) { progname = argv[0]; if (argc < 2 || argc > 3) usage(); return resume(argv[1], (argc > 2) ? strtoull(argv[2], NULL, 0) : 0ULL); } klibc-2.0.7/usr/kinit/resume/Kbuild0000644000175000017500000000123413546663605015300 0ustar benben# # Kbuild file for resume # static-y := static/resume shared-y := shared/resume # common .o files objs := resume.o resumelib.o # TODO - do we want a stripped version # TODO - do we want the static.g + shared.g directories? # Create lib.a with all object files (used by kinit) lib-y := $(objs) # Additional include paths files KLIBCCFLAGS += -I$(srctree)/$(src)/.. # .o files used to built executables static/resume-y := $(objs) static/resume-lib := ../lib.a shared/resume-y := $(objs) shared/resume-lib := ../lib.a # Cleaning clean-dirs := static shared # install binary ifdef KLIBCSHAREDFLAGS install-y := $(shared-y) else install-y := $(static-y) endif klibc-2.0.7/usr/kinit/readfile.c0000644000175000017500000000272413546663605014567 0ustar benben/* * 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 #include "kinit.h" 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; } klibc-2.0.7/usr/kinit/ramdisk_load.c0000644000175000017500000001461213546663605015444 0ustar benben#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); } #ifdef CONFIG_KLIBC_ZLIB /* 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; dprintf("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); dprintf("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); dprintf("kinit: writing %d bytes\n", BUF_SZ - zs.avail_out); inflateEnd(&zs); return 0; err2: inflateEnd(&zs); err1: return -1; } #else int load_ramdisk_compressed(const char *devpath, FILE * wfd, off_t ramdisk_start) { fprintf(stderr, "Compressed ramdisk not supported\n"); return -1; } #endif 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; dprintf("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[]) { 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"); close(rfd); fclose(wfd); return 0; } dprintf("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; } klibc-2.0.7/usr/kinit/nfsroot.c0000644000175000017500000000463313546663605014507 0ustar benben#include #include #include #include #include #include #include #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); dprintf("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; } klibc-2.0.7/usr/kinit/nfsmount/0000755000175000017500000000000013546663605014514 5ustar benbenklibc-2.0.7/usr/kinit/nfsmount/sunrpc.h0000644000175000017500000000360313546663605016201 0ustar benben/* * 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 enum { AUTH_NULL, AUTH_UNIX, }; struct rpc_auth { uint32_t flavor; uint32_t len; uint32_t body[]; }; 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 */ klibc-2.0.7/usr/kinit/nfsmount/sunrpc.c0000644000175000017500000001155213546663605016176 0ustar benben#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 - 4)); 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) { dprintf("Timeout #%d\n", i + 1); break; } if ((ret = rpc_do_reply(clnt, rpc, UDP_HDR_OFF)) == 0) { goto done; } else { dprintf("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); } klibc-2.0.7/usr/kinit/nfsmount/portmap.c0000644000175000017500000000273513546663605016351 0ustar benben#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; clnt = tcp_client(server, RPC_PMAP_PORT, 0); if (clnt == NULL) { clnt = udp_client(server, RPC_PMAP_PORT, 0); if (clnt == 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: dprintf("Port for %d/%d[%s]: %d\n", program, version, proto == IPPROTO_TCP ? "tcp" : "udp", port); if (clnt) client_free(clnt); return port; } klibc-2.0.7/usr/kinit/nfsmount/nfsmount.h0000644000175000017500000000123713546663605016541 0ustar benben#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 #ifdef DEBUG # define dprintf printf #else # define dprintf(...) ((void)0) #endif #ifndef MNTPROC_MNT #define MNTPROC_MNT 1 #endif #ifndef MNTPROC_UMNT #define MNTPROC_UMNT 3 #endif #endif /* NFSMOUNT_NFSMOUNT_H */ klibc-2.0.7/usr/kinit/nfsmount/mount.c0000644000175000017500000001735413546663605016034 0ustar benben#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 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 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); mnt_call = malloc(call_len); if (mnt_call == 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 - server replied: %s.\n", strerror(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; } dprintf("Mounted %s on %s\n", pathname, path); goto done; bail: if (mounted) { if (data->flags & NFS_MOUNT_VER3) umount_v3(rem_path, clnt); else umount_v2(rem_path, clnt); } ret = -1; done: if (clnt) client_free(clnt); if (sock != -1) close(sock); return ret; } klibc-2.0.7/usr/kinit/nfsmount/main.c0000644000175000017500000001417013546663605015607 0ustar benben#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 = 0, /* Kernel client's default */ .retrans = 3, .acregmin = 3, .acregmax = 60, .acdirmin = 30, .acdirmax = 60, .namlen = NAME_MAX, }; int nfs_port; int nfs_version; static struct int_opts { char *name; int *val; } int_opts[] = { {"port", &nfs_port}, {"nfsvers", &nfs_version}, {"vers", &nfs_version}, {"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}, {"acl", ~NFS_MOUNT_NOACL, 0}, {"noacl", ~NFS_MOUNT_NOACL, NFS_MOUNT_NOACL}, {"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; val = strchr(cp, '='); if (val != 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); } } } /* If new-style options "nfsvers=" or "vers=" are passed, override old "v2" and "v3" options */ if (nfs_version != 0) { switch (nfs_version) { case 2: mount_data.flags &= ~NFS_MOUNT_VER3; break; case 3: mount_data.flags |= NFS_MOUNT_VER3; break; default: fprintf(stderr, "%s: bad NFS version '%d'\n", progname, nfs_version); 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, ret; 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]; rem_name = strdup(rem_path); if (rem_name == NULL) { perror("strdup"); return 1; } rem_path = strchr(rem_path, ':'); if (rem_path == NULL) { fprintf(stderr, "%s: need a server\n", progname); free(rem_name); return 1; } *rem_path++ = '\0'; if (*rem_path != '/') { fprintf(stderr, "%s: need a path\n", progname); free(rem_name); 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) { free(rem_name); return 1; } #endif ret = 0; if (nfs_mount(rem_name, hostname, server, rem_path, path, &mount_data) != 0) ret = 1; /* If we set up the spoofer, tear it down now */ if (spoof_portmap) { kill(spoof_portmap, SIGTERM); while (waitpid(spoof_portmap, NULL, 0) == -1 && errno == EINTR) ; } free(rem_name); return ret; } klibc-2.0.7/usr/kinit/nfsmount/dummypmap_test.c0000644000175000017500000000004413546663605017726 0ustar benben#define TEST #include "dummypmap.c" klibc-2.0.7/usr/kinit/nfsmount/dummypmap.h0000644000175000017500000000032513546663605016676 0ustar benben/* * 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 */ klibc-2.0.7/usr/kinit/nfsmount/dummypmap.c0000644000175000017500000001342713546663605016700 0ustar benben/* * 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 "dummypmap.h" #include "sunrpc.h" extern const char *progname; struct portmap_args { uint32_t program; uint32_t version; uint32_t proto; uint32_t port; }; struct portmap_call { struct rpc_call rpc; struct portmap_args args; }; 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 void *get_auth(struct rpc_auth *auth) { switch (ntohl(auth->flavor)) { case AUTH_NULL: /* Fallthrough */ case AUTH_UNIX: return (char *)&auth->body + ntohl(auth->len); default: return NULL; } } static int check_unix_cred(struct rpc_auth *cred) { uint32_t len; int quad_len; uint32_t node_name_len; int quad_name_len; uint32_t *base; uint32_t *pos; int ret = -1; len = ntohl(cred->len); quad_len = (len + 3) >> 2; if (quad_len < 6) /* Malformed creds */ goto out; base = pos = cred->body; /* Skip timestamp */ pos++; /* Skip node name: only localhost can succeed. */ node_name_len = ntohl(*pos++); quad_name_len = (node_name_len + 3) >> 2; if (pos + quad_name_len + 3 > base + quad_len) /* Malformed creds */ goto out; pos += quad_name_len; /* uid must be 0 */ if (*pos++ != 0) goto out; /* gid must be 0 */ if (*pos++ != 0) goto out; /* Skip remaining gids */ ret = 0; out: return ret; } static int check_cred(struct rpc_auth *cred) { switch (ntohl(cred->flavor)) { case AUTH_NULL: return 0; case AUTH_UNIX: return check_unix_cred(cred); default: return -1; } } static int check_vrf(struct rpc_auth *vrf) { return (vrf->flavor == htonl(AUTH_NULL)) ? 0 : -1; } #define MAX_UDP_PACKET 65536 static int dummy_portmap(int sock, FILE *portmap_file) { struct sockaddr_in sin; int pktlen, addrlen; union { struct rpc_call rpc; /* Max UDP packet size + unused TCP fragment size */ char payload[MAX_UDP_PACKET + offsetof(struct rpc_header, udp)]; } pkt; struct rpc_call *rpc = &pkt.rpc; struct rpc_auth *cred; struct rpc_auth *vrf; struct portmap_args *args; struct portmap_reply rply; for (;;) { addrlen = sizeof sin; pktlen = recvfrom(sock, &rpc->hdr.udp, MAX_UDP_PACKET, 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 (rpc->hdr.udp.msg_type != htonl(RPC_CALL)) continue; /* Bad packet */ memset(&rply, 0, sizeof rply); rply.rpc.hdr.udp.xid = rpc->hdr.udp.xid; rply.rpc.hdr.udp.msg_type = htonl(RPC_REPLY); cred = (struct rpc_auth *) &rpc->cred_flavor; if (rpc->rpc_vers != htonl(2)) { rply.rpc.reply_state = htonl(REPLY_DENIED); /* state <- RPC_MISMATCH == 0 */ } else if (rpc->program != htonl(PORTMAP_PROGRAM)) { rply.rpc.reply_state = htonl(PROG_UNAVAIL); } else if (rpc->prog_vers != htonl(2)) { rply.rpc.reply_state = htonl(PROG_MISMATCH); } else if (!(vrf = get_auth(cred)) || (char *)vrf > ((char *)&rpc->hdr.udp + pktlen - 8 - sizeof(*args)) || !(args = get_auth(vrf)) || (char *)args > ((char *)&rpc->hdr.udp + pktlen - sizeof(*args)) || check_cred(cred) || check_vrf(vrf)) { /* Can't deal with credentials data; the kernel won't send them */ rply.rpc.reply_state = htonl(SYSTEM_ERR); } else { switch (ntohl(rpc->proc)) { case PMAP_PROC_NULL: break; case PMAP_PROC_SET: if (args->proto == htonl(IPPROTO_TCP) || args->proto == htonl(IPPROTO_UDP)) { if (portmap_file) fprintf(portmap_file, "%u %u %s %u\n", ntohl(args->program), ntohl(args->version), protoname(args->proto), ntohl(args->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 { fclose(portmap_filep); fprintf(stderr, "%s: portmap spoofing failed\n", progname); return -1; } } spoof_portmap = fork(); if (spoof_portmap == -1) { fclose(portmap_filep); 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; } } klibc-2.0.7/usr/kinit/nfsmount/README.locking0000644000175000017500000000213213546663605017017 0ustar benbenI 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 klibc-2.0.7/usr/kinit/nfsmount/Kbuild0000644000175000017500000000123313546663605015650 0ustar benben# # 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 ifdef KLIBCSHAREDFLAGS install-y := $(shared-y) else install-y := $(static-y) endif klibc-2.0.7/usr/kinit/name_to_dev.c0000644000175000017500000001067313546663605015276 0ustar benben#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_num, minor_num; 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_num = strtoul(buf, &s, 10); if (*s != ':') goto fail; minor_num = strtoul(s + 1, &s, 10); if (*s) goto fail; res = makedev(major_num, minor_num); /* 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) { dprintf("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_num, minor_num; /* Are we a multi root line? */ if (strchr(name, ',')) return Root_MULTI; 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)) { cptr = strchr(devname+5, ':'); if (cptr && cptr[1] != '\0') { /* Colon-separated decimal device number */ *cptr = '\0'; major_num = strtoul(devname+5, &e1, 10); minor_num = strtoul(cptr+1, &e2, 10); if (!*e1 && !*e2) return makedev(major_num, minor_num); *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); dprintf("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 klibc-2.0.7/usr/kinit/kinit.h0000644000175000017500000000260513546663605014135 0ustar benben/* * 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[]); void md_run(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 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; }) #ifdef DEBUG # define dprintf printf #else # define dprintf(...) ((void)0) #endif #ifdef DEBUG void dump_args(int argc, char *argv[]); #else static inline void dump_args(int argc, char *argv[]) { (void)argc; (void)argv; } #endif int drop_capabilities(const char *caps); #endif /* KINIT_H */ klibc-2.0.7/usr/kinit/kinit.c0000644000175000017500000001431413546663605014130 0ustar benben#include #include #include #include #include #include #include #include #include #include #include #include "kinit.h" #include "ipconfig.h" #include "run-init.h" #include "resume.h" const char *progname = "kinit"; int mnt_procfs; int mnt_sysfs; #ifdef 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 /* DEBUG */ static int do_ipconfig(int argc, char *argv[]) { int i, a = 0; char **args = alloca((argc + 3) * sizeof(char *)); if (!args) return -1; args[a++] = (char *)"IP-Config"; args[a++] = (char *)"-i"; args[a++] = (char *)"Linux kinit"; dprintf("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) dprintf("Checking for init: %s\n", user); if (user && user[0] == '/' && !access(user+1, X_OK)) { path = user; } else { for (p = init_paths; *p; p++) { dprintf("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", get_arg(cmdc, cmdv, "drop_capabilities="), false, false, 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; } klibc-2.0.7/usr/kinit/ipconfig/0000755000175000017500000000000013546663605014441 5ustar benbenklibc-2.0.7/usr/kinit/ipconfig/packet.h0000644000175000017500000000054313546663605016063 0ustar benben#ifndef IPCONFIG_PACKET_H #define IPCONFIG_PACKET_H struct iovec; int packet_open(struct netdev *dev); void packet_close(struct netdev *dev); int packet_send(struct netdev *dev, struct iovec *iov, int iov_len); void packet_discard(struct netdev *dev); int packet_recv(struct netdev *dev, struct iovec *iov, int iov_len); #endif /* IPCONFIG_PACKET_H */ klibc-2.0.7/usr/kinit/ipconfig/packet.c0000644000175000017500000001333013546663605016054 0ustar benben#include /*XXX*/ /* * 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" uint16_t cfg_local_port = LOCAL_PORT; uint16_t cfg_remote_port = REMOTE_PORT; int packet_open(struct netdev *dev) { struct sockaddr_ll sll; int fd, rv, one = 1; /* * 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); return -1; } memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = dev->ifindex; rv = bind(fd, (struct sockaddr *)&sll, sizeof(sll)); if (-1 == rv) { perror("bind"); close(fd); return -1; } dev->pkt_fd = fd; return fd; } void packet_close(struct netdev *dev) { close(dev->pkt_fd); dev->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 DEBUG /* Only used with dprintf() */ static char *ntoa(uint32_t addr) { struct in_addr in = { addr }; return inet_ntoa(in); } #endif /* DEBUG */ /* * Send a packet. The options are listed in iov[1...iov_len-1]. * 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; int i, len = 0; memset(&sll, 0, sizeof(sll)); msg.msg_name = &sll; msg.msg_namelen = sizeof(sll); msg.msg_iov = iov; msg.msg_iovlen = iov_len; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; if (cfg_local_port != LOCAL_PORT) { ipudp_hdrs.udp.source = htons(cfg_local_port); ipudp_hdrs.udp.dest = htons(cfg_remote_port); } dprintf("\n udp src %d dst %d", ntohs(ipudp_hdrs.udp.source), ntohs(ipudp_hdrs.udp.dest)); dprintf("\n ip src %s ", ntoa(ipudp_hdrs.ip.saddr)); dprintf("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)); dprintf("\n bytes %d\n", len); return sendmsg(dev->pkt_fd, &msg, 0); } void packet_discard(struct netdev *dev) { struct iphdr iph; struct sockaddr_ll sll; socklen_t sllen = sizeof(sll); sll.sll_ifindex = dev->ifindex; recvfrom(dev->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. * Returns: * -1 = Error, try again later * 0 = Discarded packet (non-DHCP/BOOTP traffic) * >0 = Size of packet */ int packet_recv(struct netdev *dev, 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; struct sockaddr_ll sll; socklen_t sllen = sizeof(sll); sll.sll_ifindex = dev->ifindex; msg.msg_name = &sll; msg.msg_namelen = sllen; ret = recvfrom(dev->pkt_fd, &iph, sizeof(struct iphdr), MSG_PEEK, (struct sockaddr *)&sll, &sllen); 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(dev->pkt_fd, &msg, 0); if (ret == -1) goto free_pkt; dprintf("<- bytes %d ", ret); if (ip_checksum((uint16_t *) ip, ip->ihl) != 0) goto free_pkt; dprintf("\n ip src %s ", ntoa(ip->saddr)); dprintf("dst %s ", ntoa(ip->daddr)); if (ntohs(ip->tot_len) > ret || ip->protocol != IPPROTO_UDP) goto free_pkt; ret -= 4 * ip->ihl; dprintf("\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: dprintf("freed\n"); free(ip); return 0; discard_pkt: dprintf("discarded\n"); packet_discard(dev); return 0; } klibc-2.0.7/usr/kinit/ipconfig/netdev.h0000644000175000017500000000602013546663605016075 0ustar benben#ifndef IPCONFIG_NETDEV_H #define IPCONFIG_NETDEV_H #include #include #include #define BPLEN 256 #define FNLEN 128 /* from DHCP RFC 2131 */ struct route { uint32_t subnet; /* subnet */ uint32_t netmask_width; /* subnet mask width */ uint32_t gateway; /* gateway */ struct route *next; }; struct netdev { 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; uint8_t proto; /* a protocol used (e.g. PROTO_DHCP) */ 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 */ uint32_t dhcpleasetime; /* duration in seconds */ char reqhostname[SYS_NMLN]; /* requested hostname */ char hostname[SYS_NMLN]; /* hostname */ char dnsdomainname[SYS_NMLN]; /* dns domain name */ char nisdomainname[SYS_NMLN]; /* nis domain name */ char bootpath[BPLEN]; /* boot path */ char filename[FNLEN]; /* filename */ char *domainsearch; /* decoded, NULL or malloc-ed */ struct route *routes; /* decoded, NULL or malloc-ed list */ long uptime; /* when complete configuration */ int pkt_fd; /* packet socket for this interface */ 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_setroutes(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); } static inline uint32_t netdev_genmask(uint32_t netmask_width) { /* Map netmask width to network mask in network byte order. Example: 24 -> "255.255.255.0" -> htonl(0xFFFFFF00) */ if (netmask_width == 0) { return 0; } else { return htonl(~((1u << (32 - netmask_width)) - 1)); } } #endif /* IPCONFIG_NETDEV_H */ klibc-2.0.7/usr/kinit/ipconfig/netdev.c0000644000175000017500000001315713546663605016101 0ustar benben/* * ioctl-based device configuration */ #include #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; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; memcpy(&ifr->ifr_addr, &sin, sizeof sin); 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; } static void set_s_addr(struct sockaddr *saddr, uint32_t ipaddr) { struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr.s_addr = ipaddr, }; memcpy(saddr, &sin, sizeof sin); } int netdev_setroutes(struct netdev *dev) { struct rtentry r; /* RFC3442 demands: If the DHCP server returns both a Classless Static Routes option and a Router option, the DHCP client MUST ignore the Router option. */ if (dev->routes != NULL) { struct route *cur; for (cur = dev->routes; cur != NULL; cur = cur->next) { memset(&r, 0, sizeof(r)); r.rt_dev = dev->name; set_s_addr(&r.rt_dst, cur->subnet); set_s_addr(&r.rt_gateway, cur->gateway); set_s_addr(&r.rt_genmask, netdev_genmask(cur->netmask_width)); r.rt_flags = RTF_UP; if (cur->gateway != 0) { r.rt_flags |= RTF_GATEWAY; } if (ioctl(cfd, SIOCADDRT, &r) == -1 && errno != EEXIST) { perror("SIOCADDRT"); return -1; } } } else if (dev->ip_gateway != INADDR_ANY) { memset(&r, 0, sizeof(r)); set_s_addr(&r.rt_dst, INADDR_ANY); set_s_addr(&r.rt_gateway, dev->ip_gateway); set_s_addr(&r.rt_genmask, 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; } klibc-2.0.7/usr/kinit/ipconfig/main.c0000644000175000017500000004741313546663605015542 0ustar benben#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; static int n_devices = 0; /* DHCP vendor class identifier */ char vendor_class_identifier[260]; int vendor_class_identifier_len; struct state { int state; int restart_state; time_t expire; int retry_period; struct netdev *dev; struct state *next; }; /* #define PROTO_x : for uint8_t proto of struct netdev */ struct protoinfo { char *name; } protoinfos[] = { #define PROTO_NONE 0 {"none"}, #define PROTO_BOOTP 1 {"bootp"}, #define PROTO_DHCP 2 {"dhcp"}, #define PROTO_RARP 3 {"rarp"} }; 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) { int dns0_spaces; int dns1_spaces; printf("IP-Config: %s complete", dev->name); if (dev->proto == PROTO_BOOTP || dev->proto == PROTO_DHCP) printf(" (%s from %s)", protoinfos[dev->proto].name, my_inet_ntoa(dev->serverid ? dev->serverid : dev->ip_server)); printf(":\n 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)); if (dev->routes != NULL) { struct route *cur; char *delim = ""; printf(" routes :"); for (cur = dev->routes; cur != NULL; cur = cur->next) { printf("%s %s/%u", delim, my_inet_ntoa(cur->subnet), cur->netmask_width); if (cur->gateway != 0) { printf(" via %s", my_inet_ntoa(cur->gateway)); } delim = ","; } printf("\n"); dns0_spaces = 3; dns1_spaces = 5; } else { printf(" gateway: %-16s", my_inet_ntoa(dev->ip_gateway)); dns0_spaces = 5; dns1_spaces = 3; } printf(" dns0%*c: %-16s", dns0_spaces, ' ', my_inet_ntoa(dev->ip_nameserver[0])); printf(" dns1%*c: %-16s\n", dns1_spaces, ' ', 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); printf(" filename : %s\n", dev->filename); } 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_setroutes(dev)) printf("IP-Config: failed to set routes on %s\n", dev->name); if (dev->hostname[0] && sethostname(dev->hostname, strlen(dev->hostname))) printf("IP-Config: failed to set hostname '%s' from %s\n", dev->hostname, dev->name); } /* * Escape shell varialbes in git style: * Always start with a single quote ('), then leave all characters * except ' and ! unchanged. */ static void write_option(FILE *f, const char *name, const char *chr) { fprintf(f, "%s='", name); while (*chr) { switch (*chr) { case '!': case '\'': fprintf(f, "'\\%c'", *chr); break; default: fprintf(f, "%c", *chr); break; } ++chr; } fprintf(f, "'\n"); } static void dump_device_config(struct netdev *dev) { char fn[40]; FILE *f; /* * char UINT64_MAX[] = "18446744073709551615"; * sizeof(UINT64_MAX)==21 */ char buf21[21]; const char path[] = "/run/"; snprintf(fn, sizeof(fn), "%snet-%s.conf", path, dev->name); f = fopen(fn, "w"); if (f) { write_option(f, "DEVICE", dev->name); write_option(f, "PROTO", protoinfos[dev->proto].name); write_option(f, "IPV4ADDR", my_inet_ntoa(dev->ip_addr)); write_option(f, "IPV4BROADCAST", my_inet_ntoa(dev->ip_broadcast)); write_option(f, "IPV4NETMASK", my_inet_ntoa(dev->ip_netmask)); if (dev->routes != NULL) { /* Use 6 digits to encode the index */ char key[23]; char value[19]; int i = 0; struct route *cur; for (cur = dev->routes; cur != NULL; cur = cur->next) { snprintf(key, sizeof(key), "IPV4ROUTE%iSUBNET", i); snprintf(value, sizeof(value), "%s/%u", my_inet_ntoa(cur->subnet), cur->netmask_width); write_option(f, key, value); snprintf(key, sizeof(key), "IPV4ROUTE%iGATEWAY", i); write_option(f, key, my_inet_ntoa(cur->gateway)); i++; } } else { write_option(f, "IPV4GATEWAY", my_inet_ntoa(dev->ip_gateway)); } write_option(f, "IPV4DNS0", my_inet_ntoa(dev->ip_nameserver[0])); write_option(f, "IPV4DNS1", my_inet_ntoa(dev->ip_nameserver[1])); write_option(f, "HOSTNAME", dev->hostname); write_option(f, "DNSDOMAIN", dev->dnsdomainname); write_option(f, "NISDOMAIN", dev->nisdomainname); write_option(f, "ROOTSERVER", my_inet_ntoa(dev->ip_server)); write_option(f, "ROOTPATH", dev->bootpath); write_option(f, "filename", dev->filename); sprintf(buf21, "%ld", (long)dev->uptime); write_option(f, "UPTIME", buf21); sprintf(buf21, "%u", (unsigned int)dev->dhcpleasetime); write_option(f, "DHCPLEASETIME", buf21); write_option(f, "DOMAINSEARCH", dev->domainsearch == NULL ? "" : dev->domainsearch); 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)); } } static void complete_device(struct netdev *dev) { struct sysinfo info; if (!sysinfo(&info)) dev->uptime = info.uptime; postprocess_device(dev); configure_device(dev); dump_device_config(dev); print_device_config(dev); packet_close(dev); ++configured; dev->next = ifaces; ifaces = dev; } /* * Returns: * 0 = Not handled, try again later * 1 = Handled */ static int process_receive_event(struct state *s, time_t now) { int handled = 1; switch (s->state) { case DEVST_ERROR: return 0; /* Not handled */ case DEVST_COMPLETE: return 0; /* Not handled as already configured */ case DEVST_BOOTP: s->restart_state = DEVST_BOOTP; switch (bootp_recv_reply(s->dev)) { case -1: s->state = DEVST_ERROR; break; case 0: handled = 0; break; case 1: s->state = DEVST_COMPLETE; s->dev->proto = PROTO_BOOTP; dprintf("\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 0: handled = 0; break; case DHCPOFFER: /* 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 0: handled = 0; break; case DHCPACK: /* ACK received */ s->state = DEVST_COMPLETE; s->dev->proto = PROTO_DHCP; break; case DHCPNAK: /* NAK received */ s->state = DEVST_DHCPDISC; break; } break; default: dprintf("\n"); handled = 0; 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; 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; /* * Returns: * 0 = No dhcp/bootp packet was received * 1 = A packet was received and handled */ static int do_pkt_recv(int nr, struct pollfd *fds, time_t now) { int i, ret = 0; struct state *s; for (i = 0, s = slist; s && nr; s = s->next, i++) { if (fds[i].revents & POLLRDNORM) { ret |= process_receive_event(s, now); nr--; } } return ret; } static int loop(void) { struct pollfd *fds; struct state *s; int i, nr = 0, rc = 0; struct timeval now, prev; time_t start; fds = malloc(sizeof(struct pollfd) * n_devices); if (!fds) { fprintf(stderr, "malloc failed\n"); rc = -1; goto bail; } memset(fds, 0, sizeof(*fds)); gettimeofday(&now, NULL); start = now.tv_sec; while (1) { int timeout = 60; int pending = 0; int done = 0; int timeout_ms; int x; for (i = 0, s = slist; s; s = s->next, i++) { dprintf("%s: state = %d\n", s->dev->name, s->state); fds[i].fd = s->dev->pkt_fd; fds[i].events = POLLRDNORM; if (s->state == DEVST_COMPLETE) { done++; continue; } pending++; if (s->expire - now.tv_sec <= 0) { dprintf("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, n_devices, timeout_ms); prev = now; gettimeofday(&now, NULL); if ((nr > 0) && do_pkt_recv(nr, fds, now.tv_sec)) break; if (loop_timeout >= 0 && now.tv_sec - start >= loop_timeout) { printf("IP-Config: no response after %d " "secs - giving up\n", loop_timeout); rc = -1; goto bail; } delta_ms = (now.tv_sec - prev.tv_sec) * 1000; delta_ms += (now.tv_usec - prev.tv_usec) / 1000; dprintf("Delta: %d ms\n", delta_ms); timeout_ms -= delta_ms; } } bail: if (fds) free(fds); return rc; } 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; n_devices++; 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, char *ip) { char *cp; int opt; int is_ip = 0; dprintf("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 an interface name */ if (is_ip) { dev->caps = parse_proto(ip); bringup_first = 1; } else { dev->name = ip; } } else { for (opt = 0; ip && *ip; ip = cp, opt++) { if ((cp = strchr(ip, ':'))) { *cp++ = '\0'; } if (opt > 8) { fprintf(stderr, "%s: too many options for %s\n", progname, dev->name); longjmp(abort_buf, 1); } if (*ip == '\0') continue; dprintf("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'; memcpy(dev->reqhostname, dev->hostname, SYS_NMLN); break; case 5: dev->name = ip; break; case 6: dev->caps = parse_proto(ip); break; case 7: parse_addr(&dev->ip_nameserver[0], ip); break; case 8: parse_addr(&dev->ip_nameserver[1], ip); break; } } } if (dev->name == NULL || dev->name[0] == '\0' || strcmp(dev->name, "all") == 0) { add_all_devices(dev); bringup_first = 1; return 0; } return 1; } static void bringup_device(struct netdev *dev) { if (netdev_up(dev) == 0) { if (dev->caps) add_one_dev(dev); else { dev->proto = PROTO_NONE; 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); if (template->reqhostname[0] != '\0') strcpy(dev->reqhostname, template->reqhostname); dev->caps &= template->caps; bringup_device(dev); } static struct netdev *add_device(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; if (packet_open(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))) { dprintf("Trying to bring up %s\n", de->d_name); dev = add_device(de->d_name); if (!dev) 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; } static void set_vendor_identifier(const char *id) { int len = strlen(id); if (len >= 255) { fprintf(stderr, "%s: invalid vendor class identifier: " "%s\n", progname, id); longjmp(abort_buf, 1); } memcpy(vendor_class_identifier+2, id, len); vendor_class_identifier[0] = 60; vendor_class_identifier[1] = len; vendor_class_identifier_len = len+2; } 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 = 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)); } if ((err = setjmp(abort_buf))) return err; /* Default vendor identifier */ set_vendor_identifier("Linux ipconfig"); do { c = getopt(argc, argv, "c:d:i: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 'i': set_vendor_identifier(optarg); 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); } err = loop(); } return err; } klibc-2.0.7/usr/kinit/ipconfig/ipconfig.h0000644000175000017500000000100113546663605016400 0ustar benben#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; extern char vendor_class_identifier[]; extern int vendor_class_identifier_len; int ipconfig_main(int argc, char *argv[]); uint32_t ipconfig_server_address(void *next); #ifdef DEBUG # define dprintf printf #else # define dprintf(...) ((void)0) #endif #endif /* IPCONFIG_IPCONFIG_H */ klibc-2.0.7/usr/kinit/ipconfig/dhcp_proto.h0000644000175000017500000000076213546663605016760 0ustar benben#ifndef IPCONFIG_DHCP_PROTO_H #define 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); #endif /* IPCONFIG_DHCP_PROTO_H */ klibc-2.0.7/usr/kinit/ipconfig/dhcp_proto.c0000644000175000017500000001545313546663605016756 0ustar benben/* * 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?) */ 119, /* Domain Search Option */ 121, /* Classless Static Route Option (RFC3442) */ }; 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, }; /* Both iovecs below have to have the same structure, since dhcp_send() pokes at the internals */ #define DHCP_IOV_LEN 8 static struct iovec dhcp_discover_iov[DHCP_IOV_LEN] = { /* [0] = ip + udp header */ /* [1] = bootp header */ [2] = {dhcp_discover_hdr, sizeof(dhcp_discover_hdr)}, [3] = {dhcp_params, sizeof(dhcp_params)}, /* [4] = optional vendor class */ /* [5] = optional hostname */ /* [6] = {dhcp_end, sizeof(dhcp_end)} */ /* [7] = optional padding */ }; static struct iovec dhcp_request_iov[DHCP_IOV_LEN] = { /* [0] = ip + udp header */ /* [1] = bootp header */ [2] = {dhcp_request_hdr, sizeof(dhcp_request_hdr)}, [3] = {dhcp_params, sizeof(dhcp_params)}, /* [4] = optional vendor class */ /* [5] = optional hostname */ /* [6] = {dhcp_end, sizeof(dhcp_end)} */ /* [7] = optional padding */ }; /* * Parse a DHCP response packet * Returns: * 0 = Unexpected packet, not parsed * 2 = DHCPOFFER (from dhcp_proto.h) * 5 = DHCPACK * 6 = DHCPNACK */ 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; uint32_t leasetime = 0; 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;) { int len; uint8_t opt = *ext++; if (opt == 0) continue; else if (opt == 255) break; if (ext - exts >= extlen) break; len = *ext++; if (ext - exts + len > extlen) break; switch (opt) { case 51: /* IP Address Lease Time */ if (len == 4) leasetime = ntohl(*(uint32_t *)ext); break; case 53: /* DHCP Message Type */ if (len == 1) type = *ext; break; case 54: /* Server Identifier */ if (len == 4) memcpy(&serverid, ext, 4); break; } ext += len; } } switch (type) { case DHCPOFFER: ret = bootp_parse(dev, hdr, exts, extlen) ? DHCPOFFER : 0; if (ret == DHCPOFFER && serverid != INADDR_NONE) dev->serverid = serverid; dprintf("\n dhcp offer\n"); break; case DHCPACK: dev->dhcpleasetime = leasetime; ret = bootp_parse(dev, hdr, exts, extlen) ? DHCPACK : 0; dprintf("\n dhcp ack\n"); break; case DHCPNAK: ret = DHCPNAK; dprintf("\n dhcp nak\n"); break; } return ret; } /* * Receive and parse a DHCP packet * Returns: *-1 = Error in packet_recv, try again later * 0 = Unexpected packet, discarded * 2 = DHCPOFFER (from dhcp_proto.h) * 5 = DHCPACK * 6 = DHCPNACK */ static int dhcp_recv(struct netdev *dev) { struct bootp_hdr bootp; uint8_t dhcp_options[BOOTP_EXTS_SIZE]; struct iovec iov[] = { /* [0] = ip + udp header */ [1] = {&bootp, sizeof(struct bootp_hdr)}, [2] = {dhcp_options, sizeof(dhcp_options)} }; int ret; ret = packet_recv(dev, iov, 3); if (ret <= 0) return ret; dprintf("\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) { struct bootp_hdr bootp; char dhcp_hostname[SYS_NMLN+2]; uint8_t padding[BOOTP_MIN_LEN - sizeof(struct bootp_hdr)]; int padding_len; int i = 4; int j; 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 = INADDR_ANY; /* yiaddr should always be set to 0 for the messages we're likely * to send as a DHCP client: DHCPDISCOVER, DHCPREQUEST, DHCPDECLINE, * DHCPINFORM, DHCPRELEASE * cf. RFC2131 section 4.1.1, table 5. */ bootp.yiaddr = INADDR_ANY; bootp.giaddr = INADDR_ANY; bootp.flags = htons(0x8000); 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); dprintf("xid %08x secs %d ", bootp.xid, ntohs(bootp.secs)); if (vendor_class_identifier_len > 2) { vec[i].iov_base = vendor_class_identifier; vec[i].iov_len = vendor_class_identifier_len; i++; dprintf("vendor_class_identifier \"%.*s\" ", vendor_class_identifier_len-2, vendor_class_identifier+2); } if (dev->reqhostname[0] != '\0') { int len = strlen(dev->reqhostname); dhcp_hostname[0] = 12; dhcp_hostname[1] = len; memcpy(dhcp_hostname+2, dev->reqhostname, len); vec[i].iov_base = dhcp_hostname; vec[i].iov_len = len+2; i++; printf("hostname %.*s ", len, dhcp_hostname+2); } vec[i].iov_base = dhcp_end; vec[i].iov_len = sizeof(dhcp_end); /* Append padding if DHCP packet length is shorter than BOOTP_MIN_LEN */ padding_len = sizeof(padding); for (j = 2; j <= i; j++) padding_len -= vec[j].iov_len; if (padding_len > 0) { memset(padding, 0, padding_len); i++; vec[i].iov_base = padding; vec[i].iov_len = padding_len; } return packet_send(dev, vec, i + 1); } /* * Send a DHCP discover packet */ int dhcp_send_discover(struct netdev *dev) { dev->ip_addr = INADDR_ANY; dev->ip_gateway = INADDR_ANY; dprintf("-> dhcp discover "); return dhcp_send(dev, dhcp_discover_iov); } /* * 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); dprintf("-> dhcp request "); return dhcp_send(dev, dhcp_request_iov); } /* * Receive a DHCP ack packet */ int dhcp_recv_ack(struct netdev *dev) { return dhcp_recv(dev); } klibc-2.0.7/usr/kinit/ipconfig/bootp_proto.h0000644000175000017500000000047313546663605017164 0ustar benben#ifndef IPCONFIG_BOOTP_PROTO_H #define IPCONFIG_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); #endif /* IPCONFIG_BOOTP_PROTO_H */ klibc-2.0.7/usr/kinit/ipconfig/bootp_proto.c0000644000175000017500000003262113546663605017157 0ustar benben/* * 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); dprintf("-> bootp xid 0x%08x secs 0x%08x ", bootp.xid, ntohs(bootp.secs)); return packet_send(dev, iov, 2); } /* * DESCRIPTION * bootp_ext119_decode() decodes Domain Search Option data. * The decoded string is separated with ' '. * For example, it is either "foo.bar.baz. bar.baz.", "foo.bar.", or "foo.". * * ARGUMENTS * const uint8_t *ext * *ext is a pointer to a DHCP Domain Search Option data. *ext does not * include a tag(code) octet and a length octet in DHCP options. * For example, if *ext is {3, 'f', 'o', 'o', 0}, this function returns * a pointer to a "foo." string. * * int16_t ext_size * ext_size is the memory size of *ext. For example, * if *ext is {3, 'f', 'o', 'o', 0}, ext_size must be 5. * * uint8_t *tmp * *tmp is a pointer to a temporary memory space for decoding. * The memory size must be equal to or more than ext_size. * 'memset(tmp, 0, sizeof(tmp));' is not required, but values in *tmp * are changed in decoding process. * * RETURN VALUE * if OK, a pointer to a decoded string malloc-ed * else , NULL * * SEE ALSO RFC3397 */ static char *bootp_ext119_decode(const void *ext, int16_t ext_size, void *tmp) { uint8_t *u8ext; int_fast32_t i; int_fast32_t decoded_size; int_fast8_t currentdomain_is_singledot; /* only for validating *ext */ uint8_t *is_pointee; int_fast32_t is_pointee_size; /* only for structing a decoded string */ char *decoded_str; int_fast32_t dst_i; if (ext == NULL || ext_size <= 0 || tmp == NULL) return NULL; u8ext = (uint8_t *)ext; is_pointee = tmp; memset(is_pointee, 0, (size_t)ext_size); is_pointee_size = 0; /* * validate the format of *ext and * calculate the memory size for a decoded string */ i = 0; decoded_size = 0; currentdomain_is_singledot = 1; while (1) { if (i >= ext_size) return NULL; if (u8ext[i] == 0) { /* Zero-ending */ if (currentdomain_is_singledot) decoded_size++; /* for '.' */ decoded_size++; /* for ' ' or '\0' */ currentdomain_is_singledot = 1; i++; if (i == ext_size) break; is_pointee_size = i; } else if (u8ext[i] < 0x40) { /* Label(sub-domain string) */ int j; /* loosely validate characters for domain names */ if (i + u8ext[i] >= ext_size) return NULL; for (j = i + 1; j <= i + u8ext[i]; j++) if (!(u8ext[j] == '-' || ('0' <= u8ext[j] && u8ext[j] <= '9') || ('A' <= u8ext[j] && u8ext[j] <= 'Z') || ('a' <= u8ext[j] && u8ext[j] <= 'z'))) return NULL; is_pointee[i] = 1; decoded_size += u8ext[i] + 1; /* for Label + '.' */ currentdomain_is_singledot = 0; i += u8ext[i] + 1; } else if (u8ext[i] < 0xc0) return NULL; else { /* Compression-pointer (to a prior Label) */ int_fast32_t p; if (i + 1 >= ext_size) return NULL; p = ((0x3f & u8ext[i]) << 8) + u8ext[i + 1]; if (!(p < is_pointee_size && is_pointee[p])) return NULL; while (1) { /* u8ext[p] was validated */ if (u8ext[p] == 0) { /* Zero-ending */ decoded_size++; break; } else if (u8ext[p] < 0x40) { /* Label(sub-domain string) */ decoded_size += u8ext[p] + 1; p += u8ext[p] + 1; } else { /* Compression-pointer */ p = ((0x3f & u8ext[p]) << 8) + u8ext[p + 1]; } } currentdomain_is_singledot = 1; i += 2; if (i == ext_size) break; is_pointee_size = i; } } /* * construct a decoded string */ decoded_str = malloc(decoded_size); if (decoded_str == NULL) return NULL; i = 0; dst_i = 0; currentdomain_is_singledot = 1; while (1) { if (u8ext[i] == 0) { /* Zero-ending */ if (currentdomain_is_singledot) { if (dst_i != 0) dst_i++; decoded_str[dst_i] = '.'; } dst_i++; decoded_str[dst_i] = ' '; currentdomain_is_singledot = 1; i++; if (i == ext_size) break; } else if (u8ext[i] < 0x40) { /* Label(sub-domain string) */ if (dst_i != 0) dst_i++; memcpy(&decoded_str[dst_i], &u8ext[i + 1], (size_t)u8ext[i]); dst_i += u8ext[i]; decoded_str[dst_i] = '.'; currentdomain_is_singledot = 0; i += u8ext[i] + 1; } else { /* Compression-pointer (to a prior Label) */ int_fast32_t p; p = ((0x3f & u8ext[i]) << 8) + u8ext[i + 1]; while (1) { if (u8ext[p] == 0) { /* Zero-ending */ decoded_str[dst_i++] = '.'; decoded_str[dst_i] = ' '; break; } else if (u8ext[p] < 0x40) { /* Label(sub-domain string) */ dst_i++; memcpy(&decoded_str[dst_i], &u8ext[p + 1], (size_t)u8ext[p]); dst_i += u8ext[p]; decoded_str[dst_i] = '.'; p += u8ext[p] + 1; } else { /* Compression-pointer */ p = ((0x3f & u8ext[p]) << 8) + u8ext[p + 1]; } } currentdomain_is_singledot = 1; i += 2; if (i == ext_size) break; } } decoded_str[dst_i] = '\0'; #ifdef DEBUG if (dst_i + 1 != decoded_size) { dprintf("bug:%s():bottom: malloc(%ld), write(%ld)\n", __func__, (long)decoded_size, (long)(dst_i + 1)); exit(1); } #endif return decoded_str; } /* * DESCRIPTION * bootp_ext121_decode() decodes Classless Route Option data. * * ARGUMENTS * const uint8_t *ext * *ext is a pointer to a DHCP Classless Route Option data. * For example, if *ext is {16, 192, 168, 192, 168, 42, 1}, * this function returns a pointer to * { * subnet = 192.168.0.0; * netmask_width = 16; * gateway = 192.168.42.1; * next = NULL; * } * * int16_t ext_size * ext_size is the memory size of *ext. For example, * if *ext is {16, 192, 168, 192, 168, 42, 1}, ext_size must be 7. * * RETURN VALUE * if OK, a pointer to a decoded struct route malloc-ed * else , NULL * * SEE ALSO RFC3442 */ struct route *bootp_ext121_decode(const uint8_t *ext, int16_t ext_size) { int16_t index = 0; uint8_t netmask_width; uint8_t significant_octets; struct route *routes = NULL; struct route *prev_route = NULL; while (index < ext_size) { netmask_width = ext[index]; index++; if (netmask_width > 32) { printf("IP-Config: Given Classless Route Option subnet mask width '%u' " "exceeds IPv4 limit of 32. Ignoring remaining option.\n", netmask_width); return routes; } significant_octets = netmask_width / 8 + (netmask_width % 8 > 0); if (ext_size - index < significant_octets + 4) { printf("IP-Config: Given Classless Route Option remaining lengths (%u octets) " "is shorter than the expected %u octets. Ignoring remaining options.\n", ext_size - index, significant_octets + 4); return routes; } struct route *route = malloc(sizeof(struct route)); if (route == NULL) return routes; /* convert only significant octets from byte array into integer in network byte order */ route->subnet = 0; memcpy(&route->subnet, &ext[index], significant_octets); index += significant_octets; /* RFC3442 demands: After deriving a subnet number and subnet mask from each destination descriptor, the DHCP client MUST zero any bits in the subnet number where the corresponding bit in the mask is zero. */ route->subnet &= netdev_genmask(netmask_width); /* convert octet array into network byte order */ memcpy(&route->gateway, &ext[index], 4); index += 4; route->netmask_width = netmask_width; route->next = NULL; if (prev_route == NULL) { routes = route; } else { prev_route->next = route; } prev_route = route; } return routes; } /* * Parse a bootp reply packet */ int bootp_parse(struct netdev *dev, struct bootp_hdr *hdr, uint8_t *exts, int extlen) { uint8_t ext119_buf[BOOTP_EXTS_SIZE]; int16_t ext119_len = 0; uint8_t ext121_buf[BOOTP_EXTS_SIZE]; int16_t ext121_len = 0; 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'; memcpy(&dev->filename, &hdr->boot_file, FNLEN); 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; if (ext - exts >= extlen) break; len = *ext++; if (ext - exts + len > extlen) break; 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; case 119: /* Domain Search Option */ if (ext119_len >= 0 && ext119_len + len <= sizeof(ext119_buf)) { memcpy(ext119_buf + ext119_len, ext, len); ext119_len += len; } else ext119_len = -1; break; case 121: /* Classless Static Route Option (RFC3442) */ if (ext121_len >= 0 && ext121_len + len <= sizeof(ext121_buf)) { memcpy(ext121_buf + ext121_len, ext, len); ext121_len += len; } else ext121_len = -1; break; } ext += len; } } if (ext119_len > 0) { char *ret; uint8_t ext119_tmp[BOOTP_EXTS_SIZE]; ret = bootp_ext119_decode(ext119_buf, ext119_len, ext119_tmp); if (ret != NULL) { if (dev->domainsearch != NULL) free(dev->domainsearch); dev->domainsearch = ret; } } if (ext121_len > 0) { struct route *ret; ret = bootp_ext121_decode(ext121_buf, ext121_len); if (ret != NULL) { struct route *cur = dev->routes; struct route *next; while (cur != NULL) { next = cur->next; free(cur); cur = next; } dev->routes = ret; } } /* * Got packet. */ return 1; } /* * Receive a bootp reply and parse packet * Returns: *-1 = Error in packet_recv, try again later * 0 = Unexpected packet, discarded * 1 = Correctly received and parsed packet */ int bootp_recv_reply(struct netdev *dev) { struct bootp_hdr bootp; uint8_t bootp_options[BOOTP_EXTS_SIZE]; struct iovec iov[] = { /* [0] = ip + udp headers */ [1] = {&bootp, sizeof(struct bootp_hdr)}, [2] = {bootp_options, sizeof(bootp_options)} }; int ret; ret = packet_recv(dev, 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; } klibc-2.0.7/usr/kinit/ipconfig/bootp_packet.h0000644000175000017500000000160413546663605017265 0ustar benben#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 */ }; /* * memory size of BOOTP Vendor Extensions/DHCP Options for receiving * * generic_ether_mtu:1500, min_sizeof(ip_hdr):20, sizeof(udp_hdr):8 * * #define BOOTP_EXTS_SIZE (1500 - 20 - 8 - sizeof(struct bootp_hdr)) */ /* larger size for backward compatibility of ipconfig */ #define BOOTP_EXTS_SIZE 1500 /* minimum length of BOOTP/DHCP packet on sending */ #define BOOTP_MIN_LEN 300 #endif /* BOOTP_PACKET_H */ klibc-2.0.7/usr/kinit/ipconfig/README.ipconfig0000644000175000017500000001045513546663605017123 0ustar benbenBOOTP/DHCP client for klibc --------------------------- Usage: ipconfig [-c proto] [-d interface] [-i identifier] [-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. -i identifier DHCP vendor class identifier. The default is "Linux ipconfig". -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) klibc-2.0.7/usr/kinit/ipconfig/Kbuild0000644000175000017500000000114313546663605015575 0ustar benben# # 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 ifdef KLIBCSHAREDFLAGS install-y := $(shared-y) else install-y := $(static-y) endif klibc-2.0.7/usr/kinit/initrd.c0000644000175000017500000001145213546663605014303 0ustar benben/* * 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; dprintf("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; dprintf("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; dprintf("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 */ dprintf("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("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0); old_fd = open("/old", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0); if (root_fd < 0 || old_fd < 0) return -errno; if (chdir("/root") || mount(".", "/", NULL, MS_MOVE, NULL) || chroot(".")) return -errno; pid = vfork(); 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) { dprintf("kinit: Waiting for linuxrc to complete...\n"); while (waitpid(pid, NULL, 0) != pid) ; dprintf("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 */ dprintf("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 */ } dprintf("kinit: initrd copied\n"); if (root_dev == Root_MULTI) { dprintf("kinit: skipping linuxrc: incompatible with multiple roots\n"); /* Mounting initrd as ordinary root */ return 0; } if (root_dev != Root_RAM0) { int err; dprintf("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 { dprintf("kinit: permament (or pivoting) initrd, not running linuxrc\n"); return 0; /* Mounting initrd as ordinary root */ } } klibc-2.0.7/usr/kinit/getintfile.c0000644000175000017500000000075513546663605015150 0ustar benben/* * 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 #include "kinit.h" 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; } klibc-2.0.7/usr/kinit/getarg.c0000644000175000017500000000254213546663605014263 0ustar benben#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; } klibc-2.0.7/usr/kinit/fstype/0000755000175000017500000000000013546663605014155 5ustar benbenklibc-2.0.7/usr/kinit/fstype/xfs_sb.h0000644000175000017500000000076313546663605015620 0ustar benben#ifndef __XFS_SB_H #define __XFS_SB_H /* * 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; #endif /* __XFS_SB_H */ klibc-2.0.7/usr/kinit/fstype/swap_fs.h0000644000175000017500000000124013546663605015765 0ustar benben#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" /* Suspend signatures, located at same addr as swap magic */ #define SUSP_MAGIC_L 9 #define SUSP_MAGIC_1 "S1SUSPEND" #define SUSP_MAGIC_2 "S2SUSPEND" #define SUSP_MAGIC_U "ULSUSPEND" /* 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 klibc-2.0.7/usr/kinit/fstype/squashfs_fs.h0000644000175000017500000000221713546663605016655 0ustar benben#ifndef __SQUASHFS_FS_H #define __SQUASHFS_FS_H /* * Squashfs */ #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 /* * Squashfs + LZMA */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 /* definitions for structures on disk */ struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; long long root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); #endif /* __SQUASHFS_FS_H */ klibc-2.0.7/usr/kinit/fstype/romfs_fs.h0000644000175000017500000000214713546663605016150 0ustar benben#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 klibc-2.0.7/usr/kinit/fstype/reiserfs_fs.h0000644000175000017500000000600313546663605016637 0ustar benben#ifndef __REISERFS_FS_H #define __REISERFS_FS_H 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) #endif /* __REISERFS_FS_H */ klibc-2.0.7/usr/kinit/fstype/reiser4_fs.h0000644000175000017500000000130513546663605016372 0ustar benben#ifndef __REISER4_FS_H #define __REISER4_FS_H #define SS_MAGIC_SIZE 16 /* reiser4 filesystem structure * * Master super block structure. It is the same for all reiser4 filesystems, * so, we can declare it here. It contains common for all format fields like * block size etc. */ struct reiser4_master_sb { /* Master super block magic. */ char ms_magic[SS_MAGIC_SIZE]; /* Disk format in use. */ __u16 ms_format; /* Filesyetem block size in use. */ __u16 ms_blksize; /* Filesyetm uuid in use. */ char ms_uuid[SS_MAGIC_SIZE]; /* Filesystem label in use. */ char ms_label[SS_MAGIC_SIZE]; } __attribute__ ((packed)); #define REISER4_SUPER_MAGIC_STRING "ReIsEr4" #endif /* __REISER4_FS_H */ klibc-2.0.7/usr/kinit/fstype/ocfs2_fs.h0000644000175000017500000000632413546663605016037 0ustar benben#ifndef _OCFS2_FS_H #define _OCFS2_FS_H /* Object signatures */ #define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2" #define OCFS2_VOL_UUID_LEN 16 #define OCFS2_MAX_VOL_LABEL_LEN 64 /* * On disk superblock for OCFS2 * Note that it is contained inside an ocfs2_dinode, so all offsets * are relative to the start of ocfs2_dinode.id2. */ struct ocfs2_super_block { /*00*/ uint16_t s_major_rev_level; uint16_t s_minor_rev_level; uint16_t s_mnt_count; int16_t s_max_mnt_count; uint16_t s_state; /* File system state */ uint16_t s_errors; /* Behaviour when detecting errors */ uint32_t s_checkinterval; /* Max time between checks */ /*10*/ uint64_t s_lastcheck; /* Time of last check */ uint32_t s_creator_os; /* OS */ uint32_t s_feature_compat; /* Compatible feature set */ /*20*/ uint32_t s_feature_incompat; /* Incompatible feature set */ uint32_t s_feature_ro_compat; /* Readonly-compatible feature set */ uint64_t s_root_blkno; /* Offset, in blocks, of root directory dinode */ /*30*/ uint64_t s_system_dir_blkno; /* Offset, in blocks, of system directory dinode */ uint32_t s_blocksize_bits; /* Blocksize for this fs */ uint32_t s_clustersize_bits; /* Clustersize for this fs */ /*40*/ uint16_t s_max_slots; /* Max number of simultaneous mounts before tunefs required */ uint16_t s_reserved1; uint32_t s_reserved2; uint64_t s_first_cluster_group; /* Block offset of 1st cluster * group header */ /*50*/ uint8_t s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */ /*90*/ uint8_t s_uuid[OCFS2_VOL_UUID_LEN]; /* 128-bit uuid */ /*A0*/ } __attribute__ ((packed)); /* * On disk inode for OCFS2 */ struct ocfs2_dinode { /*00*/ uint8_t i_signature[8]; /* Signature for validation */ uint32_t i_generation; /* Generation number */ uint16_t i_suballoc_slot; /* Slot suballocator this inode belongs to */ int16_t i_suballoc_bit; /* Bit offset in suballocator block group */ /*10*/ uint32_t i_reserved0; uint32_t i_clusters; /* Cluster count */ uint32_t i_uid; /* Owner UID */ uint32_t i_gid; /* Owning GID */ /*20*/ uint64_t i_size; /* Size in bytes */ uint16_t i_mode; /* File mode */ uint16_t i_links_count; /* Links count */ uint32_t i_flags; /* File flags */ /*30*/ uint64_t i_atime; /* Access time */ uint64_t i_ctime; /* Creation time */ /*40*/ uint64_t i_mtime; /* Modification time */ uint64_t i_dtime; /* Deletion time */ /*50*/ uint64_t i_blkno; /* Offset on disk, in blocks */ uint64_t i_last_eb_blk; /* Pointer to last extent block */ /*60*/ uint32_t i_fs_generation; /* Generation per fs-instance */ uint32_t i_atime_nsec; uint32_t i_ctime_nsec; uint32_t i_mtime_nsec; uint32_t i_attr; uint16_t i_orphaned_slot; /* Only valid when OCFS2_ORPHANED_FL was set in i_flags */ uint16_t i_reserved1; /*70*/ uint64_t i_reserved2[8]; /*B8*/ uint64_t i_pad1; uint64_t i_rdev; /* Device number */ uint32_t i_used; /* Bits (ie, clusters) used */ uint32_t i_total; /* Total bits (clusters) available */ uint32_t ij_flags; /* Mounted, version, etc. */ uint32_t ij_pad; /*C0*/ struct ocfs2_super_block i_super; /* Actual on-disk size is one block */ } __attribute__ ((packed)); #endif /* _OCFS2_FS_H */ klibc-2.0.7/usr/kinit/fstype/nilfs_fs.h0000644000175000017500000000504213546663605016132 0ustar benben#ifndef __NILFS_FS_H #define __NILFS_FS_H #define NILFS_SUPER_MAGIC 0x3434 /* NILFS filesystem magic number */ /* * struct nilfs_super_block - structure of super block on disk */ struct nilfs_super_block { __le32 s_rev_level; /* Revision level */ __le16 s_minor_rev_level; /* minor revision level */ __le16 s_magic; /* Magic signature */ __le16 s_bytes; /* Bytes count of CRC calculation for this structure. s_reserved is excluded. */ __le16 s_flags; /* flags */ __le32 s_crc_seed; /* Seed value of CRC calculation */ __le32 s_sum; /* Check sum of super block */ __le32 s_log_block_size; /* Block size represented as follows blocksize = 1 << (s_log_block_size + 10) */ __le64 s_nsegments; /* Number of segments in filesystem */ __le64 s_dev_size; /* block device size in bytes */ __le64 s_first_data_block; /* 1st seg disk block number */ __le32 s_blocks_per_segment; /* number of blocks per full segment */ __le32 s_r_segments_percentage;/* Reserved segments percentage */ /* or __le16 */ __le64 s_last_cno; /* Last checkpoint number */ __le64 s_last_pseg; /* disk block addr pseg written last */ __le64 s_last_seq; /* seq. number of seg written last */ __le64 s_free_blocks_count; /* Free blocks count */ __le64 s_ctime; /* Creation time (execution time of newfs) */ __le64 s_mtime; /* Mount time */ __le64 s_wtime; /* Write time */ __le16 s_mnt_count; /* Mount count */ __le16 s_max_mnt_count; /* Maximal mount count */ __le16 s_state; /* File system state */ __le16 s_errors; /* Behaviour when detecting errors */ __le64 s_lastcheck; /* time of last check */ __le32 s_checkinterval; /* max. time between checks */ __le32 s_creator_os; /* OS */ __le16 s_def_resuid; /* Default uid for reserved blocks */ __le16 s_def_resgid; /* Default gid for reserved blocks */ __le32 s_first_ino; /* First non-reserved inode */ /* or __le16 */ __le16 s_inode_size; /* Size of an inode */ __le16 s_dat_entry_size; /* Size of a dat entry */ __le16 s_checkpoint_size; /* Size of a checkpoint */ __le16 s_segment_usage_size; /* Size of a segment usage */ __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_c_interval; /* Commit interval of segment */ __le32 s_c_block_max; /* Threshold of data amount for the segment construction */ __u32 s_reserved[192]; /* padding to the end of the block */ }; #endif /* __NILFS_FS_H */ klibc-2.0.7/usr/kinit/fstype/minix_fs.h0000644000175000017500000000362713546663605016152 0ustar benben#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 klibc-2.0.7/usr/kinit/fstype/main.c0000644000175000017500000000207413546663605015250 0ustar benben/* * 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 "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; } klibc-2.0.7/usr/kinit/fstype/lvm2_sb.h0000644000175000017500000000047713546663605015702 0ustar benben#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 klibc-2.0.7/usr/kinit/fstype/luks_fs.h0000644000175000017500000000207713546663605016002 0ustar benben#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 klibc-2.0.7/usr/kinit/fstype/jfs_superblock.h0000644000175000017500000000726213546663605017350 0ustar benben/* * 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 */ klibc-2.0.7/usr/kinit/fstype/iso9660_sb.h0000644000175000017500000000063713546663605016137 0ustar benben#ifndef __ISO9660_SB_H #define __ISO9660_SB_H #define ISO_MAGIC_L 5 #define ISO_MAGIC "CD001" #define ISO_HS_MAGIC_L 5 #define ISO_HS_MAGIC "CDROM" /* ISO9660 Volume Descriptor */ struct iso_volume_descriptor { __u8 type; char id[ISO_MAGIC_L]; __u8 version; }; /* High Sierra Volume Descriptor */ struct iso_hs_volume_descriptor { char foo[8]; __u8 type; char id[ISO_HS_MAGIC_L]; __u8 version; }; #endif klibc-2.0.7/usr/kinit/fstype/gfs2_fs.h0000644000175000017500000000247613546663605015670 0ustar benben#ifndef __GFS2_FS_H #define __GFS2_FS_H #define GFS2_MAGIC 0x01161970 #define GFS2_FORMAT_FS 1801 #define GFS2_FORMAT_MULTI 1900 /* * An on-disk inode number */ struct gfs2_inum { __be64 no_formal_ino; __be64 no_addr; }; /* * Generic metadata head structure * Every inplace buffer logged in the journal must start with this. */ struct gfs2_meta_header { uint32_t mh_magic; uint32_t mh_type; uint64_t __pad0; /* Was generation number in gfs1 */ uint32_t mh_format; uint32_t __pad1; /* Was incarnation number in gfs1 */ }; /* Requirement: GFS2_LOCKNAME_LEN % 8 == 0 * Includes: the fencing zero at the end */ #define GFS2_LOCKNAME_LEN 64 /* * super-block structure */ struct gfs2_sb { struct gfs2_meta_header sb_header; uint32_t sb_fs_format; uint32_t sb_multihost_format; uint32_t __pad0; /* Was superblock flags in gfs1 */ uint32_t sb_bsize; uint32_t sb_bsize_shift; uint32_t __pad1; /* Was journal segment size in gfs1 */ struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ struct gfs2_inum sb_root_dir; char sb_lockproto[GFS2_LOCKNAME_LEN]; char sb_locktable[GFS2_LOCKNAME_LEN]; /* In gfs1, quota and license dinodes followed */ } __attribute__ ((__packed__)); #endif /* __GFS2_FS_H */ klibc-2.0.7/usr/kinit/fstype/fstype.h0000644000175000017500000000061213546663605015637 0ustar benben/* * 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 fs listed in struct imagetype. */ #ifndef FSTYPE_H #define FSTYPE_H #include int identify_fs(int fd, const char **fstype, unsigned long long *bytes, off_t offset); #endif klibc-2.0.7/usr/kinit/fstype/fstype.c0000644000175000017500000003223713546663605015642 0ustar benben/* * 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). */ #include #include #include #include #include #include #include #include #include #include #define cpu_to_be32(x) __cpu_to_be32(x) /* Needed by romfs_fs.h */ #include "btrfs.h" #include "cramfs_fs.h" #include "ext2_fs.h" #include "ext3_fs.h" #include "gfs2_fs.h" #include "iso9660_sb.h" #include "luks_fs.h" #include "lvm2_sb.h" #include "minix_fs.h" #include "nilfs_fs.h" #include "ocfs2_fs.h" #include "romfs_fs.h" #include "squashfs_fs.h" #include "xfs_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 "reiser4_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; } /* * Check to see if a filesystem is in /proc/filesystems. * Returns 1 if found, 0 if not */ static int fs_proc_check(const char *fs_name) { FILE *f; char buf[80], *cp, *t; f = fopen("/proc/filesystems", "r"); if (!f) return 0; while (fgets(buf, sizeof(buf), f)) { cp = buf; if (!isspace(*cp)) { while (*cp && !isspace(*cp)) cp++; } while (*cp && isspace(*cp)) cp++; t = strchr(cp, '\n'); if (t != NULL) *t = 0; t = strchr(cp, '\t'); if (t != NULL) *t = 0; t = strchr(cp, ' '); if (t != NULL) *t = 0; if (!strcmp(fs_name, cp)) { fclose(f); return 1; } } fclose(f); return 0; } /* * Check to see if a filesystem is available as a module * Returns 1 if found, 0 if not */ static int check_for_modules(const char *fs_name) { struct utsname uts; FILE *f; char buf[1024], *cp, *t; int i; if (uname(&uts)) return 0; snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release); f = fopen(buf, "r"); if (!f) return 0; while (fgets(buf, sizeof(buf), f)) { cp = strchr(buf, ':'); if (cp == NULL) continue; *cp = 0; cp = strrchr(buf, '/'); if (cp == NULL) continue; cp++; i = strlen(cp); if (i > 3) { t = cp + i - 3; if (!strcmp(t, ".ko")) *t = 0; } if (!strcmp(cp, fs_name)) { fclose(f); return 1; } } fclose(f); return 0; } static int base_ext4_image(const void *buf, unsigned long long *bytes, int *test_fs) { const struct ext3_super_block *sb = (const struct ext3_super_block *)buf; if (sb->s_magic != __cpu_to_le16(EXT2_SUPER_MAGIC)) return 0; /* There is at least one feature not supported by ext3 */ if ((sb->s_feature_incompat & __cpu_to_le32(EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) || (sb->s_feature_ro_compat & __cpu_to_le32(EXT3_FEATURE_RO_COMPAT_UNSUPPORTED))) { *bytes = (unsigned long long)__le32_to_cpu(sb->s_blocks_count) << (10 + __le32_to_cpu(sb->s_log_block_size)); *test_fs = (sb->s_flags & __cpu_to_le32(EXT2_FLAGS_TEST_FILESYS)) != 0; return 1; } return 0; } static int ext4_image(const void *buf, unsigned long long *bytes) { int ret, test_fs, ext4dev_present, ext4_present; ret = base_ext4_image(buf, bytes, &test_fs); if (ret == 0) return 0; ext4dev_present = (fs_proc_check("ext4dev") || check_for_modules("ext4dev")); ext4_present = (fs_proc_check("ext4") || check_for_modules("ext4")); if ((test_fs || !ext4_present) && ext4dev_present) return 0; return 1; } static int ext4dev_image(const void *buf, unsigned long long *bytes) { int ret, test_fs, ext4dev_present, ext4_present; ret = base_ext4_image(buf, bytes, &test_fs); if (ret == 0) return 0; ext4dev_present = (fs_proc_check("ext4dev") || check_for_modules("ext4dev")); ext4_present = (fs_proc_check("ext4") || check_for_modules("ext4")); if ((!test_fs || !ext4dev_present) && ext4_present) return 0; return 1; } 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 + __le32_to_cpu(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 + __le32_to_cpu(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 reiser4_image(const void *buf, unsigned long long *bytes) { const struct reiser4_master_sb *sb = (const struct reiser4_master_sb *)buf; if (memcmp(sb->ms_magic, REISER4_SUPER_MAGIC_STRING, sizeof(REISER4_SUPER_MAGIC_STRING) - 1) == 0) { *bytes = (unsigned long long) __le32_to_cpu(sb->ms_format) * __le32_to_cpu(sb->ms_blksize); 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 = __le64_to_cpu(sb->s_size) << __le16_to_cpu(sb->s_l2pbsize); 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 suspend_image(const void *buf, unsigned long long *blocks) { const struct swap_super_block *ssb = (const struct swap_super_block *)buf; if (!memcmp(ssb->magic, SUSP_MAGIC_1, SUSP_MAGIC_L) || !memcmp(ssb->magic, SUSP_MAGIC_2, SUSP_MAGIC_L) || !memcmp(ssb->magic, SUSP_MAGIC_U, SUSP_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; } static int iso_image(const void *buf, unsigned long long *blocks) { const struct iso_volume_descriptor *isovd = (const struct iso_volume_descriptor *)buf; const struct iso_hs_volume_descriptor *isohsvd = (const struct iso_hs_volume_descriptor *)buf; if (!memcmp(isovd->id, ISO_MAGIC, ISO_MAGIC_L) || !memcmp(isohsvd->id, ISO_HS_MAGIC, ISO_HS_MAGIC_L)) { *blocks = 0; return 1; } return 0; } static int squashfs_image(const void *buf, unsigned long long *blocks) { const struct squashfs_super_block *sb = (const struct squashfs_super_block *)buf; if (sb->s_magic == SQUASHFS_MAGIC || sb->s_magic == SQUASHFS_MAGIC_SWAP || sb->s_magic == SQUASHFS_MAGIC_LZMA || sb->s_magic == SQUASHFS_MAGIC_LZMA_SWAP) { *blocks = (unsigned long long) sb->bytes_used; return 1; } return 0; } static int gfs2_image(const void *buf, unsigned long long *bytes) { const struct gfs2_sb *sb = (const struct gfs2_sb *)buf; if (__be32_to_cpu(sb->sb_header.mh_magic) == GFS2_MAGIC && (__be32_to_cpu(sb->sb_fs_format) == GFS2_FORMAT_FS || __be32_to_cpu(sb->sb_fs_format) == GFS2_FORMAT_MULTI)) { *bytes = 0; /* cpu_to_be32(sb->sb_bsize) * ?; */ return 1; } return 0; } static int ocfs2_image(const void *buf, unsigned long long *bytes) { const struct ocfs2_dinode *sb = (const struct ocfs2_dinode *)buf; if (!memcmp(sb->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, sizeof(OCFS2_SUPER_BLOCK_SIGNATURE) - 1)) { *bytes = 0; return 1; } return 0; } static int nilfs2_image(const void *buf, unsigned long long *bytes) { const struct nilfs_super_block *sb = (const struct nilfs_super_block *)buf; if (sb->s_magic == __cpu_to_le16(NILFS_SUPER_MAGIC) && sb->s_rev_level == __cpu_to_le32(2)) { *bytes = (unsigned long long)__le64_to_cpu(sb->s_dev_size); return 1; } return 0; } static int btrfs_image(const void *buf, unsigned long long *bytes) { const struct btrfs_super_block *sb = (const struct btrfs_super_block *)buf; if (!memcmp(sb->magic, BTRFS_MAGIC, BTRFS_MAGIC_L)) { *bytes = (unsigned long long)__le64_to_cpu(sb->total_bytes); 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. * * The same goes for LUKS as for LVM. */ static struct imagetype images[] = { {0, "gzip", gzip_image}, {0, "cramfs", cramfs_image}, {0, "romfs", romfs_image}, {0, "xfs", xfs_image}, {0, "squashfs", squashfs_image}, {1, "ext4dev", ext4dev_image}, {1, "ext4", ext4_image}, {1, "ext3", ext3_image}, {1, "ext2", ext2_image}, {1, "minix", minix_image}, {1, "nilfs2", nilfs2_image}, {2, "ocfs2", ocfs2_image}, {8, "reiserfs", reiserfs_image}, {64, "reiserfs", reiserfs_image}, {64, "reiser4", reiser4_image}, {64, "gfs2", gfs2_image}, {64, "btrfs", btrfs_image}, {32, "jfs", jfs_image}, {32, "iso9660", iso_image}, {0, "luks", luks_image}, {0, "lvm2", lvm2_image}, {1, "lvm2", lvm2_image}, {-1, "swap", swap_image}, {-1, "suspend", suspend_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 */ } klibc-2.0.7/usr/kinit/fstype/ext3_fs.h0000644000175000017500000001156613546663605015712 0ustar benben#ifndef __EXT3_FS_H #define __EXT3_FS_H /* * The second extended file system magic number */ #define EXT3_SUPER_MAGIC 0xEF53 #define EXT2_FLAGS_TEST_FILESYS 0x0004 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 #define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 #define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ EXT2_FEATURE_RO_COMPAT_BTREE_DIR) #define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP #define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ EXT3_FEATURE_INCOMPAT_RECOVER| \ EXT2_FEATURE_INCOMPAT_META_BG) #define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP /* * 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_jnl_backup_type; __u16 s_reserved_word_pad; __u32 s_default_mount_opts; __u32 s_first_meta_bg; __u32 s_mkfs_time; __u32 s_jnl_blocks[17]; __u32 s_blocks_count_hi; __u32 s_r_blocks_count_hi; __u32 s_free_blocks_hi; __u16 s_min_extra_isize; __u16 s_want_extra_isize; __u32 s_flags; __u16 s_raid_stride; __u16 s_mmp_interval; __u64 s_mmp_block; __u32 s_raid_stripe_width; __u32 s_reserved[163]; }; #endif /* __EXT3_FS_H */ klibc-2.0.7/usr/kinit/fstype/ext2_fs.h0000644000175000017500000000651613546663605015710 0ustar benben#ifndef __EXT2_FS_H #define __EXT2_FS_H /* * 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 */ }; #endif /* __EXT2_FS_H */ klibc-2.0.7/usr/kinit/fstype/cramfs_fs.h0000644000175000017500000000524513546663605016277 0ustar benben#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 klibc-2.0.7/usr/kinit/fstype/btrfs.h0000644000175000017500000000230713546663605015450 0ustar benben#ifndef __BTRFS_H #define __BTRFS_H # define BTRFS_MAGIC "_BHRfS_M" # define BTRFS_MAGIC_L 8 /* * Structure of the super block */ struct btrfs_super_block { uint8_t csum[32]; uint8_t fsid[16]; uint64_t bytenr; uint64_t flags; uint8_t magic[8]; uint64_t generation; uint64_t root; uint64_t chunk_root; uint64_t log_root; uint64_t log_root_transid; uint64_t total_bytes; uint64_t bytes_used; uint64_t root_dir_objectid; uint64_t num_devices; uint32_t sectorsize; uint32_t nodesize; uint32_t leafsize; uint32_t stripesize; uint32_t sys_chunk_array_size; uint64_t chunk_root_generation; uint64_t compat_flags; uint64_t compat_ro_flags; uint64_t incompat_flags; uint16_t csum_type; uint8_t root_level; uint8_t chunk_root_level; uint8_t log_root_level; struct btrfs_dev_item { uint64_t devid; uint64_t total_bytes; uint64_t bytes_used; uint32_t io_align; uint32_t io_width; uint32_t sector_size; uint64_t type; uint64_t generation; uint64_t start_offset; uint32_t dev_group; uint8_t seek_speed; uint8_t bandwidth; uint8_t uuid[16]; uint8_t fsid[16]; } __attribute__ ((__packed__)) dev_item; uint8_t label[256]; } __attribute__ ((__packed__)); #endif /* __BTRFS_H */ klibc-2.0.7/usr/kinit/fstype/Kbuild0000644000175000017500000000102413546663605015307 0ustar benben# # 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 ifdef KLIBCSHAREDFLAGS install-y := $(shared-y) else install-y := $(static-y) endif klibc-2.0.7/usr/kinit/do_mounts_mtd.c0000644000175000017500000000166113546663605015666 0ustar benben/* * 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"; printf("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; } } klibc-2.0.7/usr/kinit/do_mounts_md.c0000644000175000017500000002252313546663605015502 0ustar benben/* * 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 "kinit.h" #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_num, level, factor, fault, partitioned = 0; char *pername = ""; char *str1; int ent; if (*str == 'd') { partitioned = 1; str++; } if (get_option(&str, &minor_num) != 2) { /* MD Number */ fprintf(stderr, "md: Too few arguments supplied to md=.\n"); return 0; } str1 = str; if (minor_num >= MAX_MD_DEVS) { fprintf(stderr, "md: md=%d, Minor device number too high.\n", minor_num); return 0; } for (ent = 0; ent < md_setup_ents; ent++) if (md_setup_args[ent].minor == minor_num && md_setup_args[ent].partitioned == partitioned) { fprintf(stderr, "md: md=%s%d, Specified more than once. " "Replacing previous definition.\n", partitioned ? "d" : "", minor_num); break; } if (ent >= MAX_MD_DEVS) { fprintf(stderr, "md: md=%s%d - too many md initialisations\n", partitioned ? "d" : "", minor_num); 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_num, pername, str); md_setup_args[ent].device_names = str; md_setup_args[ent].partitioned = partitioned; md_setup_args[ent].minor = minor_num; 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]; struct stat st_chk; 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 (stat(name, &st_chk) == 0) continue; 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(); } klibc-2.0.7/usr/kinit/do_mounts.h0000644000175000017500000000213513546663605015024 0ustar benben/* * 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) #define Root_MULTI __makedev(0, 253) 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 */ klibc-2.0.7/usr/kinit/do_mounts.c0000644000175000017500000002657113546663605015031 0ustar benben#include #include #include #include #include #include #include #include #include #include #include "do_mounts.h" #include "kinit.h" #include "fstype.h" #include "zlib.h" #ifndef MS_RELATIME # define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */ #endif #ifndef MS_STRICTATIME # define MS_STRICTATIME (1<<24) /* Always perform atime updates */ #endif /* * The following mount option parsing was stolen from * * usr/utils/mount_opts.c * * and adapted to add some later mount flags. */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) struct mount_opts { const char str[16]; 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) /* These must be in alphabetic order! */ 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}, {"nodev", MS_NODEV, MS_NODEV, 0}, {"noexec", MS_NOEXEC, MS_NOEXEC, 0}, {"nosuid", MS_NOSUID, MS_NOSUID, 0}, {"recurse", MS_REC, MS_REC, 0}, {"relatime", MS_RELATIME, MS_RELATIME, 0}, {"remount", MS_TYPE, MS_REMOUNT, 0}, {"ro", MS_RDONLY, MS_RDONLY, 0}, {"rw", MS_RDONLY, 0, MS_RDONLY}, {"strictatime", MS_STRICTATIME, MS_STRICTATIME, 0}, {"suid", MS_NOSUID, 0, MS_NOSUID}, {"sync", MS_SYNCHRONOUS, MS_SYNCHRONOUS, 0}, {"verbose", MS_VERBOSE, MS_VERBOSE, 0}, }; /* * Append 's' to 'extra->str'. 's' is a mount option that can't be turned into * a flag. Return 0 on success, -1 on error. */ static int 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) { if (extra->str) free(extra->str); return -1; } 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; return 0; } /* * Parse the options in 'arg'; put numeric mount flags into 'flags' and * the rest into 'extra'. Return 0 on success, -1 on error. */ static int parse_mount_options(char *arg, unsigned long *flags, struct extra_opts *extra) { char *s; while ((s = strsep(&arg, ",")) != NULL) { char *opt = s; unsigned int i; int res; int no = (s[0] == 'n' && s[1] == 'o'); int found = 0; if (no) s += 2; for (i = 0; i < ARRAY_SIZE(options); i++) { res = strcmp(s, options[i].str); if (res == 0) { found = 1; *flags &= ~options[i].rwmask; if (no) *flags |= options[i].rwnoset; else *flags |= options[i].rwset; break; /* If we're beyond 's' alphabetically, we're done */ } else if (res < 0) break; } if (! found) if (add_extra_option(extra, opt) != 0) return -1; } return 0; } /* Create the device node "name" */ int create_dev(const char *name, dev_t dev) { unlink(name); return mknod(name, S_IFBLK | 0600, dev); } /* * If there is not a block device for the input 'name', try to create one; if * we can't that's okay. */ static void create_dev_if_not_present(const char *name) { struct stat st; dev_t dev; if (stat(name, &st) == 0) /* file present; we're done */ return; dev = name_to_dev_t(name); if (dev) (void) create_dev(name, 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) { dprintf("kinit: trying to mount %s on %s " "with type %s, flags 0x%lx, data '%s'\n", source, target, type, flags, (char *)data); int rv = mount(source, target, type, flags, data); if (rv != 0) dprintf("kinit: mount %s on %s failed " "with errno = %d\n", source, target, errno); /* 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) { dprintf("kinit: %s appears to be a %s filesystem\n", source, type); type = mount_block(source, target, type, flags, data); if (type) return type; } } dprintf("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'; /* We can't mount a block device as a "nodev" fs */ if (*type != '\t') 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; } static int mount_roots(int argc, char *argv[], const char *root_dev_name) { char *roots = strdup(root_dev_name); char *root; const char *sep = ","; char *saveptr; int ret = -ESRCH; root = strtok_r(roots, sep, &saveptr); while (root) { dev_t root_dev; dprintf("kinit: trying to mount %s\n", root); root_dev = name_to_dev_t(root); ret = mount_root(argc, argv, root_dev, root); if (!ret) break; root = strtok_r(NULL, sep, &saveptr); } free(roots); return ret; } 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")) { dprintf("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; } /* Allocate a buffer and prepend '/root' onto 'src'. */ static char *prepend_root_dir(const char *src) { size_t len = strlen(src) + 6; /* "/root" */ char *p = malloc(len); if (!p) return NULL; strcpy(p, "/root"); strcat(p, src); return p; } int do_cmdline_mounts(int argc, char *argv[]) { int arg_i; int ret = 0; for (arg_i = 0; arg_i < argc; arg_i++) { const char *fs_dev, *fs_dir, *fs_type; char *fs_opts; unsigned long flags = 0; char *saveptr = NULL; char *new_dir; struct extra_opts extra = { 0, 0, 0, 0 }; if (strncmp(argv[arg_i], "kinit_mount=", 12)) continue; /* * Format: * ;;;[opt1],[optn...] */ fs_dev = strtok_r(&argv[arg_i][12], ";", &saveptr); if (!fs_dev) { fprintf(stderr, "Failed to parse fs_dev\n"); continue; } fs_dir = strtok_r(NULL, ";", &saveptr); if (!fs_dir) { fprintf(stderr, "Failed to parse fs_dir\n"); continue; } fs_type = strtok_r(NULL, ";", &saveptr); if (!fs_type) { fprintf(stderr, "Failed to parse fs_type\n"); continue; } fs_opts = strtok_r(NULL, ";", &saveptr); /* Don't error if there is no option string sent */ new_dir = prepend_root_dir(fs_dir); if (! new_dir) return -ENOMEM; create_dev_if_not_present(fs_dev); ret = parse_mount_options(fs_opts, &flags, &extra); if (ret != 0) break; if (!mount_block(fs_dev, new_dir, fs_type, flags, extra.str)) fprintf(stderr, "Skipping failed mount '%s'\n", fs_dev); free(new_dir); if (extra.str) free(extra.str); } return ret; } int do_fstab_mounts(FILE *fp) { struct mntent *ent = NULL; char *new_dir; int ret = 0; while ((ent = getmntent(fp))) { unsigned long flags = 0; struct extra_opts extra = { 0, 0, 0, 0 }; new_dir = prepend_root_dir(ent->mnt_dir); if (! new_dir) return -ENOMEM; create_dev_if_not_present(ent->mnt_fsname); ret = parse_mount_options(ent->mnt_opts, &flags, &extra); if (ret != 0) break; if (!mount_block(ent->mnt_fsname, new_dir, ent->mnt_type, flags, extra.str)) { fprintf(stderr, "Skipping failed mount '%s'\n", ent->mnt_fsname); } free(new_dir); if (extra.str) free(extra.str); } return 0; } 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; int err; FILE *fp; dprintf("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; } dprintf("kinit: root_dev = %s\n", bdevname(root_dev)); if (initrd_load(argc, argv, root_dev)) { dprintf("initrd loaded\n"); return 0; } if (load_ramdisk && atoi(load_ramdisk)) { if (ramdisk_load(argc, argv)) root_dev = Root_RAM0; } if (root_dev == Root_MULTI) err = mount_roots(argc, argv, root_dev_name); else err = mount_root(argc, argv, root_dev, root_dev_name); if (err) return err; if ((fp = setmntent("/etc/fstab", "r"))) { err = do_fstab_mounts(fp); fclose(fp); } if (err) return err; if (get_arg(argc, argv, "kinit_mount=")) err = do_cmdline_mounts(argc, argv); return err; } klibc-2.0.7/usr/kinit/devname.c0000644000175000017500000000421113546663605014424 0ustar benben#include #include #include #include #include #include #include #include "kinit.h" /* * 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; dir = opendir(sysdir); if (!dir) 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"); sysdev = fopen(sysdir, "r"); if (!sysdev) 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 */ klibc-2.0.7/usr/kinit/capabilities.h0000644000175000017500000000024613546663605015447 0ustar benben/* * capabilities.h */ #ifndef KINIT_CAPABILITIES_H #define KINIT_CAPABILITIES_H int drop_capabilities(const char *caps); #endif /* KINIT_CAPABILITIES_H */ klibc-2.0.7/usr/kinit/capabilities.c0000644000175000017500000001242013546663605015437 0ustar benben/* * Copyright 2011 Google Inc. All Rights Reserved * Author: mikew@google.com (Mike Waychison) */ /* * We have to include the klibc types.h here to keep the kernel's * types.h from being used. */ #include #include #include #include #include #include #include #include #include #include "kinit.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #define MAKE_CAP(cap) [cap] = { .cap_name = #cap } struct capability { const char *cap_name; } capabilities[] = { MAKE_CAP(CAP_CHOWN), MAKE_CAP(CAP_DAC_OVERRIDE), MAKE_CAP(CAP_DAC_READ_SEARCH), MAKE_CAP(CAP_FOWNER), MAKE_CAP(CAP_FSETID), MAKE_CAP(CAP_KILL), MAKE_CAP(CAP_SETGID), MAKE_CAP(CAP_SETUID), MAKE_CAP(CAP_SETPCAP), MAKE_CAP(CAP_LINUX_IMMUTABLE), MAKE_CAP(CAP_NET_BIND_SERVICE), MAKE_CAP(CAP_NET_BROADCAST), MAKE_CAP(CAP_NET_ADMIN), MAKE_CAP(CAP_NET_RAW), MAKE_CAP(CAP_IPC_LOCK), MAKE_CAP(CAP_IPC_OWNER), MAKE_CAP(CAP_SYS_MODULE), MAKE_CAP(CAP_SYS_RAWIO), MAKE_CAP(CAP_SYS_CHROOT), MAKE_CAP(CAP_SYS_PTRACE), MAKE_CAP(CAP_SYS_PACCT), MAKE_CAP(CAP_SYS_ADMIN), MAKE_CAP(CAP_SYS_BOOT), MAKE_CAP(CAP_SYS_NICE), MAKE_CAP(CAP_SYS_RESOURCE), MAKE_CAP(CAP_SYS_TIME), MAKE_CAP(CAP_SYS_TTY_CONFIG), MAKE_CAP(CAP_MKNOD), MAKE_CAP(CAP_LEASE), MAKE_CAP(CAP_AUDIT_WRITE), MAKE_CAP(CAP_AUDIT_CONTROL), MAKE_CAP(CAP_SETFCAP), MAKE_CAP(CAP_MAC_OVERRIDE), MAKE_CAP(CAP_MAC_ADMIN), MAKE_CAP(CAP_SYSLOG), }; static void fail(const char *fmt, ...) __attribute__((format(printf, 1, 2))); static void fail(const char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); exit(1); } /* * Find the capability ordinal by name, and return its ordinal. * Returns -1 on failure. */ static int find_capability(const char *s) { int i; for (i = 0; i < ARRAY_SIZE(capabilities); i++) { if (capabilities[i].cap_name && strcasecmp(s, capabilities[i].cap_name) == 0) { return i; } } return -1; } static void do_capset(int cap_ordinal) { struct __user_cap_header_struct hdr; struct __user_cap_data_struct caps[2]; /* Get the current capability mask */ hdr.version = _LINUX_CAPABILITY_VERSION_3; hdr.pid = getpid(); if (capget(&hdr, caps)) { perror("capget()"); exit(1); } /* Drop the bits */ if (cap_ordinal < 32) caps[0].inheritable &= ~(1U << cap_ordinal); else caps[1].inheritable &= ~(1U << (cap_ordinal - 32)); /* And drop the capability. */ hdr.version = _LINUX_CAPABILITY_VERSION_3; hdr.pid = getpid(); if (capset(&hdr, caps)) fail("Couldn't drop the capability \"%s\"\n", capabilities[cap_ordinal].cap_name); } static void do_bset(int cap_ordinal) { int ret; ret = prctl(PR_CAPBSET_READ, cap_ordinal); if (ret == 1) { ret = prctl(PR_CAPBSET_DROP, cap_ordinal); if (ret != 0) fail("Error dropping capability %s from bset\n", capabilities[cap_ordinal].cap_name); } else if (ret < 0) fail("Kernel doesn't recognize capability %d\n", cap_ordinal); } static void do_usermodehelper_file(const char *filename, int cap_ordinal) { uint32_t lo32, hi32; FILE *file; static const size_t buf_size = 80; char buf[buf_size]; char tail; size_t bytes_read; int ret; /* Try and open the file */ file = fopen(filename, "r+"); if (!file && errno == ENOENT) fail("Could not disable usermode helpers capabilities as " "%s is not available\n", filename); if (!file) fail("Failed to access file %s errno %d\n", filename, errno); /* Read and process the current bits */ bytes_read = fread(buf, 1, buf_size - 1, file); if (bytes_read == 0) fail("Trouble reading %s\n", filename); buf[bytes_read] = '\0'; ret = sscanf(buf, "%u %u %c", &lo32, &hi32, &tail); if (ret != 2) fail("Failed to understand %s \"%s\"\n", filename, buf); /* Clear the bits in the local copy */ if (cap_ordinal < 32) lo32 &= ~(1 << cap_ordinal); else hi32 &= ~(1 << (cap_ordinal - 32)); /* Commit the new bit masks to the kernel */ ret = fflush(file); if (ret != 0) fail("Failed on file %s to fflush %d\n", filename, ret); sprintf(buf, "%u %u", lo32, hi32); ret = fwrite(buf, 1, strlen(buf) + 1, file); if (ret != 0) fail("Failed to commit usermode helper bitmasks: %d\n", ret); /* Cleanup */ fclose(file); } static void do_usermodehelper(int cap_ordinal) { static const char * const files[] = { "/proc/sys/kernel/usermodehelper/bset", "/proc/sys/kernel/usermodehelper/inheritable", }; int i; for (i = 0; i < ARRAY_SIZE(files); i++) do_usermodehelper_file(files[i], cap_ordinal); } static void drop_capability(int cap_ordinal) { do_usermodehelper(cap_ordinal); do_bset(cap_ordinal); do_capset(cap_ordinal); printf("Dropped capability: %s\n", capabilities[cap_ordinal].cap_name); } int drop_capabilities(const char *caps) { char *s, *saveptr = NULL; char *token; if (!caps) return 0; /* Create a duplicate string that can be modified. */ s = strdup(caps); if (!s) fail("Failed to drop caps as requested. Exiting\n"); token = strtok_r(s, ",", &saveptr); while (token) { int cap_ordinal = find_capability(token); if (cap_ordinal < 0) fail("Could not understand capability name \"%s\" " "on command line, failing init\n", token); drop_capability(cap_ordinal); token = strtok_r(NULL, ",", &saveptr); } free(s); return 0; } klibc-2.0.7/usr/kinit/README0000644000175000017500000000034213546663605013522 0ustar benbenkinit - 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) klibc-2.0.7/usr/kinit/Kbuild0000644000175000017500000000220413546663605013776 0ustar benben# # Kbuild file for kinit # # library part of kinit. Is used by programs in sub-directories (resume et al) lib-y := name_to_dev.o devname.o getarg.o capabilities.o # use lib for kinit static/kinit-y := lib.a static/kinit-y += kinit.o do_mounts.o ramdisk_load.o initrd.o static/kinit-y += getintfile.o readfile.o xpio.o static/kinit-y += do_mounts_md.o do_mounts_mtd.o nfsroot.o static/kinit-y += ipconfig/ static/kinit-y += nfsmount/ static/kinit-y += run-init/ static/kinit-y += fstype/ static/kinit-y += resume/ static-y := static/kinit shared-y := shared/kinit shared/kinit-y := $(static/kinit-y) # Additional include paths files KLIBCCFLAGS += -I$(srctree)/$(src)/fstype \ -I$(srctree)/$(src)/ipconfig \ -I$(srctree)/$(src)/nfsmount \ -I$(srctree)/$(src)/resume \ -I$(srctree)/$(src)/run-init # Cleaning targets += static/kinit static/kinit.g shared/kinit shared/kinit.g subdir- := fstype ipconfig nfsmount resume run-init # Clean deletes the static and shared dir clean-dirs := static shared # install binary ifdef KLIBCSHAREDFLAGS install-y := shared/kinit else install-y := static/kinit endif klibc-2.0.7/usr/kinit/.gitignore0000644000175000017500000000003113546663605014625 0ustar benbenlib.a kinit kinit.shared klibc-2.0.7/usr/include/0000755000175000017500000000000013546663605013150 5ustar benbenklibc-2.0.7/usr/include/zlib.h0000644000175000017500000020121413546663605014261 0ustar benben/* 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 */ klibc-2.0.7/usr/include/zconf.h0000644000175000017500000002256413546663605014451 0ustar benben/* 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 */ klibc-2.0.7/usr/include/utime.h0000644000175000017500000000032513546663605014444 0ustar benben/* * utime.h */ #ifndef _UTIME_H #define _UTIME_H #include #include #include __extern int utime(const char *, const struct utimbuf *); #endif /* _UTIME_H */ klibc-2.0.7/usr/include/unistd.h0000644000175000017500000001142613546663605014633 0ustar benben/* * unistd.h */ #ifndef _UNISTD_H #define _UNISTD_H #include #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 nice(int); __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, int); __extern int link(const char *, const char *); __extern int linkat(int, const char *, int, const char *, int); __extern int unlink(const char *); __extern int unlinkat(int, const char *, int); __extern int chdir(const char *); __extern int fchdir(int); __extern int chmod(const char *, mode_t); __extern int fchmod(int, mode_t); __extern int mkdir(const char *, mode_t); __extern int mkdirat(int, const char *, mode_t); __extern int rmdir(const char *); __extern int pipe(int *); __extern int pipe2(int *, int); __extern int chroot(const char *); __extern int symlink(const char *, const char *); __extern int symlinkat(const char *, int, 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); __extern int fchownat(int, const char *, uid_t, gid_t, int); /* Also in */ #ifndef _KLIBC_IN_OPEN_C __extern int open(const char *, int, ...); __extern int openat(int, const char *, int, ...); #endif __extern int creat(const char *, mode_t); __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, const void *, size_t, off_t); __extern int dup(int); __extern int dup2(int, int); __extern int dup3(int, int, int); __extern int fcntl(int, int, ...); __extern int ioctl(int, int, void *); __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); __extern unsigned int __page_size; static __inline__ int getpagesize(void) { return __page_size; } __extern unsigned int __page_shift; static __inline__ int __getpageshift(void) { 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 */ klibc-2.0.7/usr/include/time.h0000644000175000017500000000065313546663605014263 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/termios.h0000644000175000017500000000357713546663605015017 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/syslog.h0000644000175000017500000000313713546663605014645 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sysexits.h0000644000175000017500000000173313546663605015220 0ustar benben#ifndef _SYSEXITS_H #define _SYSEXITS_H #define EX_OK 0 /* successful termination */ #define EX__BASE 64 /* base value for error messages */ #define EX_USAGE 64 /* command line usage error */ #define EX_DATAERR 65 /* data format error */ #define EX_NOINPUT 66 /* cannot open input */ #define EX_NOUSER 67 /* addressee unknown */ #define EX_NOHOST 68 /* host name unknown */ #define EX_UNAVAILABLE 69 /* service unavailable */ #define EX_SOFTWARE 70 /* internal software error */ #define EX_OSERR 71 /* system error (e.g., can't fork) */ #define EX_OSFILE 72 /* critical OS file missing */ #define EX_CANTCREAT 73 /* can't create (user) output file */ #define EX_IOERR 74 /* input/output error */ #define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ #define EX_PROTOCOL 76 /* remote error in protocol */ #define EX_NOPERM 77 /* permission denied */ #define EX_CONFIG 78 /* configuration error */ #define EX__MAX 78 /* maximum listed value */ #endif /* _SYSEXITS_H */ klibc-2.0.7/usr/include/sys/0000755000175000017500000000000013546663605013766 5ustar benbenklibc-2.0.7/usr/include/sys/wait.h0000644000175000017500000000127713546663605015112 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/vfs.h0000644000175000017500000000727113546663605014744 0ustar benben/* * 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]; }; #elif _KLIBC_STATFS_F_TYPE_32B struct statfs { uint32_t f_type; uint32_t f_bsize; uint32_t f_frsize; uint32_t __pad; uint64_t f_blocks; uint64_t f_bfree; uint64_t f_files; uint64_t f_ffree; uint64_t f_bavail; __kernel_fsid_t f_fsid; uint32_t f_namelen; uint32_t f_spare[6]; }; #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 */ klibc-2.0.7/usr/include/sys/utsname.h0000644000175000017500000000055513546663605015620 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/utime.h0000644000175000017500000000017113546663605015261 0ustar benben/* * sys/utime.h */ #ifndef _SYS_UTIME_H #define _SYS_UTIME_H #include #endif /* _SYS_UTIME_H */ klibc-2.0.7/usr/include/sys/un.h0000644000175000017500000000020413546663605014555 0ustar benben/* * */ #ifndef _SYS_UN_H #define _SYS_UN_H #include #include #endif /* _SYS_UN_H */ klibc-2.0.7/usr/include/sys/uio.h0000644000175000017500000000041213546663605014730 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/types.h0000644000175000017500000000442013546663605015303 0ustar benben/* * sys/types.h */ #ifndef _SYS_TYPES_H #define _SYS_TYPES_H #include #include #include #define _SSIZE_T /* __SIZE_TYPE__ defined either by GCC or */ #define unsigned /* nothing, temporarily */ typedef signed __SIZE_TYPE__ ssize_t; #undef unsigned #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_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 _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 __u16 __bitwise __le16; typedef __u16 __bitwise __be16; typedef __u32 __bitwise __le32; typedef __u32 __bitwise __be32; typedef __u64 __bitwise __le64; typedef __u64 __bitwise __be64; typedef __u16 __bitwise __sum16; typedef __u32 __bitwise __sum32; typedef __u64 __bitwise __sum64; typedef __u32 __bitwise __wsum; #define __aligned_u64 __u64 __attribute__((aligned(8))) #define __aligned_be64 __be64 __attribute__((aligned(8))) #define __aligned_le64 __le64 __attribute__((aligned(8))) /* * Some headers seem to require this... */ #ifndef BITS_PER_LONG # define BITS_PER_LONG _BITSIZE #endif /* * Some apps want this in */ #include #endif klibc-2.0.7/usr/include/sys/times.h0000644000175000017500000000032113546663605015254 0ustar benben/* * sys/times.h */ #ifndef _SYS_TIMES_H #define _SYS_TIMES_H #include #include #include __extern clock_t times(struct tms *); #endif /* _SYS_TIMES_H */ klibc-2.0.7/usr/include/sys/time.h0000644000175000017500000000312313546663605015074 0ustar benben/* * sys/time.h */ #ifndef _SYS_TIME_H #define _SYS_TIME_H #include #include #include #include /* The 2.6.20 Linux headers always #define FD_ZERO __FD_ZERO, etc, in but not all architectures define the double-underscore ones, except __NFDBITS, __FD_SETSIZE and __FDSET_LONGS which are defined in . Unfortunately, some architectures define the double-underscore ones as inlines, so we can't use a simple #ifdef test. Thus, the only safe option remaining is to #undef the top-level macros. */ #undef FD_ZERO #undef FD_SET #undef FD_CLR #undef FD_ISSET #undef FD_SETSIZE __extern void *memset(void *, int, size_t); static inline void FD_ZERO(fd_set *__fdsetp) { memset(__fdsetp, 0, sizeof(fd_set)); } static inline void FD_SET(int __fd, fd_set *__fdsetp) { __fdsetp->fds_bits[__fd/BITS_PER_LONG] |= (1UL << (__fd % BITS_PER_LONG)); } static inline void FD_CLR(int __fd, fd_set *__fdsetp) { __fdsetp->fds_bits[__fd/BITS_PER_LONG] &= ~(1UL << (__fd % BITS_PER_LONG)); } static inline int FD_ISSET(int __fd, fd_set *__fdsetp) { return (__fdsetp->fds_bits[__fd/BITS_PER_LONG] >> (__fd % BITS_PER_LONG)) & 1; } #define FD_SETSIZE __FD_SETSIZE __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 */ klibc-2.0.7/usr/include/sys/sysmacros.h0000644000175000017500000000154113546663605016163 0ustar benben/* * 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 #include #include #define __major(__d) ((int)(((__d) >> 8) & 0xfffU)) __static_inline int _major(dev_t __d) { return __major(__d); } #define major(__d) _major(__d) #define __minor(__d) ((int)(((__d) & 0xffU)|(((__d) >> 12) & 0xfff00U))) __static_inline int _minor(dev_t __d) { return __minor(__d); } #define minor(__d) _minor(__d) #define __makedev(__ma, __mi) \ ((dev_t)((((__ma) & 0xfffU) << 8)| \ ((__mi) & 0xffU)|(((__mi) & 0xfff00U) << 12))) __static_inline dev_t _makedev(int __ma, int __mi) { return __makedev(__ma, __mi); } #define makedev(__ma, __mi) _makedev(__ma, __mi) #endif /* _SYS_SYSMACROS_H */ klibc-2.0.7/usr/include/sys/sysinfo.h0000644000175000017500000000025513546663605015633 0ustar benben/* * sys/sysinfo.h */ #ifndef _SYS_SYSINFO_H #define _SYS_SYSINFO_H #include extern int sysinfo(struct sysinfo *info); #endif /* _SYS_SYSINFO_H */ klibc-2.0.7/usr/include/sys/syscall.h0000644000175000017500000000032413546663605015610 0ustar benben/* * sys/syscall.h * * Generic system call interface macros */ #ifndef _SYS_SYSCALL_H #define _SYS_SYSCALL_H #include #include #include #endif /* _SYS_SYSCALL_H */ klibc-2.0.7/usr/include/sys/statfs.h0000644000175000017500000000002513546663605015440 0ustar benben#include klibc-2.0.7/usr/include/sys/stat.h0000644000175000017500000000426313546663605015117 0ustar benben/* * sys/stat.h */ #ifndef _SYS_STAT_H #define _SYS_STAT_H #include #include #include /* For struct timespec */ #include /* 2.6.21 kernels have once again hidden a bunch of stuff... */ #ifndef S_IFMT #define S_IFMT 00170000 #define S_IFSOCK 0140000 #define S_IFLNK 0120000 #define S_IFREG 0100000 #define S_IFBLK 0060000 #define S_IFDIR 0040000 #define S_IFCHR 0020000 #define S_IFIFO 0010000 #define S_ISUID 0004000 #define S_ISGID 0002000 #define S_ISVTX 0001000 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #define S_IRWXU 00700 #define S_IRUSR 00400 #define S_IWUSR 00200 #define S_IXUSR 00100 #define S_IRWXG 00070 #define S_IRGRP 00040 #define S_IWGRP 00020 #define S_IXGRP 00010 #define S_IRWXO 00007 #define S_IROTH 00004 #define S_IWOTH 00002 #define S_IXOTH 00001 #define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) #define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) #define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) #define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) #endif #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 *, mode_t, dev_t); __extern int mkfifo(const char *, mode_t); __extern int utimensat(int, const char *, const struct timespec *, int); __extern int fchmodat(int, const char *, mode_t, int); __extern_inline int mkfifo(const char *__p, mode_t __m) { return mknod(__p, (__m & ~S_IFMT) | S_IFIFO, (dev_t) 0); } #endif /* _SYS_STAT_H */ klibc-2.0.7/usr/include/sys/splice.h0000644000175000017500000000072013546663605015415 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/socket.h0000644000175000017500000002131113546663605015425 0ustar benben/* * sys/socket.h */ #ifndef _SYS_SOCKET_H #define _SYS_SOCKET_H #include #include #include #include #include #include #include #if _KLIBC_HAS_ARCHSOCKET_H #include #endif /* Great job, guys! These are *architecture-specific* ABI constants, that are hidden under #ifdef __KERNEL__... what a brilliant idea! These are the "common" definitions; if not appropriate, override them in . */ #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 # define SOCK_CLOEXEC 02000000 # define SOCK_NONBLOCK 04000 #endif /* The maximum backlock queue length. */ #define SOMAXCONN 128 #ifndef AF_INET #define AF_UNSPEC 0 #define AF_UNIX 1 /* Unix domain sockets */ #define AF_LOCAL 1 /* POSIX name for AF_UNIX */ #define AF_INET 2 /* Internet IP Protocol */ #define AF_AX25 3 /* Amateur Radio AX.25 */ #define AF_IPX 4 /* Novell IPX */ #define AF_APPLETALK 5 /* AppleTalk DDP */ #define AF_NETROM 6 /* Amateur Radio NET/ROM */ #define AF_BRIDGE 7 /* Multiprotocol bridge */ #define AF_ATMPVC 8 /* ATM PVCs */ #define AF_X25 9 /* Reserved for X.25 project */ #define AF_INET6 10 /* IP version 6 */ #define AF_ROSE 11 /* Amateur Radio X.25 PLP */ #define AF_DECnet 12 /* Reserved for DECnet project */ #define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/ #define AF_SECURITY 14 /* Security callback pseudo AF */ #define AF_KEY 15 /* PF_KEY key management API */ #define AF_NETLINK 16 #define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */ #define AF_PACKET 17 /* Packet family */ #define AF_ASH 18 /* Ash */ #define AF_ECONET 19 /* Acorn Econet */ #define AF_ATMSVC 20 /* ATM SVCs */ #define AF_RDS 21 /* RDS sockets */ #define AF_SNA 22 /* Linux SNA Project (nutters!) */ #define AF_IRDA 23 /* IRDA sockets */ #define AF_PPPOX 24 /* PPPoX sockets */ #define AF_WANPIPE 25 /* Wanpipe API Sockets */ #define AF_LLC 26 /* Linux LLC */ #define AF_CAN 29 /* Controller Area Network */ #define AF_TIPC 30 /* TIPC sockets */ #define AF_BLUETOOTH 31 /* Bluetooth sockets */ #define AF_IUCV 32 /* IUCV sockets */ #define AF_RXRPC 33 /* RxRPC sockets */ #define AF_ISDN 34 /* mISDN sockets */ #define AF_PHONET 35 /* Phonet sockets */ #define AF_IEEE802154 36 /* IEEE802154 sockets */ #define AF_MAX 37 /* For now.. */ #endif // !AF_INET #ifndef PF_UNSPEC #define PF_UNSPEC AF_UNSPEC #define PF_UNIX AF_UNIX #define PF_LOCAL AF_LOCAL #define PF_INET AF_INET #define PF_AX25 AF_AX25 #define PF_IPX AF_IPX #define PF_APPLETALK AF_APPLETALK #define PF_NETROM AF_NETROM #define PF_BRIDGE AF_BRIDGE #define PF_ATMPVC AF_ATMPVC #define PF_X25 AF_X25 #define PF_INET6 AF_INET6 #define PF_ROSE AF_ROSE #define PF_DECnet AF_DECnet #define PF_NETBEUI AF_NETBEUI #define PF_SECURITY AF_SECURITY #define PF_KEY AF_KEY #define PF_NETLINK AF_NETLINK #define PF_ROUTE AF_ROUTE #define PF_PACKET AF_PACKET #define PF_ASH AF_ASH #define PF_ECONET AF_ECONET #define PF_ATMSVC AF_ATMSVC #define PF_RDS AF_RDS #define PF_SNA AF_SNA #define PF_IRDA AF_IRDA #define PF_PPPOX AF_PPPOX #define PF_WANPIPE AF_WANPIPE #define PF_LLC AF_LLC #define PF_CAN AF_CAN #define PF_TIPC AF_TIPC #define PF_BLUETOOTH AF_BLUETOOTH #define PF_IUCV AF_IUCV #define PF_RXRPC AF_RXRPC #define PF_ISDN AF_ISDN #define PF_PHONET AF_PHONET #define PF_IEEE802154 AF_IEEE802154 #define PF_MAX AF_MAX #endif // !PF_UNSPEC #ifndef MSG_OOB #define MSG_OOB 1 #define MSG_PEEK 2 #define MSG_DONTROUTE 4 #define MSG_TRYHARD 4 /* Synonym for MSG_DONTROUTE for DECnet */ #define MSG_CTRUNC 8 #define MSG_PROBE 0x10 /* Do not send. Only probe path f.e. for MTU */ #define MSG_TRUNC 0x20 #define MSG_DONTWAIT 0x40 /* Nonblocking io */ #define MSG_EOR 0x80 /* End of record */ #define MSG_WAITALL 0x100 /* Wait for a full request */ #define MSG_FIN 0x200 #define MSG_SYN 0x400 #define MSG_CONFIRM 0x800 /* Confirm path validity */ #define MSG_RST 0x1000 #define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue */ #define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */ #define MSG_MORE 0x8000 /* Sender will send more */ #define MSG_EOF MSG_FIN #define MSG_CMSG_CLOEXEC 0x40000000 /* Set close_on_exit for file descriptor received through SCM_RIGHTS */ #if defined(CONFIG_COMPAT) #define MSG_CMSG_COMPAT 0x80000000 /* This message needs 32 bit fixups */ #else #define MSG_CMSG_COMPAT 0 /* We never have 32 bit fixups */ #endif #endif // !MSG_OOB /* These types is hidden under __KERNEL__ in kernel sources */ typedef unsigned short sa_family_t; struct sockaddr { sa_family_t sa_family; /* address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */ }; typedef int socklen_t; struct msghdr { void *msg_name; int msg_namelen; struct iovec *msg_iov; size_t msg_iovlen; void *msg_control; size_t msg_controllen; unsigned msg_flags; }; /* Ancillary data structures and cmsg macros are also hidden under __KERNEL__ */ #ifndef CMSG_FIRSTHDR /* * POSIX 1003.1g - ancillary data object information * Ancillary data consits of a sequence of pairs of * (cmsghdr, cmsg_data[]) */ struct cmsghdr { __kernel_size_t cmsg_len; /* data byte count, including hdr */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ }; /* * Ancilliary data object information MACROS * Table 5-14 of POSIX 1003.1g */ #define __CMSG_NXTHDR(ctl, len, cmsg) __cmsg_nxthdr((ctl),(len),(cmsg)) #define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg)) #define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) ) #define CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr)))) #define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len)) #define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len)) #define __CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr) ? \ (struct cmsghdr *)(ctl) : \ (struct cmsghdr *)NULL) #define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) #define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && \ (cmsg)->cmsg_len <= (unsigned long) \ ((mhdr)->msg_controllen - \ ((char *)(cmsg) - (char *)(mhdr)->msg_control))) /* * Get the next cmsg header * * PLEASE, do not touch this function. If you think, that it is * incorrect, grep kernel sources and think about consequences * before trying to improve it. * * Now it always returns valid, not truncated ancillary object * HEADER. But caller still MUST check, that cmsg->cmsg_len is * inside range, given by msg->msg_controllen before using * ancillary object DATA. --ANK (980731) */ static inline struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size, struct cmsghdr *__cmsg) { struct cmsghdr * __ptr; __ptr = (struct cmsghdr*)(((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len)); if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) return (struct cmsghdr *)0; return __ptr; } static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__cmsg) { return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg); } /* "Socket"-level control message types: */ #define SCM_RIGHTS 0x01 /* rw: access rights (array of int) */ #define SCM_CREDENTIALS 0x02 /* rw: struct ucred */ #define SCM_SECURITY 0x03 /* rw: security label */ struct ucred { __u32 pid; __u32 uid; __u32 gid; }; #endif /* CMSG_FIRSTHDR */ __extern int socket(int, int, int); __extern int bind(int, const struct sockaddr *, int); __extern int connect(int, const struct sockaddr *, socklen_t); __extern int listen(int, int); __extern int accept(int, struct sockaddr *, socklen_t *); __extern int accept4(int, struct sockaddr *, socklen_t *, int); __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 */ klibc-2.0.7/usr/include/sys/sendfile.h0000644000175000017500000000035413546663605015732 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/select.h0000644000175000017500000000056513546663605015424 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/resource.h0000644000175000017500000000054613546663605015773 0ustar benben/* * 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); __extern int getrusage(int, struct rusage *); #endif /* _SYS_RESOURCE_H */ klibc-2.0.7/usr/include/sys/reboot.h0000644000175000017500000000114413546663605015431 0ustar benben/* * 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 /* two-arguments version of reboot */ __extern int reboot(int, void *); /* Native four-argument system call */ __extern int __reboot(int, int, int, void *); #endif /* _SYS_REBOOT_H */ klibc-2.0.7/usr/include/sys/prctl.h0000644000175000017500000000033013546663605015257 0ustar benben#ifndef _SYS_PRCTL_H #define _SYS_PRCTL_H #include #include /* glibc has this as a varadic function, so join the club... */ __extern int prctl(int, ...); #endif /* _SYS_PRCTL_H */ klibc-2.0.7/usr/include/sys/poll.h0000644000175000017500000000063013546663605015104 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/param.h0000644000175000017500000000021513546663605015235 0ustar benben/* * sys/param.h */ #ifndef _SYS_PARAM_H #define _SYS_PARAM_H #include #include #endif /* _SYS_PARAM_H */ klibc-2.0.7/usr/include/sys/mount.h0000644000175000017500000000454213546663605015306 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/mman.h0000644000175000017500000000126013546663605015066 0ustar benben/* * 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 shm_open(const char *, int, mode_t); __extern int shm_unlink(const char *); __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 */ klibc-2.0.7/usr/include/sys/md.h0000644000175000017500000000201113546663605014531 0ustar benben/* ----------------------------------------------------------------------- * * * 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 */ klibc-2.0.7/usr/include/sys/klog.h0000644000175000017500000000063113546663605015073 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/ioctl.h0000644000175000017500000000041713546663605015253 0ustar benben/* * sys/ioctl.h */ #ifndef _SYS_IOCTL_H #define _SYS_IOCTL_H #include #include #include /* the SIOCxxx I/O are hidden */ #include __extern int ioctl(int, int, void *); #endif /* _SYS_IOCTL_H */ klibc-2.0.7/usr/include/sys/inotify.h0000644000175000017500000000047313546663605015624 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/fsuid.h0000644000175000017500000000031613546663605015251 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/file.h0000644000175000017500000000021513546663605015054 0ustar benben#ifndef _SYS_FILE_H #define _SYS_FILE_H /* LOCK_ definitions */ #include __extern int flock(int, int); #endif /* _SYS_FILE_H */ klibc-2.0.7/usr/include/sys/elfcommon.h0000644000175000017500000001302213546663605016114 0ustar benben/* * 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 */ #define AT_SYSINFO 32 /* vdso entry point address */ #define AT_SYSINFO_EHDR 33 /* vdso header address */ /* 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 /* End of a chain. */ #define STN_UNDEF 0 /* 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 /* Legal values for ST_BIND subfield of st_info (symbol binding). */ #define STB_LOCAL 0 /* Local symbol */ #define STB_GLOBAL 1 /* Global symbol */ #define STB_WEAK 2 /* Weak symbol */ #define STB_NUM 3 /* Number of defined types. */ #define STB_LOOS 10 /* Start of OS-specific */ #define STB_HIOS 12 /* End of OS-specific */ #define STB_LOPROC 13 /* Start of processor-specific */ #define STB_HIPROC 15 /* End of processor-specific */ #endif /* _SYS_ELFCOMMON_H */ klibc-2.0.7/usr/include/sys/elf64.h0000644000175000017500000000446213546663605015065 0ustar benben/* * 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; /* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ #define ELF64_ST_BIND(val) ELF32_ST_BIND (val) #define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) #endif /* _SYS_ELF64_H */ klibc-2.0.7/usr/include/sys/elf32.h0000644000175000017500000000444313546663605015057 0ustar benben/* * 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; /* How to extract and insert information held in the st_info field. */ #define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) #define ELF32_ST_TYPE(val) ((val) & 0xf) #endif /* _SYS_ELF32_H */ klibc-2.0.7/usr/include/sys/dirent.h0000644000175000017500000000107013546663605015422 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sys/capability.h0000644000175000017500000000041113546663605016254 0ustar benben#ifndef _SYS_CAPABILITY_H #define _SYS_CAPABILITY_H #include #include __extern int capget(cap_user_header_t, cap_user_data_t); __extern int capset(cap_user_header_t, const cap_user_data_t); #endif /* _SYS_CAPABILITY_H */ klibc-2.0.7/usr/include/sys/auxv.h0000644000175000017500000000052013546663605015117 0ustar benben#ifndef _SYS_AUXV_H #define _SYS_AUXV_H #include #include #include #define _AUXVAL_MAX AT_SYSINFO_EHDR __extern unsigned long __auxval[_AUXVAL_MAX]; __static_inline unsigned long getauxval(unsigned long __t) { return (__t >= _AUXVAL_MAX) ? 0 : __auxval[__t]; } #endif /* _SYS_AUXV_H */ klibc-2.0.7/usr/include/string.h0000644000175000017500000000361413546663605014633 0ustar benben/* * 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 void bzero(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 *); __extern char *strtok_r(char *, const char *, char **); #endif /* _STRING_H */ klibc-2.0.7/usr/include/stdlib.h0000644000175000017500000000460113546663605014603 0ustar benben/* * stdlib.h */ #ifndef _STDLIB_H #define _STDLIB_H #include #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); static __inline__ int posix_openpt(int __mode) { __extern int open(const char *, int, ...); __mode &= ~(O_CREAT | O_TMPFILE); return open("/dev/ptmx", __mode); } static __inline__ int grantpt(int __fd) { (void)__fd; return 0; /* devpts does this all for us! */ } __extern char *realpath(const char *, char *); #endif /* _STDLIB_H */ klibc-2.0.7/usr/include/stdio.h0000644000175000017500000000622713546663605014452 0ustar benben/* * stdio.h */ #ifndef _STDIO_H #define _STDIO_H #include #include #include #include #include #include struct _IO_file { int _IO_fileno; /* Underlying file descriptor */ _Bool _IO_eof; /* End of file flag */ _Bool _IO_error; /* Error flag */ }; typedef struct _IO_file FILE; #ifndef EOF # define EOF (-1) #endif #ifndef BUFSIZ # define BUFSIZ _KLIBC_BUFSIZ #endif enum _IO_bufmode { _IONBF, _IOLBF, _IOFBF }; #define _IONBF _IONBF #define _IOLBF _IOLBF #define _IOFBF _IOFBF /* * Convert between a FILE * and a file descriptor. */ __extern FILE *stdin, *stdout, *stderr; __extern FILE *fopen(const char *, const char *); __extern FILE *fdopen(int, const char *); __extern int fclose(FILE *); __extern int fseek(FILE *, off_t, int); #define fseeko fseek __extern void rewind(FILE *); __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) __extern int getc_unlocked(FILE *); #define getc_unlocked(f) fgetc(f) #define getchar() fgetc(stdin) __extern int ungetc(int, FILE *); __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); __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 renameat2(int, const char *, int, const char *, unsigned int); __extern int remove(const char *); __extern size_t _fread(void *, size_t, FILE *); __extern size_t _fwrite(const void *, size_t, FILE *); __extern int fflush(FILE *); __extern size_t fread(void *, size_t, size_t, FILE *); __extern size_t fwrite(const void *, size_t, size_t, FILE *); __extern off_t ftell(FILE *__f); #define ftello ftell __extern int ferror(FILE * ); __extern int feof(FILE *); __extern int fileno(FILE *); __extern void clearerr(FILE *); #ifndef __NO_STDIO_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; } __extern_inline int fileno(FILE *__f) { return __f->_IO_fileno; } __extern_inline int ferror(FILE *__f) { return __f->_IO_error; } __extern_inline int feof(FILE *__f) { return __f->_IO_eof; } __extern_inline void clearerr(FILE *__f) { __f->_IO_error = 0; __f->_IO_eof = 0; } #endif #endif /* _STDIO_H */ klibc-2.0.7/usr/include/stdint.h0000644000175000017500000000516613546663605014636 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/stddef.h0000644000175000017500000000233513546663605014575 0ustar benben/* * stddef.h */ #ifndef _STDDEF_H #define _STDDEF_H #ifndef __KLIBC__ # error "__KLIBC__ not defined, compiler invocation error!" #endif /* * __SIZE_TYPE__ and __PTRDIFF_TYPE__ are defined by GCC and * many other compilers to what types the ABI expects on the * target platform for size_t and ptrdiff_t, so we use these * for size_t, ssize_t, ptrdiff_t definitions, if available; * fall back to unsigned long, which is correct on ILP32 and * LP64 platforms (Linux does not have any others) otherwise. * * Note: the order "long unsigned int" precisely matches GCC. */ #ifndef __SIZE_TYPE__ #define __SIZE_TYPE__ long unsigned int #endif #ifndef __PTRDIFF_TYPE__ #define __PTRDIFF_TYPE__ long int #endif #define _SIZE_T typedef __SIZE_TYPE__ size_t; #define _PTRDIFF_T typedef __PTRDIFF_TYPE__ ptrdiff_t; #undef NULL #ifdef __cplusplus # define NULL 0 #else # define NULL ((void *)0) #endif #undef offsetof #define offsetof(t,m) ((size_t)&((t *)0)->m) /* * The container_of construct: if p is a pointer to member m of * container class c, then return a pointer to the container of which * *p is a member. */ #undef container_of #define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m))) #endif /* _STDDEF_H */ klibc-2.0.7/usr/include/stdarg.h0000644000175000017500000000051413546663605014605 0ustar benben/* * 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 klibc-2.0.7/usr/include/signal.h0000644000175000017500000000552213546663605014602 0ustar benben/* * 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; __signum--; /* Signal 0 is not in the 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; __signum--; /* Signal 0 is not in the 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; __signum--; /* Signal 0 is not in the set */ return (int)((__lset[__signum / LONG_BIT] >> (__signum % LONG_BIT)) & 1); } __extern __sighandler_t __signal(int, __sighandler_t, int); #ifndef signal __extern __sighandler_t signal(int, __sighandler_t); #endif __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 */ klibc-2.0.7/usr/include/setjmp.h0000644000175000017500000000173613546663605014632 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/sched.h0000644000175000017500000000176113546663605014414 0ustar benben/* * sched.h */ #ifndef _SCHED_H #define _SCHED_H #include #include /* linux/sched.h is unusable; put the declarations we need here... */ #define SCHED_OTHER 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_setaffinity(pid_t, unsigned int, unsigned long *); __extern int sched_getaffinity(pid_t, unsigned int, unsigned long *); __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 */ klibc-2.0.7/usr/include/pwd.h0000644000175000017500000000051513546663605014114 0ustar benben#ifndef _PWD_H #define _PWD_H #include #include struct passwd { char *pw_name; char *pw_passwd; uid_t pw_uid; gid_t pw_gid; char *pw_gecos; char *pw_dir; char *pw_shell; }; __extern struct passwd *getpwuid(uid_t uid); __extern struct passwd *getpwnam(const char *name); #endif /* _PWD_H */ klibc-2.0.7/usr/include/poll.h0000644000175000017500000000002613546663605014265 0ustar benben#include klibc-2.0.7/usr/include/paths.h0000644000175000017500000000557313546663605014452 0ustar benben/* * 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_ */ klibc-2.0.7/usr/include/netpacket/0000755000175000017500000000000013546663605015126 5ustar benbenklibc-2.0.7/usr/include/netpacket/packet.h0000644000175000017500000000003513546663605016544 0ustar benben#include klibc-2.0.7/usr/include/netinet/0000755000175000017500000000000013546663605014616 5ustar benbenklibc-2.0.7/usr/include/netinet/udp.h0000644000175000017500000000040013546663605015551 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/netinet/tcp.h0000644000175000017500000000026713546663605015562 0ustar benben/* * netinet/tcp.h */ #ifndef _NETINET_TCP_H #define _NETINET_TCP_H #include /* Include *before* linux/tcp.h */ #include #endif /* _NETINET_TCP_H */ klibc-2.0.7/usr/include/netinet/ip.h0000644000175000017500000000030213546663605015372 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/netinet/in6.h0000644000175000017500000000017713546663605015470 0ustar benben/* * netinet/in6.h */ #ifndef _NETINET_IN6_H #define _NETINET_IN6_H #include #endif /* _NETINET_IN6_H */ klibc-2.0.7/usr/include/netinet/in.h0000644000175000017500000000133413546663605015376 0ustar benben/* * netinet/in.h */ #ifndef _NETINET_IN_H #define _NETINET_IN_H #include #include #include /* Must be included *before* */ #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 */ klibc-2.0.7/usr/include/netinet/if_ether.h0000644000175000017500000000003413546663605016551 0ustar benben#include klibc-2.0.7/usr/include/net/0000755000175000017500000000000013546663605013736 5ustar benbenklibc-2.0.7/usr/include/net/route.h0000644000175000017500000000003113546663605015237 0ustar benben#include klibc-2.0.7/usr/include/net/if_packet.h0000644000175000017500000000003513546663605016032 0ustar benben#include klibc-2.0.7/usr/include/net/if_arp.h0000644000175000017500000000012013546663605015340 0ustar benben/* if_arp.h needs sockaddr */ #include #include klibc-2.0.7/usr/include/net/if.h0000644000175000017500000000020213546663605014477 0ustar benben#ifndef _NET_IF_H #define _NET_IF_H #include #include #include #endif /* _NET_IF_H */ klibc-2.0.7/usr/include/mntent.h0000644000175000017500000000104513546663605014626 0ustar benben#ifndef _MNTENT_H #define _MNTENT_H 1 #define MNTTYPE_SWAP "swap" struct mntent { char *mnt_fsname; /* name of mounted file system */ char *mnt_dir; /* file system path prefix */ char *mnt_type; /* mount type (see mntent.h) */ char *mnt_opts; /* mount options (see mntent.h) */ int mnt_freq; /* dump frequency in days */ int mnt_passno; /* pass number on parallel fsck */ }; extern FILE *setmntent(const char *, const char *); extern struct mntent *getmntent(FILE *); extern int endmntent(FILE *fp); #endif /* mntent.h */ klibc-2.0.7/usr/include/malloc.h0000644000175000017500000000077313546663605014577 0ustar benben/* * 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 *zalloc(size_t); __extern __mallocfunc void *calloc(size_t, size_t); __extern __mallocfunc void *realloc(void *, size_t); #endif /* _MALLOC_H */ klibc-2.0.7/usr/include/limits.h0000644000175000017500000000151313546663605014622 0ustar benben/* * limits.h */ #ifndef _LIMITS_H #define _LIMITS_H /* No multibyte characters seen */ #define MB_LEN_MAX 1 #define OPEN_MAX 256 #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 LLONG_MIN (-9223372036854775807LL-1) #define LLONG_MAX 9223372036854775807LL #define ULLONG_MAX 18446744073709551615ULL #include #include #define SSIZE_MAX LONG_MAX #endif /* _LIMITS_H */ klibc-2.0.7/usr/include/klibc/0000755000175000017500000000000013546663605014234 5ustar benbenklibc-2.0.7/usr/include/klibc/sysconfig.h0000644000175000017500000001223413546663605016413 0ustar benben/* * 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_BUFSIZ: * This is the size of an stdio buffer. By default this is * _KLIBC_MALLOC_CHUNK_SIZE/4, which allows the three standard * streams to fit inside a malloc chunk. */ #ifndef _KLIBC_BUFSIZ # define _KLIBC_BUFSIZ (_KLIBC_MALLOC_CHUNK_SIZE >> 2) #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 /* * _KLIBC_STATFS_F_TYPE_32B: * * mips has it's own definition of statfs, which is * different from any other 32 bit arch. */ #ifndef _KLIBC_STATFS_F_TYPE_32B # define _KLIBC_STATFS_F_TYPE_32B 0 #endif /* * _KLIBC_HAS_ARCHSOCKET_H * * This architecture has */ #ifndef _KLIBC_HAS_ARCHSOCKET_H # define _KLIBC_HAS_ARCHSOCKET_H 0 #endif /* * _KLIBC_SYS_SOCKETCALL * * This architecture (e.g. SPARC) advertises socket-related * system calls, which are not actually implemented. Use * socketcalls unconditionally instead. */ #ifndef _KLIBC_SYS_SOCKETCALL # define _KLIBC_SYS_SOCKETCALL 0 #endif /* * _KLIBC_ARM_USE_BX * * This arm architecture supports bx instruction. */ #ifndef _KLIBC_ARM_USE_BX # define _KLIBC_ARM_USE_BX 0 #endif /* * _KLIBC_HAS_ARCHINIT * * This architecture has klibc/archinit.h and __libc_archinit() */ #ifndef _KLIBC_HAS_ARCHINIT # define _KLIBC_HAS_ARCHINIT 0 #endif #endif /* _KLIBC_SYSCONFIG_H */ klibc-2.0.7/usr/include/klibc/stathelp.h0000644000175000017500000000076213546663605016236 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/klibc/seek.h0000644000175000017500000000033213546663605015332 0ustar benben/* * klibc/seek.h * * SEEK constants - needed by stdio.h, fcntl.h, and unistd.h */ #ifndef _KLIBC_SEEK_H #define _KLIBC_SEEK_H #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif /* _KLIBC_SEEK_H */ klibc-2.0.7/usr/include/klibc/extern.h0000644000175000017500000000036413546663605015715 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/klibc/endian.h0000644000175000017500000000175513546663605015653 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/klibc/diverr.h0000644000175000017500000000030113546663605015672 0ustar benben/* * klibc/diverr.h */ #ifndef _KLIBC_DIVERR_H #define _KLIBC_DIVERR_H #include static __inline__ void __divide_error(void) { raise(SIGFPE); } #endif /* _KLIBC_DIVERR_H */ klibc-2.0.7/usr/include/klibc/compiler.h0000644000175000017500000001017513546663605016223 0ustar benben/* * 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 which should be inlined or instantiated locally */ #ifdef __GNUC__ # ifdef __GNUC_STDC_INLINE__ # define __static_inline static __inline__ __attribute__((__gnu_inline__)) # else # define __static_inline static __inline__ # endif #else # define __static_inline inline /* Just hope this works... */ #endif /* * How to declare a function which should be inlined or have a call to * an external module */ #ifdef __GNUC__ # ifdef __GNUC_STDC_INLINE__ # define __extern_inline extern __inline__ __attribute__((__gnu_inline__)) # else # define __extern_inline extern __inline__ # endif #else # define __extern_inline inline /* Just hope this works... */ #endif /* How to declare a function that *must* be inlined */ /* Use "extern inline" even in the gcc3+ case to avoid warnings in ctype.h */ #ifdef __GNUC__ # if __GNUC__ >= 3 # define __must_inline __extern_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 /* Shut up unused warnings */ #ifdef __GNUC__ # define __attribute_used__ __attribute__((used)) #else # define __attribute_used__ #endif /* Compiler pragma to make an alias symbol */ #define __ALIAS(__t, __f, __p, __a) \ __t __f __p __attribute__((weak, alias(#__a))); #endif klibc-2.0.7/usr/include/inttypes.h0000644000175000017500000001170713546663605015206 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/grp.h0000644000175000017500000000052413546663605014112 0ustar benben/* * grp.h */ #ifndef _GRP_H #define _GRP_H #include #include struct group { char *gr_name; char *gr_passwd; gid_t gr_gid; char **gr_mem; }; __extern int setgroups(size_t, const gid_t *); __extern struct group *getgrgid(gid_t); __extern struct group *getgrnam(const char *); #endif /* _GRP_H */ klibc-2.0.7/usr/include/getopt.h0000644000175000017500000000052013546663605014620 0ustar benben#ifndef _GETOPT_H #define _GETOPT_H #include struct option { const char *name; int has_arg; int *flag; int val; }; enum { no_argument = 0, required_argument = 1, optional_argument = 2, }; __extern int getopt_long(int, char *const *, const char *, const struct option *, int *); #endif /* _GETOPT_H */ klibc-2.0.7/usr/include/fnmatch.h0000644000175000017500000000042513546663605014742 0ustar benben#ifndef _FNMATCH_H #define _FNMATCH_H #include #define FNM_NOMATCH 1 #define FNM_PATHNAME 1 #define FNM_FILE_NAME FNM_PATHNAME #define FNM_NOESCAPE 2 #define FNM_PERIOD 4 __extern int fnmatch(const char *, const char *, int); #endif /* _FNMATCH_H */ klibc-2.0.7/usr/include/fcntl.h0000644000175000017500000000252413546663605014432 0ustar benben/* * fcntl.h */ #ifndef _FCNTL_H #define _FCNTL_H #include #include #include #include #if defined(__mips__) && ! defined(__mips64) # include #elif _BITSIZE == 32 /* We want a struct flock with 64-bit offsets, which we define below */ # define HAVE_ARCH_STRUCT_FLOCK #endif #include #include #if !defined(__mips__) && _BITSIZE == 32 /* * defines struct flock with offsets of type * __kernel_off_t (= long) and struct flock64 with offsets of * type __kernel_loff_t (= long long). We want struct flock * to have 64-bit offsets, so we define it here. */ struct flock { short l_type; short l_whence; __kernel_loff_t l_start; __kernel_loff_t l_len; __kernel_pid_t l_pid; __ARCH_FLOCK64_PAD }; #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 #endif /* _BITSIZE == 32 */ /* This is defined here as well as in */ #ifndef _KLIBC_IN_OPEN_C __extern int open(const char *, int, ...); __extern int openat(int, const char *, int, ...); #endif __extern int creat(const char *, mode_t); __extern int fcntl(int, int, ...); #endif /* _FCNTL_H */ klibc-2.0.7/usr/include/errno.h0000644000175000017500000000022313546663605014443 0ustar benben/* * errno.h */ #ifndef _ERRNO_H #define _ERRNO_H #include #include __extern int errno; #endif /* _ERRNO_H */ klibc-2.0.7/usr/include/endian.h0000644000175000017500000000062613546663605014563 0ustar benben/* * 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 #if __BYTE_ORDER == __LITTLE_ENDIAN # define __LONG_LONG_PAIR(HI, LO) LO, HI #elif __BYTE_ORDER == __BIG_ENDIAN # define __LONG_LONG_PAIR(HI, LO) HI, LO #endif #endif /* _ENDIAN_H */ klibc-2.0.7/usr/include/elf.h0000644000175000017500000000016613546663605014072 0ustar benben/* * elf.h */ #ifndef _ELF_H #define _ELF_H #include #include #endif /* _ELF_H */ klibc-2.0.7/usr/include/dirent.h0000644000175000017500000000166313546663605014614 0ustar benben/* * dirent.h */ #ifndef _DIRENT_H #define _DIRENT_H #include #include #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[_KLIBC_BUFSIZ / sizeof(struct dirent)]; #endif }; typedef struct _IO_dir DIR; __extern DIR *fdopendir(int); __extern DIR *opendir(const char *); __extern struct dirent *readdir(DIR *); __extern int closedir(DIR *); __static_inline int dirfd(DIR * __d) { return __d->__fd; } __extern int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); __extern int alphasort(const struct dirent **, const struct dirent **); #endif /* _DIRENT_H */ klibc-2.0.7/usr/include/ctype.h0000644000175000017500000000731213546663605014450 0ustar benben/* * ctype.h * * This assumes ISO 8859-1, being a reasonable superset of ASCII. */ #ifndef _CTYPE_H #define _CTYPE_H #include #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 int isalnum(int); __extern int isalpha(int); __extern int isascii(int); __extern int isblank(int); __extern int iscntrl(int); __extern int isdigit(int); __extern int isgraph(int); __extern int islower(int); __extern int isprint(int); __extern int ispunct(int); __extern int isspace(int); __extern int isupper(int); __extern int isxdigit(int); __extern int toupper(int); __extern int tolower(int); extern const unsigned char __ctypes[]; __must_inline int __ctype_isalnum(int); __must_inline int __ctype_isalpha(int); __must_inline int __ctype_isascii(int); __must_inline int __ctype_isblank(int); __must_inline int __ctype_iscntrl(int); __must_inline int __ctype_isdigit(int); __must_inline int __ctype_isgraph(int); __must_inline int __ctype_islower(int); __must_inline int __ctype_isprint(int); __must_inline int __ctype_ispunct(int); __must_inline int __ctype_isspace(int); __must_inline int __ctype_isupper(int); __must_inline int __ctype_isxdigit(int); __must_inline int __ctype_isalnum(int __c) { return __ctypes[__c + 1] & (__ctype_upper | __ctype_lower | __ctype_digit); } __must_inline int __ctype_isalpha(int __c) { return __ctypes[__c + 1] & (__ctype_upper | __ctype_lower); } __must_inline int __ctype_isascii(int __c) { return !(__c & ~0x7f); } __must_inline int __ctype_isblank(int __c) { return (__c == '\t') || (__c == ' '); } __must_inline int __ctype_iscntrl(int __c) { return __ctypes[__c + 1] & __ctype_cntrl; } __must_inline int __ctype_isdigit(int __c) { return ((unsigned)__c - '0') <= 9; } __must_inline int __ctype_isgraph(int __c) { return __ctypes[__c + 1] & (__ctype_upper | __ctype_lower | __ctype_digit | __ctype_punct); } __must_inline int __ctype_islower(int __c) { return __ctypes[__c + 1] & __ctype_lower; } __must_inline int __ctype_isprint(int __c) { return __ctypes[__c + 1] & __ctype_print; } __must_inline int __ctype_ispunct(int __c) { return __ctypes[__c + 1] & __ctype_punct; } __must_inline int __ctype_isspace(int __c) { return __ctypes[__c + 1] & __ctype_space; } __must_inline int __ctype_isupper(int __c) { return __ctypes[__c + 1] & __ctype_upper; } __must_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) __must_inline int __ctype_toupper(int); __must_inline int __ctype_tolower(int); __must_inline int __ctype_toupper(int __c) { return __ctype_islower(__c) ? _toupper(__c) : __c; } __must_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 */ klibc-2.0.7/usr/include/byteswap.h0000644000175000017500000000036413546663605015162 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits64/0000755000175000017500000000000013546663605014263 5ustar benbenklibc-2.0.7/usr/include/bits64/bitsize/0000755000175000017500000000000013546663605015734 5ustar benbenklibc-2.0.7/usr/include/bits64/bitsize/stdintlimits.h0000644000175000017500000000075413546663605020642 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits64/bitsize/stdintconst.h0000644000175000017500000000060113546663605020456 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits64/bitsize/stdint.h0000644000175000017500000000131213546663605017407 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits64/bitsize/limits.h0000644000175000017500000000040213546663605017402 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits64/bitsize.h0000644000175000017500000000005413546663605016104 0ustar benben#ifndef _BITSIZE #define _BITSIZE 64 #endif klibc-2.0.7/usr/include/bits32/0000755000175000017500000000000013546663605014256 5ustar benbenklibc-2.0.7/usr/include/bits32/bitsize/0000755000175000017500000000000013546663605015727 5ustar benbenklibc-2.0.7/usr/include/bits32/bitsize/stdintlimits.h0000644000175000017500000000075413546663605020635 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits32/bitsize/stdintconst.h0000644000175000017500000000060113546663605020451 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits32/bitsize/stdint.h0000644000175000017500000000130113546663605017400 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits32/bitsize/limits.h0000644000175000017500000000034613546663605017404 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/bits32/bitsize.h0000644000175000017500000000005413546663605016077 0ustar benben#ifndef _BITSIZE #define _BITSIZE 32 #endif klibc-2.0.7/usr/include/assert.h0000644000175000017500000000111513546663605014620 0ustar benben/* * assert.h */ #ifndef _ASSERT_H #define _ASSERT_H #include #ifdef NDEBUG /* * NDEBUG doesn't just suppress the faulting behavior of assert(), * but also all side effects of the assert() argument. This behavior * is required by the C standard, and allows the argument to reference * variables that are not defined without NDEBUG. */ #define assert(x) ((void)(0)) #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 */ klibc-2.0.7/usr/include/arpa/0000755000175000017500000000000013546663605014073 5ustar benbenklibc-2.0.7/usr/include/arpa/inet.h0000644000175000017500000000114713546663605015206 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/0000755000175000017500000000000013546663605014065 5ustar benbenklibc-2.0.7/usr/include/arch/x86_64/0000755000175000017500000000000013546663605015023 5ustar benbenklibc-2.0.7/usr/include/arch/x86_64/sys/0000755000175000017500000000000013546663605015641 5ustar benbenklibc-2.0.7/usr/include/arch/x86_64/sys/io.h0000644000175000017500000000662213546663605016427 0ustar benben/* ----------------------------------------------------------------------- * * * 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 */ klibc-2.0.7/usr/include/arch/x86_64/klibc/0000755000175000017500000000000013546663605016107 5ustar benbenklibc-2.0.7/usr/include/arch/x86_64/klibc/archstat.h0000644000175000017500000000077413546663605020101 0ustar benben#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 klibc-2.0.7/usr/include/arch/x86_64/klibc/archsignal.h0000644000175000017500000000047413546663605020400 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/x86_64/klibc/archsetjmp.h0000644000175000017500000000056213546663605020423 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/x86_64/klibc/archconfig.h0000644000175000017500000000047513546663605020371 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/sparc64/0000755000175000017500000000000013546663605015347 5ustar benbenklibc-2.0.7/usr/include/arch/sparc64/machine/0000755000175000017500000000000013546663605016753 5ustar benbenklibc-2.0.7/usr/include/arch/sparc64/machine/frame.h0000644000175000017500000000004713546663605020217 0ustar benben#include "../../sparc/machine/frame.h" klibc-2.0.7/usr/include/arch/sparc64/machine/asm.h0000644000175000017500000000004513546663605017703 0ustar benben#include "../../sparc/machine/asm.h" klibc-2.0.7/usr/include/arch/sparc64/klibc/0000755000175000017500000000000013546663605016433 5ustar benbenklibc-2.0.7/usr/include/arch/sparc64/klibc/archstat.h0000644000175000017500000000073413546663605020421 0ustar benben#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 klibc-2.0.7/usr/include/arch/sparc64/klibc/archsignal.h0000644000175000017500000000045013546663605020716 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/sparc64/klibc/archsetjmp.h0000644000175000017500000000040213546663605020740 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/sparc64/klibc/archconfig.h0000644000175000017500000000064713546663605020716 0ustar benben/* * 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 */ #define _KLIBC_SYS_SOCKETCALL 1 /* Use sys_socketcall unconditionally */ #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/sparc/0000755000175000017500000000000013546663605015175 5ustar benbenklibc-2.0.7/usr/include/arch/sparc/machine/0000755000175000017500000000000013546663605016601 5ustar benbenklibc-2.0.7/usr/include/arch/sparc/machine/trap.h0000644000175000017500000001410413546663605017720 0ustar benben/* $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_ */ klibc-2.0.7/usr/include/arch/sparc/machine/frame.h0000644000175000017500000001264013546663605020047 0ustar benben/* $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 */ klibc-2.0.7/usr/include/arch/sparc/machine/asm.h0000644000175000017500000001466313546663605017544 0ustar benben/* $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 #define SET(var,base,dest) \ sethi %gdop_hix22(var), dest; \ xor dest, %gdop_lox10(var), dest; \ ldx [base + dest], dest, %gdop(var) #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 #define SET(var,base,dest) \ sethi %gdop_hix22(var), dest; \ xor dest, %gdop_lox10(var), dest; \ ld [base + dest], dest, %gdop(var) #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 SET(var,base,dest) \ sethi %hi(var), dest; \ or dest, %lo(var), dest #define PICCY_SET(var,dest,tmp) SET(var,tmp,dest) #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_ */ klibc-2.0.7/usr/include/arch/sparc/klibc/0000755000175000017500000000000013546663605016261 5ustar benbenklibc-2.0.7/usr/include/arch/sparc/klibc/archstat.h0000644000175000017500000000105313546663605020242 0ustar benben#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 klibc-2.0.7/usr/include/arch/sparc/klibc/archsignal.h0000644000175000017500000000040013546663605020537 0ustar benben/* * * 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 klibc-2.0.7/usr/include/arch/sparc/klibc/archsetjmp.h0000644000175000017500000000040013546663605020564 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/sparc/klibc/archconfig.h0000644000175000017500000000054313546663605020537 0ustar benben/* * 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 */ #define _KLIBC_SYS_SOCKETCALL 1 /* Use sys_socketcall unconditionally */ #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/sh/0000755000175000017500000000000013546663605014477 5ustar benbenklibc-2.0.7/usr/include/arch/sh/klibc/0000755000175000017500000000000013546663605015563 5ustar benbenklibc-2.0.7/usr/include/arch/sh/klibc/archstat.h0000644000175000017500000000124013546663605017542 0ustar benben#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; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; unsigned long __unused1; unsigned long __unused2; }; #endif klibc-2.0.7/usr/include/arch/sh/klibc/archsignal.h0000644000175000017500000000034613546663605020052 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/sh/klibc/archsetjmp.h0000644000175000017500000000061313546663605020074 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/sh/klibc/archconfig.h0000644000175000017500000000042713546663605020042 0ustar benben/* * 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 /* Use rt_* signals */ #define _KLIBC_USE_RT_SIG 1 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/s390/0000755000175000017500000000000013546663605014563 5ustar benbenklibc-2.0.7/usr/include/arch/s390/klibc/0000755000175000017500000000000013546663605015647 5ustar benbenklibc-2.0.7/usr/include/arch/s390/klibc/archstat.h0000644000175000017500000000232713546663605017635 0ustar benben#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 klibc-2.0.7/usr/include/arch/s390/klibc/archsignal.h0000644000175000017500000000035013546663605020131 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/s390/klibc/archsetjmp.h0000644000175000017500000000076413546663605020167 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/s390/klibc/archconfig.h0000644000175000017500000000051513546663605020124 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/riscv64/0000755000175000017500000000000013546663605015365 5ustar benbenklibc-2.0.7/usr/include/arch/riscv64/machine/0000755000175000017500000000000013546663605016771 5ustar benbenklibc-2.0.7/usr/include/arch/riscv64/machine/asm.h0000644000175000017500000000076713546663605017734 0ustar benben/* * arch/riscv64/include/machine/asm.h * * Mostly cribbed from mips. */ #ifndef _MACHINE_ASM_H #define _MACHINE_ASM_H /* * ENTRY - declare entry point */ #define ENTRY(symbol) \ .globl symbol; \ .align 2; \ .type symbol, @function; \ symbol: /* * END - mark end of function */ #define END(function) \ .size function, . - function #endif /* _MACHINE_ASM_H */ klibc-2.0.7/usr/include/arch/riscv64/klibc/0000755000175000017500000000000013546663605016451 5ustar benbenklibc-2.0.7/usr/include/arch/riscv64/klibc/archstat.h0000644000175000017500000000155113546663605020435 0ustar benben#ifndef _KLIBC_ARCHSTAT_H #define _KLIBC_ARCHSTAT_H #include #define _STATBUF_ST_NSEC struct stat { __stdev64 (st_dev); /* Device */ unsigned 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 long __pad1; long st_size; /* Size of file, in bytes */ int st_blksize; /* Optimal block size for I/O */ int __pad2; 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 int __unused4; unsigned int __unused5; }; #endif klibc-2.0.7/usr/include/arch/riscv64/klibc/archsignal.h0000644000175000017500000000035113546663605020734 0ustar benben/* * arch/riscv/include/klibc/archsignal.h * * Architecture-specific signal definitions * */ #ifndef _KLIBC_ARCHSIGNAL_H #define _KLIBC_ARCHSIGNAL_H #include /* No special stuff for this architecture */ #endif klibc-2.0.7/usr/include/arch/riscv64/klibc/archsetjmp.h0000644000175000017500000000075313546663605020767 0ustar benben/* * arch/riscv64/include/klibc/archsetjmp.h */ #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H struct __jmp_buf { unsigned long __pc; 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 __s8; unsigned long __s9; unsigned long __s10; unsigned long __s11; unsigned long __sp; }; typedef struct __jmp_buf jmp_buf[1]; #endif /* _SETJMP_H */ klibc-2.0.7/usr/include/arch/riscv64/klibc/archconfig.h0000644000175000017500000000045413546663605020730 0ustar benben/* * include/arch/riscv64/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 /* We have an MMU but no fork() syscall */ #define _KLIBC_NO_MMU 0 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/ppc64/0000755000175000017500000000000013546663605015021 5ustar benbenklibc-2.0.7/usr/include/arch/ppc64/klibc/0000755000175000017500000000000013546663605016105 5ustar benbenklibc-2.0.7/usr/include/arch/ppc64/klibc/archstat.h0000644000175000017500000000116013546663605020065 0ustar benben#ifndef _KLIBC_ARCHSTAT_H #define _KLIBC_ARCHSTAT_H #include #define _STATBUF_ST_NSEC struct stat { __stdev64 (st_dev); ino_t st_ino; unsigned long st_nlink; mode_t st_mode; uid_t st_uid; gid_t st_gid; unsigned int __pad1; __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 klibc-2.0.7/usr/include/arch/ppc64/klibc/archsignal.h0000644000175000017500000000035113546663605020370 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/ppc64/klibc/archsetjmp.h0000644000175000017500000000126713546663605020424 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/ppc64/klibc/archconfig.h0000644000175000017500000000037513546663605020366 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/ppc/0000755000175000017500000000000013546663605014647 5ustar benbenklibc-2.0.7/usr/include/arch/ppc/klibc/0000755000175000017500000000000013546663605015733 5ustar benbenklibc-2.0.7/usr/include/arch/ppc/klibc/archstat.h0000644000175000017500000000170513546663605017720 0ustar benben#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 klibc-2.0.7/usr/include/arch/ppc/klibc/archsignal.h0000644000175000017500000000034713546663605020223 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/ppc/klibc/archsetjmp.h0000644000175000017500000000126513546663605020250 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/ppc/klibc/archconfig.h0000644000175000017500000000040113546663605020202 0ustar benben/* * 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 #define _KLIBC_USE_RT_SIG 1 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/parisc/0000755000175000017500000000000013546663605015346 5ustar benbenklibc-2.0.7/usr/include/arch/parisc/klibc/0000755000175000017500000000000013546663605016432 5ustar benbenklibc-2.0.7/usr/include/arch/parisc/klibc/archstat.h0000644000175000017500000000106513546663605020416 0ustar benben#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 klibc-2.0.7/usr/include/arch/parisc/klibc/archsignal.h0000644000175000017500000000062013546663605020714 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/parisc/klibc/archsetjmp.h0000644000175000017500000000032413546663605020742 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/parisc/klibc/archconfig.h0000644000175000017500000000037313546663605020711 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/mips64/0000755000175000017500000000000013546663605015207 5ustar benbenklibc-2.0.7/usr/include/arch/mips64/machine/0000755000175000017500000000000013546663605016613 5ustar benbenklibc-2.0.7/usr/include/arch/mips64/machine/asm.h0000644000175000017500000000426113546663605017547 0ustar benben/* * arch/mips64/include/machine/asm.h */ #ifndef _MACHINE_ASM_H #define _MACHINE_ASM_H /* * Symbolic register names for 64 bit ABI */ #define zero $0 /* wired zero */ #define AT $at /* assembler temp - uppercase because of ".set at" */ #define v0 $2 /* return value - caller saved */ #define v1 $3 #define a0 $4 /* argument registers */ #define a1 $5 #define a2 $6 #define a3 $7 #define a4 $8 /* arg reg 64 bit; caller saved in 32 bit */ #define ta0 $8 #define a5 $9 #define ta1 $9 #define a6 $10 #define ta2 $10 #define a7 $11 #define ta3 $11 #define t4 $12 /* caller saved */ #define t5 $13 #define t6 $14 #define t7 $15 #define s0 $16 /* callee saved */ #define s1 $17 #define s2 $18 #define s3 $19 #define s4 $20 #define s5 $21 #define s6 $22 #define s7 $23 #define t8 $24 /* caller saved */ #define t9 $25 /* callee address for PIC/temp */ #define jp $25 /* PIC jump register */ #define k0 $26 /* kernel temporary */ #define k1 $27 #define gp $28 /* global pointer - caller saved for PIC */ #define sp $29 /* stack pointer */ #define fp $30 /* frame pointer */ #define s8 $30 /* callee saved */ #define ra $31 /* return address */ /* * LEAF - declare leaf routine */ #define LEAF(symbol) \ .globl symbol; \ .align 2; \ .type symbol,@function; \ .ent symbol,0; \ symbol: .frame sp,0,ra /* * NESTED - declare nested routine entry point */ #define NESTED(symbol, framesize, rpc) \ .globl symbol; \ .align 2; \ .type symbol,@function; \ .ent symbol,0; \ symbol: .frame sp, framesize, rpc /* * END - mark end of function */ #define END(function) \ .end function; \ .size function,.-function #endif /* _MACHINE_ASM_H */ klibc-2.0.7/usr/include/arch/mips64/klibc/0000755000175000017500000000000013546663605016273 5ustar benbenklibc-2.0.7/usr/include/arch/mips64/klibc/archstat.h0000644000175000017500000000110713546663605020254 0ustar benben#ifndef _KLIBC_ARCHSTAT_H #define _KLIBC_ARCHSTAT_H #include #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; __u32 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 klibc-2.0.7/usr/include/arch/mips64/klibc/archsocket.h0000644000175000017500000000047513546663605020600 0ustar benben/* * arch/mips64/klibc/archsocket.h */ #ifndef _KLIBC_ARCHSOCKET_H #define _KLIBC_ARCHSOCKET_H #ifndef SOCK_STREAM # define SOCK_DGRAM 1 # define SOCK_STREAM 2 # define SOCK_RAW 3 # define SOCK_RDM 4 # define SOCK_SEQPACKET 5 # define SOCK_PACKET 10 #endif #endif /* _KLIBC_ARCHSOCKET_H */ klibc-2.0.7/usr/include/arch/mips64/klibc/archsignal.h0000644000175000017500000000035213546663605020557 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/mips64/klibc/archsetjmp.h0000644000175000017500000000074513546663605020612 0ustar benben/* * arch/mips64/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; } __attribute__ ((aligned(8))); typedef struct __jmp_buf jmp_buf[1]; #endif /* _KLIBC_ARCHSETJMP_H */ klibc-2.0.7/usr/include/arch/mips64/klibc/archconfig.h0000644000175000017500000000075713546663605020560 0ustar benben/* * 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 /* MIPS has nonstandard socket definitions */ #define _KLIBC_HAS_ARCHSOCKET_H 1 #define _KLIBC_STATFS_F_TYPE_64 1 /* We can use RT signals on MIPS */ #define _KLIBC_USE_RT_SIG 1 /* MIPS has architecture-specific code for vfork() */ #define _KLIBC_REAL_VFORK 1 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/mips/0000755000175000017500000000000013546663605015035 5ustar benbenklibc-2.0.7/usr/include/arch/mips/spaces.h0000644000175000017500000000006713546663605016467 0ustar benben/* Included by but not actually needed */ klibc-2.0.7/usr/include/arch/mips/sgidefs.h0000644000175000017500000000055513546663605016637 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/mips/machine/0000755000175000017500000000000013546663605016441 5ustar benbenklibc-2.0.7/usr/include/arch/mips/machine/asm.h0000644000175000017500000000374213546663605017400 0ustar benben/* * arch/mips/include/machine/asm.h */ #ifndef _MACHINE_ASM_H #define _MACHINE_ASM_H /* * Symbolic register names for 32 bit ABI */ #define zero $0 /* wired zero */ #define AT $1 /* assembler temp - uppercase because of ".set at" */ #define v0 $2 /* return value */ #define v1 $3 #define a0 $4 /* argument registers */ #define a1 $5 #define a2 $6 #define a3 $7 #define t0 $8 /* caller saved */ #define t1 $9 #define t2 $10 #define t3 $11 #define t4 $12 #define t5 $13 #define t6 $14 #define t7 $15 #define s0 $16 /* callee saved */ #define s1 $17 #define s2 $18 #define s3 $19 #define s4 $20 #define s5 $21 #define s6 $22 #define s7 $23 #define t8 $24 /* caller saved */ #define t9 $25 #define jp $25 /* PIC jump register */ #define k0 $26 /* kernel scratch */ #define k1 $27 #define gp $28 /* global pointer */ #define sp $29 /* stack pointer */ #define fp $30 /* frame pointer */ #define s8 $30 /* same like fp! */ #define ra $31 /* return address */ /* * LEAF - declare leaf routine */ #define LEAF(symbol) \ .globl symbol; \ .align 2; \ .type symbol,@function; \ .ent symbol,0; \ symbol: .frame sp,0,ra /* * NESTED - declare nested routine entry point */ #define NESTED(symbol, framesize, rpc) \ .globl symbol; \ .align 2; \ .type symbol,@function; \ .ent symbol,0; \ symbol: .frame sp, framesize, rpc /* * END - mark end of function */ #define END(function) \ .end function; \ .size function,.-function #endif /* _MACHINE_ASM_H */ klibc-2.0.7/usr/include/arch/mips/klibc/0000755000175000017500000000000013546663605016121 5ustar benbenklibc-2.0.7/usr/include/arch/mips/klibc/archstat.h0000644000175000017500000000147613546663605020113 0ustar benben#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. 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; __u32 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 klibc-2.0.7/usr/include/arch/mips/klibc/archsocket.h0000644000175000017500000000047313546663605020424 0ustar benben/* * arch/mips/klibc/archsocket.h */ #ifndef _KLIBC_ARCHSOCKET_H #define _KLIBC_ARCHSOCKET_H #ifndef SOCK_STREAM # define SOCK_DGRAM 1 # define SOCK_STREAM 2 # define SOCK_RAW 3 # define SOCK_RDM 4 # define SOCK_SEQPACKET 5 # define SOCK_PACKET 10 #endif #endif /* _KLIBC_ARCHSOCKET_H */ klibc-2.0.7/usr/include/arch/mips/klibc/archsignal.h0000644000175000017500000000035013546663605020403 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/mips/klibc/archsetjmp.h0000644000175000017500000000074313546663605020436 0ustar benben/* * 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; } __attribute__ ((aligned(8))); typedef struct __jmp_buf jmp_buf[1]; #endif /* _KLIBC_ARCHSETJMP_H */ klibc-2.0.7/usr/include/arch/mips/klibc/archfcntl.h0000644000175000017500000000376413546663605020250 0ustar benben/* * 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_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_SYNC 0x4010 #define O_DIRECT 0x8000 #define O_DIRECTORY 0x10000 #define O_NOFOLLOW 0x20000 #define O_NOATIME 0x40000 #define O_CLOEXEC 0x80000 #define O_PATH 0x200000 #define O_TMPFILE 0x410000 #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 F_SETOWN_EX 15 #define F_GETOWN_EX 16 #define F_GETOWNER_UIDS 17 #define F_OFD_GETLK 36 #define F_OFD_SETLK 37 #define F_OFD_SETLKW 38 #define F_OWNER_TID 0 #define F_OWNER_PID 1 #define F_OWNER_PGRP 2 struct f_owner_ex { int type; pid_t pid; }; #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 */ klibc-2.0.7/usr/include/arch/mips/klibc/archconfig.h0000644000175000017500000000102113546663605020367 0ustar benben/* * 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 /* MIPS defines it's own statfs */ #define _KLIBC_STATFS_F_TYPE_32B 1 /* MIPS has nonstandard socket definitions */ #define _KLIBC_HAS_ARCHSOCKET_H 1 /* We can use RT signals on MIPS */ #define _KLIBC_USE_RT_SIG 1 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/m68k/0000755000175000017500000000000013546663605014652 5ustar benbenklibc-2.0.7/usr/include/arch/m68k/klibc/0000755000175000017500000000000013546663605015736 5ustar benbenklibc-2.0.7/usr/include/arch/m68k/klibc/archstat.h0000644000175000017500000000125013546663605017716 0ustar benben#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 klibc-2.0.7/usr/include/arch/m68k/klibc/archsignal.h0000644000175000017500000000035013546663605020220 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/m68k/klibc/archsetjmp.h0000644000175000017500000000075113546663605020252 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/m68k/klibc/archconfig.h0000644000175000017500000000053213546663605020212 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/ia64/0000755000175000017500000000000013546663605014630 5ustar benbenklibc-2.0.7/usr/include/arch/ia64/klibc/0000755000175000017500000000000013546663605015714 5ustar benbenklibc-2.0.7/usr/include/arch/ia64/klibc/archstat.h0000644000175000017500000000075013546663605017700 0ustar benben#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 klibc-2.0.7/usr/include/arch/ia64/klibc/archsignal.h0000644000175000017500000000110413546663605020174 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/ia64/klibc/archsetjmp.h0000644000175000017500000000054213546663605020226 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/ia64/klibc/archconfig.h0000644000175000017500000000063113546663605020170 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/i386/0000755000175000017500000000000013546663605014556 5ustar benbenklibc-2.0.7/usr/include/arch/i386/sys/0000755000175000017500000000000013546663605015374 5ustar benbenklibc-2.0.7/usr/include/arch/i386/sys/vm86.h0000644000175000017500000000273513546663605016354 0ustar benben/* ----------------------------------------------------------------------- * * * 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 klibc-2.0.7/usr/include/arch/i386/sys/io.h0000644000175000017500000000664313546663605016165 0ustar benben/* ----------------------------------------------------------------------- * * * 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 */ klibc-2.0.7/usr/include/arch/i386/klibc/0000755000175000017500000000000013546663605015642 5ustar benbenklibc-2.0.7/usr/include/arch/i386/klibc/diverr.h0000644000175000017500000000033513546663605017307 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/i386/klibc/archstat.h0000644000175000017500000000126313546663605017626 0ustar benben#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 klibc-2.0.7/usr/include/arch/i386/klibc/archsignal.h0000644000175000017500000000032313546663605020124 0ustar benben/* * * Architecture-specific signal definitions * */ #ifndef _KLIBC_ARCHSIGNAL_H #define _KLIBC_ARCHSIGNAL_H /* The in-kernel headers for i386 got clean up, use them. */ #include #endif klibc-2.0.7/usr/include/arch/i386/klibc/archsetjmp.h0000644000175000017500000000047613546663605020162 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/i386/klibc/archinit.h0000644000175000017500000000055013546663605017614 0ustar benben/* * arch/i386/include/klibc/archinit.h * * Architecture-specific libc initialization */ #include #include #include #include extern void (*__syscall_entry)(int, ...); static inline void __libc_archinit(void) { if (__auxval[AT_SYSINFO]) __syscall_entry = (void (*)(int, ...)) __auxval[AT_SYSINFO]; } klibc-2.0.7/usr/include/arch/i386/klibc/archconfig.h0000644000175000017500000000063213546663605020117 0ustar benben/* * 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 /* The i386 is still not clean enough for this... */ #define _KLIBC_USE_RT_SIG 0 /* We have klibc/archinit.h and __libc_archinit() */ #define _KLIBC_HAS_ARCHINIT 1 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/cris/0000755000175000017500000000000013546663605015025 5ustar benbenklibc-2.0.7/usr/include/arch/cris/klibc/0000755000175000017500000000000013546663605016111 5ustar benbenklibc-2.0.7/usr/include/arch/cris/klibc/archstat.h0000644000175000017500000000136013546663605020073 0ustar benben#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 klibc-2.0.7/usr/include/arch/cris/klibc/archsignal.h0000644000175000017500000000035013546663605020373 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/cris/klibc/archsetjmp.h0000644000175000017500000000066213546663605020426 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/cris/klibc/archconfig.h0000644000175000017500000000047613546663605020374 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/arm64/0000755000175000017500000000000013546663605015016 5ustar benbenklibc-2.0.7/usr/include/arch/arm64/klibc/0000755000175000017500000000000013546663605016102 5ustar benbenklibc-2.0.7/usr/include/arch/arm64/klibc/archstat.h0000644000175000017500000000155113546663605020066 0ustar benben#ifndef _KLIBC_ARCHSTAT_H #define _KLIBC_ARCHSTAT_H #include #define _STATBUF_ST_NSEC struct stat { __stdev64 (st_dev); /* Device */ unsigned 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 long __pad1; long st_size; /* Size of file, in bytes */ int st_blksize; /* Optimal block size for I/O */ int __pad2; 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 int __unused4; unsigned int __unused5; }; #endif klibc-2.0.7/usr/include/arch/arm64/klibc/archsignal.h0000644000175000017500000000035113546663605020365 0ustar benben/* * arch/arm64/include/klibc/archsignal.h * * Architecture-specific signal definitions * */ #ifndef _KLIBC_ARCHSIGNAL_H #define _KLIBC_ARCHSIGNAL_H #include /* No special stuff for this architecture */ #endif klibc-2.0.7/usr/include/arch/arm64/klibc/archsetjmp.h0000644000175000017500000000070613546663605020416 0ustar benben/* * arch/arm64/include/klibc/archsetjmp.h */ #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H /* * x19-x28 are callee saved, also save fp, lr, sp. * d8-d15 are unused as we specify -mgeneral-regs-only as a build flag. */ struct __jmp_buf { uint64_t __x19, __x20, __x21, __x22; uint64_t __x23, __x24, __x25, __x26; uint64_t __x27, __x28, __x29, __x30; uint64_t __sp; }; typedef struct __jmp_buf jmp_buf[1]; #endif /* _SETJMP_H */ klibc-2.0.7/usr/include/arch/arm64/klibc/archconfig.h0000644000175000017500000000051613546663605020360 0ustar benben/* * include/arch/arm64/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 /* Use rt_* signals */ #define _KLIBC_USE_RT_SIG 1 #define _KLIBC_NO_MMU 0 #define _KLIBC_REAL_VFORK 1 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/arm/0000755000175000017500000000000013546663605014644 5ustar benbenklibc-2.0.7/usr/include/arch/arm/klibc/0000755000175000017500000000000013546663605015730 5ustar benbenklibc-2.0.7/usr/include/arch/arm/klibc/asmmacros.h0000644000175000017500000000041613546663605020067 0ustar benben/* * usr/include/arch/arm/klibc/asmmacros.h * * Assembly macros used by ARM system call stubs */ #ifndef _KLIBC_ASMMACROS_H #define _KLIBC_ASMMACROS_H #if _KLIBC_ARM_USE_BX # define BX(x) bx x #else # define BX(x) mov pc, x #endif #endif /* _KLIBC_ASMMACROS_H */ klibc-2.0.7/usr/include/arch/arm/klibc/archstat.h0000644000175000017500000000150713546663605017715 0ustar benben#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 klibc-2.0.7/usr/include/arch/arm/klibc/archsignal.h0000644000175000017500000000536713546663605020227 0ustar benben/* * arch/arm/include/klibc/archsignal.h * * Architecture-specific signal definitions * */ #ifndef _KLIBC_ARCHSIGNAL_H #define _KLIBC_ARCHSIGNAL_H /* The in-kernel headers for arm 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 SIGLOST 29 */ #define SIGPWR 30 #define SIGSYS 31 #define SIGUNUSED 31 /* These should not be considered constants from userland. */ #define SIGRTMIN 32 #define SIGRTMAX _NSIG #define SIGSWI 32 /* * SA_FLAGS values: * * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. * SA_SIGINFO deliver the signal with SIGINFO structs * SA_THIRTYTWO delivers the signal in 32-bit mode, even if the task * is running in 26-bit. * SA_ONSTACK allows alternate signal stacks (see sigaltstack(2)). * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NODEFER prevents the current signal from being masked in the handler. * SA_RESETHAND clears the handler when the signal is delivered. * * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single * Unix names RESETHAND and NODEFER respectively. */ #define SA_NOCLDSTOP 0x00000001 #define SA_NOCLDWAIT 0x00000002 #define SA_SIGINFO 0x00000004 #define SA_THIRTYTWO 0x02000000 #define SA_RESTORER 0x04000000 #define SA_ONSTACK 0x08000000 #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND /* * 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 klibc-2.0.7/usr/include/arch/arm/klibc/archsetjmp.h0000644000175000017500000000033013546663605020235 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/arm/klibc/archconfig.h0000644000175000017500000000074013546663605020205 0ustar benben/* * 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 /* newer arm arch support bx instruction */ #if (!defined(__ARM_ARCH_2__) && !defined(__ARM_ARCH_3__) \ && !defined(__ARM_ARCH_3M__) && !defined(__ARM_ARCH_4__)) # define _KLIBC_ARM_USE_BX 1 #endif /* Use rt_* signals */ #define _KLIBC_USE_RT_SIG 1 #endif /* _KLIBC_ARCHCONFIG_H */ klibc-2.0.7/usr/include/arch/alpha/0000755000175000017500000000000013546663605015152 5ustar benbenklibc-2.0.7/usr/include/arch/alpha/machine/0000755000175000017500000000000013546663605016556 5ustar benbenklibc-2.0.7/usr/include/arch/alpha/machine/asm.h0000644000175000017500000000132313546663605017506 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/alpha/klibc/0000755000175000017500000000000013546663605016236 5ustar benbenklibc-2.0.7/usr/include/arch/alpha/klibc/archstat.h0000644000175000017500000000074213546663605020223 0ustar benben#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 klibc-2.0.7/usr/include/arch/alpha/klibc/archsignal.h0000644000175000017500000000035113546663605020521 0ustar benben/* * 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 klibc-2.0.7/usr/include/arch/alpha/klibc/archsetjmp.h0000644000175000017500000000122513546663605020547 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/arch/alpha/klibc/archconfig.h0000644000175000017500000000044513546663605020515 0ustar benben/* * 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 */ klibc-2.0.7/usr/include/alloca.h0000644000175000017500000000025613546663605014557 0ustar benben/* * alloca.h * * Just call the builtin alloca() function */ #ifndef _ALLOCA_H #define _ALLOCA_H #define alloca(size) __builtin_alloca(size) #endif /* _ALLOCA_H */ klibc-2.0.7/usr/include/Kbuild0000644000175000017500000000043713546663605014311 0ustar benbenalways := 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 klibc-2.0.7/usr/gzip/0000755000175000017500000000000013546663605012476 5ustar benbenklibc-2.0.7/usr/gzip/zip.c0000644000175000017500000000572713546663605013457 0ustar benben/* 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; } klibc-2.0.7/usr/gzip/util.c0000644000175000017500000002710513546663605013624 0ustar benben/* 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 }; klibc-2.0.7/usr/gzip/unzip.c0000644000175000017500000000410413546663605014006 0ustar benben/* 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; } klibc-2.0.7/usr/gzip/trees.c0000644000175000017500000011670613546663605013777 0ustar benben/* 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", ""); } } klibc-2.0.7/usr/gzip/tailor.h0000644000175000017500000000174613546663605014151 0ustar benben/* 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 klibc-2.0.7/usr/gzip/revision.h0000644000175000017500000000056013546663605014506 0ustar benben/* 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 $ */ klibc-2.0.7/usr/gzip/inflate.c0000644000175000017500000007546313546663605014303 0ustar benben/* 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; } klibc-2.0.7/usr/gzip/gzip.h0000644000175000017500000002354013546663605013624 0ustar benben/* 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 klibc-2.0.7/usr/gzip/gzip.c0000644000175000017500000011120113546663605013607 0ustar benben/* 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); } klibc-2.0.7/usr/gzip/deflate.c0000644000175000017500000007050213546663605014252 0ustar benben/* 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 */ } klibc-2.0.7/usr/gzip/bits.c0000644000175000017500000001323713546663605013611 0ustar benben/* 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++); } } klibc-2.0.7/usr/gzip/README0000644000175000017500000001620313546663605013360 0ustar benbenThis 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 klibc-2.0.7/usr/gzip/Kbuild0000644000175000017500000000076613546663605013644 0ustar benben# # 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_KLIBC_ZIP) += zip.o deflate.o trees.o bits.o cflags-$(CONFIG_KLIBC_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 klibc-2.0.7/usr/gzip/COPYING0000644000175000017500000004307613546663605013543 0ustar benben 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. klibc-2.0.7/usr/gzip/.gitignore0000644000175000017500000000002113546663605014457 0ustar benbengunzip gzip zcat klibc-2.0.7/usr/dash/0000755000175000017500000000000013546663605012444 5ustar benbenklibc-2.0.7/usr/dash/var.h0000644000175000017500000001236113546663605013410 0ustar benben/*- * 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 */ #include /* * 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 */ }; struct localvar_list; 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] #ifdef WITH_LINENO #define vlineno (&voptind)[1] #endif #ifndef SMALL #ifdef WITH_LINENO #define vterm (&vlineno)[1] #else #define vterm (&voptind)[1] #endif #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) extern int lineno; extern char linenovar[]; /* * 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) #define linenoval() (vlineno.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); struct var *setvar(const char *name, const char *val, int flags); intmax_t setvarint(const char *, intmax_t, int); struct var *setvareq(char *s, int flags); struct strlist; void listsetvar(struct strlist *, int); char *lookupvar(const char *); intmax_t lookupvarint(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 mklocal(char *); struct localvar_list *pushlocalvars(void); void poplocalvars(int); void unwindlocalvars(struct localvar_list *stop); int unsetcmd(int, char **); void unsetvar(const char *); int varcmp(const char *, const char *); static inline int varequal(const char *a, const char *b) { return !varcmp(a, b); } /* * Search the environment of a builtin command. */ static inline char *bltinlookup(const char *name) { return lookupvar(name); } klibc-2.0.7/usr/dash/var.c0000644000175000017500000003403113546663605013401 0ustar benben/*- * 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 #ifdef HAVE_PATHS_H #include #endif /* * Shell variables. */ #include "shell.h" #include "output.h" #include "expand.h" #include "nodes.h" /* for other headers */ #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_list { struct localvar_list *next; struct localvar *lv; }; MKINIT struct localvar_list *localvar_stack; 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 int lineno; char linenovar[sizeof("LINENO=")+sizeof(int)*CHAR_BIT/3+1] = "LINENO="; /* Some macros in var.h depend on the order, add new variables to the end. */ 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 }, #ifdef WITH_LINENO { 0, VSTRFIXED|VTEXTFIXED, linenovar, 0 }, #endif #ifndef SMALL { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM\0", 0 }, { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE\0", sethistsize }, #endif }; STATIC struct var *vartab[VTABSIZE]; 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++) { p = endofname(*envp); if (p != *envp && *p == '=') { 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); } RESET { unwindlocalvars(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=# "; } /* * 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. */ struct var *setvar(const char *name, const char *val, int flags) { char *p, *q; size_t namelen; char *nameeq; size_t vallen; struct var *vp; 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'; vp = setvareq(nameeq, flags | VNOSAVE); INTON; return vp; } /* * Set the given integer as the value of a variable. The flags argument is * ored with the flags of the variable. */ intmax_t setvarint(const char *name, intmax_t val, int flags) { int len = max_int_length(sizeof(val)); char buf[len]; fmtstr(buf, len, "%" PRIdMAX, val); setvar(name, buf, flags); return val; } /* * 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. */ struct var *setvareq(char *s, int flags) { struct var *vp, **vpp; vpp = hashvar(s); flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); vpp = findvar(vpp, s); vp = *vpp; 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) goto out; if (vp->func && (flags & VNOFUNC) == 0) (*vp->func)(strchrnul(s, '=') + 1); if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) ckfree(vp->text); if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) { *vpp = vp->next; ckfree(vp); out_free: if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE) ckfree(s); goto out; } flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET); } else { if (flags & VNOSET) goto out; if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET) goto out_free; /* 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; out: return vp; } /* * 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)) { #ifdef WITH_LINENO if (v == &vlineno && v->text == linenovar) { fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno); } #endif return strchrnul(v->text, '=') + 1; } return NULL; } intmax_t lookupvarint(const char *name) { return atomax(lookupvar(name) ?: nullstr, 0); } /* * 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; if (!localvar_stack) sh_error("not in a function"); 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. */ 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) vp = setvareq(name, VSTRFIXED); else vp = setvar(name, NULL, VSTRFIXED); 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 = localvar_stack->lv; localvar_stack->lv = lvp; INTON; } /* * Called after a function returns. * Interrupts must be off. */ void poplocalvars(int keep) { struct localvar_list *ll; struct localvar *lvp, *next; struct var *vp; INTOFF; ll = localvar_stack; localvar_stack = ll->next; next = ll->lv; ckfree(ll); while ((lvp = next) != NULL) { next = lvp->next; vp = lvp->vp; TRACE(("poplocalvar %s", vp ? vp->text : "-")); if (keep) { int bits = VSTRFIXED; if (lvp->flags != VUNSET) { if (vp->text == lvp->text) bits |= VTEXTFIXED; else if (!(lvp->flags & (VTEXTFIXED|VSTACK))) ckfree(lvp->text); } vp->flags &= ~bits; vp->flags |= (lvp->flags & bits); if ((vp->flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET) unsetvar(vp->text); } else if (vp == NULL) { /* $- saved */ memcpy(optlist, lvp->text, sizeof(optlist)); ckfree(lvp->text); optschanged(); } else if (lvp->flags == VUNSET) { vp->flags &= ~(VSTRFIXED|VREADONLY); 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); } INTON; } /* * Create a new localvar environment. */ struct localvar_list *pushlocalvars(void) { struct localvar_list *ll; INTOFF; ll = ckmalloc(sizeof(*ll)); ll->lv = NULL; ll->next = localvar_stack; localvar_stack = ll; INTON; return ll->next; } void unwindlocalvars(struct localvar_list *stop) { while (localvar_stack != stop) poplocalvars(0); } /* * 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; while ((i = nextopt("vf")) != '\0') { flag = i; } for (ap = argptr; *ap ; ap++) { if (flag != 'f') { unsetvar(*ap); continue; } if (flag != 'v') unsetfunc(*ap); } return 0; } /* * Unset the specified variable. */ void unsetvar(const char *s) { setvar(s, 0, 0); } /* * 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; } klibc-2.0.7/usr/dash/trap.h0000644000175000017500000000435013546663605013565 0ustar benben/*- * 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 int trapcnt; extern char sigmode[]; extern volatile sig_atomic_t pendingsigs; extern int gotsigchld; int trapcmd(int, char **); void clear_traps(void); void setsignal(int); void ignoresig(int); void onsig(int); void dotrap(void); void setinteractive(int); void exitshell(void) __attribute__((__noreturn__)); int decode_signal(const char *, int); const char *signal_name(int); static inline int have_traps(void) { return trapcnt; } klibc-2.0.7/usr/dash/trap.c0000644000175000017500000002141413546663605013560 0ustar benben/*- * 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 */ static char *trap[NSIG]; /* number of non-null traps */ int trapcnt; /* current value of signal */ char sigmode[NSIG - 1]; /* indicates specified signal received */ static char gotsig[NSIG - 1]; /* last pending signal */ volatile sig_atomic_t pendingsigs; /* received SIGCHLD */ int gotsigchld; #ifdef mkinit INCLUDE "trap.h" INIT { sigmode[SIGCHLD - 1] = S_DFL; setsignal(SIGCHLD); } #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) { outfmt(out2, "trap: %s: bad trap\n", *ap); return 1; } INTOFF; if (action) { if (action[0] == '-' && action[1] == '\0') action = NULL; else { if (*action) trapcnt++; action = savestr(action); } } if (trap[signo]) { if (*trap[signo]) trapcnt--; 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; INTOFF; for (tp = trap ; tp < &trap[NSIG] ; tp++) { if (*tp && **tp) { /* trap not NULL or SIG_IGN */ ckfree(*tp); *tp = NULL; if (tp != &trap[0]) setsignal(tp - trap); } } trapcnt = 0; 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 } } if (signo == SIGCHLD) action = S_CATCH; 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) { if (signo == SIGCHLD) { gotsigchld = 1; if (!trap[SIGCHLD]) return; } gotsig[signo - 1] = 1; pendingsigs = signo; if (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. */ void dotrap(void) { char *p; char *q; int i; int savestatus; 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; evalstring(p, 0); exitstatus = savestatus; if (evalskip) break; } } /* * 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; volatile 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) status = exitstatus; goto out; } handler = &loc; if ((p = trap[0])) { trap[0] = NULL; evalskip = 0; evalstring(p, 0); } out: /* * Disable job control so that whoever had the foreground before we * started can get it back. */ if (likely(!setjmp(loc.loc))) setjobctl(0); flushall(); _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; } } klibc-2.0.7/usr/dash/system.h0000644000175000017500000000533113546663605014143 0ustar benben/* * 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 #if !HAVE_DECL_ISBLANK int isblank(int c); #endif /* * A trick to suppress uninitialized variable warning without generating any * code */ #define uninitialized_var(x) x = x klibc-2.0.7/usr/dash/system.c0000644000175000017500000000770013546663605014140 0ustar benben/* * 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); } #if HAVE_DECL_ISBLANK int isblank(int c) { return _isblank(c); } #endif int isgraph(int c) { return _isgraph(c); } int ispunct(int c) { return _ispunct(c); } int isxdigit(int c) { return _isxdigit(c); } #endif #if !HAVE_DECL_ISBLANK int isblank(int c) { return c == ' ' || c == '\t'; } #endif klibc-2.0.7/usr/dash/show.h0000644000175000017500000000365613546663605013607 0ustar benben/*- * 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 klibc-2.0.7/usr/dash/show.c0000644000175000017500000001756613546663605013607 0ustar benben/*- * 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: 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 CTLBACKQ: 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) { #ifndef __KLIBC__ if (!freopen(s, "a", tracefile)) { #else if (!(!fclose(tracefile) && (tracefile = fopen(s, "a")))) { #endif /* __KLIBC__ */ 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 #ifndef __KLIBC__ setlinebuf(tracefile); #endif /* __KLIBC__ */ fputs("\nTracing started.\n", tracefile); } #endif /* DEBUG */ klibc-2.0.7/usr/dash/shell.h0000644000175000017500000000664113546663605013733 0ustar benben/*- * 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) /* * Hack to calculate maximum length. * (length * 8 - 1) * log10(2) + 1 + 1 + 12 * The second 1 is for the minus sign and the 12 is a safety margin. */ static inline int max_int_length(int bytes) { return (bytes * 8 - 1) * 0.30102999566398119521 + 14; } klibc-2.0.7/usr/dash/sh.10000644000175000017500000020113613546663605013143 0ustar benben.\" 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. klibc-2.0.7/usr/dash/redir.h0000644000175000017500000000440213546663605013722 0ustar benben/*- * 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 */ struct redirtab; union node; void redirect(union node *, int); void popredir(int); void clearredir(void); int savefd(int, int); int redirectsafe(union node *, int); void unwindredir(struct redirtab *stop); struct redirtab *pushredir(union node *redir); klibc-2.0.7/usr/dash/redir.c0000644000175000017500000002162513546663605013723 0ustar benben/*- * 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 REALLY_CLOSED -3 /* fd that was closed and still is */ #define EMPTY -2 /* marks an unused slot in redirtab */ #define CLOSED -1 /* fd opened for redir needs to be closed */ #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]; }; MKINIT struct redirtab *redirlist; 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 *); /* * 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 if (!redir) return; sv = NULL; INTOFF; if (likely(flags & REDIR_PUSH)) sv = redirlist; n = redir; do { newfd = openredirect(n); if (newfd < -1) continue; fd = n->nfile.fd; if (sv) { p = &sv->renamed[fd]; i = *p; if (likely(i == EMPTY)) { i = CLOSED; if (fd != newfd) { i = savefd(fd, fd); fd = -1; } } if (i == newfd) /* Can only happen if i == newfd == CLOSED */ i = REALLY_CLOSED; *p = i; } if (fd == newfd) continue; #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->renamed[2] >= 0) preverrout.fd = sv->renamed[2]; } STATIC int openredirect(union node *redir) { struct stat64 sb; 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, 0666)) < 0) goto ecreate; break; case NTO: /* Take care of noclobber mode. */ if (Cflag) { fname = redir->nfile.expfname; if (stat64(fname, &sb) < 0) { if ((f = open64(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) goto ecreate; } else if (!S_ISREG(sb.st_mode)) { if ((f = open64(fname, O_WRONLY, 0666)) < 0) goto ecreate; if (fstat64(f, &sb) < 0 && S_ISREG(sb.st_mode)) { close(f); errno = EEXIST; goto ecreate; } } else { errno = EEXIST; 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; case NTOFD: case NFROMFD: f = redir->ndup.dupfd; if (f == redir->nfile.fd) f = -2; break; default: #ifdef DEBUG abort(); #endif /* Fall through to eliminate warning. */ 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; int err = 0; #ifdef notyet memory[fd] = 0; #endif if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { /* if not ">&-" */ if (f >= 0) { #ifdef notyet if (memory[f]) memory[fd] = 1; else #endif if (dup2(f, fd) < 0) { err = errno; goto err; } return; } f = fd; } else if (dup2(f, fd) < 0) err = errno; close(f); if (err < 0) goto err; return; err: sh_error("%d: %s", f, strerror(err)); } /* * 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) { char *p; int pip[2]; size_t len = 0; if (pipe(pip) < 0) sh_error("Pipe call failed"); p = redir->nhere.doc->narg.text; if (redir->type == NXHERE) { expandarg(redir->nhere.doc, NULL, EXP_QUOTED); p = stackblock(); } len = strlen(p); if (len <= PIPESIZE) { xwrite(pip[1], p, 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); xwrite(pip[1], p, len); _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; INTOFF; rp = redirlist; for (i = 0 ; i < 10 ; i++) { switch (rp->renamed[i]) { case CLOSED: if (!drop) close(i); break; case EMPTY: case REALLY_CLOSED: break; default: if (!drop) dup2(rp->renamed[i], i); close(rp->renamed[i]); break; } } redirlist = rp->next; ckfree(rp); INTON; } /* * Undo all redirections. Called on error or interrupt. */ #ifdef mkinit INCLUDE "redir.h" RESET { /* * Discard all saved file descriptors. */ unwindredir(0); } #endif /* * Move a file descriptor to > 10. Invokes sh_error on error unless * the original file dscriptor is not open. */ int savefd(int from, int ofd) { int newfd; int err; newfd = fcntl(from, F_DUPFD, 10); err = newfd < 0 ? errno : 0; if (err != EBADF) { close(ofd); if (err) sh_error("%d: %s", from, strerror(err)); else fcntl(newfd, F_SETFD, FD_CLOEXEC); } return newfd; } 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; } void unwindredir(struct redirtab *stop) { while (redirlist != stop) popredir(0); } struct redirtab *pushredir(union node *redir) { struct redirtab *sv; struct redirtab *q; int i; q = redirlist; if (!redir) goto out; sv = ckmalloc(sizeof (struct redirtab)); sv->next = q; redirlist = sv; for (i = 0; i < 10; i++) sv->renamed[i] = EMPTY; out: return q; } klibc-2.0.7/usr/dash/parser.h0000644000175000017500000000677713546663605014132 0ustar benben/*- * 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 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 */ /* 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 #define CHKEOFMARK 0x8 /* * 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; 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); } klibc-2.0.7/usr/dash/parser.c0000644000175000017500000007667513546663605014131 0ustar benben/*- * 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. */ #if HAVE_ALLOCA_H #include #endif #include #include "shell.h" #include "parser.h" #include "nodes.h" #include "expand.h" /* defines rmescapes() */ #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" #include "system.h" #ifndef SMALL #include "myhistedit.h" #endif /* * Shell command parser. */ /* values returned by readtoken */ #include "token.h" /* Used by expandstr to get here-doc like behaviour. */ #define FAKEEOFMARK (char *)1 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 */ 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 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 == '='; } static inline int realeofmark(const char *eofmark) { return eofmark && eofmark != FAKEEOFMARK; } /* * 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; int savelinno; redir = NULL; rpp2 = &redir; savelinno = plinno; 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.linno = savelinno; n1->nfor.var = wordtext; checkkwd = CHKNL | 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 != 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; n1->ncase.linno = savelinno; 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; checkkwd = CHKNL | CHKKWD | CHKALIAS; if (readtoken() != 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.linno = savelinno; 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.linno = savelinno; 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; int savelinno; args = NULL; app = &args; vars = NULL; vpp = &vars; redir = NULL; rpp = &redir; savecheckkwd = CHKALIAS; savelinno = plinno; 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->ndefun.text = n->narg.text; n->ndefun.linno = plinno; n->ndefun.body = 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.linno = savelinno; 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 (n->type == NHERE) checkkwd = CHKEOFMARK; if (readtoken() != TWORD) synexpect(-1); if (n->type == NHERE) { struct heredoc *here = heredoc; struct heredoc *p; if (quoteflag == 0) n->type = NXHERE; TRACE(("Here document %d\n", n->type)); 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; int kwd = checkkwd; #ifdef DEBUG int alreadyseen = tokpushback; #endif top: t = xxreadtoken(); /* * eat newlines */ if (kwd & CHKNL) { while (t == TNL) { parseheredoc(); t = xxreadtoken(); } } if (t != TWORD || quoteflag) { goto out; } /* * check for keywords */ if (kwd & 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. * * [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); } 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') { 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; size_t len; 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; /* syntax before arithmetic */ char const *uninitialized_var(prevsyntax); 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; /* backslash */ case CBACK: c = pgetc2(); if (c == PEOF) { USTPUTC(CTLESC, out); USTPUTC('\\', out); pungetc(); } else if (c == '\n') { plinno++; if (doprompt) setprompt(2); } else { if ( dblquote && c != '\\' && c != '`' && c != '$' && ( c != '"' || eofmark != NULL ) ) { USTPUTC('\\', out); } 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 && !varnest) 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() == ')') { USTPUTC(CTLENDARI, out); if (!--arinest) syntax = prevsyntax; } 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) { /* { */ 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 (realeofmark(eofmark)) { int markloc; char *p; if (c == PEOA) { c = pgetc2(); } if (striptabs) { while (c == '\t') { c = pgetc2(); } } markloc = out - (char *)stackblock(); for (p = eofmark; STPUTC(c, out), *p; p++) { if (c != *p) goto more_heredoc; c = pgetc2(); } if (c == '\n' || c == PEOF) { c = PEOF; plinno++; needprompt = doprompt; } else { int len; more_heredoc: p = (char *)stackblock() + markloc + 1; len = out - p; if (len) { len -= c < 0; c = p[-1]; if (len) { char *str; str = alloca(len + 1); *(char *)mempcpy(str, p, len) = 0; pushstring(str, NULL); } } } STADJUST((char *)stackblock() + markloc - out, out); } 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; char *p; static const char types[] = "}-+?="; c = pgetc(); if ( (checkkwd & CHKEOFMARK) || 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(); STADJUST(1, out); subtype = VSNORMAL; if (likely(c == '{')) { c = pgetc(); subtype = 0; } varname: if (is_name(c)) { do { STPUTC(c, out); c = pgetc(); } while (is_in_name(c)); } else if (is_digit(c)) { do { STPUTC(c, out); c = pgetc(); } while (is_digit(c)); } else if (is_special(c)) { int cc = c; c = pgetc(); if (!subtype && cc == '#') { subtype = VSLENGTH; if (c == '_' || isalnum(c)) goto varname; cc = c; c = pgetc(); if (cc == '}' || c != '}') { pungetc(); subtype = 0; c = cc; cc = '#'; } } USTPUTC(cc, out); } else goto badsub; if (subtype == 0) { switch (c) { case ':': subtype = VSNUL; c = pgetc(); /*FALLTHROUGH*/ default: p = strchr(types, c); if (p == NULL) break; subtype |= p - types + VSNORMAL; break; case '%': case '#': { int cc = c; subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT; c = pgetc(); if (c == cc) subtype++; else pungetc(); break; } } } else { badsub: pungetc(); } *((char *)stackblock() + typeloc) = subtype; if (subtype != VSNORMAL) { varnest++; if (dblquote) dqvarnest++; } STPUTC('=', out); } 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 uninitialized_var(saveprompt); 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: 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); } 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); goto parsearith_return; } } /* end of readtoken */ #ifdef mkinit INCLUDE "parser.h" RESET { tokpushback = 0; checkkwd = 0; } #endif /* * 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) { errlinno = plinno; 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) { pushstackmark(&smark, stackblocksize()); out2str(getprompt(NULL)); popstackmark(&smark); } } const char * expandstr(const char *ps) { union node n; int saveprompt; /* XXX Fix (char *) cast. */ setinputstring((char *)ps); saveprompt = doprompt; doprompt = 0; readtoken1(pgetc(), DQSYNTAX, FAKEEOFMARK, 0); doprompt = saveprompt; popfile(); n.narg.type = NARG; n.narg.next = NULL; n.narg.text = wordtext; n.narg.backquote = backquotelist; expandarg(&n, NULL, EXP_QUOTED); 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 *) ); } klibc-2.0.7/usr/dash/output.h0000644000175000017500000000706313546663605014163 0ustar benben/*- * 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 static inline void outc(int ch, struct output *file) { putc(ch, file->stream); } #define doformat(d, f, a) vfprintf((d)->stream, (f), (a)) #else static inline void outc(int ch, struct output *file) { if (file->nextc == file->end) outcslow(ch, file); else { *file->nextc = ch; 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 klibc-2.0.7/usr/dash/output.c0000644000175000017500000001715413546663605014160 0ustar benben/*- * 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; #ifdef __sun /* * vsnprintf() on older versions of Solaris returns -1 when * passed a length of 0. To avoid this, use a dummy * 1-character buffer instead. */ char dummy[1]; if (length == 0) { outbuf = dummy; length = sizeof(dummy); } #endif INTOFF; ret = vsnprintf(outbuf, length, fmt, ap); INTON; return ret; } klibc-2.0.7/usr/dash/options.h0000644000175000017500000000613313546663605014313 0ustar benben/*- * 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 */ int 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 *); klibc-2.0.7/usr/dash/options.c0000644000175000017500000002600213546663605014303 0ustar benben/*- * 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 "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 int options(int); STATIC void minus_o(char *, int); STATIC void setoption(int, int); STATIC int getopts(char *, char *, char **); /* * Process the shell command line arguments. */ int procargs(int argc, char **argv) { int i; const char *xminusc; char **xargv; int login; xargv = argv; login = xargv[0] && xargv[0][0] == '-'; arg0 = xargv[0]; if (argc > 0) xargv++; for (i = 0; i < NOPTS; i++) optlist[i] = 2; argptr = xargv; login |= 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(); return login; } 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 int options(int cmdline) { char *p; int val; int c; int login = 0; 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 == 'l' && cmdline) { login = 1; } else if (c == 'o') { minus_o(*argptr, val); if (*argptr) argptr++; } else { setoption(c, val); } } } return login; } STATIC void minus_o(char *name, int val) { int i; if (name == NULL) { if (val) { 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++) out1fmt("set %s %s\n", optlist[i] ? "-o" : "+o", optnames[i]); } } 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) ?: 1; 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 ((unsigned)shellparam.optind > shellparam.nparam + 1) { shellparam.optind = 1; shellparam.optoff = -1; } } else { optbase = &argv[3]; if ((unsigned)shellparam.optind > argc - 2) { shellparam.optind = 1; shellparam.optoff = -1; } } return getopts(argv[1], argv[2], optbase); } STATIC int getopts(char *optstr, char *optvar, char **optfirst) { char *p, *q; char c = '?'; int done = 0; char s[2]; char **optnext; int ind = shellparam.optind; int off = shellparam.optoff; shellparam.optind = -1; optnext = optfirst + ind - 1; if (ind <= 1 || off < 0 || strlen(optnext[-1]) < off) p = NULL; else p = optnext[-1] + off; 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'; setvar("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'; setvar("OPTARG", s, 0); c = ':'; } else { outfmt(&errout, "No arg for -%c option\n", c); (void) unsetvar("OPTARG"); c = '?'; } goto out; } if (p == *optnext) optnext++; setvar("OPTARG", p, 0); p = NULL; } else setvar("OPTARG", nullstr, 0); out: ind = optnext - optfirst + 1; setvarint("OPTIND", ind, VNOFUNC); s[0] = c; s[1] = '\0'; setvar(optvar, s, 0); shellparam.optoff = p ? p - *(optnext - 1) : -1; shellparam.optind = ind; 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; } klibc-2.0.7/usr/dash/nodetypes0000644000175000017500000001221413546663605014401 0ustar benben# 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 linno 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 linno 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 linno int args nodeptr # for var in args body nodeptr # do body; done var string # the for variable NCASE ncase # a case statement type int linno 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 ndefun # a function type int linno int text string body nodeptr 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. * * @(#)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); } klibc-2.0.7/usr/dash/mystring.h0000644000175000017500000000505113546663605014472 0ustar benben/*- * 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 #include extern const char snlfmt[]; extern const char spcstr[]; extern const char dolatstr[]; #define DOLATSTRLEN 6 extern const char qchars[]; extern const char illnum[]; extern const char homestr[]; #if 0 void scopyn(const char *, char *, int); #endif char *prefix(const char *, const char *); void badnum(const char *s) __attribute__ ((noreturn)); intmax_t atomax(const char *, int); intmax_t atomax10(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)) klibc-2.0.7/usr/dash/mystring.c0000644000175000017500000001237013546663605014467 0ustar benben/*- * 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 #include #include #include #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[] = { CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0' }; const char qchars[] = { CTLESC, CTLQUOTEMARK, 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; } void badnum(const char *s) { sh_error(illnum, s); } /* * Convert a string into an integer of type intmax_t. Alow trailing spaces. */ intmax_t atomax(const char *s, int base) { char *p; intmax_t r; errno = 0; r = strtoimax(s, &p, base); if (errno != 0) badnum(s); /* * Disallow completely blank strings in non-arithmetic (base != 0) * contexts. */ if (p == s && base) badnum(s); while (isspace((unsigned char)*p)) p++; if (*p) badnum(s); return r; } intmax_t atomax10(const char *s) { return atomax(s, 10); } /* * Convert a string of digits to an integer, printing an error message on * failure. */ int number(const char *s) { intmax_t n = atomax10(s); if (n < 0 || n > INT_MAX) badnum(s); return n; } /* * 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); } klibc-2.0.7/usr/dash/myhistedit.h0000644000175000017500000000370713546663605015007 0ustar benben/*- * 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); klibc-2.0.7/usr/dash/mktokens0000644000175000017500000000563713546663605014235 0ustar benben#!/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$$ klibc-2.0.7/usr/dash/mksyntax.c0000644000175000017500000002010213546663605014461 0ustar benben/*- * 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 < 258; 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[] = {\n", name); col = 0; for (i = 0 ; i < 258; 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); } klibc-2.0.7/usr/dash/mknodes.c0000644000175000017500000002520713546663605014256 0ustar benben/*- * 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; } klibc-2.0.7/usr/dash/mkinit.c0000644000175000017500000002426013546663605014107 0ustar benben/*- * 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) { if ((fwrite(bp->text, sizeof (char), BLOCKSIZE, fp)) != BLOCKSIZE) error("Can't write data\n"); } if ((fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp)) != (BLOCKSIZE - text->nleft)) error("Can't write data\n"); } } 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 */ } klibc-2.0.7/usr/dash/mkbuiltins0000644000175000017500000000700113546663605014546 0ustar benben#!/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 && ! type mktemp > /dev/null 2>&1; then _my_tempfile() { local index=0 while test -f "${TMPDIR:-/tmp}/builtin.$$.$index"; do index=`expr $index + 1` done touch "${TMPDIR:-/tmp}/builtin.$$.$index" echo "${TMPDIR:-/tmp}/builtin.$$.$index" } tempfile="_my_tempfile" elif ! 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 | LC_ALL=C sort -k 1,1 | tee $temp2 | awk '{ opt = "" if (NF > 2) { opt = substr($2, 2) $2 = $3 } printf "\t{ \"%s\", %s, %d },\n", $1, (opt ~ /n/) ? "NULL" : $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 -b a -v 0 | LC_COLLATE=C 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[];' klibc-2.0.7/usr/dash/miscbltin.h0000644000175000017500000000316113546663605014602 0ustar benben/* * 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 **); klibc-2.0.7/usr/dash/miscbltin.c0000644000175000017500000002753313546663605014606 0ustar benben/*- * 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 /* strtotimeval() */ #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" #include "expand.h" #include "parser.h" #include "trap.h" #undef rflag /** handle one line of the read command. * more fields than variables -> remainder shall be part of last variable. * less fields than variables -> remaining variables unset. * * @param line complete line of input * @param ap argument (variable) list * @param len length of line including trailing '\0' */ static void readcmd_handle_line(char *s, char **ap) { struct arglist arglist; struct strlist *sl; char *backup; char *line; /* ifsbreakup will fiddle with stack region... */ line = stackblock(); s = grabstackstr(s); /* need a copy, so that delimiters aren't lost * in case there are more fields than variables */ backup = sstrdup(line); arglist.lastp = &arglist.list; ifsbreakup(s, &arglist); *arglist.lastp = NULL; ifsfree(); sl = arglist.list; do { if (!sl) { /* nullify remaining arguments */ do { setvar(*ap, nullstr, 0); } while (*++ap); return; } /* remaining fields present, but no variables left. */ if (!ap[1] && sl->next) { size_t offset; char *remainder; /* FIXME little bit hacky, assuming that ifsbreakup * will not modify the length of the string */ offset = sl->text - s; remainder = backup + offset; rmescapes(remainder); setvar(*ap, remainder, 0); return; } /* set variable to field */ rmescapes(sl->text); setvar(*ap, sl->text, 0); sl = sl->next; } while (*++ap); } /* * The read builtin. The -e option causes backslashes to escape the * following character. The -p option followed by an argument prompts * with the argument. * * This uses unbuffered input, which may be avoidable in some cases. */ int readcmd(int argc, char **argv) { char **ap; char c; int rflag; char *prompt; char *p; int startloc; int newloc; int status; int timeout; int i; fd_set set; struct timeval ts, t0, t1, to; ts.tv_sec = ts.tv_usec = 0; rflag = 0; timeout = 0; prompt = NULL; while ((i = nextopt("p:rt:")) != '\0') { switch(i) { case 'p': prompt = optionarg; break; case 't': p = strtotimeval(optionarg, &ts); if (*p || (!ts.tv_sec && !ts.tv_usec)) sh_error("invalid timeout"); timeout = 1; break; case 'r': rflag = 1; break; default: break; } } if (prompt && isatty(0)) { out2str(prompt); #ifdef FLUSHERR flushall(); #endif } if (*(ap = argptr) == NULL) sh_error("arg count"); status = 0; if (timeout) { gettimeofday(&t0, NULL); /* ts += t0; */ ts.tv_usec += t0.tv_usec; while (ts.tv_usec >= 1000000) { ts.tv_sec++; ts.tv_usec -= 1000000; } ts.tv_sec += t0.tv_sec; } STARTSTACKSTR(p); goto start; for (;;) { if (timeout) { gettimeofday(&t1, NULL); if (t1.tv_sec > ts.tv_sec || (t1.tv_sec == ts.tv_sec && t1.tv_usec >= ts.tv_usec)) { status = 1; break; /* Timeout! */ } /* to = ts - t1; */ if (ts.tv_usec >= t1.tv_usec) { to.tv_usec = ts.tv_usec - t1.tv_usec; to.tv_sec = ts.tv_sec - t1.tv_sec; } else { to.tv_usec = ts.tv_usec - t1.tv_usec + 1000000; to.tv_sec = ts.tv_sec - t1.tv_sec - 1; } FD_ZERO(&set); FD_SET(0, &set); if (select(1, &set, NULL, NULL, &to) != 1) { status = 1; break; /* Timeout! */ } } switch (read(0, &c, 1)) { case 1: break; default: if (errno == EINTR && !pendingsigs) continue; /* fall through */ case 0: status = 1; goto out; } if (c == '\0') continue; if (newloc >= startloc) { if (c == '\n') goto resetbs; goto put; } if (!rflag && c == '\\') { newloc = p - (char *)stackblock(); continue; } if (c == '\n') break; put: CHECKSTRSPACE(2, p); if (strchr(qchars, c)) USTPUTC(CTLESC, p); USTPUTC(c, p); if (newloc >= startloc) { resetbs: recordregion(startloc, newloc, 0); start: startloc = p - (char *)stackblock(); newloc = startloc - 1; } } out: recordregion(startloc, p - (char *)stackblock(), 0); STACKSTRNUL(p); readcmd_handle_line(p + 1, ap); 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((unsigned char) *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 #ifdef RLIMIT_RTPRIO { "rtprio", RLIMIT_RTPRIO, 1, 'r' }, #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("%" PRIdMAX "\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 klibc-2.0.7/usr/dash/memalloc.h0000644000175000017500000000644613546663605014420 0ustar benben/*- * 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; }; extern char *stacknxt; extern size_t stacknleft; extern char *sstrend; pointer ckmalloc(size_t); pointer ckrealloc(pointer, size_t); char *savestr(const char *); pointer stalloc(size_t); void stunalloc(pointer); void pushstackmark(struct stackmark *mark, size_t len); void setstackmark(struct stackmark *); void popstackmark(struct stackmark *); void growstackblock(void); void *growstackstr(void); char *makestrspace(size_t, char *); char *stnputs(const char *, size_t, char *); char *stputs(const char *, char *); static inline void grabstackblock(size_t len) { stalloc(len); } static inline char *_STPUTC(int 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)) klibc-2.0.7/usr/dash/memalloc.c0000644000175000017500000001624313546663605014407 0ustar benben/*- * 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; char *stacknxt = stackbase.space; size_t stacknleft = MINSIZE; char *sstrend = stackbase.space + MINSIZE; 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 pushstackmark(struct stackmark *mark, size_t len) { mark->stackp = stackp; mark->stacknxt = stacknxt; mark->stacknleft = stacknleft; grabstackblock(len); } void setstackmark(struct stackmark *mark) { pushstackmark(mark, stacknxt == stackp->space && stackp != &stackbase); } void popstackmark(struct stackmark *mark) { struct stack_block *sp; INTOFF; 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 *sp; struct stack_block *prevstackp; size_t grosslen; INTOFF; 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; 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; } } /* * 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(); growstackblock(); return stackblock() + len; } /* * Called from CHECKSTRSPACE. */ char * makestrspace(size_t newlen, char *p) { size_t len = p - stacknxt; size_t size; 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); } klibc-2.0.7/usr/dash/main.h0000644000175000017500000000421213546663605013540 0ustar benben/*- * 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 **); klibc-2.0.7/usr/dash/main.c0000644000175000017500000001563313546663605013544 0ustar benben/*- * 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; int login; #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; 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); login = procargs(argc, argv); if (login) { state = 1; read_profile("/etc/profile"); state1: state = 2; read_profile("$HOME/.profile"); } state2: state = 3; if ( #ifndef linux getuid() == geteuid() && getgid() == getegid() && #endif iflag ) { if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { read_profile(shinit); } } popstackmark(&smark); 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 status = 0; 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); status = exitstatus; } popstackmark(&smark); skip = evalskip; if (skip) { evalskip &= ~SKIPFUNC; break; } } return status; } /* * Read /etc/profile or .profile. Return on error. */ STATIC void read_profile(const char *name) { name = expandstr(name); if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0) return; cmdloop(0); popfile(); } /* * 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; status = cmdloop(0); popfile(); } return status; } int exitcmd(int argc, char **argv) { if (stoppedjobs()) return 0; if (argc > 1) exitstatus = number(argv[1]); exraise(EXEXIT); /* NOTREACHED */ } klibc-2.0.7/usr/dash/mail.h0000644000175000017500000000351513546663605013543 0ustar benben/*- * 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 *); klibc-2.0.7/usr/dash/mail.c0000644000175000017500000000615613546663605013542 0ustar benben/*- * 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++; } klibc-2.0.7/usr/dash/machdep.h0000644000175000017500000000450113546663605014216 0ustar benben/*- * 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) klibc-2.0.7/usr/dash/jobs.h0000644000175000017500000000754413546663605013564 0ustar benben/*- * 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) ((void)(on)) /* do nothing */ #endif klibc-2.0.7/usr/dash/jobs.c0000644000175000017500000007066213546663605013560 0ustar benben/*- * 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 #ifdef HAVE_PATHS_H #include #endif #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 #define DOWAIT_WAITCMD 2 /* 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)) if (--fd < 0) goto out; } fd = savefd(fd, ofd); 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 argc, char **argv) #ifdef HAVE_ALIAS_ATTRIBUTE __attribute__((__alias__("fgcmd"))); #else { return fgcmd(argc, argv); } #endif 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)); #ifdef WCOREDUMP if (WCOREDUMP(status)) { col += fmtstr(s + col, 16, " (core dumped)"); } #endif } 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; 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; } if (dowait(DOWAIT_WAITCMD, 0) <= 0) goto sigout; } } 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) if (dowait(DOWAIT_WAITCMD, 0) <= 0) goto sigout; job->waited = 1; retval = getstatus(job); repeat: ; } while (*++argv); out: return retval; sigout: retval = 128 + pendingsigs; goto out; } /* * 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 = NULL; int state; INTOFF; TRACE(("dowait(%d) called\n", block)); pid = waitproc(block, &status); TRACE(("wait returns pid %d, status=%d\n", pid, status)); if (pid <= 0) goto out; 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) { sigset_t mask, oldmask; int flags = block == DOWAIT_BLOCK ? 0 : WNOHANG; int err; #if JOBS if (jobctl) flags |= WUNTRACED; #endif do { gotsigchld = 0; err = wait3(status, flags, NULL); if (err || !block) break; block = 0; sigfillset(&mask); sigprocmask(SIG_SETMASK, &mask, &oldmask); while (!gotsigchld && !pendingsigs) sigsuspend(&oldmask); sigclearmask(); } while (gotsigchld); return err; } /* * 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", name, cmdnextc)); 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 "); if (n->nif.elsepart) { cmdtxt(n->nif.ifpart); cmdputs("; else "); n = n->nif.elsepart; } else { n = n->nif.ifpart; } 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->ndefun.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 = "${"; goto dostr; case CTLENDVAR: str = "\"}" + !(quoted & 1); quoted >>= 1; subtype = 0; goto dostr; case CTLBACKQ: 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; } klibc-2.0.7/usr/dash/input.h0000644000175000017500000000510413546663605013754 0ustar benben/*- * 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 */ 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 setinputstring(char *); void popfile(void); void popallfiles(void); void closescript(void); #define pgetc_macro() \ (--parsenleft >= 0 ? (signed char)*parsenextc++ : preadbuffer()) klibc-2.0.7/usr/dash/input.c0000644000175000017500000002505213546663605013753 0ustar benben/*- * 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 "eval.h" #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); static void setinputfd(int fd, int push); #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 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; INTOFF; if ((fd = open(fname, O_RDONLY)) < 0) { if (flags & INPUT_NOFILE_OK) goto out; exitstatus = 127; exerror(EXERROR, "Can't open %s", fname); } if (fd < 10) fd = savefd(fd, fd); setinputfd(fd, flags & INPUT_PUSH_FILE); out: INTON; return fd; } /* * Like setinputfile, but takes an open file descriptor. Call this with * interrupts off. */ static void setinputfd(int fd, int push) { 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; } } klibc-2.0.7/usr/dash/init.h0000644000175000017500000000352713546663605013567 0ustar benben/*- * 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); klibc-2.0.7/usr/dash/histedit.c0000644000175000017500000002502213546663605014426 0ustar benben/*- * 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 #ifdef HAVE_PATHS_H #include #endif #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 klibc-2.0.7/usr/dash/hetio.h0000644000175000017500000000121213546663605013721 0ustar benben/* * 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; klibc-2.0.7/usr/dash/hetio.c0000644000175000017500000002075513546663605013731 0ustar benben/* * 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; } klibc-2.0.7/usr/dash/gendeps.pl0000755000175000017500000000160313546663605014431 0ustar benben#!/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); klibc-2.0.7/usr/dash/funcs/0000755000175000017500000000000013546663605013562 5ustar benbenklibc-2.0.7/usr/dash/funcs/suspend0000644000175000017500000000343713546663605015175 0ustar benben# 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 } klibc-2.0.7/usr/dash/funcs/pushd0000644000175000017500000000451713546663605014637 0ustar benben# 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 } klibc-2.0.7/usr/dash/funcs/popd0000644000175000017500000000451613546663605014455 0ustar benben# 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 } klibc-2.0.7/usr/dash/funcs/newgrp0000644000175000017500000000341313546663605015010 0ustar benben# 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 "$@" klibc-2.0.7/usr/dash/funcs/login0000644000175000017500000000346713546663605014627 0ustar benben# 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 "$@" klibc-2.0.7/usr/dash/funcs/kill0000644000175000017500000000366113546663605014446 0ustar benben# 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 } klibc-2.0.7/usr/dash/funcs/dirs0000644000175000017500000000451613546663605014454 0ustar benben# 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 } klibc-2.0.7/usr/dash/funcs/cmv0000644000175000017500000000367613546663605014306 0ustar benben# 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" } klibc-2.0.7/usr/dash/expand.h0000644000175000017500000000611013546663605014072 0ustar benben/*- * 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 #include 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_QPAT 0x20 /* pattern in quoted parameter expansion */ #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */ #define EXP_WORD 0x80 /* expand word in parameter expansion */ #define EXP_QUOTED 0x100 /* expand word in double quotes */ union node; 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 *); void recordregion(int, int, int); void removerecordregions(int); void ifsbreakup(char *, struct arglist *); void ifsfree(void); /* From arith.y */ intmax_t 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 */ klibc-2.0.7/usr/dash/expand.c0000644000175000017500000010000213546663605014060 0ustar benben/*- * 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 #include #include #ifdef HAVE_GLOB #include #endif #include /* * 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_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 | EXP_QPAT) /* 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); 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 expandmeta(struct strlist *, int); #ifdef HAVE_GLOB STATIC void addglob(const glob_t *); #else STATIC void expmeta(char *, char *); STATIC struct strlist *expsort(struct strlist *); STATIC struct strlist *msort(struct strlist *, int); #endif STATIC void addfname(char *); STATIC int patmatch(char *, const char *); #ifndef HAVE_FNMATCH STATIC int pmatch(const char *, const char *); #else #define pmatch(a, b) !fnmatch((a), (b), 0) #endif STATIC int cvtnum(intmax_t); 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 flag) { flag |= RMESCAPE_GLOB; 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 } /* * 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); argstr(arg->narg.text, flag); p = _STPUTC('\0', expdest); expdest = p - 1; if (arglist == NULL) { /* here document expanded */ goto out; } 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 { sp = (struct strlist *)stalloc(sizeof (struct strlist)); sp->text = p; *exparg.lastp = sp; exparg.lastp = &sp->next; } *exparg.lastp = NULL; if (exparg.list) { *arglist->lastp = exparg.list; arglist->lastp = exparg.lastp; } out: ifsfree(); } /* * 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, CTLENDARI, 0 }; const char *reject = spclchars; int c; int breakall = (flag & (EXP_WORD | EXP_QUOTED)) == 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 == '~') 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: inquotes ^= EXP_QUOTED; /* "$@" syntax adherence hack */ if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) { p = evalvar(p + 1, flag | inquotes) + 1; goto start; } addquote: if (flag & QUOTES_ESC) { p--; length++; startloc++; } break; case CTLESC: startloc++; length++; /* * Quoted parameter expansion pattern: remove quote * unless inside inner quotes or we have a literal * backslash. */ if (((flag | inquotes) & (EXP_QPAT | EXP_QUOTED)) == EXP_QPAT && *p != '\\') break; goto addquote; case CTLVAR: p = evalvar(p, flag | inquotes); goto start; case CTLBACKQ: expbackq(argbackq->n, flag | inquotes); argbackq = argbackq->next; goto start; case CTLENDARI: p--; expari(flag | inquotes); 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; 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; strtodest(home, SQSYNTAX, quotes); return (p); lose: *p = c; return (startp); } 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 flag) { struct stackmark sm; char *p, *start; int begoff; int len; intmax_t result; /* ifsfree(); */ /* * This routine is slightly over-complicated for * efficiency. Next we scan backwards looking for the * start of arithmetic. */ start = stackblock(); p = expdest; pushstackmark(&sm, p - start); *--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); expdest = p; if (likely(flag & QUOTES_ESC)) rmescapes(p + 1); result = arith(p + 1); popstackmark(&sm); len = cvtnum(result); if (likely(!(flag & EXP_QUOTED))) recordregion(begoff, begoff + len, 0); } /* * Expand stuff in backwards quotes. */ STATIC void expbackq(union node *cmd, int flag) { struct backcmd in; int i; char buf[128]; char *p; char *dest; int startloc; char const *syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX; struct stackmark smark; INTOFF; startloc = expdest - (char *)stackblock(); pushstackmark(&smark, startloc); evalbackcmd(cmd, (struct backcmd *) &in); popstackmark(&smark); p = in.buf; i = in.nleft; if (i == 0) goto read; for (;;) { memtodest(p, i, syntax, flag & QUOTES_ESC); 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 (!(flag & EXP_QUOTED)) 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 flag) { int quotes = flag & QUOTES_ESC; char *startp; char *loc; struct nodelist *saveargbackq = argbackq; int amount; char *rmesc, *rmescend; int zero; char *(*scan)(char *, char *, char *, char *, int , int); argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? (flag & EXP_QUOTED ? EXP_QPAT : EXP_CASE) : 0)); STPUTC('\0', expdest); 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, 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 quoted; varflags = *p++; subtype = varflags & VSTYPE; if (!subtype) sh_error("Bad substitution"); quoted = flag & EXP_QUOTED; 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 | 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, flag & ~QUOTES_ESC)) { 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, flag) == 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) { 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) || (((quotes & EXP_FULL) || syntax != BASESYNTAX) && 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 = flags & EXP_QUOTED; 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. */ 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. */ 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; } void ifsfree(void) { struct ifsregion *p = ifsfirst.next; if (!p) goto out; INTOFF; do { struct ifsregion *ifsp; ifsp = p->next; ckfree(p); p = ifsp; } while (p); ifsfirst.next = NULL; INTON; out: ifslastp = NULL; } /* * Expand shell metacharacters. At this point, the only control characters * should be escapes. The results are stored in the list exparg. */ #ifdef HAVE_GLOB 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, 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 /* HAVE_GLOB */ 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, 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; int esc; metaflag = 0; start = name; for (p = name; esc = 0, *p; p += esc + 1) { 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 == '\\') esc++; if (p[esc] == '/') { if (metaflag) break; start = p + esc + 1; } } } 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'; endname += esc + 1; } 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[-esc - 1] = esc ? '\\' : '/'; } #endif /* HAVE_GLOB */ /* * 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; } #ifndef HAVE_GLOB /* * 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), string); } #ifndef HAVE_FNMATCH 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; 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) { int strloc = str - (char *)stackblock(); r = makestrspace(fulllen, expdest); str = (char *)stackblock() + strloc; p = str + len; } else if (flag & RMESCAPE_HEAP) { r = ckmalloc(fulllen); } else { r = stalloc(fulllen); } q = r; if (len > 0) { q = mempcpy(q, str, len); } } inquotes = 0; globbing = flag & RMESCAPE_GLOB; notescaped = globbing; while (*p) { if (*p == (char)CTLQUOTEMARK) { inquotes = ~inquotes; p++; notescaped = globbing; continue; } if (*p == (char)CTLESC) { p++; if (notescaped) *q++ = '\\'; } else if (*p == '\\' && !inquotes) { /* naked back slash */ notescaped = 0; goto copy; } 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); argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); STACKSTRNUL(expdest); ifsfree(); result = patmatch(stackblock(), val); popstackmark(&smark); return result; } /* * Our own itoa(). */ STATIC int cvtnum(intmax_t num) { int len = max_int_length(sizeof(num)); expdest = makestrspace(len, expdest); len = fmtstr(expdest, len, "%" PRIdMAX, 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); } #ifdef mkinit INCLUDE "expand.h" RESET { ifsfree(); } #endif klibc-2.0.7/usr/dash/exec.h0000644000175000017500000000573613546663605013554 0ustar benben/*- * 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(union node *); void unsetfunc(const char *); int typecmd(int, char **); int commandcmd(int, char **); klibc-2.0.7/usr/dash/exec.c0000644000175000017500000004305213546663605013540 0ustar benben/*- * 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_PATHS_H #include #endif /* * 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; 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(EXEXIT, "%s: %s", argv[0], errmsg(e, E_EXEC)); /* NOTREACHED */ } STATIC void tryexec(char *cmd, char **argv, char **envp) { char *const path_bshell = _PATH_BSHELL; repeat: #ifdef SYSV do { execve(cmd, argv, envp); } while (errno == EINTR); #else execve(cmd, argv, envp); #endif if (cmd != path_bshell && errno == ENOEXEC) { *argv-- = cmd; *argv = cmd = path_bshell; 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(union node *func) { struct cmdentry entry; INTOFF; entry.cmdtype = CMDFUNCTION; entry.u.func = copyfunc(func); addcmdentry(func->ndefun.text, &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; { char *cmd; 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 cmd = *argptr; if (verify && cmd) return describe_command(out1, cmd, verify - VERIFY_BRIEF); return 0; } klibc-2.0.7/usr/dash/eval.h0000644000175000017500000000476013546663605013553 0ustar benben/*- * 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 */ 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) klibc-2.0.7/usr/dash/eval.c0000644000175000017500000005335513546663605013552 0ustar benben/*- * 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 */ 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 funcline; /* starting line number of current function, or 0 if not in a function */ char *commandname; 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 **, int); 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. */ static int evalcmd(int argc, char **argv, int flags) { 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); } return evalstring(p, flags & EV_TESTED); } return 0; } /* * Execute a command or commands contained in a string. */ int evalstring(char *s, int flags) { union node *n; struct stackmark smark; int status; setinputstring(s); setstackmark(&smark); status = 0; while ((n = parsecmd(0)) != NEOF) { evaltree(n, flags); status = exitstatus; popstackmark(&smark); if (evalskip) break; } popfile(); return status; } /* * 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: errlinno = lineno = n->nredir.linno; if (funcline) lineno -= funcline - 1; expredir(n->nredir.redirect); pushredir(n->nredir.redirect); status = redirectsafe(n->nredir.redirect, REDIR_PUSH); if (!status) { evaltree(n->nredir.n, flags & EV_TESTED); status = exitstatus; } if (n->nredir.redirect) 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 checkexit; case NPIPE: evalfn = evalpipe; goto checkexit; 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); success: status = 0; setstatus: exitstatus = status; break; } out: if (checkexit & exitstatus) goto exexit; if (pendingsigs) dotrap(); if (flags & EV_EXIT) { exexit: exraise(EXEXIT); } } #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) STATIC #endif void evaltreenr(union node *n, int flags) #ifdef HAVE_ATTRIBUTE_ALIAS __attribute__ ((alias("evaltree"))); #else { evaltree(n, flags); abort(); } #endif 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; errlinno = lineno = n->nfor.linno; if (funcline) lineno -= funcline - 1; setstackmark(&smark); arglist.lastp = &arglist.list; for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); /* 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; errlinno = lineno = n->ncase.linno; if (funcline) lineno -= funcline - 1; 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; errlinno = lineno = n->nredir.linno; if (funcline) lineno -= funcline - 1; expredir(n->nredir.redirect); if (!backgnd && flags & EV_EXIT && !have_traps()) 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 pip[2]; struct job *jp; result->fd = -1; result->buf = NULL; result->nleft = 0; result->jp = NULL; if (n == NULL) { goto out; } 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) { dup2(pip[1], 1); close(pip[1]); } ifsfree(); evaltreenr(n, EV_EXIT); /* NOTREACHED */ } close(pip[1]); result->fd = pip[0]; result->jp = jp; 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) { if (!*++argv) return 0; 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 localvar_list *localvar_stop; struct redirtab *redir_stop; 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; errlinno = lineno = cmd->ncmd.linno; if (funcline) lineno -= funcline - 1; /* First expand the arguments. */ TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); setstackmark(&smark); localvar_stop = pushlocalvars(); 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++; } /* Reserve one extra spot at the front for shellexec. */ nargv = stalloc(sizeof (char *) * (argc + 2)); argv = ++nargv; for (sp = arglist.list ; sp ; sp = sp->next) { TRACE(("evalcommand arg: %s\n", sp->text)); *nargv++ = sp->text; } *nargv = NULL; lastarg = NULL; if (iflag && funcline == 0 && argc > 0) lastarg = nargv[-1]; preverrout.fd = 2; expredir(cmd->ncmd.redirect); redir_stop = pushredir(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); mklocal((*spp)->text); /* * 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) { bail: exitstatus = status; /* We have a redirection error. */ if (spclbltin > 0) exraise(EXERROR); goto out; } /* Execute the command. */ switch (cmdentry.cmdtype) { default: /* Fork off a child process if necessary. */ if (!(flags & EV_EXIT) || have_traps()) { 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: if (spclbltin > 0 || argc == 0) { poplocalvars(1); if (execcmd && argc > 1) listsetvar(varlist.list, VEXPORT); } if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { int status; int i; i = exception; if (i == EXEXIT) goto raise; status = (i == EXINT) ? SIGINT + 128 : 2; exitstatus = status; if (i == EXINT || spclbltin > 0) { raise: longjmp(handler->loc, 1); } FORCEINTON; } break; case CMDFUNCTION: poplocalvars(1); if (evalfun(cmdentry.u.func, argc, argv, flags)) goto raise; break; } out: if (cmd->ncmd.redirect) popredir(execcmd); unwindredir(redir_stop); unwindlocalvars(localvar_stop); 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, int flags) { char *volatile savecmdname; struct jmploc *volatile savehandler; struct jmploc jmploc; int status; int i; savecmdname = commandname; savehandler = handler; if ((i = setjmp(jmploc.loc))) goto cmddone; handler = &jmploc; commandname = argv[0]; argptr = argv + 1; optptr = NULL; /* initialize nextopt */ if (cmd == EVALCMD) status = evalcmd(argc, argv, flags); else status = (*cmd->builtin)(argc, argv); flushall(); status |= outerr(out1); exitstatus = status; cmddone: freestdout(); commandname = savecmdname; handler = savehandler; return i; } STATIC int evalfun(struct funcnode *func, int argc, char **argv, int flags) { volatile struct shparam saveparam; struct jmploc *volatile savehandler; struct jmploc jmploc; int e; int savefuncline; saveparam = shellparam; savefuncline = funcline; savehandler = handler; if ((e = setjmp(jmploc.loc))) { goto funcdone; } INTOFF; handler = &jmploc; shellparam.malloc = 0; func->count++; funcline = func->n.ndefun.linno; INTON; shellparam.nparam = argc - 1; shellparam.p = argv + 1; shellparam.optind = 1; shellparam.optoff = -1; pushlocalvars(); evaltree(func->n.ndefun.body, flags & EV_TESTED); poplocalvars(0); funcdone: INTOFF; funcline = savefuncline; freefunc(func); 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) badnum(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 = SKIPFUNC; 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; } klibc-2.0.7/usr/dash/error.h0000644000175000017500000001016113546663605013745 0ustar benben/*- * 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 EXEXIT 4 /* exit the shell */ /* * 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; #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 void exraise(int) __attribute__((__noreturn__)); #ifdef USE_NORETURN void onint(void) __attribute__((__noreturn__)); #else void onint(void); #endif extern int errlinno; 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 */ klibc-2.0.7/usr/dash/error.c0000644000175000017500000001210013546663605013733 0ustar benben/*- * 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 "system.h" /* * Code to handle exceptions in C. */ struct jmploc *handler; int exception; int suppressint; volatile sig_atomic_t intpending; int errlinno; 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) { intpending = 0; sigclearmask(); if (!(rootshell && iflag)) { signal(SIGINT, SIG_DFL); raise(SIGINT); } exraise(EXINT); /* NOTREACHED */ } static void exvwarning2(const char *msg, va_list ap) { struct output *errs; const char *name; const char *fmt; errs = out2; name = arg0 ? arg0 : "sh"; if (!commandname) fmt = "%s: %d: "; else fmt = "%s: %d: %s: "; outfmt(errs, fmt, name, errlinno, commandname); 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) { va_list aq; TRACE(("exverror(%d, \"", cond)); va_copy(aq, ap); TRACEV((msg, aq)); va_end(aq); 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; exitstatus = 2; 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 klibc-2.0.7/usr/dash/config.h0000644000175000017500000001167413546663605014073 0ustar benben/* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* Define if __attribute__((__alias__())) is supported */ #define HAVE_ALIAS_ATTRIBUTE 1 /* Define to 1 if you have the header file. */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the `bsearch' function. */ #define HAVE_BSEARCH 1 /* Define to 1 if you have the declaration of `isblank', and to 0 if you don't. */ #define HAVE_DECL_ISBLANK 1 /* Define to 1 if you have the `faccessat' function. */ /* #undef HAVE_FACCESSAT */ /* Define to 1 if you have the `fnmatch' function. */ /* #undef HAVE_FNMATCH */ /* Define to 1 if you have the `getpwnam' function. */ #define HAVE_GETPWNAM 1 /* Define to 1 if you have the `getrlimit' function. */ /* #undef HAVE_GETRLIMIT */ /* Define to 1 if you have the `glob' function. */ /* #undef HAVE_GLOB */ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* 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 header file. */ /* #undef HAVE_MEMORY_H */ /* Define to 1 if you have the `mempcpy' function. */ /* #undef HAVE_MEMPCPY */ /* Define to 1 if you have the header file. */ #define HAVE_PATHS_H 1 /* Define to 1 if you have the `sigsetmask' function. */ /* #undef HAVE_SIGSETMASK */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ /* #undef HAVE_STPCPY */ /* Define to 1 if you have the `strchrnul' function. */ /* #undef HAVE_STRCHRNUL */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STRINGS_H */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* 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 */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* 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.7" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "dash" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "0.5.7" /* Define to printf format string for intmax_t */ /* #undef PRIdMAX */ /* The size of `intmax_t', as computed by sizeof. */ #define SIZEOF_INTMAX_T 8 /* The size of `long long int', as computed by sizeof. */ #define SIZEOF_LONG_LONG_INT 8 /* Define if you build with -DSMALL */ #define SMALL 1 /* Define to 1 if you have the ANSI C header files. */ /* #undef STDC_HEADERS */ /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS 1 #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # define _TANDEM_SOURCE 1 #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # define __EXTENSIONS__ 1 #endif /* Version number of package */ #define VERSION "0.5.7" /* Define if you build with -DWITH_LINENO */ #define WITH_LINENO 1 /* Define to 1 if on MINIX. */ /* #undef _MINIX */ /* Define to system shell path */ /* #undef _PATH_BSHELL */ /* Define to devnull device node path */ /* #undef _PATH_DEVNULL */ /* Define to tty device node path */ /* #undef _PATH_TTY */ /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ /* #undef _POSIX_1_SOURCE */ /* Define to 1 if you need to in order for `stat' and other things to work. */ /* #undef _POSIX_SOURCE */ /* 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 */ /* #undef signal */ /* 64-bit operations are the same as 32-bit */ #define stat64 stat klibc-2.0.7/usr/dash/cd.h0000644000175000017500000000335213546663605013206 0ustar benben/*- * 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); klibc-2.0.7/usr/dash/cd.c0000644000175000017500000001424313546663605013202 0ustar benben/*- * 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 /* * 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 "main.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 step6; if (*dest == '.') { c = dest[1]; dotdot: switch (c) { case '\0': case '/': goto step6; case '.': c = dest[2]; if (c != '.') goto dotdot; } } if (!*dest) dest = "."; path = bltinlookup("CDPATH"); while (path) { 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; goto err; } } step6: p = dest; goto docd; err: 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(); } /* * Find out what the current directory is. If we already know the current * directory, this routine returns immediately. */ inline STATIC char * getpwd() { #ifdef __GLIBC__ char *dir = getcwd(0, 0); if (dir) return dir; #else char buf[PATH_MAX]; if(getcwd(buf, sizeof(buf))) return savestr(buf); #endif sh_warnx("getcwd() failed: %s", strerror(errno)); return 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); } klibc-2.0.7/usr/dash/builtins.def.in0000644000175000017500000000570513546663605015371 0ustar benben/* * 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 -n flag specifies that this command has a special entry point. * 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 -ns eval execcmd -s exec exitcmd -s exit exportcmd -as export -as readonly falsecmd -u false getoptscmd -u getopts hashcmd hash jobscmd -u jobs localcmd -as 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 klibc-2.0.7/usr/dash/bltin/0000755000175000017500000000000013546663605013554 5ustar benbenklibc-2.0.7/usr/dash/bltin/test.c0000644000175000017500000002346713546663605014713 0ustar benben/* * 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(char **); static int newerf(const char *, const char *); static int olderf(const char *, const char *); static int equalf(const char *, const char *); #ifdef HAVE_FACCESSAT static int test_file_access(const char *, int); #else static int test_st_mode(const struct stat64 *, int); static int bash_group_member(gid_t); #endif static inline intmax_t getn(const char *s) { return atomax10(s); } static const struct t_op *getop(const char *s) { const struct t_op *op; for (op = ops; op->op_text; op++) { if (strcmp(s, op->op_text) == 0) return op; } return NULL; } int testcmd(int argc, char **argv) { const struct t_op *op; enum token n; int res; if (*argv[0] == '[') { if (*argv[--argc] != ']') error("missing ]"); argv[argc] = NULL; } argv++; argc--; if (argc < 1) return 1; /* * POSIX prescriptions: he who wrote this deserves the Nobel * peace prize. */ switch (argc) { case 3: op = getop(argv[1]); if (op && op->op_type == BINOP) { n = OPERAND; goto eval; } /* fall through */ case 4: if (!strcmp(argv[0], "(") && !strcmp(argv[argc - 1], ")")) { argv[--argc] = NULL; argv++; argc--; } } n = t_lex(argv); eval: t_wp = argv; res = !oexpr(n); argv = t_wp; if (argv[0] != NULL && argv[1] != NULL) syntax(argv[0], "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 = 0; for (;;) { res |= aexpr(n); n = t_lex(t_wp + 1); if (n != BOR) break; n = t_lex(t_wp += 2); } return res; } static int aexpr(enum token n) { int res = 1; for (;;) { if (!nexpr(n)) res = 0; n = t_lex(t_wp + 1); if (n != BAND) break; n = t_lex(t_wp += 2); } 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)); #ifdef HAVE_FACCESSAT case FILRD: return test_file_access(*t_wp, R_OK); case FILWR: return test_file_access(*t_wp, W_OK); case FILEX: return test_file_access(*t_wp, X_OK); #endif 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) { #ifndef HAVE_FACCESSAT 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); #endif 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 **tp) { struct t_op const *op; char *s = *tp; if (s == 0) { t_wp_op = (struct t_op *)0; return EOI; } op = getop(s); if (op && !(op->op_type == UNOP && isoperand(tp)) && !(op->op_num == LPAREN && !tp[1])) { t_wp_op = op; return op->op_num; } t_wp_op = (struct t_op *)0; return OPERAND; } static int isoperand(char **tp) { struct t_op const *op; char *s; if (!(s = tp[1])) return 1; if (!tp[2]) return 0; op = getop(s); return op && op->op_type == BINOP; } 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); } #ifdef HAVE_FACCESSAT static int test_file_access(const char *path, int mode) { return !faccessat(AT_FDCWD, path, mode, AT_EACCESS); } #else /* HAVE_FACCESSAT */ /* * 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)); if ((getgroups(ngroups, group_array)) != ngroups) return (0); /* Search through the list looking for GID. */ for (i = 0; i < ngroups; i++) if (gid == group_array[i]) return (1); return (0); } #endif /* HAVE_FACCESSAT */ klibc-2.0.7/usr/dash/bltin/test.10000644000175000017500000001543013546663605014620 0ustar benben.\" 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. klibc-2.0.7/usr/dash/bltin/printf.c0000644000175000017500000002162613546663605015231 0ustar benben/* * 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 int 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': { int done = conv_escape_str(getstr()); char *p = stackblock(); *fmt = 's'; PF(start, p); /* escape if a \c was encountered */ if (done) 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; err: return 1; } /* * Print SysV echo(1) style escape string * Halts processing string if a \c escape is encountered. */ static int 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.... */ ch = 0x100; 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), (char)ch); return ch; } /* * 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 { int c; nonl += conv_escape_str(*argv); outstr(stackblock(), outs); if (nonl > 0) break; c = ' '; if (!*++argv) { end: if (nonl) { break; } c = '\n'; } outc(c, outs); } while (*argv); return 0; } klibc-2.0.7/usr/dash/bltin/printf.10000644000175000017500000002352513546663605015147 0ustar benben.\" 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. klibc-2.0.7/usr/dash/bltin/echo.10000644000175000017500000000702213546663605014555 0ustar benben.\" 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. klibc-2.0.7/usr/dash/bltin/bltin.h0000644000175000017500000000567113546663605015046 0ustar benben/*- * 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; klibc-2.0.7/usr/dash/arith_yylex.c0000644000175000017500000001153113546663605015152 0ustar benben/*- * 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 #include #include "arith_yacc.h" #include "expand.h" #include "error.h" #include "shell.h" #include "memalloc.h" #include "syntax.h" #include "system.h" #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ #error Arithmetic tokens are out of order. #endif extern const char *arith_buf; int yylex() { int value; const char *buf = arith_buf; const char *p; for (;;) { value = *buf; switch (value) { case ' ': case '\t': case '\n': buf++; continue; default: return ARITH_BAD; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': yylval.val = strtoimax(buf, (char **)&arith_buf, 0); return ARITH_NUM; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': p = buf; while (buf++, is_in_name(*buf)) ; yylval.name = stalloc(buf - p + 1); *(char *)mempcpy(yylval.name, p, buf - p) = 0; value = ARITH_VAR; goto out; case '=': value += ARITH_ASS - '='; checkeq: buf++; checkeqcur: if (*buf != '=') goto out; value += 11; break; case '>': switch (*++buf) { case '=': value += ARITH_GE - '>'; break; case '>': value += ARITH_RSHIFT - '>'; goto checkeq; default: value += ARITH_GT - '>'; goto out; } break; case '<': switch (*++buf) { case '=': value += ARITH_LE - '<'; break; case '<': value += ARITH_LSHIFT - '<'; goto checkeq; default: value += ARITH_LT - '<'; goto out; } break; case '|': if (*++buf != '|') { value += ARITH_BOR - '|'; goto checkeqcur; } value += ARITH_OR - '|'; break; case '&': if (*++buf != '&') { value += ARITH_BAND - '&'; goto checkeqcur; } value += ARITH_AND - '&'; break; case '!': if (*++buf != '=') { value += ARITH_NOT - '!'; goto out; } value += ARITH_NE - '!'; break; case 0: goto out; case '(': value += ARITH_LPAREN - '('; break; case ')': value += ARITH_RPAREN - ')'; break; case '*': value += ARITH_MUL - '*'; goto checkeq; case '/': value += ARITH_DIV - '/'; goto checkeq; case '%': value += ARITH_REM - '%'; goto checkeq; case '+': value += ARITH_ADD - '+'; goto checkeq; case '-': value += ARITH_SUB - '-'; goto checkeq; case '~': value += ARITH_BNOT - '~'; break; case '^': value += ARITH_BXOR - '^'; goto checkeq; case '?': value += ARITH_QMARK - '?'; break; case ':': value += ARITH_COLON - ':'; break; } break; } buf++; out: arith_buf = buf; return value; } klibc-2.0.7/usr/dash/arith_yacc.h0000644000175000017500000000537213546663605014732 0ustar benben/*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 2007 * 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. */ #define ARITH_ASS 1 #define ARITH_OR 2 #define ARITH_AND 3 #define ARITH_BAD 4 #define ARITH_NUM 5 #define ARITH_VAR 6 #define ARITH_NOT 7 #define ARITH_BINOP_MIN 8 #define ARITH_LE 8 #define ARITH_GE 9 #define ARITH_LT 10 #define ARITH_GT 11 #define ARITH_EQ 12 #define ARITH_REM 13 #define ARITH_BAND 14 #define ARITH_LSHIFT 15 #define ARITH_RSHIFT 16 #define ARITH_MUL 17 #define ARITH_ADD 18 #define ARITH_BOR 19 #define ARITH_SUB 20 #define ARITH_BXOR 21 #define ARITH_DIV 22 #define ARITH_NE 23 #define ARITH_BINOP_MAX 24 #define ARITH_ASS_MIN 24 #define ARITH_REMASS 24 #define ARITH_BANDASS 25 #define ARITH_LSHIFTASS 26 #define ARITH_RSHIFTASS 27 #define ARITH_MULASS 28 #define ARITH_ADDASS 29 #define ARITH_BORASS 30 #define ARITH_SUBASS 31 #define ARITH_BXORASS 32 #define ARITH_DIVASS 33 #define ARITH_ASS_MAX 34 #define ARITH_LPAREN 34 #define ARITH_RPAREN 35 #define ARITH_BNOT 36 #define ARITH_QMARK 37 #define ARITH_COLON 38 union yystype { intmax_t val; char *name; }; extern union yystype yylval; int yylex(void); klibc-2.0.7/usr/dash/arith_yacc.c0000644000175000017500000001576313546663605014732 0ustar benben/*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 2007 * 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 "arith_yacc.h" #include "expand.h" #include "shell.h" #include "error.h" #include "output.h" #include "var.h" #if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ #error Arithmetic tokens are out of order. #endif static const char *arith_startbuf; const char *arith_buf; union yystype yylval; static int last_token; #define ARITH_PRECEDENCE(op, prec) [op - ARITH_BINOP_MIN] = prec static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = { ARITH_PRECEDENCE(ARITH_MUL, 0), ARITH_PRECEDENCE(ARITH_DIV, 0), ARITH_PRECEDENCE(ARITH_REM, 0), ARITH_PRECEDENCE(ARITH_ADD, 1), ARITH_PRECEDENCE(ARITH_SUB, 1), ARITH_PRECEDENCE(ARITH_LSHIFT, 2), ARITH_PRECEDENCE(ARITH_RSHIFT, 2), ARITH_PRECEDENCE(ARITH_LT, 3), ARITH_PRECEDENCE(ARITH_LE, 3), ARITH_PRECEDENCE(ARITH_GT, 3), ARITH_PRECEDENCE(ARITH_GE, 3), ARITH_PRECEDENCE(ARITH_EQ, 4), ARITH_PRECEDENCE(ARITH_NE, 4), ARITH_PRECEDENCE(ARITH_BAND, 5), ARITH_PRECEDENCE(ARITH_BXOR, 6), ARITH_PRECEDENCE(ARITH_BOR, 7), }; #define ARITH_MAX_PREC 8 static void yyerror(const char *s) __attribute__ ((noreturn)); static void yyerror(const char *s) { sh_error("arithmetic expression: %s: \"%s\"", s, arith_startbuf); /* NOTREACHED */ } static inline int arith_prec(int op) { return prec[op - ARITH_BINOP_MIN]; } static inline int higher_prec(int op1, int op2) { return arith_prec(op1) < arith_prec(op2); } static intmax_t do_binop(int op, intmax_t a, intmax_t b) { switch (op) { default: case ARITH_REM: case ARITH_DIV: if (!b) yyerror("division by zero"); return op == ARITH_REM ? a % b : a / b; case ARITH_MUL: return a * b; case ARITH_ADD: return a + b; case ARITH_SUB: return a - b; case ARITH_LSHIFT: return a << b; case ARITH_RSHIFT: return a >> b; case ARITH_LT: return a < b; case ARITH_LE: return a <= b; case ARITH_GT: return a > b; case ARITH_GE: return a >= b; case ARITH_EQ: return a == b; case ARITH_NE: return a != b; case ARITH_BAND: return a & b; case ARITH_BXOR: return a ^ b; case ARITH_BOR: return a | b; } } static intmax_t assignment(int var, int noeval); static intmax_t primary(int token, union yystype *val, int op, int noeval) { intmax_t result; again: switch (token) { case ARITH_LPAREN: result = assignment(op, noeval); if (last_token != ARITH_RPAREN) yyerror("expecting ')'"); last_token = yylex(); return result; case ARITH_NUM: last_token = op; return val->val; case ARITH_VAR: last_token = op; return noeval ? val->val : lookupvarint(val->name); case ARITH_ADD: token = op; *val = yylval; op = yylex(); goto again; case ARITH_SUB: *val = yylval; return -primary(op, val, yylex(), noeval); case ARITH_NOT: *val = yylval; return !primary(op, val, yylex(), noeval); case ARITH_BNOT: *val = yylval; return ~primary(op, val, yylex(), noeval); default: yyerror("expecting primary"); } } static intmax_t binop2(intmax_t a, int op, int prec, int noeval) { for (;;) { union yystype val; intmax_t b; int op2; int token; token = yylex(); val = yylval; b = primary(token, &val, yylex(), noeval); op2 = last_token; if (op2 >= ARITH_BINOP_MIN && op2 < ARITH_BINOP_MAX && higher_prec(op2, op)) { b = binop2(b, op2, arith_prec(op), noeval); op2 = last_token; } a = noeval ? b : do_binop(op, a, b); if (op2 < ARITH_BINOP_MIN || op2 >= ARITH_BINOP_MAX || arith_prec(op2) >= prec) return a; op = op2; } } static intmax_t binop(int token, union yystype *val, int op, int noeval) { intmax_t a = primary(token, val, op, noeval); op = last_token; if (op < ARITH_BINOP_MIN || op >= ARITH_BINOP_MAX) return a; return binop2(a, op, ARITH_MAX_PREC, noeval); } static intmax_t and(int token, union yystype *val, int op, int noeval) { intmax_t a = binop(token, val, op, noeval); intmax_t b; op = last_token; if (op != ARITH_AND) return a; token = yylex(); *val = yylval; b = and(token, val, yylex(), noeval | !a); return a && b; } static intmax_t or(int token, union yystype *val, int op, int noeval) { intmax_t a = and(token, val, op, noeval); intmax_t b; op = last_token; if (op != ARITH_OR) return a; token = yylex(); *val = yylval; b = or(token, val, yylex(), noeval | !!a); return a || b; } static intmax_t cond(int token, union yystype *val, int op, int noeval) { intmax_t a = or(token, val, op, noeval); intmax_t b; intmax_t c; if (last_token != ARITH_QMARK) return a; b = assignment(yylex(), noeval | !a); if (last_token != ARITH_COLON) yyerror("expecting ':'"); token = yylex(); *val = yylval; c = cond(token, val, yylex(), noeval | !!a); return a ? b : c; } static intmax_t assignment(int var, int noeval) { union yystype val = yylval; int op = yylex(); intmax_t result; if (var != ARITH_VAR) return cond(var, &val, op, noeval); if (op != ARITH_ASS && (op < ARITH_ASS_MIN || op >= ARITH_ASS_MAX)) return cond(var, &val, op, noeval); result = assignment(yylex(), noeval); if (noeval) return result; return setvarint(val.name, op == ARITH_ASS ? result : do_binop(op - 11, lookupvarint(val.name), result), 0); } intmax_t arith(const char *s) { intmax_t result; arith_buf = arith_startbuf = s; result = assignment(yylex(), 0); if (last_token) yyerror("expecting EOF"); return result; } klibc-2.0.7/usr/dash/alias.h0000644000175000017500000000411313546663605013705 0ustar benben/*- * 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 *); klibc-2.0.7/usr/dash/alias.c0000644000175000017500000001133013546663605013677 0ustar benben/*- * 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; } klibc-2.0.7/usr/dash/TOUR0000644000175000017500000004014113546663605013160 0ustar benben# @(#)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 */ } 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. 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 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} 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, terminated 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 the CTLBACKQ character. 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. klibc-2.0.7/usr/dash/README.dash0000644000175000017500000000164613546663605014251 0ustar benbenThis version of dash was obtained from git://git.kernel.org/pub/scm/utils/dash/dash.git It corresponds up to changeset 46abc8c6d8a5e9a5712bdc1312c0b6960eec65a4 omitting ee5cbe9fd6bc02f31b4d955606288de36c3d4eab. HOWTO sync branch: 1) Generate patch and fix up their path git format-patch --subject-prefix=klibc -N .. Path fixup: perl -i -pe 's#^([-+]{3} [ab]/)src/#$1#g' 00*patch 2) Import patches on by one git am --directory="usr/dash" --exclude="usr/dash/configure.ac" \ --exclude="usr/dash/ChangeLog" --exclude="usr/dash/dash.1" \ --exclude="usr/dash/Makefile.am" --exclude="usr/dash/mksignames.c" \ --whitespace=fix -k -i -s ../dash/000X-foo.patch The only changes made are the addition of config.h, Kbuild usage, the omition of Changelog and manpage and automatic whitespace fixups. 3) update config.h Generate klibc config.h in dash repository: automake --add-missing autoreconf ./configure CC=klcc klibc-2.0.7/usr/dash/Kbuild0000644000175000017500000000555113546663605013607 0ustar benben# # Kbuild file for dash # config-cppflags := -DBSD=1 -DSMALL -DJOBS=0 -DHAVE_CONFIG_H -DSHELL config-cppflags += -DGLOB_BROKEN -DIFS_BROKEN EXTRA_KLIBCCFLAGS := -I$(srctree)/$(src) -I$(objtree)/$(obj) EXTRA_KLIBCCFLAGS += -include $(srctree)/$(src)/config.h EXTRA_KLIBCCFLAGS += $(config-cppflags) HOST_EXTRACFLAGS := $(config-cppflags) init-o-files := alias.o arith_yacc.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 gen-o-files := builtins.o init.o nodes.o syntax.o static/sh-y := $(init-o-files) $(gen-o-files) hostprogs-y := mkinit mksyntax mknodes mksignames gen-h-files := builtins.h nodes.h syntax.h token.h static-y := static/sh # The shared binary shared-y := shared/sh shared/sh-y := $(static/sh-y) # For cleaning targets := static/sh static/sh.g shared/sh shared/sh.g $(gen-o-files) # explicit dependency for all generated files $(addprefix $(obj)/, $(static/sh-y)): $(addprefix $(obj)/, $(gen-h-files)) # Generate token.h targets += token.h quiet_cmd_mktokens = GEN $@ cmd_mktokens = sh $< > $@ $(obj)/token.h: $(src)/mktokens $(call if_changed,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 if_changed,mkbuiltins_def) # Generate builtins{.c + .h} targets += builtins.c builtins.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 targets += init.c init-c-files := $(addprefix $(srctree)/$(src)/, $(init-o-files:.o=.c)) quiet_cmd_mkinit = GEN $@ cmd_mkinit = cd $(obj) && ./mkinit $(init-c-files) $(obj)/init.c: $(obj)/mkinit $(init-c-files) $(call cmd,mkinit) # Generate nodes{.c + .h} targets += nodes.c nodes.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) # side effect.. $(obj)/nodes.h: $(obj)/nodes.c $(Q): # Generate syntax{.c + .h} targets += syntax.c syntax.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): # Clean deletes the static and shared dir clean-dirs := static shared # Targets to install ifdef KLIBCSHAREDFLAGS install-y := shared/sh else install-y := static/sh endif klibc-2.0.7/usr/dash/.gitignore0000644000175000017500000000020113546663605014425 0ustar benbenarith.[ch] .builtins.def.d builtins.[ch] builtins.def init.c mkinit mknodes mksyntax nodes.[ch] sh sh.shared syntax.[ch] token.h klibc-2.0.7/usr/Kbuild0000644000175000017500000000513113546663605012662 0ustar benben# # 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) klibc-2.0.7/usr/.gitignore0000644000175000017500000000015013546663605013511 0ustar benben# Generated headers (we don't want a .gitignore in the include directory!) /include/klibc/havesyscall.h klibc-2.0.7/scripts/0000755000175000017500000000000013546663605012403 5ustar benbenklibc-2.0.7/scripts/basic/0000755000175000017500000000000013546663605013464 5ustar benbenklibc-2.0.7/scripts/basic/fixdep.c0000644000175000017500000002254513546663605015117 0ustar benben/* * "Optimize" a list of dependencies as spit out by gcc -MD * for the kernel build * =========================================================================== * * Author Kai Germaschewski * Copyright 2002 by Kai Germaschewski * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * * Introduction: * * gcc produces a very nice and correct list of dependencies which * tells make when to remake a file. * * To use this list as-is however has the drawback that virtually * every file in the kernel includes which then again * includes * * If the user re-runs make *config, linux/autoconf.h will be * regenerated. make notices that and will rebuild every file which * includes autoconf.h, i.e. basically all files. This is extremely * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. * * So we play the same trick that "mkdep" played before. We replace * the dependency on linux/autoconf.h by a dependency on every config * option which is mentioned in any of the listed prequisites. * * To be exact, split-include populates a tree in include/config/, * e.g. include/config/his/driver.h, which contains the #define/#undef * for the CONFIG_HIS_DRIVER option. * * So if the user changes his CONFIG_HIS_DRIVER option, only the objects * which depend on "include/linux/config/his/driver.h" will be rebuilt, * so most likely only his driver ;-) * * The idea above dates, by the way, back to Michael E Chastain, AFAIK. * * So to get dependencies right, there are two issues: * o if any of the files the compiler read changed, we need to rebuild * o if the command line given to the compile the file changed, we * better rebuild as well. * * The former is handled by using the -MD output, the later by saving * the command line used to compile the old object and comparing it * to the one we would now use. * * Again, also this idea is pretty old and has been discussed on * kbuild-devel a long time ago. I don't have a sensibly working * internet connection right now, so I rather don't mention names * without double checking. * * This code here has been based partially based on mkdep.c, which * says the following about its history: * * Copyright abandoned, Michael Chastain, . * This is a C version of syncdep.pl by Werner Almesberger. * * * It is invoked as * * fixdep * * and will read the dependency file * * The transformed dependency snipped is written to stdout. * * It first generates a line * * cmd_ = * * and then basically copies the ..d file to stdout, in the * process filtering out the dependency on linux/autoconf.h and adding * dependencies on include/config/my/option.h for every * CONFIG_MY_OPTION encountered in any of the prequisites. * * It will also filter out all the dependencies on *.ver. We need * to make sure that the generated version checksum are globally up * to date before even starting the recursive build, so it's too late * at this point anyway. * * The algorithm to grep for "CONFIG_..." is bit unusual, but should * be fast ;-) We don't even try to really parse the header files, but * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will * be picked up as well. It's not a problem with respect to * correctness, since that can only give too many dependencies, thus * we cannot miss a rebuild. Since people tend to not mention totally * unrelated CONFIG_ options all over the place, it's not an * efficiency problem either. * * (Note: it'd be easy to port over the complete mkdep state machine, * but I don't think the added complexity is worth it) */ /* * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h, * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that * those files will have correct dependencies. */ #include #include #include #include #include #include #include #include #include #include #include #define INT_CONF ntohl(0x434f4e46) #define INT_ONFI ntohl(0x4f4e4649) #define INT_NFIG ntohl(0x4e464947) #define INT_FIG_ ntohl(0x4649475f) char *target; char *depfile; char *cmdline; static void usage(void) { fprintf(stderr, "Usage: fixdep \n"); exit(1); } static void print_cmdline(void) { printf("cmd_%s := %s\n\n", target, cmdline); } char * str_config = NULL; int size_config = 0; int len_config = 0; /* * Grow the configuration string to a desired length. * Usually the first growth is plenty. */ static void grow_config(int len) { while (len_config + len > size_config) { if (size_config == 0) size_config = 2048; str_config = realloc(str_config, size_config *= 2); if (str_config == NULL) { perror("fixdep:malloc"); exit(1); } } } /* * Lookup a value in the configuration string. */ static int is_defined_config(const char *name, int len) { const char * pconfig; const char * plast = str_config + len_config - len; for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { if (pconfig[ -1] == '\n' && pconfig[len] == '\n' && !memcmp(pconfig, name, len)) return 1; } return 0; } /* * Add a new value to the configuration string. */ static void define_config(const char *name, int len) { grow_config(len + 1); memcpy(str_config+len_config, name, len); len_config += len; str_config[len_config++] = '\n'; } /* * Clear the set of configuration strings. */ static void clear_config(void) { len_config = 0; define_config("", 0); } /* * Record the use of a CONFIG_* word. */ static void use_config(char *m, int slen) { char s[PATH_MAX]; char *p; if (is_defined_config(m, slen)) return; define_config(m, slen); memcpy(s, m, slen); s[slen] = 0; for (p = s; p < s + slen; p++) { if (*p == '_') *p = '/'; else *p = tolower((int)*p); } printf(" $(wildcard include/config/%s.h) \\\n", s); } static void parse_config_file(char *map, size_t len) { int *end = (int *) (map + len); /* start at +1, so that p can never be < map */ int *m = (int *) map + 1; char *p, *q; for (; m < end; m++) { if (*m == INT_CONF) { p = (char *) m ; goto conf; } if (*m == INT_ONFI) { p = (char *) m-1; goto conf; } if (*m == INT_NFIG) { p = (char *) m-2; goto conf; } if (*m == INT_FIG_) { p = (char *) m-3; goto conf; } continue; conf: if (p > map + len - 7) continue; if (memcmp(p, "CONFIG_", 7)) continue; for (q = p + 7; q < map + len; q++) { if (!(isalnum(*q) || *q == '_')) goto found; } continue; found: use_config(p+7, q-p-7); } } /* test is s ends in sub */ static int strrcmp(char *s, char *sub) { int slen = strlen(s); int sublen = strlen(sub); if (sublen > slen) return 1; return memcmp(s + slen - sublen, sub, sublen); } static void do_config_file(char *filename) { struct stat st; int fd; void *map; fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "fixdep: "); perror(filename); exit(2); } fstat(fd, &st); if (st.st_size == 0) { close(fd); return; } map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if ((long) map == -1) { perror("fixdep: mmap"); close(fd); return; } parse_config_file(map, st.st_size); munmap(map, st.st_size); close(fd); } static void parse_dep_file(void *map, size_t len) { char *m = map; char *end = m + len; char *p; char s[PATH_MAX]; p = strchr(m, ':'); if (!p) { fprintf(stderr, "fixdep: parse error\n"); exit(1); } memcpy(s, m, p-m); s[p-m] = 0; printf("deps_%s := \\\n", target); m = p+1; clear_config(); while (m < end) { while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) m++; p = m; while (p < end && *p != ' ') p++; if (p == end) { do p--; while (!isalnum(*p)); p++; } memcpy(s, m, p-m); s[p-m] = 0; if (strrcmp(s, "include/linux/autoconf.h") && strrcmp(s, "arch/um/include/uml-config.h") && strrcmp(s, ".ver")) { printf(" %s \\\n", s); do_config_file(s); } m = p + 1; } printf("\n%s: $(deps_%s)\n\n", target, target); printf("$(deps_%s):\n", target); } static void print_deps(void) { struct stat st; int fd; void *map; fd = open(depfile, O_RDONLY); if (fd < 0) { fprintf(stderr, "fixdep: "); perror(depfile); exit(2); } fstat(fd, &st); if (st.st_size == 0) { fprintf(stderr,"fixdep: %s is empty\n",depfile); close(fd); return; } map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if ((long) map == -1) { perror("fixdep: mmap"); close(fd); return; } parse_dep_file(map, st.st_size); munmap(map, st.st_size); close(fd); } static void traps(void) { static char test[] __attribute__((aligned(sizeof(int)))) = "CONF"; int *p = (int *)test; if (*p != INT_CONF) { fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n", *p); exit(2); } } int main(int argc, char *argv[]) { traps(); if (argc != 4) usage(); depfile = argv[1]; target = argv[2]; cmdline = argv[3]; print_cmdline(); print_deps(); return 0; } klibc-2.0.7/scripts/basic/Kbuild0000644000175000017500000000014613546663605014622 0ustar benben# # Kbuild file to build basic kbuild programs # hostprogs-y := fixdep always := $(hostprogs-y) klibc-2.0.7/scripts/basic/.gitignore0000644000175000017500000000000713546663605015451 0ustar benbenfixdep klibc-2.0.7/scripts/Makefile.host0000644000175000017500000001404313546663605015021 0ustar benben# ========================================================================== # Building binaries on the host system # Binaries are used during the compilation of the kernel, for example # to preprocess a data file. # # Both C and C++ is supported, but preferred language is C for such utilities. # # Sample syntax (see Documentation/kbuild/makefile.txt for reference) # hostprogs-y := bin2hex # Will compile bin2hex.c and create an executable named bin2hex # # hostprogs-y := lxdialog # lxdialog-objs := checklist.o lxdialog.o # Will compile lxdialog.c and checklist.c, and then link the executable # lxdialog, based on checklist.o and lxdialog.o # # hostprogs-y := qconf # qconf-cxxobjs := qconf.o # qconf-objs := menu.o # Will compile qconf as a C++ program, and menu as a C program. # They are linked as C++ code to the executable qconf # hostprogs-y := conf # conf-objs := conf.o libkconfig.so # libkconfig-objs := expr.o type.o # Will create a shared library named libkconfig.so that consist of # expr.o and type.o (they are both compiled as C code and the object file # are made as position independent code). # conf.c is compiled as a c program, and conf.o is linked together with # libkconfig.so as the executable conf. # Note: Shared libraries consisting of C++ files are not supported __hostprogs := $(sort $(hostprogs-y)$(hostprogs-m)) # hostprogs-y := tools/build may have been specified. Retreive directory obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs)))) # C code # Executables compiled from a single .c file host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) # C executables linked based on several .o files host-cmulti := $(foreach m,$(__hostprogs),\ $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m)))) # Object (.o) files compiled from .c files host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) # C++ code # C++ executables compiled from at least on .cc file # and zero or more .c files host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) # C++ Object (.o) files compiled from .cc files host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) # Shared libaries (only .c supported) # Shared libraries (.so) - all .so files referenced in "xxx-objs" host-cshlib := $(sort $(filter %.so, $(host-cobjs))) # Remove .so files from "xxx-objs" host-cobjs := $(filter-out %.so,$(host-cobjs)) #Object (.o) files used by the shared libaries host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) __hostprogs := $(addprefix $(obj)/,$(__hostprogs)) host-csingle := $(addprefix $(obj)/,$(host-csingle)) host-cmulti := $(addprefix $(obj)/,$(host-cmulti)) host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti)) host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs)) host-cshlib := $(addprefix $(obj)/,$(host-cshlib)) host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs)) obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) ##### # Handle options to gcc. Support building with separate output directory # 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 flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) _hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS_$(*F).o) _hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o) ifeq ($(KBUILD_SRC),) __hostc_flags = $(_hostc_flags) __hostcxx_flags = $(_hostcxx_flags) else __hostc_flags = -I$(obj) $(call flags,_hostc_flags) __hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags) endif hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags) hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags) ##### # Compile programs on the host # Create executable from a single .c file # host-csingle -> Executable quiet_cmd_host-csingle = HOSTCC $@ cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) $(host-csingle): %: %.c FORCE $(call if_changed_dep,host-csingle) # Link an executable based on list of .o files, all plain c # host-cmulti -> executable quiet_cmd_host-cmulti = HOSTLD $@ cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \ $(addprefix $(obj)/,$($(@F)-objs)) \ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) $(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE $(call if_changed,host-cmulti) # Create .o file from a single .c file # host-cobjs -> .o quiet_cmd_host-cobjs = HOSTCC $@ cmd_host-cobjs = $(HOSTCC) $(hostc_flags) -c -o $@ $< $(host-cobjs): %.o: %.c FORCE $(call if_changed_dep,host-cobjs) # Link an executable based on list of .o files, a mixture of .c and .cc # host-cxxmulti -> executable quiet_cmd_host-cxxmulti = HOSTLD $@ cmd_host-cxxmulti = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \ $(foreach o,objs cxxobjs,\ $(addprefix $(obj)/,$($(@F)-$(o)))) \ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) $(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE $(call if_changed,host-cxxmulti) # Create .o file from a single .cc (C++) file quiet_cmd_host-cxxobjs = HOSTCXX $@ cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $< $(host-cxxobjs): %.o: %.cc FORCE $(call if_changed_dep,host-cxxobjs) # Compile .c file, create position independent .o file # host-cshobjs -> .o quiet_cmd_host-cshobjs = HOSTCC -fPIC $@ cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $< $(host-cshobjs): %.o: %.c FORCE $(call if_changed_dep,host-cshobjs) # Link a shared library, based on position independent .o files # *.o -> .so shared library (host-cshlib) quiet_cmd_host-cshlib = HOSTLLD -shared $@ cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \ $(addprefix $(obj)/,$($(@F:.so=-objs))) \ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) $(host-cshlib): %: $(host-cshobjs) FORCE $(call if_changed,host-cshlib) targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\ $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) klibc-2.0.7/scripts/Makefile.clean0000644000175000017500000000606313546663605015131 0ustar benben# ========================================================================== # Cleaning up # ========================================================================== src := $(obj) .PHONY := __clean __clean: # Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir # Usage: # $(Q)$(MAKE) $(clean)=dir clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj # The filename Kbuild has precedence over Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) # Figure out what we need to build from the various variables # ========================================================================== subdirs := $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-) subdirs += $(patsubst %/,%,$(filter %/, $(obj-y))) subdirs += $(patsubst %/,%,$(filter %/, $(obj-m))) subdirs += $(patsubst %/,%,$(filter %/, $(obj-n))) subdirs += $(patsubst %/,%,$(filter %/, $(obj-))) subdirs += $(patsubst %/,%,$(filter %/, $(klib-y))) subdirs += $(patsubst %/,%,$(filter %/, $(klib-))) # Subdirectories we need to descend into subdirs := $(addprefix $(obj)/,$(sort $(subdirs))) # build a list of files to remove, usually releative to the current # directory __clean-files := $(extra-y) $(EXTRA_TARGETS) $(always) \ $(targets) $(clean-files) \ $(host-progs) \ $(hostprogs-y) $(hostprogs-m) $(hostprogs-) \ klib.list # as clean-files is given relative to the current directory, this adds # a $(obj) prefix, except for absolute paths __clean-files := $(wildcard \ $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \ $(filter /%, $(__clean-files))) # as clean-dirs is given relative to the current directory, this adds # a $(obj) prefix, except for absolute paths __clean-dirs := $(wildcard \ $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs))) \ $(filter /%, $(clean-dirs))) # ========================================================================== quiet_cmd_clean = CLEAN $(obj) cmd_clean = rm -f $(__clean-files) quiet_cmd_cleandir = CLEAN $(__clean-dirs) cmd_cleandir = rm -rf $(__clean-dirs) __clean: $(subdirs) ifneq ($(strip $(__clean-files)),) +$(call cmd,clean) endif ifneq ($(strip $(__clean-dirs)),) +$(call cmd,cleandir) endif ifneq ($(strip $(clean-rule)),) +$(clean-rule) endif @: # =========================================================================== # Generic stuff # =========================================================================== # Descending # --------------------------------------------------------------------------- PHONY += $(subdirs) $(subdirs): $(Q)$(MAKE) $(clean)=$@ # If quiet is set, only print short version of command cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) # Declare the contents of the PHONY variable as phony. We keep the variable for # if_changed. .PHONY: $(PHONY) klibc-2.0.7/scripts/Kbuild.klibc.include0000644000175000017500000000063413546663605016250 0ustar benben # klibc-cc-option # Usage: cflags-y += $(call klibc-cc-option,-march=winchip-c6,-march=i586) klibc-cc-option = $(call try-run,\ $(CC) $(KLIBCCPPFLAGS) $(KLIBCCFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) # klibc-cc-option-yn # Usage: flag := $(call klibc-cc-option-yn,-march=winchip-c6) klibc-cc-option-yn = $(call try-run,\ $(CC) $(KLIBCCPPFLAGS) $(KLIBCCFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) klibc-2.0.7/scripts/Kbuild.klibc0000644000175000017500000003342413546663605014631 0ustar benben# ========================================================================== # Support for building klibc programs and klibc library # ========================================================================== # # 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 composite files do the following: # Kbuild: # # static-y := kinit # kinit-y := main.o netdev.c # So kinit will be linked statically using the two .o files # specified with kinit-y. # # Are part of the program located in a sub-directory do like this: # kinit-y += ipconfig/ # # And in the subdirectory: # ipconfig/Kbuild: # lib-y := packet.o dhcp_proto.o # # All .o files listed with lib-y will be used to create a single .a file. # # The .a file is created before any subdirectories are visited so it # # may be used in the sub-directory programs. # ##### # For a klibc libary file do like this # klibc/Kbuild # klib-y := error.o pipe.o zlib/ # ##### # Handling of compiler/linker options # # 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 $(objtree)/.config # Generic Kbuild routines include $(srctree)/scripts/Kbuild.include # Defines used when compiling early userspace (klibc programs) # --------------------------------------------------------------------------- KLIBCREQFLAGS := $(call cc-option, -fno-stack-protector, ) \ $(call cc-option, -fwrapv, ) \ $(call cc-option, -fno-PIE, ) \ -ggdb KLIBCARCHREQFLAGS := KLIBCOPTFLAGS := KLIBCWARNFLAGS := -W -Wall -Wno-sign-compare -Wno-unused-parameter KLIBCSHAREDFLAGS := KLIBCBITSIZE := KLIBCLDFLAGS := KLIBCCFLAGS := # Defaults for arch to override KLIBCARCHINCFLAGS = # Arch specific definitions for klibc include $(srctree)/$(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) # klibc-ar is a macro that invokes KLIBCAR and takes 2 arguments of ar commands. # The second will be used for reproducible builds, the first otherwise. klibc-ar = $(KLIBCAR) $(if $(KBUILD_REPRODUCIBLE),$(2),$(1)) KLIBCRANLIB := $(RANLIB) $(if $(KBUILD_REPRODUCIBLE),-D) KLIBCSTRIP := $(if $(CONFIG_DEBUG_INFO),true,$(STRIP)) KLIBCNM := $(NM) KLIBCOBJCOPY := $(OBJCOPY) KLIBCOBJDUMP := $(OBJDUMP) # klibc include paths KLIBCCPPFLAGS := -nostdinc -iwithprefix include \ -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$(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 ifdef CONFIG_DEBUG_INFO KLIBCLDFLAGS += --build-id=sha1 endif # # 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 # 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 $(srctree)/$(obj)/Kbuild ##### # static-y + shared-y handling kprogs := $(static-y) $(shared-y) # kprogs based on a single .o file (with same name + .o) kprog-objs := $(foreach p, $(kprogs), $(if $($(p)-y),,$(p))) kprog-objs := $(addsuffix .o, $(kprog-objs)) # kprogs which is based on several .o files kprog-multi := $(foreach p, $(kprogs), $(if $($(p)-y),$(p))) # objects used for kprogs with more then one .o file kprog-objs += $(foreach p, $(kprog-multi), $($(p)-y)) # objects build in this dir kprog-real-objs := $(patsubst %/,,$(kprog-objs)) # Directories we need to visit before kprogs-objs are up-to-date kprog-dirs := $(patsubst %/,%,$(filter %/, $(kprog-objs))) # replace all dir/ with dir/lib.a kprog-objs := $(patsubst %/, %/lib.a, $(kprog-objs)) targets += $(static-y) $(shared-y) ##### # klib-y handling # .o files to build in this dir klib-real-objs := $(patsubst %/,,$(klib-y)) # Directories we need to visit before libs are up-to-date klib-dirs := $(patsubst %/,%,$(filter %/, $(klib-y))) # replace all dir/ with dir/klib.list klib-objs := $(patsubst %/, %/klib.list, $(klib-y)) # $(output-dirs) are a list of directories that contain object files output-dirs := $(dir $(kprog-dirs) $(kprog-objs)) output-dirs += $(foreach f, $(hostprogs-y) $(targets), \ $(if $(dir $(f)), $(dir $(f)))) output-dirs += $(dir $(klib-objs)) 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)) kprog-objs := $(addprefix $(obj)/,$(kprog-objs)) kprog-real-objs := $(addprefix $(obj)/,$(kprog-real-objs)) output-dirs := $(addprefix $(obj)/,$(output-dirs)) kprog-dirs := $(addprefix $(obj)/,$(kprog-dirs)) subdir-y := $(addprefix $(obj)/,$(subdir-y)) always := $(addprefix $(obj)/,$(always)) targets := $(addprefix $(obj)/,$(targets)) lib-y := $(addprefix $(obj)/,$(lib-y)) klib-y := $(addprefix $(obj)/,$(klib-y)) klib-objs := $(addprefix $(obj)/,$(klib-objs)) klib-real-objs := $(addprefix $(obj)/,$(klib-real-objs)) klib-dirs := $(addprefix $(obj)/,$(klib-dirs)) ##### # Handle options to gcc. Support building with separate output directory __klibccflags = $(KLIBCCFLAGS) $(EXTRA_KLIBCCFLAGS) $(KLIBCCFLAGS_$(*F).o) __klibcaflags = $(KLIBCAFLAGS) $(EXTRA_KLIBCAFLAGS) $(KLIBCAFLAGS_$(*F).o) _klibccflags = $(call flags,__klibccflags) _klibcaflags = $(call flags,__klibcaflags) 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) $(Q): # 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 $@; $(call klibc-ar,cru,Dcr) $@ $(filter $(lib-y), $^),\ rm -f $@; $(call klibc-ar,crs,Dcrs) $@) $(lib-target): $(lib-y) FORCE $(call if_changed,link_o_target) targets += $(lib-target) $(lib-y) endif # lib-target # # Create klib.list # # Do we have to create a klibc library file in this dir? ifneq ($(strip $(klib-y) $(klib-n) $(klib-)),) klib-target := $(obj)/klib.list endif ifdef klib-target # include this in build __build: $(klib-target) $(klib-dirs) # descend if needed $(sort $(addsuffix /klib.list,$(klib-dirs))): $(klib-dirs) ; # create klib.list quiet_cmd_klib-list = LIST $@ cmd_klib-list = echo $(klib-real-objs) > $@ $(klib-target): $(klib-objs) FORCE $(call if_changed,klib-list) targets += $(klib-target) $(klib-real-objs) endif # klib-target ifdef kprogs # Compile klibc-programs for the target # =========================================================================== __build : $(kprog-dirs) $(static-y) ifdef KLIBCSHAREDFLAGS __build : $(shared-y) endif # Descend if needed $(sort $(addsuffix /lib.a,$(kprog-dirs))): $(kprog-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) \ $(call objectify,$($(stripobj)-lib)) quiet_cmd_ld-static = KLIBCLD $@ cmd_ld-static = $(KLIBCLD) $(KLIBCLDFLAGS) -o $@ \ $(EXTRA_KLIBCLDFLAGS) \ $(KLIBCCRT0) \ --start-group \ $(link-deps) \ $(KLIBCLIBC) \ $(KLIBCLIBGCC) \ --end-group ; \ cp -f $@ $@.g ; \ $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@ $(static-y): $(kprog-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) \ --start-group \ $(link-deps) \ -R $(KLIBCLIBCSHARED) \ $(KLIBCLIBGCC) \ --end-group ; \ cp -f $@ $@.g ; \ $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@ $(shared-y): $(kprog-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 += $(kprog-real-objs) endif # Compile programs on the host # =========================================================================== ifdef hostprogs-y include $(srctree)/scripts/Makefile.host endif # Descending # --------------------------------------------------------------------------- PHONY += $(subdir-y) $(kprog-dirs) $(klib-dirs) $(sort $(subdir-y) $(kprog-dirs) $(klib-dirs)): $(lib-target) $(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 $(srctree)/scripts/Kbuild.klibc obj # Declare the contents of the PHONY variable as phony. We keep the variable for # if_changed. .PHONY: $(PHONY) klibc-2.0.7/scripts/Kbuild.install0000644000175000017500000000746613546663605015222 0ustar benben# # Install klibc # # File is logically seperated in two pieces. # First piece is used when during a recursive descend of the klibc tree # and second piece is used to do the final steps in the install # If KLIBC_INSTALL is defined it tells us we are descending and we # use first piece of the file. # 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 # First rule PHONY := __install install-rule __install: # Install commands install-data := install -m 644 install-lib := install -m 755 install-bin := install -m 755 # Install command quiet_cmd_install = INSTALL $(install-y) cmd_install = $(install-bin) $(install-y) \ $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)bin ifeq ($(KLIBC_INSTALL),1) # First part - we are descending.. # Reset variables (to get right type of assingment) subdir- := # Read .config if it exist, otherwise ignore -include $(objtree)/.config # Include Kbuild file include $(srctree)/scripts/Kbuild.include # Arch specific definitions for klibc include $(srctree)/$(KLIBCSRC)/arch/$(KLIBCARCHDIR)/MCONFIG include $(srctree)/$(obj)/Kbuild # Directories to visit # First find directories specified in lib-?, static-y and shared-y find-dir = $(patsubst %/,%,$(filter %/, $(1))) __subdir := $(call find-dir, $(lib-)) __subdir += $(call find-dir, $(lib-y)) __subdir += $(foreach e, $(static-y), $(call find-dir, $(e))) __subdir += $(foreach e, $(shared-y), $(call find-dir, $(e))) # Use subdir- in Kbuild file to tell kbuild to visit a specific dir subdir- += $(__subdir) # Remove duplicates and add prefix subdir- := $(addprefix $(obj)/,$(sort $(subdir-))) # Files to install install-y := $(strip $(addprefix $(obj)/, $(install-y))) __install: $(subdir-) install-rule ifneq ($(install-y),) $(call cmd,install) else @: endif # Descending PHONY += $(subdir-) $(subdir-): $(Q)$(MAKE) KLIBC_INSTALL=1 \ -f $(srctree)/scripts/Kbuild.install obj=$@ # If quiet is set, only print short version of command cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) else ########################################################################## # This is the first time this file is invoked, so kick off the # install process. # First we descend all sub-directories to let them do their install. # Second we do the final install steps. # Do actual install as a three steps approach # 1) Create directories, install headers and man pages # 2) Tell that we now install binaries # 3) Install binaries by descending PHONY += header footer descend header: $(Q)echo " INSTALL headers + man pages to $(INSTALLROOT)$(INSTALLDIR)" $(Q)mkdir -p $(INSTALLROOT)$(bindir) $(Q)mkdir -p $(INSTALLROOT)$(mandir)/man1 $(Q)mkdir -p $(INSTALLROOT)$(SHLIBDIR) $(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR) $(Q)-rm -rf $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include $(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include $(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)lib $(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)bin $(Q)cp -rfL $(KLIBCKERNELSRC)/include/. $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include/. $(Q)cp -rf usr/include/. $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include/. $(Q)chmod -R a+rX,go-w $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include $(Q)$(install-data) $(srctree)/klcc/klcc.1 $(INSTALLROOT)$(mandir)/man1/$(KCROSS)klcc.1 $(Q)$(install-bin) $(objtree)/klcc/$(KCROSS)klcc $(INSTALLROOT)$(bindir) footer: header $(Q)echo " INSTALL binaries to $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)bin" descend: footer $(Q)$(MAKE) KLIBC_INSTALL=1 \ -f $(srctree)/scripts/Kbuild.install obj=$(obj) __install: descend @: endif # Declare the contents of the PHONY variable as phony. We keep the variable for # if_changed. .PHONY: $(PHONY) klibc-2.0.7/scripts/Kbuild.include0000644000175000017500000002401113546663605015160 0ustar benben#### # kbuild: Generic definitions # Convenient variables comma := , squote := ' empty := space := $(empty) $(empty) ### # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o dot-target = $(dir $@).$(notdir $@) ### # The temporary file to save gcc -MD generated dependencies must not # contain a comma depfile = $(subst $(comma),_,$(dot-target).d) ### # filename of target with directory and extension stripped basetarget = $(basename $(notdir $@)) ### # filename of first prerequisite with directory and extension stripped baseprereq = $(basename $(notdir $<)) ### # Escape single quote for use in echo statements escsq = $(subst $(squote),'\$(squote)',$1) ### # Easy method for doing a status message kecho := : quiet_kecho := echo silent_kecho := : kecho := $($(quiet)kecho) ### # filechk is used to check if the content of a generated file is updated. # Sample usage: # define filechk_sample # echo $KERNELRELEASE # endef # version.h : Makefile # $(call filechk,sample) # The rule defined shall write to stdout the content of the new file. # The existing file will be compared with the new one. # - If no file exist it is created # - If the content differ the new file is used # - If they are equal no change, and no timestamp update # - stdin is piped in from the first prerequisite ($<) so one has # to specify a valid file as first prerequisite (often the kbuild file) define filechk $(Q)set -e; \ $(kecho) ' CHK $@'; \ mkdir -p $(dir $@); \ $(filechk_$(1)) < $< > $@.tmp; \ if [ -r $@ ] && cmp -s $@ $@.tmp; then \ rm -f $@.tmp; \ else \ $(kecho) ' UPD $@'; \ mv -f $@.tmp $@; \ fi endef ###### # gcc support functions # See documentation in Documentation/kbuild/makefiles.txt # cc-cross-prefix # Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-) # Return first prefix where a prefix$(CC) is found in PATH. # If no $(CC) found in PATH with listed prefixes return nothing cc-cross-prefix = \ $(word 1, $(foreach c,$(1), \ $(shell set -e; \ if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \ echo $(c); \ fi))) # output directory for tests below TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/) # try-run # Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise) # Exit code chooses option. "$$TMP" is can be used as temporary file and # is automatically cleaned up. try-run = $(shell set -e; \ TMP="$(TMPOUT).$$$$.tmp"; \ TMPO="$(TMPOUT).$$$$.o"; \ if ($(1)) >/dev/null 2>&1; \ then echo "$(2)"; \ else echo "$(3)"; \ fi; \ rm -f "$$TMP" "$$TMPO") # as-option # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) as-option = $(call try-run,\ $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) # as-instr # Usage: cflags-y += $(call as-instr,instr,option1,option2) as-instr = $(call try-run,\ printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) # cc-option # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) cc-option = $(call try-run,\ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) # cc-option-yn # Usage: flag := $(call cc-option-yn,-march=winchip-c6) cc-option-yn = $(call try-run,\ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) # cc-option-align # Prefix align with either -falign or -malign cc-option-align = $(subst -functions=0,,\ $(call cc-option,-falign-functions=0,-malign-functions=0)) # cc-disable-warning # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) cc-disable-warning = $(call try-run,\ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) # cc-version # Usage gcc-ver := $(call cc-version) cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) # cc-fullversion # Usage gcc-ver := $(call cc-fullversion) cc-fullversion = $(shell $(CONFIG_SHELL) \ $(srctree)/scripts/gcc-version.sh -p $(CC)) # cc-ifversion # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) # cc-ldoption # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) cc-ldoption = $(call try-run,\ $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) # ld-option # Usage: LDFLAGS += $(call ld-option, -X) ld-option = $(call try-run,\ $(CC) /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2)) # ar-option # Usage: KBUILD_ARFLAGS := $(call ar-option,D) # Important: no spaces around options ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2)) ###### ### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= # Usage: # $(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. # skip if -I has no parameter addtree = $(if $(patsubst -I%,%,$(1)), \ $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)) # Find all -I options and call addtree flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) # echo command. # Short version is used, if $(quiet) equals `quiet_', otherwise full one. echo-cmd = $(if $($(quiet)cmd_$(1)),\ echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) # printing commands cmd = @$(echo-cmd) $(cmd_$(1)) # Add $(obj)/ for paths that are not absolute objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) ### # if_changed - execute command if any prerequisite is newer than # target, or command line has changed # if_changed_dep - as if_changed, but uses fixdep to reveal dependencies # including used config symbols # if_changed_rule - as if_changed but execute rule instead # See Documentation/kbuild/makefiles.txt for more info ifneq ($(KBUILD_NOCMDDEP),1) # Check if both arguments has same arguments. Result is empty string if equal. # User may override this check using make KBUILD_NOCMDDEP=1 arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ $(filter-out $(cmd_$@), $(cmd_$(1))) ) else arg-check = $(if $(strip $(cmd_$@)),,1) endif # >'< substitution is for echo to work, # >$< substitution to preserve $ when reloading .cmd file # note: when using inline perl scripts [perl -e '...$$t=1;...'] # in $(cmd_xxx) double $$ your perl vars make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) # Find any prerequisites that is newer than target or that does not exist. # PHONY targets skipped in both cases. any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) # Execute command if command has changed or prerequisite(s) are updated. # if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ @set -e; \ $(echo-cmd) $(cmd_$(1)); \ echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) # Execute the command and also postprocess generated .d dependencies file. if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ @set -e; \ $(echo-cmd) $(cmd_$(1)); \ scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\ rm -f $(depfile); \ mv -f $(dot-target).tmp $(dot-target).cmd) # Usage: $(call if_changed_rule,foo) # Will check if $(cmd_foo) or any of the prerequisites changed, # and if so will execute $(rule_foo). if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \ @set -e; \ $(rule_$(1))) ### # why - tell why a a target got build # enabled by make V=2 # Output (listed in the order they are checked): # (1) - due to target is PHONY # (2) - due to target missing # (3) - due to: file1.h file2.h # (4) - due to command line change # (5) - due to missing .cmd file # (6) - due to target not in $(targets) # (1) PHONY targets are always build # (2) No target, so we better build it # (3) Prerequisite is newer than target # (4) The command line stored in the file named dir/.target.cmd # differed from actual command line. This happens when compiler # options changes # (5) No dir/.target.cmd file (used to store command line) # (6) No dir/.target.cmd file and target not listed in $(targets) # This is a good hint that there is a bug in the kbuild file ifeq ($(KBUILD_VERBOSE),2) why = \ $(if $(filter $@, $(PHONY)),- due to target is PHONY, \ $(if $(wildcard $@), \ $(if $(strip $(any-prereq)),- due to: $(any-prereq), \ $(if $(arg-check), \ $(if $(cmd_$@),- due to command line change, \ $(if $(filter $@, $(targets)), \ - due to missing .cmd file, \ - due to $(notdir $@) not in $$(targets) \ ) \ ) \ ) \ ), \ - due to target missing \ ) \ ) echo-why = $(call escsq, $(strip $(why))) endif klibc-2.0.7/klibc.spec.in0000644000175000017500000000772513546663605013274 0ustar benbenSummary: A minimal libc subset for use with initramfs. Name: klibc Version: @@VERSION@@ Release: 1 License: BSD/GPL Group: Development/Libraries URL: https://www.zytor.com/mailman/listinfo/klibc Source: https://www.kernel.org/pub/linux/libs/klibc/2.0/klibc-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot BuildRequires: kernel >= 2.6.0, kernel-devel Packager: H. Peter Anvin Prefix: /usr Vendor: Starving Linux Artists %define klibcdir %{_prefix}/lib/klibc %define libdocdir %{_docdir}/%{name}-%{version}-%{release} %define bindocdir %{_docdir}/%{name}-utils-%{version}-%{release} %description %{name} is intended to be a minimalistic libc subset for use with initramfs. It is deliberately written for small size, minimal entanglement, and portability, not speed. %package devel Summary: Libraries and tools needed to compile applications against klibc. Group: Development/Libraries Requires: klibc = %{version}-%{release} %description devel This package contains the link libraries, header files, and gcc wrapper scripts needed to compile applications against klibc. %package utils Summary: Small utilities built with klibc. Group: Utilities/System Requires: klibc = %{version}-%{release} %description utils This package contains a collection of programs that are linked against klibc. These duplicate some of the functionality of a regular Linux toolset, but are typically much smaller than their full-function counterparts. They are intended for inclusion in initramfs images and embedded systems. %prep %setup -q cp -dRs /lib/modules/`uname -r`/build/ ./linux # Shouldn't need this when getting the build tree from /lib/modules # make -C linux defconfig ARCH=%{_target_cpu} # make -C linux prepare ARCH=%{_target_cpu} # Deal with braindamage in RedHat's kernel-source RPM rm -f linux/include/linux/config.h cat < linux/include/linux/config.h #ifndef _LINUX_CONFIG_H #define _LINUX_CONFIG_H #include #endif EOF mkdir -p %{buildroot} %build make %{_smp_mflags} \ KLIBCARCH=%{_target_cpu} prefix=%{_prefix} bindir=%{_bindir} \ INSTALLDIR=%{klibcdir} mandir=%{_mandir} INSTALLROOT=%{buildroot} %install rm -rf %{buildroot} make KLIBCARCH=%{_target_cpu} prefix=%{_prefix} bindir=%{_bindir} \ INSTALLDIR=%{klibcdir} mandir=%{_mandir} INSTALLROOT=%{buildroot} \ install # Make the .so file in /lib a hardlink (they will be expanded as two # files automatically if it crosses filesystems when extracted.) ln -f %{buildroot}%{klibcdir}/lib/klibc-*.so %{buildroot}/lib # Install the docs mkdir -p %{buildroot}%{bindocdir} %{buildroot}%{libdocdir} install -m 444 README %{buildroot}%{libdocdir} install -m 444 usr/klibc/README.klibc %{buildroot}%{libdocdir} install -m 444 usr/klibc/arch/README.klibc.arch %{buildroot}%{libdocdir} install -m 444 usr/gzip/COPYING %{buildroot}%{bindocdir}/COPYING.gzip install -m 444 usr/gzip/README %{buildroot}%{bindocdir}/README.gzip install -m 444 usr/kinit/ipconfig/README.ipconfig %{buildroot}%{bindocdir} install -m 444 usr/kinit/README %{buildroot}%{bindocdir}/README.kinit %clean rm -rf $RPM_BUILD_ROOT # # Note: libc.so and interp.o are technically -devel files, but # put them in this package until we can make really, really sure # the dependency system can avoid confusion. (In fact, it would be # good to eventually get them out of here, so that multiple runtimes # can be installed should it be necessary.) # %files %defattr(-,root,root,-) /lib/klibc-*.so %{klibcdir}/lib/*.so %{klibcdir}/lib/interp.o %files devel %defattr(-,root,root,-) %{klibcdir}/include %{klibcdir}/lib/*.a %{klibcdir}/lib/crt0.o %{_bindir}/klcc %doc %{_mandir}/man1/* %doc %{libdocdir}/* %files utils %defattr(-,root,root,-) %{klibcdir}/bin %doc %{bindocdir}/* %changelog * Tue Mar 1 2005 H. Peter Anvin - New "make install" scheme, klcc * Tue Jul 6 2004 H. Peter Anvin - Update to use kernel-source RPM for the kernel symlink. * Sat Nov 29 2003 Bryan O'Sullivan - - Initial build. klibc-2.0.7/klcc/0000755000175000017500000000000013546663605011630 5ustar benbenklibc-2.0.7/klcc/makeklcc.pl0000644000175000017500000000235013546663605013737 0ustar benben#!/usr/bin/perl # # Combine klibc.config, klcc.in to produce a klcc script # # Usage: makeklcc klcc.in klibc.config perlpath # use File::Spec; ($klccin, $klibcconf, $perlpath) = @ARGV; sub pathsearch($) { my($file) = @_; my(@path); my($p,$pp); if ( $file =~ /\// ) { return File::Spec->rel2abs($file); } foreach $p ( split(/\:/, $ENV{'PATH'}) ) { $pp = File::Spec->rel2abs(File::Spec->catpath(undef, $p, $file)); return $pp if ( -x $pp ); } return undef; } print "#!${perlpath}\n"; open(KLIBCCONF, "< $klibcconf\0") or die "$0: cannot open $klibcconf: $!\n"; while ( defined($l = ) ) { chomp $l; if ( $l =~ /^([^=]+)\=\s*(.*)$/ ) { $n = $1; $s = $2; if ( $n eq 'CC' || $n eq 'LD' || $n eq 'STRIP' ) { $s1 = pathsearch($s); die "$0: Cannot find $n: $s\n" unless ( defined($s1) ); $s = $s1; } print "\$$n = \"\Q$s\E\";\n"; print "\$conf{\'\L$n\E\'} = \\\$$n;\n"; print "\@$n = ("; $sep = ''; while ( $s =~ /^\s*(\S+)/ ) { print $sep, "\"\Q$1\E\""; $sep = ', '; $s = "$'"; } print ");\n"; } } close(KLIBCCONF); open(KLCCIN, "< $klccin\0") or die "$0: cannot open $klccin: $!\n"; while ( defined($l = ) ) { print $l; } close(KLCCIN); klibc-2.0.7/klcc/klcc.in0000644000175000017500000001644413546663605013105 0ustar benben# -*- perl -*- use IPC::Open3; # Standard includes @includes = ("-I${prefix}/${KCROSS}include/arch/${ARCHDIR}", "-I${prefix}/${KCROSS}include/bits${BITSIZE}", "-I${prefix}/${KCROSS}include"); # Default optimization options (for compiles without -g) @optopt = @OPTFLAGS; @goptopt = ('-O'); # Standard library directories @stdlibpath = ("-L${prefix}/${KCROSS}lib"); # Options and libraries to pass to ld; shared versus static @staticopt = ("${prefix}/${KCROSS}lib/crt0.o"); @staticlib = ("${prefix}/${KCROSS}lib/libc.a"); @sharedopt = (@EMAIN, "${prefix}/${KCROSS}lib/interp.o"); @sharedlib = ('-R', "${prefix}/${KCROSS}lib/libc.so"); # Returns the language (-x option string) for a specific extension. sub filename2lang($) { my ($file) = @_; return 'c' if ( $file =~ /\.c$/ ); return 'c-header' if ( $file =~ /\.h$/ ); return 'cpp-output' if ( $file =~ /\.i$/ ); return 'c++-cpp-output' if ( $file =~ /\.ii$/ ); return 'objective-c' if ( $file =~ /\.m$/ ); return 'objc-cpp-output' if ( $file =~ /\.mi$/ ); return 'c++' if ( $file =~/\.(cc|cp|cxx|cpp|CPP|c\+\+|C)$/ ); return 'c++-header' if ( $file =~ /\.(hh|H)$/ ); return 'f77' if ( $file =~ /\.(f|for|FOR)$/ ); return 'f77-cpp-input' if ( $file =~ /\.(F|fpp|FPP)$/ ); return 'ratfor' if ( $file =~ /\.r$/ ); # Is this correct? return 'ada' if ( $file =~ /\.(ads|adb)$/ ); return 'assembler' if ( $file =~ /\.s$/ ); return 'assembler-with-cpp' if ( $file =~/\.S$/ ); # Linker file; there is no option to gcc to assume something # is a linker file, so we make up our own... return 'obj'; } # Produces a series of -x options and files sub files_with_lang($$) { my($files, $flang) = @_; my(@as) = (); my($xopt) = 'none'; my($need); foreach $f ( @{$files} ) { $need = ${$flang}{$f}; # Skip object files if ( $need ne 'obj' ) { unless ( $xopt eq $need || $need eq 'stdin') { push(@as, '-x', $need); $xopt = $need; } push(@as, $f); } } return @as; } # Convert a return value from system() to an exit() code sub syserr($) { my($e) = @_; return ($e & 0x7f) | 0x80 if ( $e & 0xff ); return $e >> 8; } # Run a program; printing out the command line if $verbose is set sub mysystem(@) { print STDERR join(' ', @_), "\n" if ( $verbose ); my $cmd = shift; open(INPUT, "<&STDIN"); # dup STDIN filehandle to INPUT my $childpid = open3("<&INPUT", ">&STDOUT", ">&STDERR", $cmd, @_); waitpid ($childpid, 0); return $?; } # # Initialization # open(NULL, '+<', '/dev/null') or die "$0: cannot open /dev/null\n"; # # Begin parsing options. # @ccopt = (); @ldopt = (); @libs = (); @files = (); # List of files %flang = (); # Languages for files # This is 'c' for compile only, 'E' for preprocess only, # 'S' for compile to assembly. $operation = ''; # Compile and link # Current -x option. If undefined, it means autodetect. undef $lang; $save_temps = 0; # The -save-temps option $verbose = 0; # The -v option $shared = 0; # Are we compiling shared? $debugging = 0; # -g or -p option present? $strip = 0; # -s option present? undef $output; # -o option present? while ( defined($a = shift(@ARGV)) ) { if ( $a !~ /^\-/ ) { # Not an option. Must be a filename then. push(@files, $a); $flang{$a} = $lang || filename2lang($a); } elsif ( $a eq '-' ) { # gcc gets its input from stdin push(@files, $a); # prevent setting -x $flang{$a} = 'stdin' } elsif ( $a =~ /^-print-klibc-(.*)$/ ) { # This test must precede -print if ( defined($conf{$1}) ) { print ${$conf{$1}}, "\n"; exit 0; } else { die "$0: unknown option: $a\n"; } } elsif ( $a =~ /^(-print|-dump|--help|--version|-v)/ ) { # These share prefixes with some other options, so put this test early! # Pseudo-operations; just pass to gcc and don't do anything else push(@ccopt, $a); $operation = 'c' if ( $operation eq '' ); } elsif ( $a =~ /^-Wl,(.*)$/ ) { # -Wl used to pass options to the linker push(@ldopt, split(/,/, $1)); } elsif ( $a =~ /^-([fmwWQdO]|std=|ansi|pedantic|M[GPD]|MMD)/ ) { # Options to gcc push(@ccopt, $a); } elsif ( $a =~ /^-([DUI]|M[FQT])(.*)$/ ) { # Options to gcc, which can take either a conjoined argument # (-DFOO) or a disjoint argument (-D FOO) push(@ccopt, $a); push(@ccopt, shift(@ARGV)) if ( $2 eq '' ); } elsif ( $a eq '-include' ) { # Options to gcc which always take a disjoint argument push(@ccopt, $a, shift(@ARGV)); } elsif ( $a eq '-M' || $a eq '-MM' ) { # gcc options, that force preprocessing mode push(@ccopt, $a); $operation = 'E'; } elsif ( $a =~ /^--param/ ) { # support --param name=value and --param=name=value my @values=split('=', $a); if ( @values == 1 ) { push(@ccopt, $a); push(@ccopt, shift(@ARGV)); } elsif ( @values == 3 ) { push(@ccopt, $values[0]); push(@ccopt, join('=', $values[1],$values[2])); } } elsif ( $a =~ /^-[gp]/ || $a eq '-p' ) { # Debugging options to gcc push(@ccopt, $a); $debugging = 1; } elsif ( $a eq '-v' ) { push(@ccopt, $a); $verbose = 1; } elsif ( $a eq '-save-temps' ) { push(@ccopt, $a); $save_temps = 1; } elsif ( $a =~ '^-([cSE])$' ) { push(@ccopt, $a); $operation = $1; } elsif ( $a eq '-shared' ) { $shared = 1; } elsif ( $a eq '-static' ) { $shared = 0; } elsif ( $a eq '-s' ) { $strip = 1; } elsif ( $a eq '-o' ) { $output = shift(@ARGV); } elsif ( $a =~ /^\-x(.*)$/ ) { # -x can be conjoined or disjoined $lang = $1; if ( $lang eq '' ) { $lang = shift(@ARGV); } } elsif ( $a eq '-nostdinc' ) { push(@ccopt, $a); @includes = (); } elsif ( $a =~ /^-([lL])(.*)$/ ) { # Libraries push(@libs, $a); push(@libs, shift(@ARGV)) if ( $2 eq '' ); } else { die "$0: unknown option: $a\n"; } } if ( $debugging ) { @ccopt = (@REQFLAGS, @includes, @goptopt, @ccopt); } else { @ccopt = (@REQFLAGS, @includes, @optopt, @ccopt); } if ( $operation ne '' ) { # Just run gcc with the appropriate options @outopt = ('-o', $output) if ( defined($output) ); $rv = mysystem($CC, @ccopt, @outopt, files_with_lang(\@files, \%flang)); } else { if ( scalar(@files) == 0 ) { die "$0: No input files!\n"; } @outopt = ('-o', $output || 'a.out'); @objs = (); @rmobjs = (); foreach $f ( @files ) { if ( $flang{$f} eq 'obj' ) { push(@objs, $f); } else { $fo = $f; $fo =~ s/\.[^\/.]+$/\.o/; die if ( $f eq $fo ); # safety check push(@objs, $fo); push(@rmobjs, $fo) unless ( $save_temps ); $rv = mysystem($CC, @ccopt, '-c', '-o', $fo, '-x', $flang{$f}, $f); if ( $rv ) { unlink(@rmobjs); exit syserr($rv); } } } # Get the libgcc pathname for the *current* gcc open(LIBGCC, '-|', $CC, @ccopt, '-print-libgcc-file-name') or die "$0: cannot get libgcc filename\n"; $libgcc = ; chomp $libgcc; close(LIBGCC); if ( $shared ) { $rv = mysystem($LD, @LDFLAGS, @sharedopt, @ldopt, @outopt, @objs, @libs, @stdlibpath, '--start-group', @sharedlib, $libgcc, '--end-group'); } else { $rv = mysystem($LD, @LDFLAGS, @staticopt, @ldopt, @outopt, @objs, @libs, @stdlibpath, '--start-group', @staticlib, $libgcc, '--end-group'); } unlink(@rmobjs); if ( $strip && !$rv ) { $rv = mysystem($STRIP, @STRIPFLAGS, $output); } } exit syserr($rv); klibc-2.0.7/klcc/klcc.10000644000175000017500000000763513546663605012641 0ustar benben.\" $Id: klcc.1,v 1.3 2005/04/19 23:27:46 hpa Exp $ .\" ----------------------------------------------------------------------- .\" .\" Copyright 2005 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. .\" .\" ----------------------------------------------------------------------- .TH klcc "1" "1 March 2005" "klibc" "H. Peter Anvin" .SH NAME klcc \- compile a program against klibc .SH SYNOPSIS .B klcc [\fIgcc options\fP] [\fB\-o\fP \fIoutfile\fP] \fIinfile...\fP .SH DESCRIPTION .PP .B klcc is a wrapper around .BR gcc (1) and .BR ld (1) which compiles and links a program against the .B klibc tiny C library. It supports most .B gcc options. .PP Unlike .BR gcc , .B klcc compiles with optimization on by default. Furthermore, the optimization level used depends on whether or not .B \-g is specified, since .B klcc frequently uses options in the normal case which makes debugging impossible. Therefore, compile without .BR \-g , .BR \-O , .B \-f or .B \-m option to use the default optimization level; this will generally result in the smallest binaries. You may want to use .B \-s when linking, however. Use .B \-O0 to compile without any optimization whatsoever; this may not work depending on the version of .B gcc used. .TP .B \-nostdinc allows to turn off klibc include files. .PP Use the .B \-shared or .B \-static option to compile for and link against shared or static klibc. Note that shared klibc only supports running against the exact same klibc binary as the binary was linked with. .PP In addition to standard .B gcc options, .B klcc supports options of the form \fB\-print-klibc-\fP\fIoption\fP, which prints the corresponding klibc configuration option. .SH AUTHOR Written by H. Peter Anvin . .SH COPYRIGHT Copyright \(co 2005 H. Peter Anvin \- All Rights Reserved .PP 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: .PP The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. .PP 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. .SH "SEE ALSO" .BR gcc (1) klibc-2.0.7/klcc/Kbuild0000644000175000017500000000313313546663605012765 0ustar benben# # Build klcc # always := $(KLIBCCROSS)klcc $(obj)/$(KLIBCCROSS)klibc.config: $(src)/Kbuild \ $(srctree)/Makefile \ $(srctree)/scripts/Kbuild.klibc @$(kecho) ' GEN $@' $(Q)rm -f $@ $(Q)echo 'ARCH=$(KLIBCARCH)' >> $@ $(Q)echo 'ARCHDIR=$(KLIBCARCHDIR)' >> $@ $(Q)echo 'CROSS=$(KLIBCROSS)' >> $@ $(Q)echo 'KCROSS=$(KCROSS)' >> $@ $(Q)echo 'CC=$(KLIBCCC)' >> $@ $(Q)echo 'LD=$(KLIBCLD)' >> $@ $(Q)echo 'REQFLAGS=$(filter-out -I%,$(KLIBCDEFS) $(KLIBCREQFLAGS) $(KLIBCARCHREQFLAGS) $(KLIBCCPPFLAGS))' >> $@ $(Q)echo 'OPTFLAGS=$(KLIBCOPTFLAGS)' >> $@ $(Q)echo 'LDFLAGS=$(KLIBCLDFLAGS)' >> $@ $(Q)echo 'STRIP=$(STRIP)' >> $@ $(Q)echo 'STRIPFLAGS=$(KLIBCSTRIPFLAGS)' >> $@ $(Q)echo 'EMAIN=$(KLIBCEMAIN)' >> $@ $(Q)echo 'BITSIZE=$(KLIBCBITSIZE)' >> $@ $(Q)echo 'VERSION=$(shell cat $(srctree)/usr/klibc/version)' >> $@ $(Q)echo 'prefix=$(INSTALLDIR)' >> $@ $(Q)echo 'bindir=$(INSTALLDIR)/$(KCROSS)bin' >> $@ $(Q)echo 'libdir=$(INSTALLDIR)/$(KCROSS)lib' >> $@ $(Q)echo 'includedir=$(INSTALLDIR)/$(KCROSS)include' >> $@ # Generate klcc targets := $(KLIBCCROSS)klcc quiet_cmd_klcc = GEN $@ cmd_klcc = $(PERL) $< $(srctree)/$(src)/klcc.in \ $(obj)/$(KLIBCCROSS)klibc.config \ $(shell bash -c 'type -p $(PERL)') \ > $@ || ( rm -f $@ ; exit 1 ) && \ chmod a+x $@ $(obj)/$(KLIBCCROSS)klcc: $(src)/makeklcc.pl $(src)/klcc.in \ $(obj)/$(KLIBCCROSS)klibc.config $(call if_changed,klcc) # Cleaning targets clean-files := $(KLIBCCROSS)klibc.config $(KLIBCCROSS)klcc klibc-2.0.7/klcc/.gitignore0000644000175000017500000000002213546663605013612 0ustar benbenklcc klibc.config klibc-2.0.7/git-rm-for-kernel.sh0000755000175000017500000000055213546663605014516 0ustar benben#!/bin/sh if [ -z "$RM" ]; then export RM='git rm -rf' fi nuke () { find "$@" -print | sort -r | xargs -rt $RM } nuke README Kbuild Makefile defconfig klibc.spec.in *.sh nuke contrib klcc # These files are either not needed or provided from the # kernel tree nuke scripts/Kbuild.include scripts/Kbuild.install nuke scripts/Makefile.* nuke scripts/basic klibc-2.0.7/defconfig0000644000175000017500000000032313546663605012561 0ustar benbenCONFIG_KLIBC=y CONFIG_KLIBC_ERRLIST=y CONFIG_KLIBC_ZLIB=y # CONFIG_KLIBC_ZIP is not set # i386 option CONFIG_REGPARM=y # ARM options # CONFIG_KLIBC_THUMB is not set CONFIG_AEABI=y # CONFIG_DEBUG_INFO is not set klibc-2.0.7/contrib/0000755000175000017500000000000013546663605012354 5ustar benbenklibc-2.0.7/contrib/klibc.m40000644000175000017500000000717713546663605013716 0ustar benben# klibc.m4 serial 99 ## Copyright (C) 1995-2003 Free Software Foundation, Inc. ## This file is free software, distributed under the terms of the GNU ## General Public License. As a special exception to the GNU General ## Public License, this file may be distributed as part of a program ## that contains a configuration script generated by Autoconf, under ## the same distribution terms as the rest of that program. ## ## This file can can be used in projects which are not available under ## the GNU General Public License or the GNU Library General Public ## License but which still want to provide support for the GNU gettext ## functionality. ## Please note that the actual code of the KLIBC Library is partly covered ## by the GNU Library General Public License, and party copyrighted by the ## Regents of The University of California, and the rest is covered by a ## MIT style license. # Authors: # Martin Schlemmer , 2005. # AC_CHECK_KLIBC # -------------- # Check if the user wants KLIBC support enabled. If so, set KLIBC=yes and # fill in KLIBC_PREFIX, KLIBC_BINDIR, KLIBC_SBINDIR, KLIBC_LIBDIR and # KLIBC_INCLUDEDIR. CC is also set to the proper klcc executable. # NOTE: This should be called before AC_PROG_CC, and before header, function # or type checks. AC_DEFUN([AC_CHECK_KLIBC], [AC_BEFORE([$0], [AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_ARG_ENABLE([klibc], [AS_HELP_STRING([--enable-klibc], [Enable linking to klibc [no]. You need at least klibc-1.0 or later for this. Set KLCC to the absolute file name of klcc if not in the PATH])], [KLIBC=$enableval], [KLIBC=no]) AC_ARG_ENABLE([klibc-layout], [AS_HELP_STRING([--enable-klibc-layout], [Enable installing binaries, libraries and headers into the klibc prefix [yes] ])], [if test "X$KLIBC" != Xno; then KLIBC_LAYOUT=$enableval else KLIBC_LAYOUT=no fi], [if test "X$KLIBC" != Xno; then KLIBC_LAYOUT=yes else KLIBC_LAYOUT=no fi]) if test "X$KLIBC" != Xno; then # Basic cross compiling support. I do not think it is wise to use # AC_CHECK_TOOL, because if we are cross compiling, we do not want # just 'klcc' to be returned ... if test "${host_alias}" != "${build_alias}"; then AC_CHECK_PROGS([KLCC], [${host_alias}-klcc], [no]) else AC_CHECK_PROGS([KLCC], [klcc], [no]) fi if test "X$KLCC" = Xno; then AC_MSG_ERROR([cannot find klibc frontend 'klcc'!]) fi CC="$KLCC" CFLAGS="-Os" KLIBC_KCROSS="$($KLCC -print-klibc-kcross 2>/dev/null)" KLIBC_PREFIX="$($KLCC -print-klibc-prefix 2>/dev/null)" KLIBC_BIN_DIR="$($KLCC -print-klibc-bindir 2>/dev/null)" KLIBC_SBIN_DIR="${KLIBC_PREFIX}/${KLIBC_KCROSS}sbin" KLIBC_LIB_DIR="$($KLCC -print-klibc-libdir 2>/dev/null)" KLIBC_INCLUDE_DIR="$($KLCC -print-klibc-includedir 2>/dev/null)" if test "X$KLIBC_LAYOUT" != Xno; then prefix="$KLIBC_PREFIX" bindir="$KLIBC_BIN_DIR" sbindir="$KLIBC_SBIN_DIR" libdir="$KLIBC_LIB_DIR" includedir="$KLIBC_INCLUDE_DIR" fi # At least KLIBC_LIB_DIR should be valid, else klibc is too old or # something went wrong if test ! -d "$KLIBC_LIB_DIR"; then AC_MSG_ERROR([your klibc installation is too old or not functional!]) fi fi AC_SUBST(KLIBC) ])# AC_CHECK_KLIBC klibc-2.0.7/README0000644000175000017500000000145313546663605011577 0ustar benbenPlease see usr/klibc/README.klibc for build instructions and for the status of various platforms. klibc is archived at: https://mirrors.kernel.org/pub/linux/libs/klibc/ There is a mailing list for klibc and early-userspace issues at: klibc@zytor.com https://www.zytor.com/mailman/listinfo/klibc klibc is maintained in the git version control system. The git repository can be viewed on the web at: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/ To clone the klibc repository using git: git clone https://git.kernel.org/pub/scm/libs/klibc/klibc.git To update an already cloned tree: git pull For more information on git, see: https://git-scm.com/ https://mirrors.kernel.org/pub/software/scm/git/docs/gittutorial.html https://mirrors.kernel.org/pub/software/scm/git/docs/ klibc-2.0.7/Makefile0000644000175000017500000001230113546663605012351 0ustar benbenSRCROOT = . # *DOCUMENTATION* # To see a list of typical targets execute "make help" # kbuild compatibility export srctree := $(or $(KBUILD_SRC),$(shell pwd)) export objtree := $(shell pwd) export KLIBCSRC := usr/klibc export VERSION := $(shell cat $(srctree)/$(KLIBCSRC)/version) export KLIBCINC := usr/include export KLIBCOBJ := usr/klibc export KLIBCKERNELSRC ?= linux export VPATH := $(srctree) include $(srctree)/scripts/Kbuild.include KLIBCROSS ?= $(CROSS_COMPILE) export KLIBCROSS export CC := $(KLIBCROSS)gcc export LD := $(KLIBCROSS)ld export AR := $(KLIBCROSS)ar export RANLIB := $(KLIBCROSS)ranlib export STRIP := $(KLIBCROSS)strip export NM := $(KLIBCROSS)nm export OBJCOPY := $(KLIBCROSS)objcopy export OBJDUMP := $(KLIBCROSS)objdump NOSTDINC_FLAGS := -nostdlib -nostdinc -isystem $(shell $(CC) -print-file-name=include) ARCH := $(shell uname -m | sed -e s/i.86/i386/ \ -e s/parisc64/parisc/ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ -e s/aarch64.*/arm64/ -e s/sh.*/sh/ \ -e s/ppc64le/ppc64/) export KLIBCARCH ?= $(ARCH) export KLIBCARCHDIR := $(shell echo $(KLIBCARCH) | sed -e s/s390x/s390/) export HOSTCC := gcc export HOSTCFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer export PERL := perl # Location for installation export prefix = /usr export bindir = $(prefix)/bin export libdir = $(prefix)/lib export mandir = $(prefix)/man export INSTALLDIR = $(prefix)/lib/klibc export INSTALLROOT = # Create a fake .config as present in the kernel tree # But if it exists leave it alone $(if $(wildcard $(objtree)/.config),,\ $(shell cp $(srctree)/defconfig $(objtree)/.config)) # Prefix Make commands with $(Q) to silence them # Use quiet_cmd_xxx, cmd_xxx to create nice output # use make V=1 to get verbose output ifdef V ifeq ("$(origin V)", "command line") KBUILD_VERBOSE = $(V) endif endif ifndef KBUILD_VERBOSE KBUILD_VERBOSE = 0 endif ifeq ($(KBUILD_VERBOSE),1) quiet = Q = else quiet=quiet_ Q = @ endif # If the user is running make -s (silent mode), suppress echoing of # commands ifneq ($(findstring s,$(MAKEFLAGS)),) quiet=silent_ endif export quiet Q KBUILD_VERBOSE # Do not print "Entering directory ..." MAKEFLAGS += --no-print-directory # Shorthand to call Kbuild.klibc klibc := -f $(srctree)/scripts/Kbuild.klibc obj # Very first target .PHONY: all klcc klibc all: klcc klibc $(objtree)/.config: $(srctree)/defconfig @echo "defconfig has changed, please remove or edit .config" @false $(KLIBCKERNELSRC)/include: @echo 'Missing kernel UAPI headers in $(KLIBCKERNELSRC)/include.' @echo 'Install them by running:' @echo ' make headers_install INSTALL_HDR_PATH=$(abspath $(KLIBCKERNELSRC))' @echo 'in the kernel source directory.' @false rpmbuild = $(shell which rpmbuild 2>/dev/null || which rpm) klibc.spec: klibc.spec.in $(KLIBCSRC)/version sed -e 's/@@VERSION@@/$(VERSION)/g' < $< > $@ # Build klcc - it is the first target klcc: $(objtree)/.config $(KLIBCKERNELSRC)/include $(Q)$(MAKE) $(klibc)=klcc klibc: $(objtree)/.config $(KLIBCKERNELSRC)/include $(Q)$(MAKE) $(klibc)=. test: klibc $(Q)$(MAKE) $(klibc)=usr/klibc/tests help: @echo 'Cleaning targets:' @echo ' clean - Remove most generated files' @echo ' mrproper - Remove all generated files + config' @echo ' distclean - mprproper + editor backup + patch files' @echo '' @echo 'Build targets:' @echo 'all - Build all targets' @echo 'install - Install klibc' @echo 'klcc - Wrapper around gcc to compile against klibc' @echo 'test - Run klibc tests' @echo @echo 'Build options:' @echo 'KLIBCKERNELSRC - Path to usr directory containing UAPI headers' @echo 'make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' @echo 'make V=2 [targets] 2 => give reason for rebuild of target' @echo @echo 'Sample invocation:' @echo 'make KLIBCKERNELSRC=`pwd`/../linux/usr/' ### # allow one to say make dir/file.o # Caveat: works only for .c files where we have a Kbuild file in same dir %.o: %.c FORCE $(Q)$(MAKE) $(klibc)=$(dir $<) $(dir $<)$(notdir $@) %.s: %.c FORCE $(Q)$(MAKE) $(klibc)=$(dir $<) $(dir $<)$(notdir $@) %.i: %.c FORCE $(Q)$(MAKE) $(klibc)=$(dir $<) $(dir $<)$(notdir $@) FORCE: ; ### # clean: remove generated files # mrproper does a full cleaning including .config and linux symlink FIND_IGNORE := \( -name .git -o -name .pc \) -prune -o quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),RM $(wildcard $(rm-files))) cmd_rmfiles = rm -f $(rm-files) clean: $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.clean obj=. $(Q)find . $(FIND_IGNORE) \ \( -name *.o -o -name *.a -o -name '.*.cmd' -o \ -name '.*.d' -o -name '.*.tmp' \) \ -type f -print | xargs rm -f rm-files := $(objtree)/.config linux distclean mrproper: clean $(Q)find . $(FIND_IGNORE) \ \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -o -name '.*.rej' -o -size 0 \ -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ -type f -print | xargs rm -f $(call cmd,rmfiles) install: all $(Q)$(MAKE) -f $(srctree)/scripts/Kbuild.install obj=. # This does all the prep work needed to turn a freshly exported git repository # into a release tarball tree release: klibc.spec rm -f .config klibc-2.0.7/Kbuild0000644000175000017500000000064213546663605012053 0ustar benben# # Kbuild file for klibc # .PHONY: $(obj)/all always := all $(obj)/all: $(Q)$(MAKE) $(klibc)=scripts/basic $(Q)$(MAKE) $(klibc)=usr/klibc $(Q)$(MAKE) $(klibc)=usr/kinit $(Q)$(MAKE) $(klibc)=usr/dash $(Q)$(MAKE) $(klibc)=usr/utils $(Q)$(MAKE) $(klibc)=usr/gzip # Directories to visit during clean and install subdir- := scripts/basic klcc usr/klibc usr/dash usr/utils usr/gzip \ usr/kinit usr/klibc/tests klibc-2.0.7/.gitignore0000644000175000017500000000044013546663605012702 0ustar benben# # NOTE! Don't add files that are generated in specific # subdirectories here. Add them in the ".gitignore" file # in that subdirectory instead. # # Normal rules # *.o *.o.cmd .*.cmd *.g \#* .\#* *~ # Top-level ignorables /linux /.config # Common generated subdirectores shared static