summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>1997-08-11 13:08:30 +0000
committercvs2svn <cvs2svn@FreeBSD.org>1997-08-11 13:08:30 +0000
commit3ab8ee7cc4a96eab986e46bb079a51ffa7155dbc (patch)
tree8a35c89965fedc4b13c96c0e907166eb9db2d71b
parent1114e11649f79100abc3433772522a53f09ea8f3 (diff)
Notes
-rw-r--r--bin/date/vary.c384
-rw-r--r--bin/date/vary.h8
-rw-r--r--contrib/cpio/copyin.c1377
-rw-r--r--contrib/cpio/copypass.c474
-rw-r--r--lib/libalias/alias_old.c77
-rw-r--r--lib/libc/gen/sysctlbyname.c35
-rw-r--r--lib/libc/stdtime/strptime.385
-rw-r--r--lib/libc/stdtime/timelocal.c197
-rw-r--r--lib/libc/stdtime/timelocal.h51
-rw-r--r--release/README.TXT33
-rw-r--r--release/floppies/bin/Makefile7
-rw-r--r--release/floppies/bin/doFS.sh71
-rw-r--r--release/floppies/bin/dumpnlist/Makefile8
-rw-r--r--release/floppies/bin/dumpnlist/dumpnlist.c44
-rw-r--r--release/floppies/bin/write_mfs_in_kernel/Makefile8
-rw-r--r--release/floppies/bin/write_mfs_in_kernel/write_mfs_in_kernel.c70
-rw-r--r--release/floppies/mk/crunch_fs.mk108
-rw-r--r--release/floppies/mk/makecrunch.mk25
-rw-r--r--release/sysinstall/sysinstall.8784
-rw-r--r--share/man/man4/man4.i386/sb.473
-rw-r--r--share/man/man4/man4.i386/wl.4147
-rw-r--r--share/skel/dot.shrc43
-rw-r--r--sys/i386/boot/biosboot/boot.help18
-rw-r--r--sys/i386/include/if_wl_wavelan.h167
-rw-r--r--sys/pci/dc21040reg.h598
-rw-r--r--usr.sbin/natd/HISTORY113
-rw-r--r--usr.sbin/natd/README53
-rw-r--r--usr.sbin/natd/icmp.c113
-rw-r--r--usr.sbin/natd/natd.8381
-rw-r--r--usr.sbin/natd/natd.c1434
-rw-r--r--usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m416
-rw-r--r--usr.sbin/sendmail/contrib/passwd-to-alias.pl30
-rw-r--r--usr.sbin/sendmail/src/safefile.c712
-rw-r--r--usr.sbin/sendmail/test/t_exclopen.c91
-rw-r--r--usr.sbin/wlconfig/wlconfig.8131
-rw-r--r--usr.sbin/wlconfig/wlconfig.c432
36 files changed, 8398 insertions, 0 deletions
diff --git a/bin/date/vary.c b/bin/date/vary.c
new file mode 100644
index 000000000000..be9f76240e38
--- /dev/null
+++ b/bin/date/vary.c
@@ -0,0 +1,384 @@
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include "vary.h"
+
+struct trans {
+ int val;
+ char *str;
+};
+
+static struct trans trans_mon[] = {
+ { 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" },
+ { 6, "june" }, { 7, "july" }, { 8, "august" }, { 9, "september" },
+ { 10, "october" }, { 11, "november" }, { 12, "december" },
+ { -1, NULL }
+};
+
+static struct trans trans_wday[] = {
+ { 0, "sunday" }, { 1, "monday" }, { 2, "tuesday" }, { 3, "wednesday" },
+ { 4, "thursday" }, { 5, "friday" }, { 6, "saturday" },
+ { -1, NULL }
+};
+
+static char digits[] = "0123456789";
+
+static int
+trans(const struct trans t[], const char *arg)
+{
+ int f;
+
+ for (f = 0; t[f].val != -1; f++)
+ if (!strncasecmp(t[f].str, arg, 3) ||
+ !strncasecmp(t[f].str, arg, strlen(t[f].str)))
+ return t[f].val;
+
+ return -1;
+}
+
+struct vary *
+vary_append(struct vary *v, char *arg)
+{
+ struct vary *result, **nextp;
+
+ if (v) {
+ result = v;
+ while (v->next)
+ v = v->next;
+ nextp = &v->next;
+ } else
+ nextp = &result;
+
+ *nextp = (struct vary *)malloc(sizeof(struct vary));
+ (*nextp)->arg = arg;
+ (*nextp)->next = NULL;
+ return result;
+}
+
+static int mdays[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static int
+daysinmonth(const struct tm *t)
+{
+ int year;
+
+ year = t->tm_year + 1900;
+
+ if (t->tm_mon == 1)
+ if (!(year % 400))
+ return 29;
+ else if (!(year % 100))
+ return 28;
+ else if (!(year % 4))
+ return 29;
+ else
+ return 28;
+ else if (t->tm_mon >= 0 && t->tm_mon < 12)
+ return mdays[t->tm_mon];
+
+ return 0;
+}
+
+
+static int
+adjyear(struct tm *t, char type, int val)
+{
+ switch (type) {
+ case '+':
+ t->tm_year += val;
+ break;
+ case '-':
+ t->tm_year -= val;
+ break;
+ default:
+ t->tm_year = val;
+ if (t->tm_year < 69)
+ t->tm_year += 100; /* as per date.c */
+ else if (t->tm_year > 1900)
+ t->tm_year -= 1900; /* struct tm holds years since 1900 */
+ break;
+ }
+ return mktime(t) != -1;
+}
+
+static int
+adjmon(struct tm *t, char type, int val, int istext)
+{
+ if (val < 0)
+ return 0;
+
+ switch (type) {
+ case '+':
+ if (istext)
+ if (val <= t->tm_mon)
+ val += 11 - t->tm_mon; /* early next year */
+ else
+ val -= t->tm_mon + 1; /* later this year */
+ if (!adjyear(t, '+', (t->tm_mon + val) / 12))
+ return 0;
+ val %= 12;
+ t->tm_mon += val;
+ if (t->tm_mon > 11)
+ t->tm_mon -= 12;
+ break;
+
+ case '-':
+ if (istext)
+ if (val-1 > t->tm_mon)
+ val = 13 - val + t->tm_mon; /* later last year */
+ else
+ val = t->tm_mon - val + 1; /* early this year */
+ if (!adjyear(t, '-', val / 12))
+ return 0;
+ val %= 12;
+ if (val > t->tm_mon) {
+ if (!adjyear(t, '-', 1))
+ return 0;
+ val -= 12;
+ }
+ t->tm_mon -= val;
+ break;
+
+ default:
+ if (val > 12 || val < 1)
+ return 0;
+ t->tm_mon = --val;
+ }
+
+ return mktime(t) != -1;
+}
+
+static int
+adjday(struct tm *t, char type, int val)
+{
+ int mdays;
+ switch (type) {
+ case '+':
+ while (val) {
+ mdays = daysinmonth(t);
+ if (val > mdays - t->tm_mday) {
+ val -= mdays - t->tm_mday + 1;
+ t->tm_mday = 1;
+ if (!adjmon(t, '+', 1, 0))
+ return 0;
+ } else {
+ t->tm_mday += val;
+ val = 0;
+ }
+ }
+ break;
+ case '-':
+ while (val)
+ if (val >= t->tm_mday) {
+ val -= t->tm_mday;
+ t->tm_mday = 1;
+ if (!adjmon(t, '-', 1, 0))
+ return 0;
+ t->tm_mday = daysinmonth(t);
+ } else {
+ t->tm_mday -= val;
+ val = 0;
+ }
+ break;
+ default:
+ if (val > 0 && val <= daysinmonth(t))
+ t->tm_mday = val;
+ else
+ return 0;
+ break;
+ }
+
+ return mktime(t) != -1;
+}
+
+static int
+adjwday(struct tm *t, char type, int val, int istext)
+{
+ if (val < 0)
+ return 0;
+
+ switch (type) {
+ case '+':
+ if (istext)
+ if (val < t->tm_wday)
+ val = 7 - t->tm_wday + val; /* early next week */
+ else
+ val -= t->tm_wday; /* later this week */
+ else
+ val *= 7; /* "-W +5" == "5 weeks in the future" */
+ return adjday(t, '+', val);
+ case '-':
+ if (istext)
+ if (val > t->tm_wday)
+ val = 7 - val + t->tm_wday; /* later last week */
+ else
+ val = t->tm_wday - val; /* early this week */
+ else
+ val *= 7; /* "-W -5" == "5 weeks ago" */
+ return adjday(t, '-', val);
+ default:
+ if (val < t->tm_wday)
+ return adjday(t, '-', t->tm_wday - val);
+ else if (val > 6)
+ return 0;
+ else if (val > t->tm_wday)
+ return adjday(t, '+', val - t->tm_wday);
+ }
+ return 1;
+}
+
+static int
+adjhour(struct tm *t, char type, int val)
+{
+ if (val < 0)
+ return 0;
+
+ switch (type) {
+ case '+':
+ if (!adjday(t, '+', (t->tm_hour + val) / 24))
+ return 0;
+ val %= 24;
+ t->tm_hour += val;
+ if (t->tm_hour > 23)
+ t->tm_hour -= 24;
+ break;
+
+ case '-':
+ if (!adjday(t, '-', val / 24))
+ return 0;
+ val %= 24;
+ if (val > t->tm_hour) {
+ if (!adjday(t, '-', 1))
+ return 0;
+ val -= 24;
+ }
+ t->tm_hour -= val;
+ break;
+
+ default:
+ if (val > 23)
+ return 0;
+ t->tm_hour = val;
+ }
+
+ return mktime(t) != -1;
+}
+
+static int
+adjmin(struct tm *t, char type, int val)
+{
+ if (val < 0)
+ return 0;
+
+ switch (type) {
+ case '+':
+ if (!adjhour(t, '+', (t->tm_min + val) / 60))
+ return 0;
+ val %= 60;
+ t->tm_min += val;
+ if (t->tm_min > 59)
+ t->tm_min -= 60;
+ break;
+
+ case '-':
+ if (!adjhour(t, '-', val / 60))
+ return 0;
+ val %= 60;
+ if (val > t->tm_min) {
+ if (!adjhour(t, '-', 1))
+ return 0;
+ val -= 60;
+ }
+ t->tm_min -= val;
+ break;
+
+ default:
+ if (val > 59)
+ return 0;
+ t->tm_min = val;
+ }
+
+ return mktime(t) != -1;
+}
+
+const struct vary *
+vary_apply(const struct vary *v, struct tm *t)
+{
+ char type;
+ char which;
+ char *arg;
+ int len;
+ int val;
+
+ for (; v; v = v->next) {
+ type = *v->arg;
+ arg = v->arg;
+ if (type == '+' || type == '-')
+ arg++;
+ else
+ type = '\0';
+ len = strlen(arg);
+ if (len < 2)
+ return v;
+
+ if (strspn(arg, digits) != len-1) {
+ val = trans(trans_wday, arg);
+ if (val != -1) {
+ if (!adjwday(t, type, val, 1))
+ return v;
+ } else {
+ val = trans(trans_mon, arg);
+ if (val != -1) {
+ if (!adjmon(t, type, val, 1))
+ return v;
+ } else
+ return v;
+ }
+ } else {
+ val = atoi(arg);
+ which = arg[len-1];
+
+ switch (which) {
+ case 'M':
+ if (!adjmin(t, type, val))
+ return v;
+ break;
+ case 'H':
+ if (!adjhour(t, type, val))
+ return v;
+ break;
+ case 'd':
+ if (!adjday(t, type, val))
+ return v;
+ break;
+ case 'w':
+ if (!adjwday(t, type, val, 0))
+ return v;
+ break;
+ case 'm':
+ if (!adjmon(t, type, val, 0))
+ return v;
+ break;
+ case 'y':
+ if (!adjyear(t, type, val))
+ return v;
+ break;
+ default:
+ return v;
+ }
+ }
+ }
+ return 0;
+}
+
+void
+vary_destroy(struct vary *v)
+{
+ struct vary *n;
+
+ while (v) {
+ n = v->next;
+ free(v);
+ v = n;
+ }
+}
diff --git a/bin/date/vary.h b/bin/date/vary.h
new file mode 100644
index 000000000000..6f54b88c4d96
--- /dev/null
+++ b/bin/date/vary.h
@@ -0,0 +1,8 @@
+struct vary {
+ char *arg;
+ struct vary *next;
+};
+
+extern struct vary *vary_append(struct vary *v, char *arg);
+extern const struct vary *vary_apply(const struct vary *v, struct tm *t);
+extern void vary_destroy(struct vary *v);
diff --git a/contrib/cpio/copyin.c b/contrib/cpio/copyin.c
new file mode 100644
index 000000000000..6f2db393f094
--- /dev/null
+++ b/contrib/cpio/copyin.c
@@ -0,0 +1,1377 @@
+/* copyin.c - extract or list a cpio archive
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#if (defined(BSD) && (BSD >= 199306))
+#define HAVE_STRFTIME
+#include <ctype.h>
+#endif
+#include "filetypes.h"
+#include "system.h"
+#include "cpiohdr.h"
+#include "dstring.h"
+#include "extern.h"
+#include "defer.h"
+#include "rmt.h"
+#ifndef FNM_PATHNAME
+#include <fnmatch.h>
+#endif
+
+#ifndef HAVE_LCHOWN
+#define lchown chown
+#endif
+
+static void read_pattern_file ();
+static void tape_skip_padding ();
+static void defer_copyin ();
+static void create_defered_links ();
+static void create_final_defers ();
+
+/* 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. */
+
+void
+read_in_header (file_hdr, in_des)
+ 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. */
+
+ if (archive_format == arf_unknown)
+ {
+ char tmpbuf[512];
+ int check_tar;
+ int peeked_bytes;
+
+ while (archive_format == arf_unknown)
+ {
+ peeked_bytes = tape_buffered_peek (tmpbuf, in_des, 512);
+ if (peeked_bytes < 6)
+ error (1, 0, "premature end of archive");
+
+ if (!strncmp (tmpbuf, "070701", 6))
+ archive_format = arf_newascii;
+ else if (!strncmp (tmpbuf, "070707", 6))
+ archive_format = arf_oldascii;
+ else if (!strncmp (tmpbuf, "070702", 6))
+ {
+ archive_format = arf_crcascii;
+ crc_i_flag = TRUE;
+ }
+ else if ((*((unsigned short *) tmpbuf) == 070707) ||
+ (*((unsigned short *) tmpbuf) == swab_short ((unsigned short) 070707)))
+ archive_format = arf_binary;
+ else if (peeked_bytes >= 512
+ && (check_tar = is_tar_header (tmpbuf)))
+ {
+ if (check_tar == 2)
+ archive_format = arf_ustar;
+ else
+ archive_format = arf_tar;
+ }
+ else
+ {
+ tape_buffered_read ((char *) tmpbuf, in_des, 1L);
+ ++bytes_skipped;
+ }
+ }
+ }
+
+ if (archive_format == arf_tar || archive_format == arf_ustar)
+ {
+ if (append_flag)
+ last_header_start = input_bytes - io_block_size +
+ (in_buff - input_buffer);
+ if (bytes_skipped > 0)
+ error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
+ read_in_tar_header (file_hdr, in_des);
+ return;
+ }
+
+ file_hdr->c_tar_linkname = NULL;
+
+ tape_buffered_read ((char *) file_hdr, in_des, 6L);
+ while (1)
+ {
+ if (append_flag)
+ last_header_start = input_bytes - io_block_size
+ + (in_buff - input_buffer) - 6;
+ if (archive_format == arf_newascii
+ && !strncmp ((char *) file_hdr, "070701", 6))
+ {
+ if (bytes_skipped > 0)
+ error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
+ read_in_new_ascii (file_hdr, in_des);
+ break;
+ }
+ if (archive_format == arf_crcascii
+ && !strncmp ((char *) file_hdr, "070702", 6))
+ {
+ if (bytes_skipped > 0)
+ error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
+ read_in_new_ascii (file_hdr, in_des);
+ break;
+ }
+ if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
+ && !strncmp ((char *) file_hdr, "070707", 6))
+ {
+ if (bytes_skipped > 0)
+ error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
+ read_in_old_ascii (file_hdr, in_des);
+ break;
+ }
+ if ( (archive_format == arf_binary || archive_format == arf_hpbinary)
+ && (file_hdr->c_magic == 070707
+ || file_hdr->c_magic == swab_short ((unsigned short) 070707)))
+ {
+ /* Having to skip 1 byte because of word alignment is normal. */
+ if (bytes_skipped > 0)
+ error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
+ read_in_binary (file_hdr, in_des);
+ break;
+ }
+ bytes_skipped++;
+ bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
+ tape_buffered_read ((char *) file_hdr + 5, in_des, 1L);
+ }
+}
+
+/* Fill in FILE_HDR by reading an old-format ASCII format cpio header from
+ file descriptor IN_DES, except for the magic number, which is
+ already filled in. */
+
+void
+read_in_old_ascii (file_hdr, in_des)
+ struct new_cpio_header *file_hdr;
+ int in_des;
+{
+ char ascii_header[78];
+ unsigned long dev;
+ unsigned long rdev;
+
+ tape_buffered_read (ascii_header, in_des, 70L);
+ ascii_header[70] = '\0';
+ sscanf (ascii_header,
+ "%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
+ &dev, &file_hdr->c_ino,
+ &file_hdr->c_mode, &file_hdr->c_uid, &file_hdr->c_gid,
+ &file_hdr->c_nlink, &rdev, &file_hdr->c_mtime,
+ &file_hdr->c_namesize, &file_hdr->c_filesize);
+ file_hdr->c_dev_maj = major (dev);
+ file_hdr->c_dev_min = minor (dev);
+ file_hdr->c_rdev_maj = major (rdev);
+ file_hdr->c_rdev_min = minor (rdev);
+
+ /* Read file name from input. */
+ if (file_hdr->c_name != NULL)
+ free (file_hdr->c_name);
+ file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize + 1);
+ tape_buffered_read (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
+#ifndef __MSDOS__
+ /* HP/UX cpio creates archives that look just like ordinary archives,
+ but for devices it sets major = 0, minor = 1, and puts the
+ actual major/minor number in the filesize field. See if this
+ is an HP/UX cpio archive, and if so fix it. We have to do this
+ here because process_copy_in() assumes filesize is always 0
+ for devices. */
+ switch (file_hdr->c_mode & CP_IFMT)
+ {
+ case CP_IFCHR:
+ case CP_IFBLK:
+#ifdef CP_IFSOCK
+ case CP_IFSOCK:
+#endif
+#ifdef CP_IFIFO
+ case CP_IFIFO:
+#endif
+ if (file_hdr->c_filesize != 0
+ && file_hdr->c_rdev_maj == 0
+ && file_hdr->c_rdev_min == 1)
+ {
+ file_hdr->c_rdev_maj = major (file_hdr->c_filesize);
+ file_hdr->c_rdev_min = minor (file_hdr->c_filesize);
+ file_hdr->c_filesize = 0;
+ }
+ break;
+ default:
+ break;
+ }
+#endif /* __MSDOS__ */
+}
+
+/* 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. */
+
+void
+read_in_new_ascii (file_hdr, in_des)
+ struct new_cpio_header *file_hdr;
+ int in_des;
+{
+ char ascii_header[112];
+
+ tape_buffered_read (ascii_header, in_des, 104L);
+ ascii_header[104] = '\0';
+ sscanf (ascii_header,
+ "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
+ &file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid,
+ &file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime,
+ &file_hdr->c_filesize, &file_hdr->c_dev_maj, &file_hdr->c_dev_min,
+ &file_hdr->c_rdev_maj, &file_hdr->c_rdev_min, &file_hdr->c_namesize,
+ &file_hdr->c_chksum);
+ /* Read file name from input. */
+ if (file_hdr->c_name != NULL)
+ 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);
+}
+
+/* Fill in FILE_HDR by reading a binary format cpio header from
+ file descriptor IN_DES, except for the first 6 bytes (the magic
+ number, device, and inode number), which are already filled in. */
+
+void
+read_in_binary (file_hdr, in_des)
+ struct new_cpio_header *file_hdr;
+ int in_des;
+{
+ struct old_cpio_header short_hdr;
+
+ /* Copy the data into the short header, then later transfer
+ it into the argument long header. */
+ short_hdr.c_dev = ((struct old_cpio_header *) file_hdr)->c_dev;
+ short_hdr.c_ino = ((struct old_cpio_header *) file_hdr)->c_ino;
+ tape_buffered_read (((char *) &short_hdr) + 6, in_des, 20L);
+
+ /* If the magic number is byte swapped, fix the header. */
+ if (file_hdr->c_magic == swab_short ((unsigned short) 070707))
+ {
+ static int warned = 0;
+
+ /* Alert the user that they might have to do byte swapping on
+ the file contents. */
+ if (warned == 0)
+ {
+ error (0, 0, "warning: archive header has reverse byte-order");
+ warned = 1;
+ }
+ swab_array ((char *) &short_hdr, 13);
+ }
+
+ file_hdr->c_dev_maj = major (short_hdr.c_dev);
+ file_hdr->c_dev_min = minor (short_hdr.c_dev);
+ file_hdr->c_ino = short_hdr.c_ino;
+ file_hdr->c_mode = short_hdr.c_mode;
+ file_hdr->c_uid = short_hdr.c_uid;
+ file_hdr->c_gid = short_hdr.c_gid;
+ file_hdr->c_nlink = short_hdr.c_nlink;
+ file_hdr->c_rdev_maj = major (short_hdr.c_rdev);
+ file_hdr->c_rdev_min = minor (short_hdr.c_rdev);
+ file_hdr->c_mtime = (unsigned long) short_hdr.c_mtimes[0] << 16
+ | short_hdr.c_mtimes[1];
+
+ file_hdr->c_namesize = short_hdr.c_namesize;
+ file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16
+ | short_hdr.c_filesizes[1];
+
+ /* Read file name from input. */
+ if (file_hdr->c_name != NULL)
+ 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 binary mode, the amount of space allocated in the header for
+ the filename is `c_namesize' rounded up to the next short-word,
+ so we might need to drop a byte. */
+ if (file_hdr->c_namesize % 2)
+ tape_toss_input (in_des, 1L);
+
+#ifndef __MSDOS__
+ /* HP/UX cpio creates archives that look just like ordinary archives,
+ but for devices it sets major = 0, minor = 1, and puts the
+ actual major/minor number in the filesize field. See if this
+ is an HP/UX cpio archive, and if so fix it. We have to do this
+ here because process_copy_in() assumes filesize is always 0
+ for devices. */
+ switch (file_hdr->c_mode & CP_IFMT)
+ {
+ case CP_IFCHR:
+ case CP_IFBLK:
+#ifdef CP_IFSOCK
+ case CP_IFSOCK:
+#endif
+#ifdef CP_IFIFO
+ case CP_IFIFO:
+#endif
+ if (file_hdr->c_filesize != 0
+ && file_hdr->c_rdev_maj == 0
+ && file_hdr->c_rdev_min == 1)
+ {
+ file_hdr->c_rdev_maj = major (file_hdr->c_filesize);
+ file_hdr->c_rdev_min = minor (file_hdr->c_filesize);
+ file_hdr->c_filesize = 0;
+ }
+ break;
+ default:
+ break;
+ }
+#endif /* __MSDOS__ */
+}
+
+/* Exchange the bytes of each element of the array of COUNT shorts
+ starting at PTR. */
+
+void
+swab_array (ptr, count)
+ char *ptr;
+ int count;
+{
+ char tmp;
+
+ while (count-- > 0)
+ {
+ tmp = *ptr;
+ *ptr = *(ptr + 1);
+ ++ptr;
+ *ptr = tmp;
+ ++ptr;
+ }
+}
+
+/* Current time for verbose table. */
+static time_t current_time;
+
+/* Read the collection from standard input and create files
+ in the file system. */
+
+void
+process_copy_in ()
+{
+ char done = FALSE; /* True if trailer reached. */
+ int res; /* Result of various function calls. */
+ dynamic_string new_name; /* New file name for rename option. */
+ FILE *tty_in; /* Interactive file for rename option. */
+ FILE *tty_out; /* Interactive file for rename option. */
+ FILE *rename_in; /* Batch file for rename option. */
+ char *str_res; /* Result for string function. */
+ struct utimbuf times; /* For setting file times. */
+ struct stat file_stat; /* Output file stat record. */
+ struct new_cpio_header file_hdr; /* Output header information. */
+ int out_file_des; /* Output file descriptor. */
+ int in_file_des; /* Input file descriptor. */
+ char skip_file; /* Flag for use with patterns. */
+ int existing_dir; /* True if file is a dir & already exists. */
+ int i; /* Loop index variable. */
+ char *link_name = NULL; /* Name of hard and symbolic links. */
+#ifdef HPUX_CDF
+ int cdf_flag; /* True if file is a CDF. */
+ int cdf_char; /* Index of `+' char indicating a CDF. */
+#endif
+
+ /* Initialize the copy in. */
+ if (pattern_file_name)
+ read_pattern_file ();
+ file_hdr.c_name = NULL;
+ ds_init (&new_name, 128);
+ /* Initialize this in case it has members we don't know to set. */
+ bzero (&times, sizeof (struct utimbuf));
+
+ if (rename_batch_file)
+ {
+ rename_in = fopen (rename_batch_file, "r");
+ if (rename_in == NULL)
+ error (2, errno, CONSOLE);
+ }
+ else if (rename_flag)
+ {
+ /* Open interactive file pair for rename operation. */
+ tty_in = fopen (CONSOLE, "r");
+ if (tty_in == NULL)
+ error (2, errno, CONSOLE);
+ tty_out = fopen (CONSOLE, "w");
+ if (tty_out == NULL)
+ error (2, errno, CONSOLE);
+ }
+
+ /* Get date and time if needed for processing the table option. */
+ if (table_flag && verbose_flag)
+ time (&current_time);
+
+#ifdef __MSDOS__
+ setmode (archive_des, O_BINARY);
+#endif
+ /* Check whether the input file might be a tape. */
+ in_file_des = archive_des;
+ if (_isrmt (in_file_des))
+ {
+ input_is_special = 1;
+ input_is_seekable = 0;
+ }
+ else
+ {
+ if (fstat (in_file_des, &file_stat))
+ error (1, errno, "standard input is closed");
+ input_is_special =
+#ifdef S_ISBLK
+ S_ISBLK (file_stat.st_mode) ||
+#endif
+ S_ISCHR (file_stat.st_mode);
+ input_is_seekable = S_ISREG (file_stat.st_mode);
+ }
+ output_is_seekable = TRUE;
+
+ /* While there is more input in the collection, process the input. */
+ while (!done)
+ {
+ link_name = NULL;
+ swapping_halfwords = swapping_bytes = FALSE;
+
+ /* Start processing the next file by reading the header. */
+ read_in_header (&file_hdr, in_file_des);
+
+#ifdef DEBUG_CPIO
+ if (debug_flag)
+ {
+ struct new_cpio_header *h;
+ h = &file_hdr;
+ fprintf (stderr,
+ "magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n",
+ h->c_magic, h->c_ino, h->c_mode, h->c_uid, h->c_gid);
+ fprintf (stderr,
+ "nlink = %d, mtime = %d, filesize = %d, dev_maj = 0x%x\n",
+ h->c_nlink, h->c_mtime, h->c_filesize, h->c_dev_maj);
+ fprintf (stderr,
+ "dev_min = 0x%x, rdev_maj = 0x%x, rdev_min = 0x%x, namesize = %d\n",
+ h->c_dev_min, h->c_rdev_maj, h->c_rdev_min, h->c_namesize);
+ fprintf (stderr,
+ "chksum = %d, name = \"%s\", tar_linkname = \"%s\"\n",
+ h->c_chksum, h->c_name,
+ h->c_tar_linkname ? h->c_tar_linkname : "(null)" );
+
+ }
+#endif
+ /* Is this the header for the TRAILER file? */
+ if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0)
+ {
+ done = TRUE;
+ break;
+ }
+
+ /* Do we have to ignore absolute paths, and if so, does the filename
+ have an absolute path? */
+ if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
+ {
+ char *p;
+
+ p = file_hdr.c_name;
+ while (*p == '/')
+ ++p;
+ if (*p == '\0')
+ {
+ strcpy (file_hdr.c_name, ".");
+ }
+ else
+ {
+ char *non_abs_name;
+
+ non_abs_name = (char *) xmalloc (strlen (p) + 1);
+ strcpy (non_abs_name, p);
+ free (file_hdr.c_name);
+ file_hdr.c_name = non_abs_name;
+ }
+ }
+
+ /* Does the file name match one of the given patterns? */
+ if (num_patterns <= 0)
+ skip_file = FALSE;
+ else
+ {
+ skip_file = copy_matching_files;
+ for (i = 0; i < num_patterns
+ && skip_file == copy_matching_files; i++)
+ {
+ if (fnmatch (save_patterns[i], file_hdr.c_name, 0) == 0)
+ skip_file = !copy_matching_files;
+ }
+ }
+
+ if (skip_file)
+ {
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ }
+ else if (table_flag)
+ {
+ if (verbose_flag)
+ {
+#ifdef CP_IFLNK
+ if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK)
+ {
+ if (archive_format != arf_tar && archive_format != arf_ustar)
+ {
+ 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);
+ long_format (&file_hdr, link_name);
+ free (link_name);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ continue;
+ }
+ else
+ {
+ long_format (&file_hdr, file_hdr.c_tar_linkname);
+ continue;
+ }
+ }
+ else
+#endif
+ long_format (&file_hdr, (char *) 0);
+ }
+ else
+ printf ("%s\n", file_hdr.c_name);
+
+ crc = 0;
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ if (only_verify_crc_flag)
+ {
+#ifdef CP_IFLNK
+ if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK)
+ continue; /* links don't have a checksum */
+#endif
+ if (crc != file_hdr.c_chksum)
+ error (0, 0, "%s: checksum error (0x%x, should be 0x%x)",
+ file_hdr.c_name, crc, file_hdr.c_chksum);
+ }
+ }
+ else if (append_flag)
+ {
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ }
+ else if (only_verify_crc_flag)
+ {
+#ifdef CP_IFLNK
+ if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK)
+ {
+ if (archive_format != arf_tar && archive_format != arf_ustar)
+ {
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ continue;
+ }
+ }
+#endif
+ crc = 0;
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ if (crc != file_hdr.c_chksum)
+ error (0, 0, "%s: checksum error (0x%x, should be 0x%x)",
+ file_hdr.c_name, crc, file_hdr.c_chksum);
+ }
+ else
+ {
+ /* Copy the input file into the directory structure. */
+
+ /* Do we need to rename the file? */
+ if (rename_flag || rename_batch_file)
+ {
+ if (rename_flag)
+ {
+ fprintf (tty_out, "rename %s -> ", file_hdr.c_name);
+ fflush (tty_out);
+ str_res = ds_fgets (tty_in, &new_name);
+ }
+ else
+ {
+ str_res = ds_fgetstr (rename_in, &new_name, '\n');
+ }
+ if (str_res == NULL || str_res[0] == 0)
+ {
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ continue;
+ }
+ else
+ file_hdr.c_name = xstrdup (new_name.ds_string);
+ }
+
+ /* See if the file already exists. */
+ existing_dir = FALSE;
+ if (lstat (file_hdr.c_name, &file_stat) == 0)
+ {
+ if (S_ISDIR (file_stat.st_mode)
+ && ((file_hdr.c_mode & CP_IFMT) == CP_IFDIR))
+ {
+ /* If there is already a directory there that
+ we are trying to create, don't complain about
+ it. */
+ existing_dir = TRUE;
+ }
+ else if (!unconditional_flag
+ && file_hdr.c_mtime <= file_stat.st_mtime)
+ {
+ error (0, 0, "%s not created: newer or same age version exists",
+ file_hdr.c_name);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ continue; /* Go to the next file. */
+ }
+ else if (S_ISDIR (file_stat.st_mode)
+ ? rmdir (file_hdr.c_name)
+ : unlink (file_hdr.c_name))
+ {
+ error (0, errno, "cannot remove current %s",
+ file_hdr.c_name);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ continue; /* Go to the next file. */
+ }
+ }
+
+ /* Do the real copy or link. */
+ switch (file_hdr.c_mode & CP_IFMT)
+ {
+ case CP_IFREG:
+#ifndef __MSDOS__
+ /* Can the current file be linked to a previously copied file? */
+ if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii
+ || archive_format == arf_crcascii) )
+ {
+ 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);
+ break;
+ }
+ /* 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). */
+ link_res = link_to_maj_min_ino (file_hdr.c_name,
+ file_hdr.c_dev_maj, file_hdr.c_dev_maj,
+ 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);
+ break;
+ }
+ }
+ else if (file_hdr.c_nlink > 1 && archive_format != arf_tar
+ && archive_format != arf_ustar)
+ {
+ int link_res;
+ link_res = link_to_maj_min_ino (file_hdr.c_name,
+ file_hdr.c_dev_maj, file_hdr.c_dev_maj,
+ 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);
+ break;
+ }
+ }
+ else if ((archive_format == arf_tar || archive_format == arf_ustar)
+ && file_hdr.c_tar_linkname &&
+ file_hdr.c_tar_linkname[0] != '\0')
+ {
+ int link_res;
+ link_res = link_to_name (file_hdr.c_name,
+ file_hdr.c_tar_linkname);
+ if (link_res < 0)
+ {
+ error (0, errno, "cannot link %s to %s",
+ file_hdr.c_tar_linkname, file_hdr.c_name);
+ }
+ break;
+ }
+#endif
+
+ /* If not linked, copy the contents of the file. */
+ if (link_name == NULL)
+ {
+ out_file_des = open (file_hdr.c_name,
+ O_CREAT | O_WRONLY | O_BINARY, 0600);
+ if (out_file_des < 0 && create_dir_flag)
+ {
+ create_all_directories (file_hdr.c_name);
+ out_file_des = open (file_hdr.c_name,
+ O_CREAT | O_WRONLY | O_BINARY,
+ 0600);
+ }
+ if (out_file_des < 0)
+ {
+ error (0, errno, "%s", file_hdr.c_name);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ continue;
+ }
+
+ crc = 0;
+ if (swap_halfwords_flag)
+ {
+ if ((file_hdr.c_filesize % 4) == 0)
+ swapping_halfwords = TRUE;
+ else
+ error (0, 0, "cannot swap halfwords of %s: odd number of halfwords",
+ file_hdr.c_name);
+ }
+ if (swap_bytes_flag)
+ {
+ if ((file_hdr.c_filesize % 2) == 0)
+ swapping_bytes = TRUE;
+ else
+ error (0, 0, "cannot swap bytes of %s: odd number of bytes",
+ file_hdr.c_name);
+ }
+ copy_files_tape_to_disk (in_file_des, out_file_des, file_hdr.c_filesize);
+ disk_empty_output_buffer (out_file_des);
+ if (close (out_file_des) < 0)
+ error (0, errno, "%s", file_hdr.c_name);
+
+ if (archive_format == arf_crcascii)
+ {
+ if (crc != file_hdr.c_chksum)
+ error (0, 0, "%s: checksum error (0x%x, should be 0x%x)",
+ file_hdr.c_name, crc, file_hdr.c_chksum);
+ }
+ /* File is now copied; set attributes. */
+ if (!no_chown_flag)
+ if ((chown (file_hdr.c_name,
+ set_owner_flag ? set_owner : file_hdr.c_uid,
+ set_group_flag ? set_group : file_hdr.c_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", file_hdr.c_name);
+ /* chown may have turned off some permissions we wanted. */
+ if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0)
+ error (0, errno, "%s", file_hdr.c_name);
+ if (retain_time_flag)
+ {
+ times.actime = times.modtime = file_hdr.c_mtime;
+ if (utime (file_hdr.c_name, &times) < 0)
+ error (0, errno, "%s", file_hdr.c_name);
+ }
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii
+ || archive_format == arf_crcascii) )
+ {
+ /* (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);
+ }
+ }
+ break;
+
+ case CP_IFDIR:
+ /* 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')
+ break;
+
+#ifdef HPUX_CDF
+ cdf_flag = 0;
+#endif
+ if (!existing_dir)
+
+ {
+#ifdef HPUX_CDF
+ /* If the directory name ends in a + and is SUID,
+ then it is a CDF. Strip the trailing + from
+ the name before creating it. */
+ cdf_char = strlen (file_hdr.c_name) - 1;
+ if ( (cdf_char > 0) &&
+ (file_hdr.c_mode & 04000) &&
+ (file_hdr.c_name [cdf_char] == '+') )
+ {
+ file_hdr.c_name [cdf_char] = '\0';
+ cdf_flag = 1;
+ }
+#endif
+ res = mkdir (file_hdr.c_name, file_hdr.c_mode);
+ }
+ else
+ res = 0;
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (file_hdr.c_name);
+ res = mkdir (file_hdr.c_name, file_hdr.c_mode);
+ }
+ 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. */
+ if ( (errno != EEXIST) ||
+ (lstat (file_hdr.c_name, &file_stat) != 0) ||
+ !(S_ISDIR (file_stat.st_mode) ) )
+ {
+ error (0, errno, "%s", file_hdr.c_name);
+ continue;
+ }
+ }
+ if (!no_chown_flag)
+ if ((chown (file_hdr.c_name,
+ set_owner_flag ? set_owner : file_hdr.c_uid,
+ set_group_flag ? set_group : file_hdr.c_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", file_hdr.c_name);
+ /* chown may have turned off some permissions we wanted. */
+ if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0)
+ error (0, errno, "%s", file_hdr.c_name);
+#ifdef HPUX_CDF
+ if (cdf_flag)
+ /* Once we "hide" the directory with the chmod(),
+ we have to refer to it using name+ instead of name. */
+ file_hdr.c_name [cdf_char] = '+';
+#endif
+ if (retain_time_flag)
+ {
+ times.actime = times.modtime = file_hdr.c_mtime;
+ if (utime (file_hdr.c_name, &times) < 0)
+ error (0, errno, "%s", file_hdr.c_name);
+ }
+ break;
+
+#ifndef __MSDOS__
+ case CP_IFCHR:
+ case CP_IFBLK:
+#ifdef CP_IFSOCK
+ case CP_IFSOCK:
+#endif
+#ifdef CP_IFIFO
+ case CP_IFIFO:
+#endif
+ if (file_hdr.c_nlink > 1 && archive_format != arf_tar
+ && archive_format != arf_ustar)
+ {
+ int link_res;
+ link_res = link_to_maj_min_ino (file_hdr.c_name,
+ file_hdr.c_dev_maj, file_hdr.c_dev_maj,
+ file_hdr.c_ino);
+ if (link_res == 0)
+ break;
+ }
+ else if (archive_format == arf_ustar &&
+ file_hdr.c_tar_linkname &&
+ file_hdr.c_tar_linkname [0] != '\0')
+ {
+ int link_res;
+ link_res = link_to_name (file_hdr.c_name,
+ file_hdr.c_tar_linkname);
+ if (link_res < 0)
+ {
+ error (0, errno, "cannot link %s to %s",
+ file_hdr.c_tar_linkname, file_hdr.c_name);
+ /* Something must be wrong, because we couldn't
+ find the file to link to. But can we assume
+ that the device maj/min numbers are correct
+ and fall through to the mknod? It's probably
+ safer to just break, rather than possibly
+ creating a bogus device file. */
+ }
+ break;
+ }
+
+#ifdef CP_IFIFO
+ if ((file_hdr.c_mode & CP_IFMT) == CP_IFIFO)
+ res = mkfifo (file_hdr.c_name, file_hdr.c_mode);
+ else
+#endif
+ res = mknod (file_hdr.c_name, file_hdr.c_mode,
+ makedev (file_hdr.c_rdev_maj, file_hdr.c_rdev_min));
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (file_hdr.c_name);
+#ifdef CP_IFIFO
+ if ((file_hdr.c_mode & CP_IFMT) == CP_IFIFO)
+ res = mkfifo (file_hdr.c_name, file_hdr.c_mode);
+ else
+#endif
+ res = mknod (file_hdr.c_name, file_hdr.c_mode,
+ makedev (file_hdr.c_rdev_maj,
+ file_hdr.c_rdev_min));
+ }
+ if (res < 0)
+ {
+ error (0, errno, "%s", file_hdr.c_name);
+ continue;
+ }
+ if (!no_chown_flag)
+ if ((chown (file_hdr.c_name,
+ set_owner_flag ? set_owner : file_hdr.c_uid,
+ set_group_flag ? set_group : file_hdr.c_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", file_hdr.c_name);
+ /* chown may have turned off some permissions we wanted. */
+ if (chmod (file_hdr.c_name, file_hdr.c_mode) < 0)
+ error (0, errno, "%s", file_hdr.c_name);
+ if (retain_time_flag)
+ {
+ times.actime = times.modtime = file_hdr.c_mtime;
+ if (utime (file_hdr.c_name, &times) < 0)
+ error (0, errno, "%s", file_hdr.c_name);
+ }
+ break;
+#endif
+
+#ifdef CP_IFLNK
+ case CP_IFLNK:
+ {
+ if (archive_format != arf_tar && archive_format != arf_ustar)
+ {
+ 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);
+ }
+ else
+ {
+ link_name = xstrdup (file_hdr.c_tar_linkname);
+ }
+
+ res = UMASKED_SYMLINK (link_name, file_hdr.c_name,
+ file_hdr.c_mode);
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (file_hdr.c_name);
+ res = UMASKED_SYMLINK (link_name, file_hdr.c_name,
+ file_hdr.c_mode);
+ }
+ if (res < 0)
+ {
+ error (0, errno, "%s", file_hdr.c_name);
+ free (link_name);
+ link_name = NULL;
+ continue;
+ }
+ if (!no_chown_flag)
+ if ((lchown (file_hdr.c_name,
+ set_owner_flag ? set_owner : file_hdr.c_uid,
+ set_group_flag ? set_group : file_hdr.c_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", file_hdr.c_name);
+ free (link_name);
+ link_name = NULL;
+ }
+ break;
+#endif
+
+ default:
+ error (0, 0, "%s: unknown file type", file_hdr.c_name);
+ tape_toss_input (in_file_des, file_hdr.c_filesize);
+ tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ }
+
+ if (verbose_flag)
+ fprintf (stderr, "%s\n", file_hdr.c_name);
+ if (dot_flag)
+ fputc ('.', stderr);
+ }
+ }
+
+ if (dot_flag)
+ fputc ('\n', stderr);
+
+ if (append_flag)
+ return;
+
+ if (archive_format == arf_newascii || archive_format == arf_crcascii)
+ create_final_defers ();
+ if (!quiet_flag)
+ {
+ res = (input_bytes + io_block_size - 1) / io_block_size;
+ if (res == 1)
+ fprintf (stderr, "1 block\n");
+ else
+ fprintf (stderr, "%d blocks\n", res);
+ }
+}
+
+/* Print the file described by FILE_HDR in long format.
+ If LINK_NAME is nonzero, it is the name of the file that
+ this file is a symbolic link to. */
+
+void
+long_format (file_hdr, link_name)
+ struct new_cpio_header *file_hdr;
+ char *link_name;
+{
+ char mbuf[11];
+ char tbuf[40];
+ time_t when;
+
+ mode_string (file_hdr->c_mode, mbuf);
+ mbuf[10] = '\0';
+
+ /* Get time values ready to print. */
+ when = file_hdr->c_mtime;
+#ifdef HAVE_STRFTIME
+ strftime(tbuf, sizeof(tbuf), "%c", localtime(&when));
+#else
+ strcpy (tbuf, ctime (&when));
+#endif
+ if (current_time - when > 6L * 30L * 24L * 60L * 60L
+ || current_time - when < 0L)
+ {
+ /* The file is older than 6 months, or in the future.
+ Show the year instead of the time of day. */
+ strcpy (tbuf + 11, tbuf + 19);
+ }
+ tbuf[16] = '\0';
+
+ printf ("%s %3u ", mbuf, file_hdr->c_nlink);
+
+#ifndef __MSDOS__
+ if (numeric_uid)
+#endif
+ printf ("%-8u %-8u ", (unsigned int) file_hdr->c_uid,
+ (unsigned int) file_hdr->c_gid);
+#ifndef __MSDOS__
+ else
+ printf ("%-8.8s %-8.8s ", getuser (file_hdr->c_uid),
+ getgroup (file_hdr->c_gid));
+
+ if ((file_hdr->c_mode & CP_IFMT) == CP_IFCHR
+ || (file_hdr->c_mode & CP_IFMT) == CP_IFBLK)
+ printf ("%3u, %3u ", file_hdr->c_rdev_maj,
+ file_hdr->c_rdev_min);
+ else
+#endif
+ printf ("%8lu ", file_hdr->c_filesize);
+
+ printf ("%s ", tbuf + 4);
+
+ print_name_with_quoting (file_hdr->c_name);
+ if (link_name)
+ {
+ printf (" -> ");
+ print_name_with_quoting (link_name);
+ }
+ putc ('\n', stdout);
+}
+
+void
+print_name_with_quoting (p)
+ register char *p;
+{
+ register unsigned char c;
+
+ while ( (c = *p++) )
+ {
+ switch (c)
+ {
+#ifndef __MSDOS__
+ case '\\':
+ printf ("\\\\");
+ break;
+#endif
+
+ case '\n':
+ printf ("\\n");
+ break;
+
+ case '\b':
+ printf ("\\b");
+ break;
+
+ case '\r':
+ printf ("\\r");
+ break;
+
+ case '\t':
+ printf ("\\t");
+ break;
+
+ case '\f':
+ printf ("\\f");
+ break;
+
+ case ' ':
+ printf ("\\ ");
+ break;
+
+ case '"':
+ printf ("\\\"");
+ break;
+
+ default:
+#if (defined(BSD) && (BSD >= 199306))
+ if (isprint(c))
+#else
+ if (c > 040 &&
+#ifdef __MSDOS__
+ c < 0377 && c != 0177
+#else
+ c < 0177
+#endif
+ )
+#endif
+ putchar (c);
+ else
+ printf ("\\%03o", (unsigned int) c);
+ }
+ }
+}
+
+/* Read a pattern file (for the -E option). Put a list of
+ `num_patterns' elements in `save_patterns'. Any patterns that were
+ already in `save_patterns' (from the command line) are preserved. */
+
+static void
+read_pattern_file ()
+{
+ int max_new_patterns;
+ char **new_save_patterns;
+ int new_num_patterns;
+ int i;
+ dynamic_string pattern_name;
+ FILE *pattern_fp;
+
+ if (num_patterns < 0)
+ num_patterns = 0;
+ max_new_patterns = 1 + num_patterns;
+ new_save_patterns = (char **) xmalloc (max_new_patterns * sizeof (char *));
+ new_num_patterns = num_patterns;
+ ds_init (&pattern_name, 128);
+
+ pattern_fp = fopen (pattern_file_name, "r");
+ if (pattern_fp == NULL)
+ error (1, errno, "%s", pattern_file_name);
+ while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL)
+ {
+ if (new_num_patterns >= max_new_patterns)
+ {
+ max_new_patterns += 1;
+ new_save_patterns = (char **)
+ xrealloc ((char *) new_save_patterns,
+ max_new_patterns * sizeof (char *));
+ }
+ new_save_patterns[new_num_patterns] = xstrdup (pattern_name.ds_string);
+ ++new_num_patterns;
+ }
+ if (ferror (pattern_fp) || fclose (pattern_fp) == EOF)
+ error (1, errno, "%s", pattern_file_name);
+
+ for (i = 0; i < num_patterns; ++i)
+ new_save_patterns[i] = save_patterns[i];
+
+ save_patterns = new_save_patterns;
+ num_patterns = new_num_patterns;
+}
+
+/* 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 (in_file_des, offset)
+ int in_file_des;
+ int offset;
+{
+ int pad;
+
+ if (archive_format == arf_crcascii || archive_format == arf_newascii)
+ pad = (4 - (offset % 4)) % 4;
+ else if (archive_format == arf_binary || archive_format == arf_hpbinary)
+ pad = (2 - (offset % 2)) % 2;
+ else if (archive_format == arf_tar || archive_format == arf_ustar)
+ pad = (512 - (offset % 512)) % 512;
+ else
+ pad = 0;
+
+ if (pad != 0)
+ tape_toss_input (in_file_des, pad);
+}
+
+
+/* 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 (file_hdr)
+ 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 (file_hdr)
+ 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)
+ {
+ error (0, errno, "cannot link %s to %s",
+ d->header.c_name, file_hdr->c_name);
+ }
+ 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 ()
+{
+ 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. */
+ bzero (&times, sizeof (struct utimbuf));
+
+ for (d = deferments; d != NULL; d = d->next)
+ {
+ link_res = link_to_maj_min_ino (d->header.c_name,
+ d->header.c_dev_maj, d->header.c_dev_maj,
+ d->header.c_ino);
+ if (link_res == 0)
+ {
+ continue;
+ }
+ out_file_des = open (d->header.c_name,
+ O_CREAT | O_WRONLY | O_BINARY, 0600);
+ if (out_file_des < 0 && create_dir_flag)
+ {
+ create_all_directories (d->header.c_name);
+ out_file_des = open (d->header.c_name,
+ O_CREAT | O_WRONLY | O_BINARY,
+ 0600);
+ }
+ if (out_file_des < 0)
+ {
+ error (0, errno, "%s", d->header.c_name);
+ continue;
+ }
+
+ if (close (out_file_des) < 0)
+ error (0, errno, "%s", d->header.c_name);
+
+ /* File is now copied; set attributes. */
+ if (!no_chown_flag)
+ if ((chown (d->header.c_name,
+ set_owner_flag ? set_owner : d->header.c_uid,
+ set_group_flag ? set_group : d->header.c_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", d->header.c_name);
+ /* chown may have turned off some permissions we wanted. */
+ if (chmod (d->header.c_name, (int) d->header.c_mode) < 0)
+ error (0, errno, "%s", d->header.c_name);
+ if (retain_time_flag)
+ {
+ times.actime = times.modtime = d->header.c_mtime;
+ if (utime (d->header.c_name, &times) < 0)
+ error (0, errno, "%s", d->header.c_name);
+ }
+ }
+}
diff --git a/contrib/cpio/copypass.c b/contrib/cpio/copypass.c
new file mode 100644
index 000000000000..9c27ac596348
--- /dev/null
+++ b/contrib/cpio/copypass.c
@@ -0,0 +1,474 @@
+/* copypass.c - cpio copy pass sub-function.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "filetypes.h"
+#include "system.h"
+#include "cpiohdr.h"
+#include "dstring.h"
+#include "extern.h"
+
+#ifndef HAVE_LCHOWN
+#define lchown chown
+#endif
+
+/* Copy files listed on the standard input into directory `directory_name'.
+ If `link_flag', link instead of copying. */
+
+void
+process_copy_pass ()
+{
+ dynamic_string input_name; /* Name of file from stdin. */
+ dynamic_string output_name; /* Name of new file. */
+ int dirname_len; /* Length of `directory_name'. */
+ int res; /* Result of functions. */
+ char *slash; /* For moving past slashes in input name. */
+ struct utimbuf times; /* For resetting file times after copy. */
+ struct stat in_file_stat; /* Stat record for input file. */
+ struct stat out_file_stat; /* Stat record for output file. */
+ int in_file_des; /* Input file descriptor. */
+ int out_file_des; /* Output file descriptor. */
+ int existing_dir; /* True if file is a dir & already exists. */
+#ifdef HPUX_CDF
+ int cdf_flag;
+ int cdf_char;
+#endif
+
+ /* Initialize the copy pass. */
+ dirname_len = strlen (directory_name);
+ ds_init (&input_name, 128);
+ ds_init (&output_name, dirname_len + 2);
+ strcpy (output_name.ds_string, directory_name);
+ output_name.ds_string[dirname_len] = '/';
+ output_is_seekable = TRUE;
+ /* Initialize this in case it has members we don't know to set. */
+ bzero (&times, sizeof (struct utimbuf));
+
+ /* Copy files with names read from stdin. */
+ while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
+ {
+ int link_res = -1;
+
+ /* Check for blank line and ignore it if found. */
+ if (input_name.ds_string[0] == '\0')
+ {
+ error (0, 0, "blank line ignored");
+ continue;
+ }
+
+ /* Check for current directory and ignore it if found. */
+ if (input_name.ds_string[0] == '.'
+ && (input_name.ds_string[1] == '\0'
+ || (input_name.ds_string[1] == '/'
+ && input_name.ds_string[2] == '\0')))
+ continue;
+
+ if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
+ {
+ error (0, errno, "%s", input_name.ds_string);
+ continue;
+ }
+
+ /* Make the name of the new file. */
+ for (slash = input_name.ds_string; *slash == '/'; ++slash)
+ ;
+#ifdef HPUX_CDF
+ /* For CDF's we add a 2nd `/' after all "hidden" directories.
+ This kind of a kludge, but it's what we do when creating
+ archives, and it's easier to do this than to separately
+ keep track of which directories in a path are "hidden". */
+ slash = add_cdf_double_slashes (slash);
+#endif
+ ds_resize (&output_name, dirname_len + strlen (slash) + 2);
+ strcpy (output_name.ds_string + dirname_len + 1, slash);
+
+ existing_dir = FALSE;
+ if (lstat (output_name.ds_string, &out_file_stat) == 0)
+ {
+ if (S_ISDIR (out_file_stat.st_mode)
+ && S_ISDIR (in_file_stat.st_mode))
+ {
+ /* If there is already a directory there that
+ we are trying to create, don't complain about it. */
+ existing_dir = TRUE;
+ }
+ else if (!unconditional_flag
+ && in_file_stat.st_mtime <= out_file_stat.st_mtime)
+ {
+ error (0, 0, "%s not created: newer or same age version exists",
+ output_name.ds_string);
+ continue; /* Go to the next file. */
+ }
+ else if (S_ISDIR (out_file_stat.st_mode)
+ ? rmdir (output_name.ds_string)
+ : unlink (output_name.ds_string))
+ {
+ error (0, errno, "cannot remove current %s",
+ output_name.ds_string);
+ continue; /* Go to the next file. */
+ }
+ }
+
+ /* Do the real copy or link. */
+ if (S_ISREG (in_file_stat.st_mode))
+ {
+#ifndef __MSDOS__
+ /* Can the current file be linked to a another file?
+ Set link_name to the original file name. */
+ if (link_flag)
+ /* User said to link it if possible. Try and link to
+ the original copy. If that fails we'll still try
+ and link to a copy we've already made. */
+ link_res = link_to_name (output_name.ds_string,
+ input_name.ds_string);
+ if ( (link_res < 0) && (in_file_stat.st_nlink > 1) )
+ link_res = link_to_maj_min_ino (output_name.ds_string,
+ major (in_file_stat.st_dev),
+ minor (in_file_stat.st_dev),
+ in_file_stat.st_ino);
+#endif
+
+ /* If the file was not linked, copy contents of file. */
+ if (link_res < 0)
+ {
+ in_file_des = open (input_name.ds_string,
+ O_RDONLY | O_BINARY, 0);
+ if (in_file_des < 0)
+ {
+ error (0, errno, "%s", input_name.ds_string);
+ continue;
+ }
+ out_file_des = open (output_name.ds_string,
+ O_CREAT | O_WRONLY | O_BINARY, 0600);
+ if (out_file_des < 0 && create_dir_flag)
+ {
+ create_all_directories (output_name.ds_string);
+ out_file_des = open (output_name.ds_string,
+ O_CREAT | O_WRONLY | O_BINARY, 0600);
+ }
+ if (out_file_des < 0)
+ {
+ error (0, errno, "%s", output_name.ds_string);
+ close (in_file_des);
+ continue;
+ }
+
+ copy_files_disk_to_disk (in_file_des, out_file_des, in_file_stat.st_size, input_name.ds_string);
+ disk_empty_output_buffer (out_file_des);
+ if (close (in_file_des) < 0)
+ error (0, errno, "%s", input_name.ds_string);
+ if (close (out_file_des) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+
+ /* Set the attributes of the new file. */
+ if (!no_chown_flag)
+ if ((chown (output_name.ds_string,
+ set_owner_flag ? set_owner : in_file_stat.st_uid,
+ set_group_flag ? set_group : in_file_stat.st_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", output_name.ds_string);
+ /* chown may have turned off some permissions we wanted. */
+ if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+ if (reset_time_flag)
+ {
+ times.actime = in_file_stat.st_atime;
+ times.modtime = in_file_stat.st_mtime;
+ if (utime (input_name.ds_string, &times) < 0)
+ error (0, errno, "%s", input_name.ds_string);
+ if (utime (output_name.ds_string, &times) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+ }
+ if (retain_time_flag)
+ {
+ times.actime = times.modtime = in_file_stat.st_mtime;
+ if (utime (output_name.ds_string, &times) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+ }
+ }
+ }
+ else if (S_ISDIR (in_file_stat.st_mode))
+ {
+#ifdef HPUX_CDF
+ cdf_flag = 0;
+#endif
+ if (!existing_dir)
+ {
+#ifdef HPUX_CDF
+ /* If the directory name ends in a + and is SUID,
+ then it is a CDF. Strip the trailing + from the name
+ before creating it. */
+ cdf_char = strlen (output_name.ds_string) - 1;
+ if ( (cdf_char > 0) &&
+ (in_file_stat.st_mode & 04000) &&
+ (output_name.ds_string [cdf_char] == '+') )
+ {
+ output_name.ds_string [cdf_char] = '\0';
+ cdf_flag = 1;
+ }
+#endif
+ res = mkdir (output_name.ds_string, in_file_stat.st_mode);
+
+ }
+ else
+ res = 0;
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (output_name.ds_string);
+ res = mkdir (output_name.ds_string, in_file_stat.st_mode);
+ }
+ if (res < 0)
+ {
+ /* In some odd cases where the output_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. */
+ if ( (errno != EEXIST) ||
+ (lstat (output_name.ds_string, &out_file_stat) != 0) ||
+ !(S_ISDIR (out_file_stat.st_mode) ) )
+ {
+ error (0, errno, "%s", output_name.ds_string);
+ continue;
+ }
+ }
+ if (!no_chown_flag)
+ if ((chown (output_name.ds_string,
+ set_owner_flag ? set_owner : in_file_stat.st_uid,
+ set_group_flag ? set_group : in_file_stat.st_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", output_name.ds_string);
+ /* chown may have turned off some permissions we wanted. */
+ if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+#ifdef HPUX_CDF
+ if (cdf_flag)
+ /* Once we "hide" the directory with the chmod(),
+ we have to refer to it using name+ isntead of name. */
+ output_name.ds_string [cdf_char] = '+';
+#endif
+ if (retain_time_flag)
+ {
+ times.actime = times.modtime = in_file_stat.st_mtime;
+ if (utime (output_name.ds_string, &times) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+ }
+ }
+#ifndef __MSDOS__
+ else if (S_ISCHR (in_file_stat.st_mode) ||
+ S_ISBLK (in_file_stat.st_mode) ||
+#ifdef S_ISFIFO
+ S_ISFIFO (in_file_stat.st_mode) ||
+#endif
+#ifdef S_ISSOCK
+ S_ISSOCK (in_file_stat.st_mode) ||
+#endif
+ 0)
+ {
+ /* Can the current file be linked to a another file?
+ Set link_name to the original file name. */
+ if (link_flag)
+ /* User said to link it if possible. */
+ link_res = link_to_name (output_name.ds_string,
+ input_name.ds_string);
+ if ( (link_res < 0) && (in_file_stat.st_nlink > 1) )
+ link_res = link_to_maj_min_ino (output_name.ds_string,
+ major (in_file_stat.st_dev),
+ minor (in_file_stat.st_dev),
+ in_file_stat.st_ino);
+
+ if (link_res < 0)
+ {
+#ifdef S_ISFIFO
+ if (S_ISFIFO (in_file_stat.st_mode))
+ res = mkfifo (output_name.ds_string, in_file_stat.st_mode);
+ else
+#endif
+ res = mknod (output_name.ds_string, in_file_stat.st_mode,
+ in_file_stat.st_rdev);
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (output_name.ds_string);
+#ifdef S_ISFIFO
+ if (S_ISFIFO (in_file_stat.st_mode))
+ res = mkfifo (output_name.ds_string, in_file_stat.st_mode);
+ else
+#endif
+ res = mknod (output_name.ds_string, in_file_stat.st_mode,
+ in_file_stat.st_rdev);
+ }
+ if (res < 0)
+ {
+ error (0, errno, "%s", output_name.ds_string);
+ continue;
+ }
+ if (!no_chown_flag)
+ if ((chown (output_name.ds_string,
+ set_owner_flag ? set_owner : in_file_stat.st_uid,
+ set_group_flag ? set_group : in_file_stat.st_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", output_name.ds_string);
+ /* chown may have turned off some permissions we wanted. */
+ if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+ if (retain_time_flag)
+ {
+ times.actime = times.modtime = in_file_stat.st_mtime;
+ if (utime (output_name.ds_string, &times) < 0)
+ error (0, errno, "%s", output_name.ds_string);
+ }
+ }
+ }
+#endif
+
+#ifdef S_ISLNK
+ else if (S_ISLNK (in_file_stat.st_mode))
+ {
+ char *link_name;
+ int link_size;
+ link_name = (char *) xmalloc ((unsigned int) in_file_stat.st_size + 1);
+
+ link_size = readlink (input_name.ds_string, link_name,
+ in_file_stat.st_size);
+ if (link_size < 0)
+ {
+ error (0, errno, "%s", input_name.ds_string);
+ free (link_name);
+ continue;
+ }
+ link_name[link_size] = '\0';
+
+ res = UMASKED_SYMLINK (link_name, output_name.ds_string,
+ in_file_stat.st_mode);
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (output_name.ds_string);
+ res = UMASKED_SYMLINK (link_name, output_name.ds_string,
+ in_file_stat.st_mode);
+ }
+ if (res < 0)
+ {
+ error (0, errno, "%s", output_name.ds_string);
+ free (link_name);
+ continue;
+ }
+
+ /* Set the attributes of the new link. */
+ if (!no_chown_flag)
+ if ((lchown (output_name.ds_string,
+ set_owner_flag ? set_owner : in_file_stat.st_uid,
+ set_group_flag ? set_group : in_file_stat.st_gid) < 0)
+ && errno != EPERM)
+ error (0, errno, "%s", output_name.ds_string);
+ free (link_name);
+ }
+#endif
+ else
+ {
+ error (0, 0, "%s: unknown file type", input_name.ds_string);
+ }
+
+ if (verbose_flag)
+ fprintf (stderr, "%s\n", output_name.ds_string);
+ if (dot_flag)
+ fputc ('.', stderr);
+ }
+
+ if (dot_flag)
+ fputc ('\n', stderr);
+ if (!quiet_flag)
+ {
+ res = (output_bytes + io_block_size - 1) / io_block_size;
+ if (res == 1)
+ fprintf (stderr, "1 block\n");
+ else
+ fprintf (stderr, "%d blocks\n", res);
+ }
+}
+
+/* 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. */
+
+int
+link_to_maj_min_ino (file_name, st_dev_maj, st_dev_min, st_ino)
+ char *file_name;
+ int st_dev_maj;
+ int st_dev_min;
+ int st_ino;
+{
+ int link_res;
+ char *link_name;
+ link_res = -1;
+#ifndef __MSDOS__
+ /* 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);
+#endif
+ return link_res;
+}
+
+/* Try and create a hard link from LINK_NAME to LINK_TARGET. If
+ `create_dir_flag' is set, any non-existent (parent) directories
+ needed by LINK_NAME will be created. If the link is successfully
+ created and `verbose_flag' is set, print "LINK_TARGET linked to LINK_NAME\n".
+ If the link can not be created and `link_flag' is set, print
+ "cannot link LINK_TARGET to LINK_NAME\n". Return 0 if the link
+ is created, -1 otherwise. */
+
+int
+link_to_name (link_name, link_target)
+ char *link_name;
+ char *link_target;
+{
+ int res;
+#ifdef __MSDOS__
+ res = -1;
+#else /* not __MSDOS__ */
+ res = link (link_target, link_name);
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (link_name);
+ res = link (link_target, link_name);
+ }
+ if (res == 0)
+ {
+ if (verbose_flag)
+ error (0, 0, "%s linked to %s",
+ link_target, link_name);
+ }
+ else if (link_flag)
+ {
+ error (0, errno, "cannot link %s to %s",
+ link_target, link_name);
+ }
+#endif /* not __MSDOS__ */
+ return res;
+}
diff --git a/lib/libalias/alias_old.c b/lib/libalias/alias_old.c
new file mode 100644
index 000000000000..3f634d448411
--- /dev/null
+++ b/lib/libalias/alias_old.c
@@ -0,0 +1,77 @@
+/*
+ This file can be considered a junk pile of old functions that
+ are either obsolete or have had their names changed. In the
+ transition from alias2.1 to alias2.2, all the function names
+ were rationalized so that they began with "PacketAlias..."
+
+ These functions are included for backwards compatibility.
+*/
+
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include "alias.h"
+#include "alias_local.h"
+
+void
+InitPacketAlias(void)
+{
+ PacketAliasInit();
+}
+
+void
+SetPacketAliasAddress(struct in_addr addr)
+{
+ PacketAliasSetAddress(addr);
+}
+
+unsigned int
+SetPacketAliasMode(unsigned int flags, unsigned int mask)
+{
+ return PacketAliasSetMode(flags, mask);
+}
+
+int
+PacketAliasPermanentLink(struct in_addr src_addr, u_short src_port,
+ struct in_addr dst_addr, u_short dst_port,
+ u_short alias_port, u_char proto)
+{
+ struct alias_link *link;
+ struct in_addr null_address;
+
+ null_address.s_addr = 0;
+ link = PacketAliasRedirectPort(src_addr, src_port,
+ dst_addr, dst_port,
+ null_address, alias_port,
+ proto);
+
+ if (link == NULL)
+ return -1;
+ else
+ return 0;
+}
+
+int
+SaveFragmentPtr(char *ptr)
+{
+ return PacketAliasSaveFragment(ptr);
+}
+
+char *
+GetNextFragmentPtr(char *ptr)
+{
+ return PacketAliasGetFragment(ptr);
+}
+
+void
+FragmentAliasIn(char *header, char *fragment)
+{
+ PacketAliasFragmentIn(header, fragment);
+}
+
+u_short
+InternetChecksum(u_short *ptr, int len)
+{
+ return PacketAliasInternetChecksum(ptr, len);
+}
diff --git a/lib/libc/gen/sysctlbyname.c b/lib/libc/gen/sysctlbyname.c
new file mode 100644
index 000000000000..9c4f34653cc0
--- /dev/null
+++ b/lib/libc/gen/sysctlbyname.c
@@ -0,0 +1,35 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $Id: sysctlbyname.c,v 1.1 1997/05/30 20:53:13 phk Exp $
+ *
+ */
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+int
+sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
+ size_t newlen)
+{
+ int name2oid_oid[2];
+ int real_oid[CTL_MAXNAME+2];
+ int error, oidlen;
+
+ name2oid_oid[0] = 0; /* This is magic & undocumented! */
+ name2oid_oid[1] = 3;
+
+ oidlen = sizeof(real_oid);
+ error = sysctl(name2oid_oid, 2, real_oid, &oidlen, (void *)name,
+ strlen(name));
+ if (error < 0)
+ return error;
+ oidlen /= sizeof (int);
+ error = sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen);
+ return (error);
+}
+
diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3
new file mode 100644
index 000000000000..bdda0e348cd1
--- /dev/null
+++ b/lib/libc/stdtime/strptime.3
@@ -0,0 +1,85 @@
+.\"
+.\" Copyright (c) 1997 Joerg Wunsch
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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.
+.\"
+.\" $Id$
+.\" "
+.Dd May 8, 1997
+.Dt STRPTIME 3
+.Os
+.Sh NAME
+.Nm strptime
+.Nd parse date and time string
+.Sh SYNOPSIS
+.Fd #include <time.h>
+.Ft const char *
+.Fn strptime "const char *buf" "const char *format" "struct tm *timeptr"
+.Sh DESCRIPTION
+The
+.Fn strptime
+function parses the string in the buffer
+.Fa buf
+according to the string pointed to by
+.Fa format ,
+and fills in the elements of the structure pointed to by
+.Fa timeptr .
+Thus, it can be considered the reverse operation of
+.Xr strftime 3 .
+.Pp
+The
+.Fa format
+string consists of zero or more conversion specifications and
+ordinary characters.
+All ordinary characters are matched exactly with the buffer, where
+white space in the format string will match any amount of white space
+in the buffer.
+All conversion specifications are identical to those described in
+.Xr strftime 3 .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn strptime
+returns the pointer to the first character in
+.Fa buf
+that has not been required to satisfy the specified conversions in
+.Fa format .
+It returns
+.Dv NULL
+if one of the conversions failed.
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr scanf 3 ,
+.Xr strftime 3
+.Sh AUTHORS
+The
+.Fn strptime
+function has been contributed by Powerdog Industries.
+.Pp
+This man page was written by
+.ie t J\(:org Wunsch.
+.el Joerg Wunsch.
+.Sh HISTORY
+The
+.Fn strptime
+function appeared in
+.Fx 3.0 .
diff --git a/lib/libc/stdtime/timelocal.c b/lib/libc/stdtime/timelocal.c
new file mode 100644
index 000000000000..ef40035c09f4
--- /dev/null
+++ b/lib/libc/stdtime/timelocal.c
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 1997 FreeBSD Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/syslimits.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include "setlocale.h"
+#include "timelocal.h"
+
+struct lc_time_T _time_localebuf;
+int _time_using_locale;
+
+const struct lc_time_T _C_time_locale = {
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ }, {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+ }, {
+ "Sun", "Mon", "Tue", "Wed",
+ "Thu", "Fri", "Sat"
+ }, {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"
+ },
+
+ /* X_fmt */
+ "%H:%M:%S",
+
+ /*
+ ** x_fmt
+ ** Since the C language standard calls for
+ ** "date, using locale's date format," anything goes.
+ ** Using just numbers (as here) makes Quakers happier;
+ ** it's also compatible with SVR4.
+ */
+ "%m/%d/%y",
+
+ /*
+ ** c_fmt (ctime-compatible)
+ ** Note that
+ ** "%a %b %d %H:%M:%S %Y"
+ ** is used by Solaris 2.3.
+ */
+ "%a %b %e %X %Y",
+
+ /* am */
+ "AM",
+
+ /* pm */
+ "PM",
+
+ /* date_fmt */
+ "%a %b %e %X %Z %Y"
+};
+
+
+int
+__time_load_locale(const char *name)
+{
+ static char * locale_buf;
+ static char locale_buf_C[] = "C";
+
+ int fd;
+ char * lbuf;
+ char * p;
+ const char ** ap;
+ const char * plim;
+ char filename[PATH_MAX];
+ struct stat st;
+ size_t namesize;
+ size_t bufsize;
+ int save_using_locale;
+
+ save_using_locale = _time_using_locale;
+ _time_using_locale = 0;
+
+ if (name == NULL)
+ goto no_locale;
+
+ if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
+ return 0;
+
+ /*
+ ** If the locale name is the same as our cache, use the cache.
+ */
+ lbuf = locale_buf;
+ if (lbuf != NULL && strcmp(name, lbuf) == 0) {
+ p = lbuf;
+ for (ap = (const char **) &_time_localebuf;
+ ap < (const char **) (&_time_localebuf + 1);
+ ++ap)
+ *ap = p += strlen(p) + 1;
+ _time_using_locale = 1;
+ return 0;
+ }
+ /*
+ ** Slurp the locale file into the cache.
+ */
+ namesize = strlen(name) + 1;
+
+ if (!_PathLocale)
+ goto no_locale;
+ /* Range checking not needed, 'name' size is limited */
+ strcpy(filename, _PathLocale);
+ strcat(filename, "/");
+ strcat(filename, name);
+ strcat(filename, "/LC_TIME");
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ goto no_locale;
+ if (fstat(fd, &st) != 0)
+ goto bad_locale;
+ if (st.st_size <= 0)
+ goto bad_locale;
+ bufsize = namesize + st.st_size;
+ locale_buf = NULL;
+ lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
+ malloc(bufsize) : realloc(lbuf, bufsize);
+ if (lbuf == NULL)
+ goto bad_locale;
+ (void) strcpy(lbuf, name);
+ p = lbuf + namesize;
+ plim = p + st.st_size;
+ if (read(fd, p, (size_t) st.st_size) != st.st_size)
+ goto bad_lbuf;
+ if (close(fd) != 0)
+ goto bad_lbuf;
+ /*
+ ** Parse the locale file into localebuf.
+ */
+ if (plim[-1] != '\n')
+ goto bad_lbuf;
+ for (ap = (const char **) &_time_localebuf;
+ ap < (const char **) (&_time_localebuf + 1);
+ ++ap) {
+ if (p == plim)
+ goto reset_locale;
+ *ap = p;
+ while (*p != '\n')
+ ++p;
+ *p++ = '\0';
+ }
+ /*
+ ** Record the successful parse in the cache.
+ */
+ locale_buf = lbuf;
+
+ _time_using_locale = 1;
+ return 0;
+
+reset_locale:
+ /*
+ * XXX - This may not be the correct thing to do in this case.
+ * setlocale() assumes that we left the old locale alone.
+ */
+ locale_buf = locale_buf_C;
+ _time_localebuf = _C_time_locale;
+ save_using_locale = 0;
+bad_lbuf:
+ free(lbuf);
+bad_locale:
+ (void) close(fd);
+no_locale:
+ _time_using_locale = save_using_locale;
+ return -1;
+}
diff --git a/lib/libc/stdtime/timelocal.h b/lib/libc/stdtime/timelocal.h
new file mode 100644
index 000000000000..8593aee3ec3e
--- /dev/null
+++ b/lib/libc/stdtime/timelocal.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1997 FreeBSD Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Private header file for the strftime and strptime localization
+ * stuff.
+ */
+struct lc_time_T {
+ const char * mon[12];
+ const char * month[12];
+ const char * wday[7];
+ const char * weekday[7];
+ const char * X_fmt;
+ const char * x_fmt;
+ const char * c_fmt;
+ const char * am;
+ const char * pm;
+ const char * date_fmt;
+};
+
+extern struct lc_time_T _time_localebuf;
+extern int _time_using_locale;
+extern const struct lc_time_T _C_time_locale;
+
+#define Locale (_time_using_locale ? &_time_localebuf : &_C_time_locale)
+
diff --git a/release/README.TXT b/release/README.TXT
new file mode 100644
index 000000000000..53fd6c839da5
--- /dev/null
+++ b/release/README.TXT
@@ -0,0 +1,33 @@
+For a normal CDROM or network installation, all you need to copy onto an
+actual floppy from this directory is the boot.flp image (for 1.44MB floppies).
+
+NOTE: These images are NOT DOS files! You cannot simply copy them to
+a DOS floppy as regular files, you need to *image* copy them to the
+floppy with fdimage.exe under DOS or `dd' under UNIX.
+
+For example:
+
+To create the boot floppy image from DOS, you'd do something like
+this:
+
+C> fdimage boot.flp a:
+
+Assuming that you'd copied fdimage.exe and boot.flp into a directory
+somewhere. If you were doing this from the base of a CD distribution,
+then the *exact* command would be:
+
+E> tools\fdimage floppies\boot.flp a:
+
+
+If you're creating the boot floppy from a UNIX machine, you may find
+that:
+
+ dd if=floppies/boot.flp of=/dev/rfd0
+
+or
+
+ dd if=floppies/boot.flp of=/dev/floppy
+
+work well, depending on your hardware and operating system environment
+(different versions of UNIX have totally different names for the
+floppy drive - neat, huh? :-).
diff --git a/release/floppies/bin/Makefile b/release/floppies/bin/Makefile
new file mode 100644
index 000000000000..15f5ebff4c19
--- /dev/null
+++ b/release/floppies/bin/Makefile
@@ -0,0 +1,7 @@
+# $Id: Makefile,v 1.1 1997/07/16 12:24:18 julian Exp $
+#
+SUBDIR= write_mfs_in_kernel dumpnlist
+
+.include <bsd.subdir.mk>
+
+
diff --git a/release/floppies/bin/doFS.sh b/release/floppies/bin/doFS.sh
new file mode 100644
index 000000000000..f0c2f2b189a3
--- /dev/null
+++ b/release/floppies/bin/doFS.sh
@@ -0,0 +1,71 @@
+:
+#set -ex
+
+VNDEVICE=vn0
+export BLOCKSIZE=512
+
+BOOTBLKDIR=$1 ; shift
+MNT=$1 ; shift
+FSSIZE=$1 ; shift
+FSPROTO=$1 ; shift
+FSINODE=$1 ; shift
+FSLABEL=$1 ; shift
+
+deadlock=20
+
+while true
+do
+ rm -f fs-image
+
+ if [ ! -b /dev/${VNDEVICE} -o ! -c /dev/r${VNDEVICE} ] ; then
+ ( cd /dev && sh MAKEDEV ${VNDEVICE} )
+ fi
+
+ umount /dev/${VNDEVICE} 2>/dev/null || true
+
+ umount ${MNT} 2>/dev/null || true
+
+ vnconfig -u /dev/r${VNDEVICE} 2>/dev/null || true
+
+ dd of=fs-image if=/dev/zero count=${FSSIZE} bs=1k 2>/dev/null
+ # this suppresses the `invalid primary partition table: no magic'
+ awk 'BEGIN {printf "%c%c", 85, 170}' |\
+ dd of=fs-image obs=1 seek=510 conv=notrunc 2>/dev/null
+
+ vnconfig -s labels -c /dev/r${VNDEVICE} fs-image
+
+ disklabel -Brw \
+ -b ${BOOTBLKDIR}/boot1 \
+ -s ${BOOTBLKDIR}/boot2 \
+ /dev/r${VNDEVICE} minimum
+
+ TPC=1
+ CPD=1
+ SPT=$(( 2 * $FSSIZE / 2))
+ newfs -u ${SPT} -t ${TPC} -s $(( ${FSSIZE} * 2 )) -i ${FSINODE} -m 0 -o space /dev/r${VNDEVICE}c
+
+ mount /dev/${VNDEVICE}c ${MNT}
+
+ ( set -e && cd ${FSPROTO} && find . -print | cpio -dump ${MNT} )
+
+ df -ki /mnt
+
+ set `df -ki /mnt | tail -1`
+
+ umount ${MNT}
+
+ fsck -p /dev/r${VNDEVICE}c < /dev/null
+
+ vnconfig -u /dev/r${VNDEVICE} 2>/dev/null || true
+
+ if [ $FSLABEL != "minimum" ] ; then
+ echo ${FSSIZE} > fs-image.size
+ break
+ fi
+
+ echo ">>> Filesystem is ${FSSIZE} K, $4 left"
+ echo ">>> ${FSINODE} bytes/inode, $7 left"
+ echo ">>> `expr ${FSSIZE} \* 1024 / ${FSINODE}`"
+ echo ${FSSIZE} > fs-image.size
+ break;
+done
diff --git a/release/floppies/bin/dumpnlist/Makefile b/release/floppies/bin/dumpnlist/Makefile
new file mode 100644
index 000000000000..1149cadbbeb6
--- /dev/null
+++ b/release/floppies/bin/dumpnlist/Makefile
@@ -0,0 +1,8 @@
+# $Id: Makefile,v 1.1 1997/07/16 12:24:19 julian Exp $
+#
+PROG=dumpnlist
+NOMAN=yes
+
+.include <bsd.prog.mk>
+
+
diff --git a/release/floppies/bin/dumpnlist/dumpnlist.c b/release/floppies/bin/dumpnlist/dumpnlist.c
new file mode 100644
index 000000000000..31f25c15879b
--- /dev/null
+++ b/release/floppies/bin/dumpnlist/dumpnlist.c
@@ -0,0 +1,44 @@
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <nlist.h>
+#include <stdio.h>
+
+struct nlist nl[] = {
+ {"_isa_devtab_bio"},
+ {"_isa_devtab_tty"},
+ {"_isa_devtab_net"},
+ {"_isa_devtab_null"},
+ {"_isa_biotab_wdc"},
+ {"_isa_biotab_fdc"},
+ {"_eisadriver_set"},
+ {"_eisa_dev_list"},
+ {"_pcidevice_set"},
+ {"_device_list"},
+ {"_scbusses"},
+ {"_scsi_cinit"},
+ {"_scsi_dinit"},
+ {"_scsi_tinit"},
+ {""},
+};
+
+int
+main(int ac, char **av)
+{
+ int i;
+
+ i = nlist(av[1], nl);
+ if (i == -1) {
+ fprintf(stderr, "nlist returns error for %s\n", av[1]);
+ perror("nlist");
+ return 1;
+ }
+ printf("%d\n", sizeof(nl) / sizeof(struct nlist));
+ for (i = 0; nl[i].n_name; i++) {
+ printf("%s\n", nl[i].n_name);
+ printf("%d %d %d %ld\n",
+ nl[i].n_type, nl[i].n_other, nl[i].n_desc, nl[i].n_value);
+ }
+ return 0;
+}
diff --git a/release/floppies/bin/write_mfs_in_kernel/Makefile b/release/floppies/bin/write_mfs_in_kernel/Makefile
new file mode 100644
index 000000000000..cd65a8e75249
--- /dev/null
+++ b/release/floppies/bin/write_mfs_in_kernel/Makefile
@@ -0,0 +1,8 @@
+# $Id: Makefile,v 1.1 1997/07/16 12:24:20 julian Exp $
+#
+PROG=write_mfs_in_kernel
+NOMAN=yes
+
+.include <bsd.prog.mk>
+
+
diff --git a/release/floppies/bin/write_mfs_in_kernel/write_mfs_in_kernel.c b/release/floppies/bin/write_mfs_in_kernel/write_mfs_in_kernel.c
new file mode 100644
index 000000000000..b624ed6387d4
--- /dev/null
+++ b/release/floppies/bin/write_mfs_in_kernel/write_mfs_in_kernel.c
@@ -0,0 +1,70 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $Id: write_mfs_in_kernel.c,v 1.1 1997/07/16 12:24:21 julian Exp $
+ *
+ * This program patches a filesystem into a kernel made with MFS_ROOT
+ * option.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ufs/ffs/fs.h>
+
+main(int argc, char **argv)
+{
+ unsigned char *buf_kernel, *buf_fs, *p,*q;
+ int fd_kernel, fd_fs;
+ struct stat st_kernel, st_fs;
+ u_long l;
+
+ if (argc < 3) {
+ fprintf(stderr,"Usage:\n\t%s kernel fs\n");
+ exit(2);
+ }
+ fd_kernel = open(argv[1],O_RDWR);
+ if (fd_kernel < 0) { perror(argv[1]); exit(2); }
+ fstat(fd_kernel,&st_kernel);
+ fd_fs = open(argv[2],O_RDONLY);
+ if (fd_fs < 0) { perror(argv[2]); exit(2); }
+ fstat(fd_fs,&st_fs);
+ buf_kernel = malloc(st_kernel.st_size);
+ if (!buf_kernel) { perror("malloc"); exit(2); }
+ buf_fs = malloc(st_fs.st_size);
+ if (!buf_fs) { perror("malloc"); exit(2); }
+ if (st_kernel.st_size != read(fd_kernel,buf_kernel,st_kernel.st_size))
+ { perror(argv[1]); exit(2); }
+ if (st_fs.st_size != read(fd_fs,buf_fs,st_fs.st_size))
+ { perror(argv[2]); exit(2); }
+ for(l=0,p=buf_kernel; l < st_kernel.st_size - st_fs.st_size ; l++,p++ )
+ if(*p == 'M' && !strcmp(p,"MFS Filesystem goes here"))
+ goto found;
+ fprintf(stderr,"MFS filesystem signature not found in %s\n",argv[1]);
+ exit(1);
+ found:
+ for(l=0,q= p + SBOFF; l < st_fs.st_size - SBOFF ; l++,q++ )
+ if (*q)
+ goto fail;
+ memcpy(p+SBOFF,buf_fs+SBOFF,st_fs.st_size-SBOFF);
+ lseek(fd_kernel,0L,SEEK_SET);
+ if (st_kernel.st_size != write(fd_kernel,buf_kernel,st_kernel.st_size))
+ { perror(argv[1]); exit(2); }
+ exit(0);
+ fail:
+ l += SBOFF;
+ fprintf(stderr,"Obstruction in kernel after %ld bytes (%ld Kbyte)\n",
+ l, l/1024);
+ fprintf(stderr,"Filesystem is %ld bytes (%ld Kbyte)\n",
+ (u_long)st_fs.st_size, (u_long)st_fs.st_size/1024);
+ exit(1);
+}
diff --git a/release/floppies/mk/crunch_fs.mk b/release/floppies/mk/crunch_fs.mk
new file mode 100644
index 000000000000..c6d51d19bf8e
--- /dev/null
+++ b/release/floppies/mk/crunch_fs.mk
@@ -0,0 +1,108 @@
+###
+# $Id: crunch_fs.mk,v 1.1 1997/07/16 12:24:29 julian Exp $
+#
+# This is included to make a floppy that includes a crunch file
+#
+# Variables that control this mk include file.
+# TOP specifies where the top of the FreeBSD source tree is.. (*)
+# FS_DIRS directories to make on the fs (*)
+# STANDLINKS added symlinks to /stand on the fs
+# VERBATIM a directory that contains tree to be copied to the fs
+# FSSIZE defaults to 1440
+# FSLABEL defaults to fd1440
+# FSINODE defaults to 4000
+# FS_DEVICES devices to make on the fs (using MAKEDEV) (default = all)
+# ZIP decides if the installed cruch will also be gzip'd(def=true)
+# (*) = Mandatory
+###
+
+# If we weren't told, default to nothing
+.if ! defined( TOP )
+# define TOP!
+xxx
+.endif
+
+# mountpoint for filesystems.
+MNT= /mnt
+
+# other floppy parameters.
+FSSIZE?= 1440
+FSLABEL?= fd1440
+FSINODE?= 2000
+FS_DEVICES?= all
+ZIP?=true
+
+# Things which will get you into trouble if you change them
+TREE= tree
+LABELDIR= ${OBJTOP}/sys/i386/boot/biosboot
+
+clean:
+ rm -rf tree fs-image fs-image.size step[0-9]
+
+.include <bsd.prog.mk>
+
+
+#
+# --==## Create a filesystem image ##==--
+#
+
+fs_image: ${TREE} step2 step3 step4 fs-image
+
+${TREE}: ${.CURDIR}/Makefile
+ rm -rf ${TREE}
+ mkdir -p ${TREE}
+ cd ${TREE} && mkdir ${FS_DIRS}
+ cd ${TREE} ; for i in ${STANDLINKS} ; \
+ do \
+ ln -s /stand $${i} ; \
+ done
+
+step2: ${.CURDIR}/${CRUNCHDIRS} ${.CURDIR}/Makefile
+.if defined(CRUNCHDIRS)
+ @cd ${.CURDIR} && $(MAKE) installCRUNCH DIR=${TREE}/stand ZIP=${ZIP}
+.endif
+ touch step2
+
+step3: step2
+.if defined (FS_DEVICES)
+ ( cd tree/dev && \
+ cp ${TOP}/etc/etc.i386/MAKEDEV . && sh MAKEDEV ${FS_DEVICES} )
+.endif
+ touch step3
+
+step4: step3
+.if defined(VERBATIM)
+ A=`pwd`;cd ${.CURDIR}/${VERBATIM}; \
+ find . \! \( -name CVS -and -prune \) -print |cpio -pdmuv $$A/tree
+.endif
+ true || cp ${TOP}/etc/spwd.db tree/etc
+ touch step4
+
+fs-image: step4
+ sh -e ${SCRIPTDIR}/doFS.sh ${LABELDIR} ${MNT} ${FSSIZE} tree \
+ ${FSINODE} ${FSLABEL}
+ cp fs-image.size ${.CURDIR}
+
+
+.if defined(CRUNCHDIRS)
+installCRUNCH:
+.if !defined(DIR)
+ @echo "DIR undefined in installCRUNCH" && exit 1
+.endif
+.if !defined(ZIP)
+ @echo "ZIP undefined in installCRUNCH" && exit 1
+.endif
+.for CRUNCHDIR in ${CRUNCHDIRS}
+ if ${ZIP} ; then \
+ gzip -9 < ${CRUNCHDIR}/crunch > ${DIR}/.crunch ; \
+ else \
+ ln -f ${CRUNCHDIR}/crunch ${DIR}/.crunch ; \
+ fi
+ chmod 555 ${DIR}/.crunch
+ for i in `crunchgen -l ${.CURDIR}/${CRUNCHDIR}/crunch.conf` ; do \
+ ln -f ${DIR}/.crunch ${DIR}/$$i ; \
+ done
+ rm -f ${DIR}/.crunch
+.endfor
+.endif
+
diff --git a/release/floppies/mk/makecrunch.mk b/release/floppies/mk/makecrunch.mk
new file mode 100644
index 000000000000..8f2d3e70afe1
--- /dev/null
+++ b/release/floppies/mk/makecrunch.mk
@@ -0,0 +1,25 @@
+
+
+SYSINSTALL= ${OBJTOP}/release/sysinstall/sysinstall
+
+NOCRYPT?= yes
+
+all: crunch
+
+crunch:
+ -crunchgen ${.CURDIR}/crunch.conf
+ ${MAKE} -f crunch.mk all NOCRYP=${NOCRYPT} \
+ "CFLAGS=${CFLAGS} -DCRUNCHED_BINARY"
+
+clean:
+ rm -f *.o *.stub *.lo *_stub.c *.mk \
+ crunch.cache \
+ crunch.mk \
+ crunch.c \
+ crunch \
+ .tmp_*
+
+install:
+ @echo " No idea what to do to install yet"
+
+.include <bsd.prog.mk>
diff --git a/release/sysinstall/sysinstall.8 b/release/sysinstall/sysinstall.8
new file mode 100644
index 000000000000..52011c3dc427
--- /dev/null
+++ b/release/sysinstall/sysinstall.8
@@ -0,0 +1,784 @@
+.\" Copyright (c) 1997
+.\" Jordan Hubbard <jkh@freebsd.org>. 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Jordan Hubbard 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 Jordan Hubbard 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.
+.\"
+.\" $Id$
+.\"
+.Dd August 9, 1997
+.Dt SYSINSTALL 8
+.Os
+.Sh NAME
+.Nm sysinstall
+.Nd system installation and configuration tool
+.Sh SYNOPSIS
+.Nm
+.Op Ar var=value
+.Op Ar sub-function
+.Op Ar ...
+.Sh DESCRIPTION
+.Nm
+is a utility for installing and configuring FreeBSD systems;
+it is the first utility invoked by the FreeBSD installation boot
+floppy and is also copied into
+.Pa /stand
+on newly installed FreeBSD systems so that it may be run
+later to further configure the system.
+.Pp
+The
+.Nm
+program is generally invoked without arguments for the default
+behavior which brings up the main installation/configuration menu.
+
+On those occasions where it is deemed necessary to invoke a subsystem
+of sysinstall directly, however, it is also possible to do so by
+naming the appropriate function entry points on the command line.
+Since this action is essentially identical to running an installation
+script, with each argument corresponding to a line of script, the
+reader is encouraged to read the section on scripting for more
+information on this feature.
+.Pp
+.Sh NOTES
+.Nm
+is essentially nothing more than a monolithic C program with
+the ability to write MBRs and disk labels (through the services
+of the
+.Xr libdisk 3
+library) and install distributions or packages onto new and
+existing FreeBSD systems. It also contains some extra intelligence
+for running as a replacement for
+.Xr init 8
+when it's invoked by the FreeBSD installation boot procedure. It
+assumes very little in the way of additional utility support and
+performs most file operations by calling the relevant syscalls
+(such as
+.Xr mount 2 )
+directly.
+.Pp
+.Nm
+currently uses the
+.Xr libdialog 3
+library to do user interaction with simple ANSI line graphics, color
+support for which is enabled by either running on a syscons VTY or some
+other color-capable terminal emulator (newer versions of xterm will support
+color when using the ``xterm-color'' termcap entry).
+.Pp
+This product is currently at the end of its life cycle and will
+be replaced in FreeBSD 3.0 by the
+.Xr setup 1
+utility.
+.Sh RUNNING SCRIPTS
+.Nm
+may be either driven interactively through its various internal menus
+or run in batch mode, driven by an external script. Such scripts can
+be loaded and executed in one of 3 ways:
+
+.Bl -tag -width Ds -compact
+.It Sy "LOAD_CONFIG_FILE"
+If
+.Nm
+is compiled with LOAD_CONFIG_FILE set in the environment
+(or in the Makefile) to some value, then that value will
+be used as the filename to automatically look for and load
+when
+.Nm
+starts up, no interaction on the part of the user being required.
+This option is aimed primarily at large sites who wish to create a
+single prototype install for multiple machines with largely identical
+configurations and/or installation options.
+
+.It Sy "MAIN MENU"
+If
+.Nm
+is run interactively, that is to say in the default manner, it will
+bring up a main menu which contains a "load config file" option.
+Selecting this option will allow the name of a script file to be
+specified and loaded from a DOS or UFS formatted floppy.
+
+.It Sy "COMMAND LINE"
+In the same fashion that script directives may be specified one
+operation per line in a file, so may each command line argument
+be a directive
+when
+.Nm
+is run in multi-user mode. Execution ends either by explicit request
+(e.g. calling the
+.Ar shutdown
+directive), upon reaching the end of the argument list or on error.
+.Pp
+For example:
+.nf
+
+/stand/sysinstall ftp=ftp:/ziggy/pub/ mediaSetFTP configPackages
+
+.fi
+Would initialize
+.Nm
+for FTP installation media (using the server `ziggy') and then
+bring up the package installation editor. When the package editor
+exits, so will
+.Nm
+.El
+.Pp
+.Sh SCRIPT SYNTAX
+A script is given one or more directives, each directive taking
+the form of:
+
+.Ar var=value
+.Ar function
+or
+.Ar #somecomment
+
+Where
+.Ar var=value
+is the assignment of some internal
+.Nm
+variable, e.g. "ftpPass=FuNkYChiKn", and
+.Ar function
+is the name of an internal
+.Nm
+function, e.g. "mediaSetFTP", and
+.Ar #comment
+is a single-line comment for documentation purposes (ignored by
+sysinstall). Functions take their arguments by examining known
+variable names, requiring that you be sure to assign those values
+first before calling the function. Where a function in the table
+below takes such arguments, they will be documented there.
+.Pp
+\fBFunction Glossary:\fR
+.Pp
+.Bl -tag -width indent
+.It configAnonFTP
+Invoke the Anonymous FTP configuration menu.
+.Pp
+\fBVariables:\fR None
+.It configRouter
+Select which routing daemon you wish to use, potentially
+loading any required 3rd-party routing daemons as necessary.
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It router
+can be set to the name of the desired routing daemon,
+e.g. ``routed'' or ``gated'', otherwise it is prompted for.
+.El
+.It configNFSServer
+Configure host as an NFS server.
+.Pp
+\fBVariables:\fR None
+.It configNTP
+Configure host as a user of the Network Time Protocol.
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It ntpdate_flags
+The flags to
+.Xr ntpdate 8 ,
+that is to say the name of the server to sync from.
+.El
+.It configPCNFSD
+Configure host to support PC NFS.
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It pcnfsd_pkg
+The name of the PCNFSD package to load if necessary (defaults to hard coded
+version).
+.El
+.It configPackages
+Bring up the interactive package management menu.
+.Pp
+\fBVariables:\fR None
+.It configRegister
+Register the user with the FreeBSD counter.
+.Pp
+\fBVariables:\fR None
+.It configUsers
+Add users and/or groups to the system.
+.Pp
+\fBVariables:\fR None
+.It configXEnvironment
+Configure the X display subsystem.
+.Pp
+\fBVariables:\fR None
+.It diskPartitionEditor
+Invokes the disk partition (MBR) editor.
+.Pp
+\fBVariables:\fR
+.Bl -tag -width findx
+.It geometry
+The disk geometry, as a cyls/heads/sectors formatted string. Default: no
+change to geometry.
+.It partition
+Set to disk partitioning type or size, its value being
+.Ar free
+in order to use only remaining free space for FreeBSD,
+.Ar all
+to use the entire disk for FreeBSD but maintain a proper partition
+table,
+.Ar existing
+to use an existing FreeBSD partition (first found),
+.Ar exclusive
+to use the disk in ``dangerously dedicated'' mode or, finally,
+.Ar somenumber
+to allocate
+.Ar somenumber
+blocks of available free space to a new FreeBSD partition.
+Default: Interactive mode.
+.It bootManager
+is set to one of
+.Ar boot
+to signify the installation of a boot manager,
+.Ar standard
+to signify installation of a "standard" non-boot MGR DOS
+MBR or
+.Ar none
+to indicate that no change to the boot manager is desired.
+Default: none.
+.El
+.Pp
+Note: Nothing is actually written to disk by this function, a explicit call to
+.Ar diskPartitionWrite
+being required for that to happen.
+.It diskPartitionWrite
+Causes any pending MBR changes (typically from the
+.Ar diskPartitionEditor )
+to be written out.
+.Pp
+\fBVariables:\fR None
+.It diskLabelEditor
+Invokes the disk label editor. This is a bit trickier from a script
+since you need to essentially label everything inside each FreeBSD
+(type 0xA5) partition created by the
+.Ar diskPartitionEditor
+function, and that requires knowing a few rules about how things are
+laid out. When creating a script to automatically allocate disk space
+and partition it up, it is suggested that you first perform the
+installation interactively at least once and take careful notes as to
+what the slice names will be, then and only then hardwiring them into
+the script.
+.Pp
+For example, let's say you have a SCSI disk on which you've created a new
+FreeBSD partition in slice 2 (your DOS partition residing in slice 1).
+The slice name would be
+.Ar sd0s2
+for the whole FreeBSD partition (
+.Ar sd0s1
+being your DOS primary
+partition). Now let's further assume that you have 500MB in this
+partition and you want to sub-partition that space into root, swap,
+var and usr file systems for FreeBSD. Your invocation of the
+.Ar diskLabelEditor
+function might involve setting the following variables:
+.Bl -tag -width findx
+.It Li "sd0s2-1=ufs 40960 /"
+A 20MB root file system (all sizes are in 512 byte blocks).
+.It Li "sd0s2-2=swap 131072 /"
+A 64MB swap partition.
+.It Li "sd0s2-3=ufs 204800 /var"
+A 100MB /var file system.
+.It Li "sd0s2-4=ufs 0 /usr"
+With the balance of free space (around 316MB) going to the /usr
+file system.
+.El
+
+One can also use the
+.Ar diskLabelEditor
+for mounting or erasing existing partitions as well as creating new
+ones. Using the previous example again, let's say that we also wanted
+to mount our DOS partition and make sure that an
+.Pa /etc/fstab
+entry is created for it in the new installation. Before calling the
+.Ar diskLabelEditor
+function, we simply add an additional line:
+.nf
+ sd0s1=/dos_c N
+
+.fi
+before the call. This tells the label editor that you want to mount
+the first slice on
+.Pa /dos_c
+and not to attempt to newfs it (not that
+.Nm
+would attempt this for a DOS partition in any case, but it could just
+as easily be an existing UFS partition being named here and the 2nd
+field is non-optional).
+.Pp
+Note: No file system data is actually written to disk until an
+explicit call to
+.Ar diskLabelCommit
+is made.
+.It diskLabelCommit
+Writes out all pending disklabel information and creates and/or mounts any
+file systems which have requests pending from the
+.Ar diskLabelEditor
+function.
+.Pp
+\fBVariables:\fR None
+.It distReset
+Resets all selected distributions to the empty set (no distributions selected).
+.Pp
+\fBVariables:\fR None
+.It distSetCustom
+Allows the selection of a custom distribution set (e.g. not just on of the
+existing "canned" sets) with no user interaction.
+\fBVariables:\fR
+.Bl -tag -width indent
+.It dists
+List of distributions to load. Possible distribution values are:
+.Bl -tag -width indent
+.It Li bin
+The base binary distribution.
+.It Li doc
+Miscellaneous documentation
+.It Li games
+Games
+.It Li manpages
+Manual pages (unformatted)
+.It Li catpages
+Pre-formatted manual pages
+.It Li proflibs
+Profiled libraries for developers.
+.It Li dict
+Dictionary information (for tools like spell).
+.It Li info
+GNU info files and other extra docs.
+.It Li des
+DES encryption binaries and libraries.
+.It Li compat1x
+Compatibility with FreeBSD 1.x
+.It Li compat20
+Compatibility with FreeBSD 2.0
+.It Li compat21
+Compatibility with FreeBSD 2.1
+.It Li ports
+The ports collection.
+.It Li krb
+Kerberos binaries.
+.It Li ssecure
+/usr/src/secure
+.It Li sebones
+/usr/src/eBones
+.It Li sbase
+/usr/src/[top level files]
+.It Li scontrib
+/usr/src/contrib
+.It Li sgnu
+/usr/src/gnu
+.It Li setc
+/usr/src/etc
+.It Li sgames
+/usr/src/games
+.It Li sinclude
+/usr/src/include
+.It Li slib
+/usr/src/lib
+.It Li slibexec
+/usr/src/libexec
+.It Li slkm
+/usr/src/lkm
+.It Li srelease
+/usr/src/release
+.It Li sbin
+/usr/src/bin
+.It Li ssbin
+/usr/src/sbin
+.It Li sshare
+/usr/src/share
+.It Li ssys
+/usr/src/sys
+.It Li subin
+/usr/src/usr.bin
+.It Li susbin
+/usr/src/usr.sbin
+.It Li ssmailcf
+/usr/src/usr.sbin/sendmail/cf
+.It Li XF86-xc
+XFree86 official sources.
+.It Li XF86-co
+XFree86 contributed sources.
+.It Li X33bin
+XFree86 3.3 binaries.
+.It Li X33cfg
+XFree86 3.3 configuration files.
+.It Li X33doc
+XFree86 3.3 documentation.
+.It Li X33html
+XFree86 3.3 HTML documentation.
+.It Li X33lib
+XFree86 3.3 libraries.
+.It Li X33lk98
+XFree86 3.3 server link-kit for PC98 machines.
+.It Li X33lkit
+XFree86 3.3 server link-kit for standard machines.
+.It Li X33man
+XFree86 3.3 manual pages.
+.It Li X33prog
+XFree86 3.3 programmer's distribution.
+.It Li X33ps
+XFree86 3.3 postscript documentation.
+.It Li X33set
+XFree86 3.3 graphical setup tool.
+.It Li X338514
+XFree86 3.3 8514 server.
+.It Li X339480
+XFree86 3.3 PC98 8-bit (256 color) PEGC-480 server.
+.It Li X339EGC
+XFree86 3.3 PC98 4-bit (16 color) EGC server.
+.It Li X339GA9
+XFree86 3.3 PC98 GA-968V4/PCI (S3 968) server.
+.It Li X339GAN
+XFree86 3.3 PC98 GANB-WAP (cirrus) server.
+.It Li X339LPW
+XFree86 3.3 PC98 PowerWindowLB (S3) server.
+.It Li X339NKV
+XFree86 3.3 PC98 NKV-NEC (cirrus) server.
+.It Li X339NS3
+XFree86 3.3 PC98 NEC (S3) server.
+.It Li X339SPW
+XFree86 3.3 PC98 SKB-PowerWindow (S3) server.
+.It Li X339TGU
+XFree86 3.3 PC98 Cyber9320 and TGUI9680 server.
+.It Li X339WEP
+XFree86 3.3 PC98 WAB-EP (cirrus) server.
+.It Li X339WS
+XFree86 3.3 PC98 WABS (cirrus) server.
+.It Li X339WSN
+XFree86 3.3 PC98 WSN-A2F (cirrus) server.
+.It Li X33AGX
+XFree86 3.3 8 bit AGX server.
+.It Li X33I128
+XFree86 3.3 #9 Imagine I128 server.
+.It Li X33Ma8
+XFree86 3.3 ATI Mach8 server.
+.It Li X33Ma32
+XFree86 3.3 ATI Mach32 server.
+.It Li X33Ma64
+XFree86 3.3 ATI Mach64 server.
+.It Li X33Mono
+XFree86 3.3 monochrome server.
+.It Li X33P9K
+XFree86 3.3 P9000 server.
+.It Li X33S3
+XFree86 3.3 S3 server.
+.It Li X33S3V
+XFree86 3.3 S3 Virge server.
+.It Li X33SVGA
+XFree86 3.3 SVGA server.
+.It Li X33VG16
+XFree86 3.3 VGA16 server.
+.It Li X33W32
+XFree86 3.3 ET4000/W32, /W32i and /W32p server.
+.It Li X33nest
+XFree86 3.3 nested X server.
+.It Li X33vfb
+XFree86 3.3 virtual frame-buffer X server.
+.It Li X33fnts
+XFree86 3.3 base font set.
+.It Li X33f100
+XFree86 3.3 100DPI font set.
+.It Li X33fcyr
+XFree86 3.3 Cyrillic font set.
+.It Li X33fscl
+XFree86 3.3 scalable font set.
+.It Li X33fnon
+XFree86 3.3 non-english font set.
+.It Li X33fsrv
+XFree86 3.3 font server.
+.El
+.It distSetDeveloper
+Selects the standard Developer's distribution set.
+.Pp
+\fBVariables:\fR None
+.It distSetXDeveloper
+Selects the standard X Developer's distribution set.
+.Pp
+\fBVariables:\fR None
+.It distSetKernDeveloper
+Selects the standard kernel Developer's distribution set.
+.Pp
+\fBVariables:\fR None
+.It distSetUser
+Selects the standard user distribution set.
+.Pp
+\fBVariables:\fR None
+.It distSetXUser
+Selects the standard X user's distribution set.
+.Pp
+\fBVariables:\fR None
+.It distSetMinimum
+Selects the very minimum distribution set.
+.Pp
+\fBVariables:\fR None
+.It distSetEverything
+Selects the full whack - all available distributions.
+.Pp
+\fBVariables:\fR None
+.It distSetDES
+Interactively select DES subcomponents.
+.Pp
+\fBVariables:\fR None
+.It distSetSrc
+Interactively select source subcomponents.
+.Pp
+\fBVariables:\fR None
+.It distSetXF86
+Interactively select XFree86 3.3 subcomponents.
+.Pp
+\fBVariables:\fR None
+.It distExtractAll
+Install all currently selected distributions (requires that
+media device also be selected).
+.Pp
+\fBVariables:\fR None
+.It docBrowser
+Install (if necessary) an HTML documentation browser and go to the
+HTML documentation submenu.
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It browserPackage
+The name of the browser package to try and install as necessary.
+Defaults to latest lynx package.
+.It browserBinary
+The name of the browser binary itself (if overriding the
+.Ar browserPackage
+variable). Defaults to lynx.
+.El
+.It installCommit
+.Pp
+Commit any and all pending changes to disk. This function
+is essentially shorthand for a number of more granular "commit"
+functions.
+\fBVariables:\fR None
+.It installExpress
+Start an "express" installation, asking few questions of
+the user.
+.Pp
+\fBVariables:\fR None
+.It installNovice
+Start a "novice" installation, the most user-friendly
+installation type available.
+.Pp
+\fBVariables:\fR None
+.It installUpgrade
+Start an upgrade installation.
+.Pp
+\fBVariables:\fR None
+.It installFixitHoloShell
+Start up the "emergency holographic shell" over on VTY4
+if running as init.
+.Pp
+\fBVariables:\fR None
+.It installFixitCDROM
+Go into "fixit" mode, assuming a live file system CDROM
+currently in the drive.
+.Pp
+\fBVariables:\fR None
+.It installFixitFloppy
+Go into "fixit" mode, assuming an available fixit floppy
+disk (user will be prompted for it).
+.Pp
+\fBVariables:\fR None
+.It installFilesystems
+Do just the file system initialization part of an install.
+.Pp
+\fBVariables:\fR None
+.It installVarDefaults
+Initialize all variables to their defaults, overriding any
+previous settings.
+.Pp
+\fBVariables:\fR None
+.It mediaSetCDROM
+Select a FreeBSD CDROM as the installation media.
+.Pp
+\fBVariables:\fR None
+.It mediaSetFloppy
+Select a pre-made floppy installation set as the installation media.
+.Pp
+\fBVariables:\fR None
+.It mediaSetDOS
+Select an existing DOS primary partition as the installation media.
+The first primary partition found is used (e.g. C:).
+.Pp
+\fBVariables:\fR None
+.It mediaSetTape
+Select a tape device as the installation media.
+.Pp
+\fBVariables:\fR None
+.It mediaSetFTP
+Select an FTP site as the installation media.
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It hostname
+The name of the host being installed (optional).
+.It domainname
+The domain name of the host being installed (optional).
+.It defaultrouter
+The default router for this host (non-optional).
+.It netDev
+Which host interface to use (
+.Ar ed0
+or
+.Ar ep0 ,
+for example. Non-optional).
+.It ipaddr
+The IP address for the selected host interface (non-optional).
+.It netmask
+The netmask for the selected host interface (non-optional).
+.It ftp
+The fully qualified URL of the FTP site containing the FreeBSD
+distribution you're interested in, e.g.
+.Ar ftp://ftp.freebsd.org/pub/FreeBSD/ .
+.El
+.It mediaSetFTPActive
+Alias for
+.Ar mediaSetFTP
+using "active" FTP transfer mode.
+.Pp
+\fBVariables:\fR Same as for
+.Ar mediaSetFTP .
+.It mediaSetFTPPassive
+Alias for
+.Ar mediaSetFTP
+using "passive" FTP transfer mode.
+.Pp
+\fBVariables:\fR Same as for
+.Ar mediaSetFTP .
+.It mediaSetUFS
+Select an existing UFS partition (mounted with the label editor) as
+the installation media.
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It ufs
+full /path to directory containing the FreeBSD distribution you're
+interested in.
+.El
+.It mediaSetNFS
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It hostname
+The name of the host being installed (optional).
+.It domainname
+The domain name of the host being installed (optional).
+.It defaultrouter
+The default router for this host (non-optional).
+.It netDev
+Which host interface to use (
+.Ar ed0
+or
+.Ar ep0 ,
+for example. Non-optional).
+.It ipaddr
+The IP address for the selected host interface (non-optional).
+.It netmask
+The netmask for the selected host interface (non-optional).
+.It nfs
+full hostname:/path specification for directory containing
+the FreeBSD distribution you're interested in.
+.El
+.It mediaSetFTPUserPass
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It ftpUser
+The username to log in as on the ftp server site.
+Default: ftp
+.It ftpPass
+The password to use for this username on the ftp
+server site.
+Default: user@host
+.El
+.It mediaSetCPIOVerbosity
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It cpioVerbose
+Can be used to set the verbosity of cpio extractions to low, medium or
+high.
+.El
+.It mediaGetType
+Interactively get the user to specify some type of media.
+.Pp
+\fBVariables:\fR None
+.It optionsEditor
+Invoke the interactive options editor.
+.Pp
+\fBVariables:\fR None
+.It register
+Bring up the FreeBSD registration form.
+.Pp
+\fBVariables:\fR None
+.It packageAdd
+Try to fetch and add a package to the system (requires
+that a media type be set),
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It package
+The name of the package to add, e.g. bash-1.14.7 or ncftp-2.4.2.
+.El
+.It addGroup
+Invoke the interactive group editor.
+.Pp
+\fBVariables:\fR None
+.It addUser
+Invoke the interactive user editor.
+.Pp
+\fBVariables:\fR None
+.It shutdown
+Stop the script and terminate sysinstall.
+.Pp
+\fBVariables:\fR None
+.It system
+Execute an arbitrary command with
+.Xr system 3
+.Pp
+\fBVariables:\fR
+.Bl -tag -width indent
+.It command
+The name of the command to execute. When running
+from a boot floppy, very minimal expectations should
+be made as to what's available until/unless a relatively
+full system installation has just been done.
+.El
+.El
+.Sh FILES
+This utility may edit the contents of
+.Pa /etc/rc.conf ,
+.Pa /etc/hosts ,
+and
+.Pa /etc/resolv.conf
+as necessary to reflect changes in the network configuration.
+.Sh BUGS
+This utility is a prototype which lasted approximately 2 years past
+its expiration date and is greatly in need of death.
+.Sh AUTHOR
+Jordan K. Hubbard <jkh@FreeBSD.org>
+.Sh HISTORY
+This version of
+.Nm
+first appeared in
+.Fx 2.0 .
diff --git a/share/man/man4/man4.i386/sb.4 b/share/man/man4/man4.i386/sb.4
new file mode 100644
index 000000000000..e6cda477118f
--- /dev/null
+++ b/share/man/man4/man4.i386/sb.4
@@ -0,0 +1,73 @@
+.\" Man page for the SoundBlaster driver
+.\"
+.\" Copyright (c) 1997, Alex Zepeda.
+.\"
+.\" This documentation is public domain, and is provided without warranty.
+.\" Alex Zepeda, the "author" of this page is not resposible for any
+.\" consequences of any sort of manipulation of this document.
+.\"
+.\" SoundBlaster and any phrases including it's name are copyright
+.\" Creative Labs, not me.
+.\"
+.\" alex!@bigfoot.com
+.\"
+.Dd August 9, 1997
+.Dt SB 4 i386
+.Os FreeBSD
+.Sh NAME
+.Nm sb
+.Nd Creative Labs Sound Blaster and compatable device driver
+.Sh SYNOPSIS
+For all sound cards supported with the sb driver this is needed:
+.Cd controller snd0
+.Pp
+For the SoundBlaster, SB Pro, SoundBlaster16, or the Pro Audio Spectrum
+ (emulating SB):
+.Cd "device sb0 at isa? port 0x220 irq 7 drq 1 vector sbintr"
+.Pp
+For specific SB16 support:
+.Cd "device sbxvi0 at isa? drq 5"
+.Pp
+For SoundBlaster 16 16 bit MIDI support:
+.Cd "device sbmidi0 at isa? port 0x300"
+.Pp
+To add Jazz16 suport:
+.Cd "options JAZZ16"
+.Pp
+To add support for the Logitech SoundMan Games:
+.Cd "options SM_GAMES"
+.Pp
+To add SG NX Pro mixer support:
+.Cd "options __SGNXPRO__"
+.Pp
+The OPL-2/3 is used in the SoundBlaster, SoundBlaster Pro, SB 16, and the
+Pro Audio Spectrum. For Yamaha OPL-2/OPL-3 FM support:
+.Cd "device opl0 at isa? port 0x388"
+.Sh DESCRIPTION
+This driver covers the SoundBlaster family of cards including the
+SoundBlaster 1.0 to the SoundBlaster 16/SoundBlaster 32. The awe driver
+provides AWE32/64 functionality. This driver is provied in FreeBSD
+versions 2.0-current through 3.0-current. You can also configure more
+then one card on a single DMA using the conflicts keyword in your
+configuration file. This is useful for boards with more then one type of
+emulation.
+.Sh BUGS
+Since the SB16 uses the same IRQ and addresses for
+the different drivers, some of the snd drivers will not be probed because
+the kernel thinks there is a conflict. This can be worked-around by
+using the "conflicts" keyword on the sb16's device line.
+.Pp
+Current version doesn't support mode changes without closing and reopening
+the device. Support for this feature may be implemented in a future
+version of this driver.
+.Sh SEE ALSO
+cdcontrol(1), cdplay(1), mixer(8)
+.Sh AUTHORS
+The original SoundBlaster DSP and SoundBlaster 16 MIDI, and Yamaha OPL-3
+drivers were written by Hannu Savolainen. The SoundBlaster 16 DSP code
+was written by J. Schuber (jsb@sth.ruhr-uni-bochum.de). Improvments to
+the OPL-3 drivers were made by Rob Hooft (hooft@chem.ruu.nl)
+.Sh HISTORY
+Sound Galaxy NX Pro support added by Hunyue Yau (Jan 6 1994). MV
+ProSonic/Jazz 16 16bit support added by JRA Gibson (April 1995). Audio
+Excel DSP 16 support added by Riccardo Facchetti (March 24 1995).
diff --git a/share/man/man4/man4.i386/wl.4 b/share/man/man4/man4.i386/wl.4
new file mode 100644
index 000000000000..114ef0f588f7
--- /dev/null
+++ b/share/man/man4/man4.i386/wl.4
@@ -0,0 +1,147 @@
+.\"
+.\" Copyright (c) 1997, Jim Binkley
+.\" 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 Jim Binkley
+.\" 4. 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 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 AUTHOR 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.
+.\"
+.\" $Id$
+.Dd July 7, 1997
+.Dt WL 4 i386
+.Os FreeBSD
+.Sh NAME
+.Nm wl
+.Nd T1 speed ISA/radio lan card
+.Sh SYNOPSIS
+.Cd "device wl0 at isa? port 0x300 net irq 5 vector wlintr"
+.Sh DESCRIPTION
+The
+.Nm wl
+driver controls a radio lan card system made originally by
+NCR, then ATT, now Lucent. The system is spread-spectrum radio
+at around 915 mhz (or 2.4 ghz). With the supplied omni-directional antennae,
+about 400 feet (indoors, more outdoors) can be covered in circumference.
+This card can talk to the companion (wlp0) pccard. Speeds vary
+from 1 megabit to theoretically 2 megabits (roughly T1 in speed).
+.Pp
+The card has 3 fundmental hardware
+units, a so-called PSA or programmable storage area, a radio modem,
+and a ethernet lan controller. The latter component is the
+ancient (and not very honorable) Intel 82586 ethernet chip.
+Fundamentally it appears to the operating system as an ethernet system,
+and speaks IEEE MAC addresses. The radio modem simply translates
+ethernet packets to/from radio packets, that are either at 2.4 Ghz
+or 915 mhz depending on the radio modem. It supports a collision
+avoidance scheme. The lan controller
+supports promiscuous mode, broadcast, and multicasting
+(although there is a glitch
+in the latter). "It thinks it is ethernet".
+.Pp
+How it is used
+depends on the kind of antennae deployed with it. Point to point
+applications are possible as are ethernet-like lan use. The vendor
+ships an omni-directional antennae that works in the
+vicinity of 400 feet (indoors).
+Point to point antennae can be purchased that will go miles.
+.Sh SETUP
+The card can either be initialized with the vendor supplied DOS setup software.
+Typically minimally an IRQ, port, and Network ID must be supplied.
+Michael Smith's
+.Nm wlconfig(8)
+utility can now be used to do this work from
+the UNIX side. The card is "not" plug and play.
+The network id controls whether one set of cards can hear another.
+If different, cards will read physical packets, but they will be discarded
+by the radio modem.
+.Sh CONTROL
+In addition to the config utility, there are several sysctl
+switches that can be used to modify runtime parameters.
+The
+.Nm sysctl(8)
+variables are as follows:
+.Bl -diag
+.It "machdep.wl_xmit_delay <useconds>"
+This variable will cause the driver to insert a delay on transmit.
+250 is the default. The delay should probably be a bit longer
+on faster cpus and less on slower cpus. It exists because the 82586
+was not designed to work with pentium-speed cpu systems and if overdriven
+will have copious xmit side errors.
+.It machdep.wl_ignore_nwid <0 | 1>
+This switch defaults to 0; i.e., the nwid is not ignored. It can
+be set to 1 to cause the nwid to not be used. This may be useful
+when the device is in promiscuous mode as one can watch for all
+packets and ignore nwid differences.
+.It machdep.wl_xmit_watch <milliseconds>
+This switch is not currently useful.
+.It machdep.wl_gather_snr <milliseconds>
+This switch is not currently useful.
+.Pp
+There is also a signal strength cache in the driver. It may be interrogated
+with
+.Nm wlconfig(8) .
+Incoming packets
+are checked for certain hardware radio-modem values including signal
+strength, silence, and quality, which range fro 0..63, 0..63, and 0..15
+respectively. Thus one can read out signal strenth values to see
+how close/far peer nodes are. The signal strength cache is indexed by
+sender MAC address.
+There are two sysctls that change how it filters packets. Both are on
+by default.
+.It machdep.wl_wlcache_mcastonly <0 | 1>
+By default this switch is on. It forces the cache to filter out
+unicast packets. Only broadcast or multicast packets are accepted.
+.It machdep.wl_wlcache_iponly <0 | 1>
+By default this switch is on. It forces the driver to discard non-IP
+packets and also stores the IP src address. ARP packets are ignored,
+as are any other network protocol barring IPv4 packets.
+.El
+.Sh CAVEATS
+The 82586 has numerous defects. It may experience transmit-side
+errors when modern faster cpus send packets at it faster than it can handle.
+The driver (and probably the chip) does not support an all multicast mode.
+As a result, it can be used with applications like mrouted(8), but
+it must go into promiscuous mode for that to work. The driver
+is slow to change modes from "normal" to promiscuous mode, presumably
+due to delays in the configuration code.
+.Sh SEE ALSO
+.Xr wlconfig 8 ,
+.Xr sysctl 8 ,
+.Xr http://www.wavelan.com
+.Sh HISTORY
+The
+.Nm wl
+driver was written by Anders Klemets (thousands of years ago?) and
+appears to be based on an even older Intel 82586 driver. The 82586
+controller was one of the first (if not the first?) integrated lan
+controller on the block. That does not mean it was the best either.
+Anders ported and or created a driver for the ISA wavelan and PCCARD
+wavelan system too (wlp). Robert T. Morris, Jr. ported the Mach
+drivers to BSDI. Jim Binkley ported them to FreeBSD 2.1. Michael
+Smith ported the wl driver only to 2.2.2. Jim and Michael have been
+maintaining them. The current state of the driver is NOT ANYONE'S
+FAULT. Thanks to Bernie Doehner and Robert Buaas for contributions.
+.Sh AUTHOR
+Too numerous to mention. See above.
diff --git a/share/skel/dot.shrc b/share/skel/dot.shrc
new file mode 100644
index 000000000000..57103fe49a2e
--- /dev/null
+++ b/share/skel/dot.shrc
@@ -0,0 +1,43 @@
+# $Id: dot.profile,v 1.12 1997/07/15 09:37:02 charnier Exp $
+#
+# .shrc - bourne shell startup file
+#
+# This file will be used if the shell is invoked for interactive use and
+# the environment variable ENV is set to this file.
+#
+# see also sh(1), environ(7).
+#
+
+
+# file permissions: rwxr-xr-x
+#
+# umask 022
+
+# Uncomment next line to enable the builtin emacs(1) command line editor
+# in sh(1), e.g. C-a -> beginning-of-line.
+# set -o emacs
+
+
+# some useful aliases
+alias h='fc -l'
+alias j=jobs
+alias m=$PAGER
+alias ll='ls -laFo'
+alias l='ls -l'
+alias g='egrep -i'
+
+# # be paranoid
+# alias cp='cp -ip'
+# alias mv='mv -i'
+# alias rm='rm -i'
+
+
+# # set prompt: ``username@hostname$ ''
+# PS1="`whoami`@`hostname | sed 's/\..*//'`"
+# case `id -u` in
+# 0) PS1="${PS1}# ";;
+# *) PS1="${PS1}$ ";;
+# esac
+
+# search path for cd(1)
+# CDPATH=.:$HOME
diff --git a/sys/i386/boot/biosboot/boot.help b/sys/i386/boot/biosboot/boot.help
new file mode 100644
index 000000000000..7cbce1354839
--- /dev/null
+++ b/sys/i386/boot/biosboot/boot.help
@@ -0,0 +1,18 @@
+Usage: bios_drive:interface(unit,partition)kernel_name options
+ bios_drive 0, 1, ...
+ interface fd, wd or sd
+ unit 0, 1, ...
+ partition a, c, ...
+ kernel_name name of kernel, or ? for list of files in root directory
+ options -a (ask name) -C (cdrom) -c (userconfig) -D (dual consoles)
+ -d (debug early) -g (gdb) -h (serial console) -P (probe kbd)
+ -r (default root) -s (single user) -v (verbose)
+Examples:
+ 1:sd(0,a)mykernel boot `mykernel' on the first SCSI drive when one IDE
+ drive is present
+ 1:wd(2,a) boot from the second (secondary master) IDE drive
+ 1:sd(0,a)? list the files in the root directory on the specified
+ drive/unit/partition, and set the default bios_drive,
+ interface, unit and partition
+ -cv boot with the defaults, then run UserConfig to modify
+ hardware parameters (c), and print verbose messages (v)
diff --git a/sys/i386/include/if_wl_wavelan.h b/sys/i386/include/if_wl_wavelan.h
new file mode 100644
index 000000000000..c75a1aecf770
--- /dev/null
+++ b/sys/i386/include/if_wl_wavelan.h
@@ -0,0 +1,167 @@
+/* $Id$ */
+/*
+ * 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 all copyright
+ * notices, this list of conditions and the following disclaimer.
+ * 2. The names of the authors may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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 _CHIPS_WAVELAN_H
+#define _CHIPS_WAVELAN_H
+
+/* This file contains definitions that are common for all versions of
+ * the NCR WaveLAN
+ */
+
+#define WAVELAN_ADDR_SIZE 6 /* Size of a MAC address */
+#define WAVELAN_MTU 1500 /* Maximum size of Wavelan packet */
+
+/* Modem Management Controler write commands */
+#define MMC_ENCR_KEY 0x00 /* to 0x07 */
+#define MMC_ENCR_ENABLE 0x08
+#define MMC_DES_IO_INVERT 0x0a
+#define MMC_LOOPT_SEL 0x10
+#define MMC_JABBER_ENABLE 0x11
+#define MMC_FREEZE 0x12
+#define MMC_ANTEN_SEL 0x13
+#define MMC_IFS 0x14
+#define MMC_MOD_DELAY 0x15
+#define MMC_JAM_TIME 0x16
+#define MMC_THR_PRE_SET 0x18
+#define MMC_DECAY_PRM 0x19
+#define MMC_DECAY_UPDAT_PRM 0x1a
+#define MMC_QUALITY_THR 0x1b
+#define MMC_NETW_ID_L 0x1c
+#define MMC_NETW_ID_H 0x1d
+#define MMC_MODE_SEL 0x1e
+#define MMC_EECTRL 0x20 /* 2.4 Gz */
+#define MMC_EEADDR 0x21 /* 2.4 Gz */
+#define MMC_EEDATAL 0x22 /* 2.4 Gz */
+#define MMC_EEDATAH 0x23 /* 2.4 Gz */
+#define MMC_ANALCTRL 0x24 /* 2.4 Gz */
+
+/* fields in MMC registers that relate to EEPROM in WaveMODEM daughtercard */
+#define MMC_EECTRL_EEPRE 0x10 /* 2.4 Gz EEPROM Protect Reg Enable */
+#define MMC_EECTRL_DWLD 0x08 /* 2.4 Gz EEPROM Download Synths */
+#define MMC_EECTRL_EEOP 0x07 /* 2.4 Gz EEPROM Opcode mask */
+#define MMC_EECTRL_EEOP_READ 0x06 /* 2.4 Gz EEPROM Read Opcode */
+#define MMC_EEADDR_CHAN 0xf0 /* 2.4 Gz EEPROM Channel # mask */
+#define MMC_EEADDR_WDCNT 0x0f /* 2.4 Gz EEPROM DNLD WordCount-1 */
+#define MMC_ANALCTRL_ANTPOL 0x02 /* 2.4 Gz Antenna Polarity mask */
+#define MMC_ANALCTRL_EXTANT 0x01 /* 2.4 Gz External Antenna mask */
+
+/* MMC read register names */
+#define MMC_DCE_STATUS 0x10
+#define MMC_CORRECT_NWID_L 0x14
+#define MMC_CORRECT_NWID_H 0x15
+#define MMC_WRONG_NWID_L 0x16
+#define MMC_WRONG_NWID_H 0x17
+#define MMC_THR_PRE_SET 0x18
+#define MMC_SIGNAL_LVL 0x19
+#define MMC_SILENCE_LVL 0x1a
+#define MMC_SIGN_QUAL 0x1b
+#define MMC_DES_AVAIL 0x09
+#define MMC_EECTRLstat 0x20 /* 2.4 Gz EEPROM r/w/dwld status */
+#define MMC_EEDATALrv 0x22 /* 2.4 Gz EEPROM read value */
+#define MMC_EEDATAHrv 0x23 /* 2.4 Gz EEPROM read value */
+
+/* fields in MMC registers that relate to EEPROM in WaveMODEM daughtercard */
+#define MMC_EECTRLstat_ID24 0xf0 /* 2.4 Gz =A0 rev-A, =B0 rev-B */
+#define MMC_EECTRLstat_DWLD 0x08 /* 2.4 Gz Synth/Tx-Pwr DWLD busy */
+#define MMC_EECTRLstat_EEBUSY 0x04 /* 2.4 Gz EEPROM busy */
+
+#endif _CHIPS_WAVELAN_H
+
+/* additional socket ioctl params for wl card
+ * see sys/sockio.h for numbers. The 2nd params here
+ * must be greater than any values in sockio.h
+ */
+
+#define SIOCGWLCNWID _IOWR('i', 60, struct ifreq) /* get wlan current nwid */
+#define SIOCSWLCNWID _IOWR('i', 61, struct ifreq) /* set wlan current nwid */
+#define SIOCGWLPSA _IOWR('i', 62, struct ifreq) /* get wlan PSA (all) */
+#define SIOCSWLPSA _IOWR('i', 63, struct ifreq) /* set wlan PSA (all) */
+#define SIOCDWLCACHE _IOW('i', 64, struct ifreq) /* clear SNR cache */
+#define SIOCSWLTHR _IOW('i', 65, struct ifreq) /* set new quality threshold */
+#define SIOCGWLEEPROM _IOWR('i', 66, struct ifreq) /* get modem EEPROM */
+#define SIOCGWLCACHE _IOWR('i', 67, struct ifreq) /* get SNR cache */
+#define SIOCGWLCITEM _IOWR('i', 68, struct ifreq) /* get cache element count */
+
+/* PSA address definitions */
+#define WLPSA_ID 0x0 /* ID byte (0 for ISA, 0x14 for MCA) */
+#define WLPSA_IO1 0x1 /* I/O address 1 */
+#define WLPSA_IO2 0x2 /* I/O address 2 */
+#define WLPSA_IO3 0x3 /* I/O address 3 */
+#define WLPSA_BR1 0x4 /* Bootrom address 1 */
+#define WLPSA_BR2 0x5 /* Bootrom address 2 */
+#define WLPSA_BR3 0x6 /* Bootrom address 3 */
+#define WLPSA_HWCONF 0x7 /* HW config bits */
+#define WLPSA_IRQNO 0x8 /* IRQ value */
+#define WLPSA_UNIMAC 0x10 /* Universal MAC address */
+#define WLPSA_LOCALMAC 0x16 /* Locally configured MAC address */
+#define WLPSA_MACSEL 0x1c /* MAC selector */
+#define WLPSA_COMPATNO 0x1d /* compatability number */
+#define WLPSA_THRESH 0x1e /* RF modem threshold preset */
+#define WLPSA_FEATSEL 0x1f /* feature select */
+#define WLPSA_SUBBAND 0x20 /* subband selector */
+#define WLPSA_QUALTHRESH 0x21 /* RF modem quality threshold preset */
+#define WLPSA_HWVERSION 0x22 /* hardware version indicator */
+#define WLPSA_NWID 0x23 /* network ID */
+#define WLPSA_NWIDENABLE 0x24 /* network ID enable */
+#define WLPSA_SECURITY 0x25 /* datalink security enable */
+#define WLPSA_DESKEY 0x26 /* datalink security DES key */
+#define WLPSA_DBWIDTH 0x2f /* databus width select */
+#define WLPSA_CALLCODE 0x30 /* call code (japan only) */
+#define WLPSA_CONFIGURED 0x3c /* configuration status */
+#define WLPSA_CRCLOW 0x3d /* CRC-16 (lowbyte) */
+#define WLPSA_CRCHIGH 0x3e /* (highbyte) */
+#define WLPSA_CRCOK 0x3f /* CRC OK flag */
+
+#define WLPSA_COMPATNO_WL24B 0x04 /* 2.4 Gz WaveMODEM ISA rev-B */
+
+/*
+ * signal strength cache
+ *
+ * driver (wlp only at the moment) keeps cache of last
+ * IP (only) packets to arrive including signal strength info.
+ * daemons may read this with kvm. See if_wlp.c for globals
+ * that may be accessed through kvm.
+ *
+ * Each entry in the w_sigcache has a unique macsrc and age.
+ * Each entry is identified by its macsrc field.
+ * Age of the packet is identified by its age field.
+ */
+
+#define MAXCACHEITEMS 10
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+#define MAX_AGE (INT_MAX - MAXCACHEITEMS)
+
+/* signal is 7 bits, 0..63, although it doesn't seem to get to 63.
+ * silence is 7 bits, 0..63
+ * quality is 4 bits, 0..15
+ */
+struct w_sigcache {
+ char macsrc[6]; /* unique MAC address for entry */
+ int ipsrc; /* ip address associated with packet */
+ int signal; /* signal strength of the packet */
+ int silence; /* silence of the packet */
+ int quality; /* quality of the packet */
+ int snr; /* packet has unique age between 1 to MAX_AGE - 1 */
+};
+
diff --git a/sys/pci/dc21040reg.h b/sys/pci/dc21040reg.h
new file mode 100644
index 000000000000..ec274709ccaf
--- /dev/null
+++ b/sys/pci/dc21040reg.h
@@ -0,0 +1,598 @@
+/*-
+ * Copyright (c) 1994, 1995, 1996 Matt Thomas <matt@3am-software.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software withough 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.
+ *
+ * $Id: dc21040reg.h,v 1.24 1997/05/16 19:47:09 thomas Exp $
+ */
+
+#if !defined(_DC21040_H)
+#define _DC21040_H
+
+#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
+#define TULIP_BITFIELD2(a, b) b, a
+#define TULIP_BITFIELD3(a, b, c) c, b, a
+#define TULIP_BITFIELD4(a, b, c, d) d, c, b, a
+#else
+#define TULIP_BITFIELD2(a, b) a, b
+#define TULIP_BITFIELD3(a, b, c) a, b, c
+#define TULIP_BITFIELD4(a, b, c, d) a, b, c, d
+#endif
+
+typedef struct {
+ u_int32_t d_status;
+ u_int32_t TULIP_BITFIELD3(d_length1 : 11,
+ d_length2 : 11,
+ d_flag : 10);
+ u_int32_t d_addr1;
+ u_int32_t d_addr2;
+} tulip_desc_t;
+
+#define TULIP_DSTS_OWNER 0x80000000 /* Owner (1 = 21040) */
+#define TULIP_DSTS_ERRSUM 0x00008000 /* Error Summary */
+/*
+ * Transmit Status
+ */
+#define TULIP_DSTS_TxBABBLE 0x00004000 /* Transmitter Babbled */
+#define TULIP_DSTS_TxCARRLOSS 0x00000800 /* Carrier Loss */
+#define TULIP_DSTS_TxNOCARR 0x00000400 /* No Carrier */
+#define TULIP_DSTS_TxLATECOLL 0x00000200 /* Late Collision */
+#define TULIP_DSTS_TxEXCCOLL 0x00000100 /* Excessive Collisions */
+#define TULIP_DSTS_TxNOHRTBT 0x00000080 /* No Heartbeat */
+#define TULIP_DSTS_TxCOLLMASK 0x00000078 /* Collision Count (mask) */
+#define TULIP_DSTS_V_TxCOLLCNT 0x00000003 /* Collision Count (bit) */
+#define TULIP_DSTS_TxLINKFAIL 0x00000004 /* Link Failure */
+#define TULIP_DSTS_TxUNDERFLOW 0x00000002 /* Underflow Error */
+#define TULIP_DSTS_TxDEFERRED 0x00000001 /* Initially Deferred */
+/*
+ * Receive Status
+ */
+#define TULIP_DSTS_RxBADLENGTH 0x00004000 /* Length Error */
+#define TULIP_DSTS_RxDATATYPE 0x00003000 /* Data Type */
+#define TULIP_DSTS_RxRUNT 0x00000800 /* Runt Frame */
+#define TULIP_DSTS_RxMULTICAST 0x00000400 /* Multicast Frame */
+#define TULIP_DSTS_RxFIRSTDESC 0x00000200 /* First Descriptor */
+#define TULIP_DSTS_RxLASTDESC 0x00000100 /* Last Descriptor */
+#define TULIP_DSTS_RxTOOLONG 0x00000080 /* Frame Too Long */
+#define TULIP_DSTS_RxCOLLSEEN 0x00000040 /* Collision Seen */
+#define TULIP_DSTS_RxFRAMETYPE 0x00000020 /* Frame Type */
+#define TULIP_DSTS_RxWATCHDOG 0x00000010 /* Receive Watchdog */
+#define TULIP_DSTS_RxDRBBLBIT 0x00000004 /* Dribble Bit */
+#define TULIP_DSTS_RxBADCRC 0x00000002 /* CRC Error */
+#define TULIP_DSTS_RxOVERFLOW 0x00000001 /* Overflow */
+
+
+#define TULIP_DFLAG_ENDRING 0x0008 /* End of Transmit Ring */
+#define TULIP_DFLAG_CHAIN 0x0004 /* Chain using d_addr2 */
+
+#define TULIP_DFLAG_TxWANTINTR 0x0200 /* Signal Interrupt on Completion */
+#define TULIP_DFLAG_TxLASTSEG 0x0100 /* Last Segment */
+#define TULIP_DFLAG_TxFIRSTSEG 0x0080 /* First Segment */
+#define TULIP_DFLAG_TxINVRSFILT 0x0040 /* Inverse Filtering */
+#define TULIP_DFLAG_TxSETUPPKT 0x0020 /* Setup Packet */
+#define TULIP_DFLAG_TxHASCRC 0x0010 /* Don't Append the CRC */
+#define TULIP_DFLAG_TxNOPADDING 0x0002 /* Don't AutoPad */
+#define TULIP_DFLAG_TxHASHFILT 0x0001 /* Hash/Perfect Filtering */
+
+/*
+ * The 21040 Registers (IO Space Addresses)
+ */
+#define TULIP_REG_BUSMODE 0x00 /* CSR0 -- Bus Mode */
+#define TULIP_REG_TXPOLL 0x08 /* CSR1 -- Transmit Poll Demand */
+#define TULIP_REG_RXPOLL 0x10 /* CSR2 -- Receive Poll Demand */
+#define TULIP_REG_RXLIST 0x18 /* CSR3 -- Receive List Base Addr */
+#define TULIP_REG_TXLIST 0x20 /* CSR4 -- Transmit List Base Addr */
+#define TULIP_REG_STATUS 0x28 /* CSR5 -- Status */
+#define TULIP_REG_CMD 0x30 /* CSR6 -- Command */
+#define TULIP_REG_INTR 0x38 /* CSR7 -- Interrupt Control */
+#define TULIP_REG_MISSES 0x40 /* CSR8 -- Missed Frame Counter */
+#define TULIP_REG_ADDRROM 0x48 /* CSR9 -- ENET ROM Register */
+#define TULIP_REG_RSRVD 0x50 /* CSR10 -- Reserved */
+#define TULIP_REG_FULL_DUPLEX 0x58 /* CSR11 -- Full Duplex */
+#define TULIP_REG_SIA_STATUS 0x60 /* CSR12 -- SIA Status */
+#define TULIP_REG_SIA_CONN 0x68 /* CSR13 -- SIA Connectivity */
+#define TULIP_REG_SIA_TXRX 0x70 /* CSR14 -- SIA Tx Rx */
+#define TULIP_REG_SIA_GEN 0x78 /* CSR15 -- SIA General */
+
+/*
+ * CSR5 -- Status Register
+ * CSR7 -- Interrupt Control
+ */
+#define TULIP_STS_ERRORMASK 0x03800000L /* ( R) Error Bits (Valid when SYSERROR is set) */
+#define TULIP_STS_ERR_PARITY 0x00000000L /* 000 - Parity Error (Perform Reset) */
+#define TULIP_STS_ERR_MASTER 0x00800000L /* 001 - Master Abort */
+#define TULIP_STS_ERR_TARGET 0x01000000L /* 010 - Target Abort */
+#define TULIP_STS_ERR_SHIFT 23
+#define TULIP_STS_TXSTATEMASK 0x00700000L /* ( R) Transmission Process State */
+#define TULIP_STS_TXS_RESET 0x00000000L /* 000 - Rset or transmit jabber expired */
+#define TULIP_STS_TXS_FETCH 0x00100000L /* 001 - Fetching transmit descriptor */
+#define TULIP_STS_TXS_WAITEND 0x00200000L /* 010 - Wait for end of transmission */
+#define TULIP_STS_TXS_READING 0x00300000L /* 011 - Read buffer and enqueue data */
+#define TULIP_STS_TXS_RSRVD 0x00400000L /* 100 - Reserved */
+#define TULIP_STS_TXS_SETUP 0x00500000L /* 101 - Setup Packet */
+#define TULIP_STS_TXS_SUSPEND 0x00600000L /* 110 - Transmit FIFO underflow or an
+ unavailable transmit descriptor */
+#define TULIP_STS_TXS_CLOSE 0x00700000L /* 111 - Close transmit descriptor */
+#define TULIP_STS_RXSTATEMASK 0x000E0000L /* ( R) Receive Process State*/
+#define TULIP_STS_RXS_STOPPED 0x00000000L /* 000 - Stopped */
+#define TULIP_STS_RXS_FETCH 0x00020000L /* 001 - Running -- Fetch receive descriptor */
+#define TULIP_STS_RXS_ENDCHECK 0x00040000L /* 010 - Running -- Check for end of receive
+ packet before prefetch of next descriptor */
+#define TULIP_STS_RXS_WAIT 0x00060000L /* 011 - Running -- Wait for receive packet */
+#define TULIP_STS_RXS_SUSPEND 0x00080000L /* 100 - Suspended -- As a result of
+ unavailable receive buffers */
+#define TULIP_STS_RXS_CLOSE 0x000A0000L /* 101 - Running -- Close receive descriptor */
+#define TULIP_STS_RXS_FLUSH 0x000C0000L /* 110 - Running -- Flush the current frame
+ from the receive FIFO as a result of
+ an unavailable receive buffer */
+#define TULIP_STS_RXS_DEQUEUE 0x000E0000L /* 111 - Running -- Dequeue the receive frame
+ from the receive FIFO into the receive
+ buffer. */
+#define TULIP_STS_NORMALINTR 0x00010000L /* (RW) Normal Interrupt */
+#define TULIP_STS_ABNRMLINTR 0x00008000L /* (RW) Abnormal Interrupt */
+#define TULIP_STS_SYSERROR 0x00002000L /* (RW) System Error */
+#define TULIP_STS_LINKFAIL 0x00001000L /* (RW) Link Failure (21040) */
+#define TULIP_STS_FULDPLXSHRT 0x00000800L /* (RW) Full Duplex Short Fram Rcvd (21040) */
+#define TULIP_STS_GPTIMEOUT 0x00000800L /* (RW) General Purpose Timeout (21140) */
+#define TULIP_STS_AUI 0x00000400L /* (RW) AUI/TP Switch (21040) */
+#define TULIP_STS_RXTIMEOUT 0x00000200L /* (RW) Receive Watchbog Timeout */
+#define TULIP_STS_RXSTOPPED 0x00000100L /* (RW) Receive Process Stopped */
+#define TULIP_STS_RXNOBUF 0x00000080L /* (RW) Receive Buffer Unavailable */
+#define TULIP_STS_RXINTR 0x00000040L /* (RW) Receive Interrupt */
+#define TULIP_STS_TXUNDERFLOW 0x00000020L /* (RW) Transmit Underflow */
+#define TULIP_STS_LINKPASS 0x00000010L /* (RW) LinkPass (21041) */
+#define TULIP_STS_TXBABBLE 0x00000008L /* (RW) Transmit Jabber Timeout */
+#define TULIP_STS_TXNOBUF 0x00000004L /* (RW) Transmit Buffer Unavailable */
+#define TULIP_STS_TXSTOPPED 0x00000002L /* (RW) Transmit Process Stopped */
+#define TULIP_STS_TXINTR 0x00000001L /* (RW) Transmit Interrupt */
+
+/*
+ * CSR6 -- Command (Operation Mode) Register
+ */
+#define TULIP_CMD_MUSTBEONE 0x02000000L /* (RW) Must Be One (21140) */
+#define TULIP_CMD_SCRAMBLER 0x01000000L /* (RW) Scrambler Mode (21140) */
+#define TULIP_CMD_PCSFUNCTION 0x00800000L /* (RW) PCS Function (21140) */
+#define TULIP_CMD_TXTHRSHLDCTL 0x00400000L /* (RW) Transmit Threshold Mode (21140) */
+#define TULIP_CMD_STOREFWD 0x00200000L /* (RW) Store and Foward (21140) */
+#define TULIP_CMD_NOHEARTBEAT 0x00080000L /* (RW) No Heartbeat (21140) */
+#define TULIP_CMD_PORTSELECT 0x00040000L /* (RW) Post Select (100Mb) (21140) */
+#define TULIP_CMD_ENHCAPTEFFCT 0x00040000L /* (RW) Enhanced Capture Effecty (21041) */
+#define TULIP_CMD_CAPTREFFCT 0x00020000L /* (RW) Capture Effect (!802.3) */
+#define TULIP_CMD_BACKPRESSURE 0x00010000L /* (RW) Back Pressure (!802.3) (21040) */
+#define TULIP_CMD_THRESHOLDCTL 0x0000C000L /* (RW) Threshold Control */
+#define TULIP_CMD_THRSHLD72 0x00000000L /* 00 - 72 Bytes */
+#define TULIP_CMD_THRSHLD96 0x00004000L /* 01 - 96 Bytes */
+#define TULIP_CMD_THRSHLD128 0x00008000L /* 10 - 128 bytes */
+#define TULIP_CMD_THRSHLD160 0x0000C000L /* 11 - 160 Bytes */
+#define TULIP_CMD_TXRUN 0x00002000L /* (RW) Start/Stop Transmitter */
+#define TULIP_CMD_FORCECOLL 0x00001000L /* (RW) Force Collisions */
+#define TULIP_CMD_OPERMODE 0x00000C00L /* (RW) Operating Mode */
+#define TULIP_CMD_FULLDUPLEX 0x00000200L /* (RW) Full Duplex Mode */
+#define TULIP_CMD_FLAKYOSCDIS 0x00000100L /* (RW) Flakey Oscillator Disable */
+#define TULIP_CMD_ALLMULTI 0x00000080L /* (RW) Pass All Multicasts */
+#define TULIP_CMD_PROMISCUOUS 0x00000040L /* (RW) Promiscuous Mode */
+#define TULIP_CMD_BACKOFFCTR 0x00000020L /* (RW) Start/Stop Backoff Counter (!802.3) */
+#define TULIP_CMD_INVFILTER 0x00000010L /* (R ) Inverse Filtering */
+#define TULIP_CMD_PASSBADPKT 0x00000008L /* (RW) Pass Bad Frames */
+#define TULIP_CMD_HASHONLYFLTR 0x00000004L /* (R ) Hash Only Filtering */
+#define TULIP_CMD_RXRUN 0x00000002L /* (RW) Start/Stop Receive Filtering */
+#define TULIP_CMD_HASHPRFCTFLTR 0x00000001L /* (R ) Hash/Perfect Receive Filtering */
+
+#define TULIP_SIASTS_OTHERRXACTIVITY 0x00000200L
+#define TULIP_SIASTS_RXACTIVITY 0x00000100L
+#define TULIP_SIASTS_LINKFAIL 0x00000004L
+#define TULIP_SIACONN_RESET 0x00000000L
+
+/*
+ * 21040 SIA definitions
+ */
+#define TULIP_21040_PROBE_10BASET_TIMEOUT 2500
+#define TULIP_21040_PROBE_AUIBNC_TIMEOUT 300
+#define TULIP_21040_PROBE_EXTSIA_TIMEOUT 300
+
+#define TULIP_21040_SIACONN_10BASET 0x00008F01L
+#define TULIP_21040_SIATXRX_10BASET 0x0000FFFFL
+#define TULIP_21040_SIAGEN_10BASET 0x00000000L
+
+#define TULIP_21040_SIACONN_10BASET_FD 0x00008F01L
+#define TULIP_21040_SIATXRX_10BASET_FD 0x0000FFFDL
+#define TULIP_21040_SIAGEN_10BASET_FD 0x00000000L
+
+#define TULIP_21040_SIACONN_AUIBNC 0x00008F09L
+#define TULIP_21040_SIATXRX_AUIBNC 0x00000705L
+#define TULIP_21040_SIAGEN_AUIBNC 0x00000006L
+
+#define TULIP_21040_SIACONN_EXTSIA 0x00003041L
+#define TULIP_21040_SIATXRX_EXTSIA 0x00000000L
+#define TULIP_21040_SIAGEN_EXTSIA 0x00000006L
+
+/*
+ * 21041 SIA definitions
+ */
+
+#define TULIP_21041_PROBE_10BASET_TIMEOUT 2500
+#define TULIP_21041_PROBE_AUIBNC_TIMEOUT 300
+
+#define TULIP_21041_SIACONN_10BASET 0x0000EF01L
+#define TULIP_21041_SIATXRX_10BASET 0x0000FF3FL
+#define TULIP_21041_SIAGEN_10BASET 0x00000000L
+
+#define TULIP_21041P2_SIACONN_10BASET 0x0000EF01L
+#define TULIP_21041P2_SIATXRX_10BASET 0x0000FFFFL
+#define TULIP_21041P2_SIAGEN_10BASET 0x00000000L
+
+#define TULIP_21041_SIACONN_10BASET_FD 0x0000EF01L
+#define TULIP_21041_SIATXRX_10BASET_FD 0x0000FF3DL
+#define TULIP_21041_SIAGEN_10BASET_FD 0x00000000L
+
+#define TULIP_21041P2_SIACONN_10BASET_FD 0x0000EF01L
+#define TULIP_21041P2_SIATXRX_10BASET_FD 0x0000FFFFL
+#define TULIP_21041P2_SIAGEN_10BASET_FD 0x00000000L
+
+#define TULIP_21041_SIACONN_AUI 0x0000EF09L
+#define TULIP_21041_SIATXRX_AUI 0x0000F73DL
+#define TULIP_21041_SIAGEN_AUI 0x0000000EL
+
+#define TULIP_21041P2_SIACONN_AUI 0x0000EF09L
+#define TULIP_21041P2_SIATXRX_AUI 0x0000F7FDL
+#define TULIP_21041P2_SIAGEN_AUI 0x0000000EL
+
+#define TULIP_21041_SIACONN_BNC 0x0000EF09L
+#define TULIP_21041_SIATXRX_BNC 0x0000F73DL
+#define TULIP_21041_SIAGEN_BNC 0x00000006L
+
+#define TULIP_21041P2_SIACONN_BNC 0x0000EF09L
+#define TULIP_21041P2_SIATXRX_BNC 0x0000F7FDL
+#define TULIP_21041P2_SIAGEN_BNC 0x00000006L
+
+/*
+ * 21142 SIA definitions
+ */
+
+#define TULIP_21142_PROBE_10BASET_TIMEOUT 2500
+#define TULIP_21142_PROBE_AUIBNC_TIMEOUT 300
+
+#define TULIP_21142_SIACONN_10BASET 0x00000001L
+#define TULIP_21142_SIATXRX_10BASET 0x0000F3FFL
+#define TULIP_21142_SIAGEN_10BASET 0x00000000L
+
+#define TULIP_21142_SIACONN_10BASET_FD 0x00000001L
+#define TULIP_21142_SIATXRX_10BASET_FD 0x0000F3FDL
+#define TULIP_21142_SIAGEN_10BASET_FD 0x00000000L
+
+#define TULIP_21142_SIACONN_AUI 0x00000009L
+#define TULIP_21142_SIATXRX_AUI 0x0000F3FDL
+#define TULIP_21142_SIAGEN_AUI 0x0000000EL
+
+#define TULIP_21142_SIACONN_BNC 0x00000009L
+#define TULIP_21142_SIATXRX_BNC 0x0000F3FDL
+#define TULIP_21142_SIAGEN_BNC 0x00000006L
+
+
+
+
+#define TULIP_WATCHDOG_TXDISABLE 0x00000001L
+#define TULIP_WATCHDOG_RXDISABLE 0x00000010L
+
+#define TULIP_BUSMODE_SWRESET 0x00000001L
+#define TULIP_BUSMODE_DESCSKIPLEN_MASK 0x0000007CL
+#define TULIP_BUSMODE_BIGENDIAN 0x00000080L
+#define TULIP_BUSMODE_BURSTLEN_MASK 0x00003F00L
+#define TULIP_BUSMODE_BURSTLEN_DEFAULT 0x00000000L
+#define TULIP_BUSMODE_BURSTLEN_1LW 0x00000100L
+#define TULIP_BUSMODE_BURSTLEN_2LW 0x00000200L
+#define TULIP_BUSMODE_BURSTLEN_4LW 0x00000400L
+#define TULIP_BUSMODE_BURSTLEN_8LW 0x00000800L
+#define TULIP_BUSMODE_BURSTLEN_16LW 0x00001000L
+#define TULIP_BUSMODE_BURSTLEN_32LW 0x00002000L
+#define TULIP_BUSMODE_CACHE_NOALIGN 0x00000000L
+#define TULIP_BUSMODE_CACHE_ALIGN8 0x00004000L
+#define TULIP_BUSMODE_CACHE_ALIGN16 0x00008000L
+#define TULIP_BUSMODE_CACHE_ALIGN32 0x0000C000L
+#define TULIP_BUSMODE_TXPOLL_NEVER 0x00000000L
+#define TULIP_BUSMODE_TXPOLL_200000ns 0x00020000L
+#define TULIP_BUSMODE_TXPOLL_800000ns 0x00040000L
+#define TULIP_BUSMODE_TXPOLL_1600000ns 0x00060000L
+#define TULIP_BUSMODE_TXPOLL_12800ns 0x00080000L /* 21041 only */
+#define TULIP_BUSMODE_TXPOLL_25600ns 0x000A0000L /* 21041 only */
+#define TULIP_BUSMODE_TXPOLL_51200ns 0x000C0000L /* 21041 only */
+#define TULIP_BUSMODE_TXPOLL_102400ns 0x000E0000L /* 21041 only */
+#define TULIP_BUSMODE_DESC_BIGENDIAN 0x00100000L /* 21041 only */
+#define TULIP_BUSMODE_READMULTIPLE 0x00200000L /* */
+
+#define TULIP_REG_CFDA 0x40
+#define TULIP_CFDA_SLEEP 0x80000000L
+#define TULIP_CFDA_SNOOZE 0x40000000L
+
+#define TULIP_GP_PINSET 0x00000100L
+/*
+ * These are the defintitions used for the DEC 21140
+ * evaluation board.
+ */
+#define TULIP_GP_EB_PINS 0x0000001F /* General Purpose Pin directions */
+#define TULIP_GP_EB_OK10 0x00000080 /* 10 Mb/sec Signal Detect gep<7> */
+#define TULIP_GP_EB_OK100 0x00000040 /* 100 Mb/sec Signal Detect gep<6> */
+#define TULIP_GP_EB_INIT 0x0000000B /* No loopback --- point-to-point */
+
+/*
+ * These are the defintitions used for the SMC9332 (21140) board.
+ */
+#define TULIP_GP_SMC_9332_PINS 0x0000003F /* General Purpose Pin directions */
+#define TULIP_GP_SMC_9332_OK10 0x00000080 /* 10 Mb/sec Signal Detect gep<7> */
+#define TULIP_GP_SMC_9332_OK100 0x00000040 /* 100 Mb/sec Signal Detect gep<6> */
+#define TULIP_GP_SMC_9332_INIT 0x00000009 /* No loopback --- point-to-point */
+
+#define TULIP_OUI_SMC_0 0x00
+#define TULIP_OUI_SMC_1 0x00
+#define TULIP_OUI_SMC_2 0xC0
+
+/*
+ * There are the definitions used for the DEC DE500
+ * 10/100 family of boards
+ */
+#define TULIP_GP_DE500_PINS 0x0000001FL
+#define TULIP_GP_DE500_LINK_PASS 0x00000080L
+#define TULIP_GP_DE500_SYM_LINK 0x00000040L
+#define TULIP_GP_DE500_SIGNAL_DETECT 0x00000020L
+#define TULIP_GP_DE500_PHY_RESET 0x00000010L
+#define TULIP_GP_DE500_HALFDUPLEX 0x00000008L
+#define TULIP_GP_DE500_PHY_LOOPBACK 0x00000004L
+#define TULIP_GP_DE500_FORCE_LED 0x00000002L
+#define TULIP_GP_DE500_FORCE_100 0x00000001L
+
+/*
+ * These are the defintitions used for the Cogent EM100
+ * 21140 board.
+ */
+#define TULIP_GP_EM100_PINS 0x0000003F /* General Purpose Pin directions */
+#define TULIP_GP_EM100_INIT 0x00000009 /* No loopback --- point-to-point */
+#define TULIP_OUI_COGENT_0 0x00
+#define TULIP_OUI_COGENT_1 0x00
+#define TULIP_OUI_COGENT_2 0x92
+#define TULIP_COGENT_EM100TX_ID 0x12
+#define TULIP_COGENT_EM100FX_ID 0x15
+
+
+/*
+ * These are the defintitions used for the Znyx ZX342
+ * 10/100 board
+ */
+#define TULIP_OUI_ZNYX_0 0x00
+#define TULIP_OUI_ZNYX_1 0xC0
+#define TULIP_OUI_ZNYX_2 0x95
+
+#define TULIP_ZNYX_ID_ZX312 0x0602
+#define TULIP_ZNYX_ID_ZX312T 0x0622
+#define TULIP_ZNYX_ID_ZX314_INTA 0x0701
+#define TULIP_ZNYX_ID_ZX314 0x0711
+#define TULIP_ZNYX_ID_ZX315_INTA 0x0801
+#define TULIP_ZNYX_ID_ZX315 0x0811
+#define TULIP_ZNYX_ID_ZX342 0x0901
+#define TULIP_ZNYX_ID_ZX342B 0x0921
+#define TULIP_ZNYX_ID_ZX342_X3 0x0902
+#define TULIP_ZNYX_ID_ZX342_X4 0x0903
+#define TULIP_ZNYX_ID_ZX344 0x0A01
+#define TULIP_ZNYX_ID_ZX351 0x0B01
+#define TULIP_ZNYX_ID_ZX345 0x0C01
+#define TULIP_ZNYX_ID_ZX311 0x0D01
+#define TULIP_ZNYX_ID_ZX346 0x0E01
+
+#define TULIP_GP_ZX34X_PINS 0x0000001F /* General Purpose Pin directions */
+#define TULIP_GP_ZX344_PINS 0x0000000B /* General Purpose Pin directions */
+#define TULIP_GP_ZX345_PINS 0x00000003 /* General Purpose Pin directions */
+#define TULIP_GP_ZX346_PINS 0x00000043 /* General Purpose Pin directions */
+#define TULIP_GP_ZX34X_LNKFAIL 0x00000080 /* 10Mb/s Link Failure */
+#define TULIP_GP_ZX34X_SYMDET 0x00000040 /* 100Mb/s Symbol Detect */
+#define TULIP_GP_ZX345_PHYACT 0x00000040 /* PHY Activity */
+#define TULIP_GP_ZX34X_SIGDET 0x00000020 /* 100Mb/s Signal Detect */
+#define TULIP_GP_ZX346_AUTONEG_ENABLED 0x00000020 /* 802.3u autoneg enabled */
+#define TULIP_GP_ZX342_COLENA 0x00000008 /* 10t Ext LB */
+#define TULIP_GP_ZX344_ROTINT 0x00000008 /* PPB IRQ rotation */
+#define TULIP_GP_ZX345_SPEED10 0x00000008 /* 10Mb speed detect */
+#define TULIP_GP_ZX346_SPEED100 0x00000008 /* 100Mb speed detect */
+#define TULIP_GP_ZX34X_NCOLENA 0x00000004 /* 10t Int LB */
+#define TULIP_GP_ZX34X_RXMATCH 0x00000004 /* RX Match */
+#define TULIP_GP_ZX346_FULLDUPLEX 0x00000004 /* Full Duplex Sensed */
+#define TULIP_GP_ZX34X_LB102 0x00000002 /* 100tx twister LB */
+#define TULIP_GP_ZX34X_NLB101 0x00000001 /* PDT/PDR LB */
+#define TULIP_GP_ZX34X_INIT 0x00000009
+
+/*
+ * Compex's OUI. We need to twiddle a bit on their 21041 card.
+ */
+#define TULIP_OUI_COMPEX_0 0x00
+#define TULIP_OUI_COMPEX_1 0x80
+#define TULIP_OUI_COMPEX_2 0x48
+#define TULIP_21041_COMPEX_XREGDATA 1
+
+/*
+ * Asante's OUI and stuff...
+ */
+#define TULIP_OUI_ASANTE_0 0x00
+#define TULIP_OUI_ASANTE_1 0x00
+#define TULIP_OUI_ASANTE_2 0x94
+#define TULIP_GP_ASANTE_PINS 0x000000bf /* GP pin config */
+#define TULIP_GP_ASANTE_PHYRESET 0x00000008 /* Reset PHY */
+
+/*
+ * SROM definitions for the 21140 and 21041.
+ */
+#define SROMXREG 0x0400
+#define SROMSEL 0x0800
+#define SROMRD 0x4000
+#define SROMWR 0x2000
+#define SROMDIN 0x0008
+#define SROMDOUT 0x0004
+#define SROMDOUTON 0x0004
+#define SROMDOUTOFF 0x0004
+#define SROMCLKON 0x0002
+#define SROMCLKOFF 0x0002
+#define SROMCSON 0x0001
+#define SROMCSOFF 0x0001
+#define SROMCS 0x0001
+
+#define SROMCMD_MODE 4
+#define SROMCMD_WR 5
+#define SROMCMD_RD 6
+
+#define SROM_BITWIDTH 6
+
+/*
+ * MII Definitions for the 21041 and 21140/21140A/21142
+ */
+#define MII_PREAMBLE (~0)
+#define MII_TEST 0xAAAAAAAA
+#define MII_RDCMD 0xF6 /* 1111.0110 */
+#define MII_WRCMD 0xF5 /* 1111.0101 */
+#define MII_DIN 0x00080000
+#define MII_RD 0x00040000
+#define MII_WR 0x00000000
+#define MII_DOUT 0x00020000
+#define MII_CLK 0x00010000
+#define MII_CLKON MII_CLK
+#define MII_CLKOFF MII_CLK
+
+#define PHYREG_CONTROL 0
+#define PHYREG_STATUS 1
+#define PHYREG_IDLOW 2
+#define PHYREG_IDHIGH 3
+#define PHYREG_AUTONEG_ADVERTISEMENT 4
+#define PHYREG_AUTONEG_ABILITIES 5
+#define PHYREG_AUTONEG_EXPANSION 6
+#define PHYREG_AUTONEG_NEXTPAGE 7
+
+#define PHYSTS_100BASET4 0x8000
+#define PHYSTS_100BASETX_FD 0x4000
+#define PHYSTS_100BASETX 0x2000
+#define PHYSTS_10BASET_FD 0x1000
+#define PHYSTS_10BASET 0x0800
+#define PHYSTS_AUTONEG_DONE 0x0020
+#define PHYSTS_REMOTE_FAULT 0x0010
+#define PHYSTS_CAN_AUTONEG 0x0008
+#define PHYSTS_LINK_UP 0x0004
+#define PHYSTS_JABBER_DETECT 0x0002
+#define PHYSTS_EXTENDED_REGS 0x0001
+
+#define PHYCTL_RESET 0x8000
+#define PHYCTL_SELECT_100MB 0x2000
+#define PHYCTL_AUTONEG_ENABLE 0x1000
+#define PHYCTL_ISOLATE 0x0400
+#define PHYCTL_AUTONEG_RESTART 0x0200
+#define PHYCTL_FULL_DUPLEX 0x0100
+
+
+#define MII_RD 0x00040000
+#define MII_WR 0x00000000
+#define MII_DIN 0x00080000
+#define MII_DOUT 0x00020000
+#define MII_DOUTON MII_DOUT
+#define MII_DOUTOFF MII_DOUT
+#define MII_CLK 0x00010000
+#define MII_CLKON MII_CLK
+#define MII_CLKOFF MII_CLK
+
+/*
+ * Definitions for the DE425.
+ */
+#define DE425_CFID 0x08 /* Configuration Id */
+#define DE425_CFCS 0x0C /* Configuration Command-Status */
+#define DE425_CFRV 0x18 /* Configuration Revision */
+#define DE425_CFLT 0x1C /* Configuration Latency Timer */
+#define DE425_CBIO 0x28 /* Configuration Base IO Address */
+#define DE425_CFDA 0x2C /* Configuration Driver Area */
+#define DE425_ENETROM_OFFSET 0xC90 /* Offset in I/O space for ENETROM */
+#define DE425_CFG0 0xC88 /* IRQ register */
+#define DE425_EISAID 0x10a34250 /* EISA device id */
+#define DE425_EISA_IOSIZE 0x100
+
+#define DEC_VENDORID 0x1011
+#define CHIPID_21040 0x0002
+#define CHIPID_21140 0x0009
+#define CHIPID_21041 0x0014
+#define CHIPID_21142 0x0019
+#define PCI_VENDORID(x) ((x) & 0xFFFF)
+#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
+
+/*
+ * Generic SROM Format
+ *
+ *
+ */
+
+typedef struct {
+ u_int8_t sh_idbuf[18];
+ u_int8_t sh_version;
+ u_int8_t sh_adapter_count;
+ u_int8_t sh_ieee802_address[6];
+} tulip_srom_header_t;
+
+typedef struct {
+ u_int8_t sai_device;
+ u_int8_t sai_leaf_offset_lowbyte;
+ u_int8_t sai_leaf_offset_highbyte;
+} tulip_srom_adapter_info_t;
+
+typedef enum {
+ TULIP_SROM_CONNTYPE_10BASET =0x0000,
+ TULIP_SROM_CONNTYPE_BNC =0x0001,
+ TULIP_SROM_CONNTYPE_AUI =0x0002,
+ TULIP_SROM_CONNTYPE_100BASETX =0x0003,
+ TULIP_SROM_CONNTYPE_100BASET4 =0x0006,
+ TULIP_SROM_CONNTYPE_100BASEFX =0x0007,
+ TULIP_SROM_CONNTYPE_MII_10BASET =0x0009,
+ TULIP_SROM_CONNTYPE_MII_100BASETX =0x000D,
+ TULIP_SROM_CONNTYPE_MII_100BASET4 =0x000F,
+ TULIP_SROM_CONNTYPE_MII_100BASEFX =0x0010,
+ TULIP_SROM_CONNTYPE_10BASET_NWAY =0x0100,
+ TULIP_SROM_CONNTYPE_10BASET_FD =0x0204,
+ TULIP_SROM_CONNTYPE_MII_10BASET_FD =0x020A,
+ TULIP_SROM_CONNTYPE_100BASETX_FD =0x020E,
+ TULIP_SROM_CONNTYPE_MII_100BASETX_FD =0x0211,
+ TULIP_SROM_CONNTYPE_10BASET_NOLINKPASS =0x0400,
+ TULIP_SROM_CONNTYPE_AUTOSENSE =0x0800,
+ TULIP_SROM_CONNTYPE_AUTOSENSE_POWERUP =0x8800,
+ TULIP_SROM_CONNTYPE_AUTOSENSE_NWAY =0x9000,
+ TULIP_SROM_CONNTYPE_NOT_USED =0xFFFF
+} tulip_srom_connection_t;
+
+typedef enum {
+ TULIP_SROM_MEDIA_10BASET =0x0000,
+ TULIP_SROM_MEDIA_BNC =0x0001,
+ TULIP_SROM_MEDIA_AUI =0x0002,
+ TULIP_SROM_MEDIA_100BASETX =0x0003,
+ TULIP_SROM_MEDIA_10BASET_FD =0x0004,
+ TULIP_SROM_MEDIA_100BASETX_FD =0x0005,
+ TULIP_SROM_MEDIA_100BASET4 =0x0006,
+ TULIP_SROM_MEDIA_100BASEFX =0x0007,
+ TULIP_SROM_MEDIA_100BASEFX_FD =0x0008
+} tulip_srom_media_t;
+
+#define TULIP_SROM_21041_EXTENDED 0x40
+
+#define TULIP_SROM_2114X_NOINDICATOR 0x8000
+#define TULIP_SROM_2114X_DEFAULT 0x4000
+#define TULIP_SROM_2114X_POLARITY 0x0080
+#define TULIP_SROM_2114X_CMDBITS(n) (((n) & 0x0071) << 18)
+#define TULIP_SROM_2114X_BITPOS(b) (1 << (((b) & 0x0E) >> 1))
+
+
+
+#endif /* !defined(_DC21040_H) */
diff --git a/usr.sbin/natd/HISTORY b/usr.sbin/natd/HISTORY
new file mode 100644
index 000000000000..404be4be06d0
--- /dev/null
+++ b/usr.sbin/natd/HISTORY
@@ -0,0 +1,113 @@
+* Version 0.1
+
+ Initial version of natd.
+
+* Version 0.2
+
+ - Alias address can now be set by giving interface name with
+ new (-n) command-line option.
+
+ - New Makefile based on bsd.prog.mk.
+
+ - Error messages are written to syslog
+ after natd has become a daemon.
+
+* Version 1.0
+
+ - Support for using only single socket (-p option)
+
+* Version 1.1
+
+ - -a option now understands a hostname also.
+ - -a option no longer dumps core.
+ - Packet aliasing software upgraded to v. 1.9
+ - added long option names (like -address)
+
+* Version 1.2
+
+ - Fixed core dump with -port option.
+ - Added -Wall to CFLAGS and some headers added to natd.c
+ to get clean compile by Brian Somers [brian@awfulhak.org].
+
+* Version 1.3
+
+ - Aliasing address initialization is delayed until first
+ packet arrives. This allows natd to start up before
+ interface address is set.
+ - SIGTERM is now catched to allow kernel to close
+ existing connections when system is shutting down.
+ - SIGHUP is now catched to allow natd to refresh aliasing
+ address from interface, which might be useful to tun devices.
+
+* Version 1.4
+
+ - Changed command line options to be compatible with
+ command names used in ppp+packetAlias package (which is the
+ original application using aliasing routines).
+
+ The options which map directly to packet aliasing options are:
+
+ -unregistered_only [yes|no]
+ -log [yes|no]
+ -deny_incoming [yes|no]
+ -use_sockets [yes|no]
+ -same_ports [yes|no]
+
+ The short option names are the same as in previous
+ releases.
+
+ - Command line parser rewritten to provide more flexible
+ way to support new packet aliasing options.
+
+ - Support for natd.cf configuration file has been added.
+
+ - SIGHUP no longer causes problems when running without
+ interface name option.
+
+ - When using -interface command line option, routing socket
+ is optionally listened for interface address changes. This
+ mode is activated by -dynamic option.
+
+ - Directory tree reorganized, alias package is now a library.
+
+ - Manual page written by Brian Somers <brian@awfulhak.org> added.
+ - README file updated.
+
+* Version 1.5
+
+ - Support for sending ICMP 'need fragmentation' messages
+ when packet size exceeds mtu size of outgoing network interface.
+
+ - ipfw rule example in manual page fixed.
+
+* Version 1.6
+
+ - Upgrade to new packet aliasing engine (2.1)
+ - redirect_port and redirect_address configuration
+ parameters added.
+ - It is no longer necessary to quote complex parameter values
+ in command line.
+ - Manual page fixed (same_port -> same_ports).
+
+* Version 1.7
+
+ - A bug in command-line parsing fixed (it appeared due
+ to changes made in 1.6).
+
+* Version 1.8
+
+ - Fixed problems with -dynamic option.
+ - Added /var/run/natd.pid
+
+* Version 1.9
+
+ - Changes to manual page by
+ Brian Somers <brian@awfulhak.org> integrated.
+ - Checksum for incoming packets is always recalculated
+ for FreeBSD 2.2 and never recalculated for newer
+ versions. This should fix the problem with wrong
+ checksum of fragmented packets.
+ - Buffer space problem found by Sergio Lenzi <lenzi@bsi.com.br>
+ fixed. Natd now waits with select(2) for buffer space
+ to become available if write fails.
+ - Packet aliasing library upgraded to 2.2.
diff --git a/usr.sbin/natd/README b/usr.sbin/natd/README
new file mode 100644
index 000000000000..6c158d5e4ca1
--- /dev/null
+++ b/usr.sbin/natd/README
@@ -0,0 +1,53 @@
+
+ A Network Address Translation Daemon for FreeBSD
+
+
+1. WHAT IS NATD ?
+
+ This is a simple daemon based on FreeBSD divert sockets
+ which performs network address translation (or masquerading)
+ for IP packets (see related RFCs 1631 and 1918).
+ It is based on packet aliasing package (see README.alias)
+ written by Charles Mott (cmott@srv.net).
+
+ This package works with any network interface (doesn't have
+ to be ppp). I run it on a computer having two ethernet cards,
+ one connected to internet and the other one to local network.
+
+2. GETTING IT RUNNING
+
+ 1) Get FreeBSD 2.2 - I think the divert sockets are
+ not available on earlier versions,
+
+ 2) Compile this software by executing "make".
+
+ 3) Install the software by executing "make install".
+
+ 4) See man natd for further instructions.
+
+3. FTP SITES FOR NATD
+
+ This package is available at ftp://ftp.suutari.iki.fi/pub/natd.
+
+4. AUTHORS
+
+ This program is the result of the efforts of many people
+ at different times:
+
+ Archie Cobbs <archie@whistle.com> Divert sockets
+ Charles Mott <cmott@srv.net> Packet aliasing engine
+ Eivind Eklund <eivind@dimaga.com> Packet aliasing engine
+ Ari Suutari <suutari@iki.fi> Natd
+ Brian Somers <brian@awfulhak.org> Manual page, glue and
+ bunch of good ideas.
+
+ The original package written by Charles Mott
+ is available at http://www.srv.net/~cmott.
+ It is described in README.alias.
+
+ Happy Networking - comments and fixes are welcome!
+
+ Ari S. (suutari@iki.fi)
+
+
+
diff --git a/usr.sbin/natd/icmp.c b/usr.sbin/natd/icmp.c
new file mode 100644
index 000000000000..2018f66128c9
--- /dev/null
+++ b/usr.sbin/natd/icmp.c
@@ -0,0 +1,113 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <netdb.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <machine/in_cksum.h>
+
+#include <alias.h>
+
+#include "natd.h"
+
+int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu)
+{
+ char icmpBuf[IP_MAXPACKET];
+ struct ip* ip;
+ struct icmp* icmp;
+ int icmpLen;
+ int failBytes;
+ int failHdrLen;
+ struct sockaddr_in addr;
+ int wrote;
+ struct in_addr swap;
+/*
+ * Don't send error if packet is
+ * not the first fragment.
+ */
+ if (ntohs (failedDgram->ip_off) & ~(IP_MF | IP_DF))
+ return 0;
+/*
+ * Dont respond if failed datagram is ICMP.
+ */
+ if (failedDgram->ip_p == IPPROTO_ICMP)
+ return 0;
+/*
+ * Start building the message.
+ */
+ ip = (struct ip*) icmpBuf;
+ icmp = (struct icmp*) (icmpBuf + sizeof (struct ip));
+/*
+ * Complete ICMP part.
+ */
+ icmp->icmp_type = ICMP_UNREACH;
+ icmp->icmp_code = ICMP_UNREACH_NEEDFRAG;
+ icmp->icmp_cksum = 0;
+ icmp->icmp_void = 0;
+ icmp->icmp_nextmtu = htons (mtu);
+/*
+ * Copy header + 64 bits of original datagram.
+ */
+ failHdrLen = (failedDgram->ip_hl << 2);
+ failBytes = failedDgram->ip_len - failHdrLen;
+ if (failBytes > 8)
+ failBytes = 8;
+
+ failBytes += failHdrLen;
+ icmpLen = ICMP_MINLEN + failBytes;
+
+ memcpy (&icmp->icmp_ip, failedDgram, failBytes);
+/*
+ * Calculate checksum.
+ */
+ icmp->icmp_cksum = PacketAliasInternetChecksum ((u_short*) icmp,
+ icmpLen);
+/*
+ * Add IP header using old IP header as template.
+ */
+ memcpy (ip, failedDgram, sizeof (struct ip));
+
+ ip->ip_v = 4;
+ ip->ip_hl = 5;
+ ip->ip_len = htons (sizeof (struct ip) + icmpLen);
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_tos = 0;
+
+ swap = ip->ip_dst;
+ ip->ip_dst = ip->ip_src;
+ ip->ip_src = swap;
+
+ PacketAliasIn ((char*) ip, IP_MAXPACKET);
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr = ip->ip_dst;
+ addr.sin_port = 0;
+/*
+ * Put packet into processing queue.
+ */
+ wrote = sendto (sock,
+ icmp,
+ icmpLen,
+ 0,
+ (struct sockaddr*) &addr,
+ sizeof addr);
+
+ if (wrote != icmpLen)
+ Warn ("Cannot send ICMP message.");
+
+ return 1;
+}
+
+
diff --git a/usr.sbin/natd/natd.8 b/usr.sbin/natd/natd.8
new file mode 100644
index 000000000000..c38887c7c55c
--- /dev/null
+++ b/usr.sbin/natd/natd.8
@@ -0,0 +1,381 @@
+.\" manual page [] for natd 1.4
+.Dd 15 April 1997
+.Os FreeBSD
+.Dt NATD 8
+.Sh NAME
+.Nm natd
+.Nd
+Network Address Translation Daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl ldsmvu
+.Op Fl permanent_link
+.Op Fl dynamic
+.Op Fl i Ar inport
+.Op Fl o Ar outport
+.Op Fl p Ar port
+.Op Fl a Ar address
+.Op Fl i Ar interface
+.Op Fl f Ar configfile
+
+.Nm
+.Op Fl log
+.Op Fl deny_incoming
+.Op Fl use_sockets
+.Op Fl same_ports
+.Op Fl verbose
+.Op Fl unregistered_only
+.Op Fl permanent_link
+.Op Fl dynamic
+.Op Fl inport Ar inport
+.Op Fl outport Ar outport
+.Op Fl port Ar port
+.Op Fl alias_address Ar address
+.Op Fl interface Ar interface
+.Op Fl config Ar configfile
+
+.Sh DESCRIPTION
+This program provides a Network Address Translation facility for use
+with
+.Xr divert 4
+sockets under FreeBSD. Most of the command line options are available
+in a single character short form or in a long form. Use of the long
+form is encouraged as it makes things clearer to the casual observer.
+
+.Pp
+.Nm Natd
+normally runs in the background as a daemon. It is passed raw IP packets
+as they travel into and out of the machine, and will possibly change these
+before re-injecting them back into the IP packet stream.
+
+.Pp
+.Nm Natd
+changes all packets destined for another host so that their source
+IP number is that of the current machine. For each packet changed
+in this manner, an internal table entry is created to record this
+fact. The source port number is also changed to indicate the
+table entry applying to the packet. Packets that are received with
+a target IP of the current host are checked against this internal
+table. If an entry is found, it is used to determine the correct
+target IP number and port to place in the packet.
+
+.Pp
+The following command line options are available.
+.Bl -tag -width Fl
+
+.It Fl log | l
+Log various aliasing statistics and information to the file
+.Pa /var/log/alias.log .
+This file is truncated each time natd is started.
+
+.It Fl deny_incoming | d
+Reject packets destined for the current IP number that have no entry
+in the internal translation table.
+
+.It Fl use_sockets | s
+Allocate a
+.Xr socket 2
+in order to establish an FTP data or IRC DCC send connection. This
+option uses more system resources, but guarantees successful connections
+when port numbers conflict.
+
+.It Fl same_ports | m
+Try to keep the same port number when altering outgoing packets.
+With this option, protocols such as RPC will have a better chance
+of working. If it is not possible to maintain the port number, it
+will be silently changed as per normal.
+
+.It Fl verbose | v
+Don't call
+.Xr fork 2
+or
+.Xr daemon 3
+on startup. Instead, stay attached to the controling terminal and
+display all packet alterations to the standard output. This option
+should only be used for debugging purposes.
+
+.It Fl unregistered_only | u
+Only alter outgoing packets with an unregistered source address.
+According to rfc 1918, unregistered source addresses are 10.0.0.0/8,
+172.16.0.0/12 and 192.168.0.0/16.
+
+.It Fl redirect_port Ar linkspec
+Redirect incoming connections arriving to given port to another host and port.
+Linkspec is of the form
+
+ proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]]
+
+where proto is either tcp or udp, targetIP is the desired target IP
+number, targetPORT is the desired target PORT number, aliasPORT
+is the requested PORT number and aliasIP is the aliasing address.
+RemoteIP and remotePORT can be used to specify the connection
+more accurately if necessary.
+For example, the argument
+
+.Ar tcp inside1:telnet 6666
+
+means that tcp packets destined for port 6666 on this machine will
+be sent to the telnet port on the inside1 machine.
+
+.It Fl redirect_address Ar localIP publicIP
+Redirect traffic for public IP address to a machine on the local
+network. This function is known as "static NAT". Normally static NAT
+is useful if your ISP has allocated a small block of IP addresses to you,
+but it can even be used in the case of single address:
+
+ redirect_address 10.0.0.8 0.0.0.0
+
+The above command would redirect all incoming traffic
+to machine 10.0.0.8.
+
+If several address aliases specify the same public address
+as follows
+
+ redirect_address 192.168.0.2 public_addr
+ redirect_address 192.168.0.3 public_addr
+ redirect_address 192.168.0.4 public_addr
+
+the incoming traffic will be directed to the last
+translated local address (192.168.0.4), but outgoing
+traffice to the first two addresses will still be aliased
+to specified public address.
+
+.It Fl permanent_link Ar linkspec
+Create a permanent entry in the internal alias table. Linkspec is
+of the form
+
+ proto targetIP:targetPORT sourceIP:sourcePORT aliasPORT
+
+where proto is either tcp or udp, targetIP is the desired target IP
+number, targetPORT is the desired target PORT number, sourceIP and
+sourcePORT match the incoming packet, and aliasPORT is the requested
+PORT number. Values of zero are considered as wildcards. For example,
+the argument
+
+.Ar tcp inside1:telnet outside1:0 6666
+
+means that tcp packets destined for port 6666 on this machine from the
+outside1 machine (any port) will be sent to the telnet port on the
+inside1 machine.
+
+New installations are encouraged to use redirect_port instead.
+
+.It Fl dynamic
+If the
+.Fl n
+or
+.Fl interface
+option is used,
+.Nm natd
+will monitor the routing socket for alterations to the
+.Ar interface
+passed. If the interfaces IP number is changed,
+.Nm natd
+will dynamically alter its concept of the alias address.
+
+.It Fl i | inport Ar inport
+Read from and write to
+.Ar inport ,
+treating all packets as packets coming into the machine.
+
+.It Fl o | outport Ar outport
+Read from and write to
+.Ar outport ,
+treating all packets as packets going out of the machine.
+
+.It Fl p | port Ar port
+Read from and write to
+.Ar port ,
+distinguishing packets as incoming our outgoing using the rules specified in
+.Xr divert 4 .
+If
+.Ar port
+is not numeric, it is searched for in the
+.Pa /etc/services
+database using the
+.Xr getservbyname 3
+function. If this flag is not specified, the divert port named natd will
+be used as a default. An example entry in the
+.Pa /etc/services
+database would be:
+
+ natd 6668/divert # Network Address Translation socket
+
+Refer to
+.Xr services 5
+for further details.
+
+.It Fl a | alias_address Ar address
+Use
+.Ar address
+as the alias address. If this option is not specified, the
+.Fl n
+or
+.Fl interface
+option must be used.
+
+.It Fl n | interface Ar interface
+Use
+.Ar interface
+to determine the alias address. If there is a possibility that the
+IP number associated with
+.Ar interface
+may change, the
+.Fl dynamic
+flag should also be used. If this option is not specified, the
+.Fl a
+or
+.Fl alias_address
+flag must be used.
+
+.It Fl f | config Ar configfile
+Read configuration from
+.Ar configfile .
+.Ar Configfile
+contains a list of options, one per line in the same form as the
+long form of the above command line flags. For example, the line
+
+ alias_address 158.152.17.1
+
+would specify an alias address of 158.152.17.1. Options that don't
+take an argument are specified with an option of
+.Ar yes
+or
+.Ar no
+in the configuration file. For example, the line
+
+ log yes
+
+is synonomous with
+.Fl log .
+Empty lines and lines beginning with '#' are ignored.
+
+.El
+
+.Sh RUNNING NATD
+The following steps are necessary before attempting to run
+.Nm natd :
+
+.Bl -enum
+.It
+Get FreeBSD version 2.2 or higher. Versions before this do not support
+.Xr divert 4
+sockets.
+
+.It
+Build a custom kernel with the following options:
+
+ options IPFIREWALL
+ options IPDIVERT
+
+Refer to the handbook for detailed instructions on building a custom
+kernel.
+
+.It
+Ensure that your machine is acting as a gateway. This can be done by
+specifying the line
+
+ gateway_enable=YES
+
+in
+.Pa /etc/rc.conf ,
+or using the command
+
+ sysctl -w net.inet.ip.forwarding=1
+
+.It
+If you wish to use the
+.Fl n
+or
+.Fl interface
+flags, make sure that your interface is already configured. If, for
+example, you wish to specify tun0 as your
+.Ar interface ,
+and you're using
+.Xr ppp 8
+on that interface, you must make sure that you start
+.Nm ppp
+prior to starting
+.Nm natd .
+
+.It
+Create an entry in
+.Pa /etc/services :
+
+ natd 6668/divert # Network Address Translation socket
+
+This gives a default for the
+.Fl p
+or
+.Fl port
+flag.
+
+.El
+.Pp
+Running
+.Nm natd
+is fairly straight forward. The line
+
+ natd -interface ed0
+
+should suffice in most cases (substituting the correct interface name). Once
+.Nm natd
+is running, you must ensure that traffic is diverted to natd:
+
+.Bl -enum
+.It
+You will need to adjust the
+.Pa /etc/rc.firewall
+script to taste. If you're not interested in having a firewall, the
+following lines will do:
+
+ /sbin/ipfw -f flush
+ /sbin/ipfw add divert natd all from any to any via ed0
+ /sbin/ipfw add pass all from any to any
+
+The second line depends on your interface (change ed0 as appropriate)
+and assumes that you've updated
+.Pa /etc/services
+with the natd entry as above. If you specify real firewall rules, it's
+best to specify line 2 at the start of the script so that
+.Nm natd
+sees all packets before they are dropped by the firewall. The firewall
+rules will be run again on each packet after translation by
+.Nm natd ,
+minus any divert rules.
+
+.It
+Enable your firewall by setting
+
+ firewall=YES
+
+in
+.Pa /etc/rc.conf .
+This tells the system startup scripts to run the
+.Pa /etc/rc.firewall
+script. If you don't wish to reboot now, just run this by hand from the
+console. NEVER run this from a virtual session unless you put it into
+the background. If you do, you'll lock yourself out after the flush
+takes place, and execution of
+.Pa /etc/rc.firewall
+will stop at this point - blocking all accesses permanently. Running
+the script in the background should be enough to prevent this disaster.
+
+.El
+
+.Sh SEE ALSO
+.Xr socket 2 ,
+.Xr getservbyname 2 ,
+.Xr divert 4 ,
+.Xr services 5 ,
+.Xr ipfw 8
+
+.Sh AUTHORS
+This program is the result of the efforts of many people at different
+times:
+
+ Divert sockets: Archie Cobbs <archie@whistle.com>
+ Packet aliasing: Charles Mott <cmott@srv.net>
+ IRC support & misc additions: Eivind Eklund <eivind@dimaga.com>
+ Natd: Ari Suutari <suutari@iki.fi>
+ Glue: Brian Somers <brian@awfulhak.org>
diff --git a/usr.sbin/natd/natd.c b/usr.sbin/natd/natd.c
new file mode 100644
index 000000000000..13cf6ab0540c
--- /dev/null
+++ b/usr.sbin/natd/natd.c
@@ -0,0 +1,1434 @@
+/*
+ * natd - Network Address Translation Daemon for FreeBSD.
+ *
+ * This software ois provided free of charge, with no
+ * warranty of any kind, either expressed or implied.
+ * Use at your own risk.
+ *
+ * You may copy, modify and distribute this software (natd.c) freely.
+ *
+ * Ari Suutari <suutari@iki.fi>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <netdb.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <machine/in_cksum.h>
+#include <netinet/tcp.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <arpa/inet.h>
+
+#include <syslog.h>
+#include <alias.h>
+
+#include "natd.h"
+
+/*
+ * Default values for input and output
+ * divert socket ports.
+ */
+
+#define DEFAULT_SERVICE "natd"
+
+/*
+ * Function prototypes.
+ */
+
+static void DoAliasing (int fd);
+static void DaemonMode ();
+static void HandleRoutingInfo (int fd);
+static void Usage ();
+static void PrintPacket (struct ip*);
+static void SetAliasAddressFromIfName (char* ifName);
+static void InitiateShutdown ();
+static void Shutdown ();
+static void RefreshAddr ();
+static void ParseOption (char* option, char* parms, int cmdLine);
+static void ReadConfigFile (char* fileName);
+static void SetupPermanentLink (char* parms);
+static void SetupPortRedirect (char* parms);
+static void SetupAddressRedirect (char* parms);
+static void StrToAddr (char* str, struct in_addr* addr);
+static int StrToPort (char* str, char* proto);
+static int StrToProto (char* str);
+static int StrToAddrAndPort (char* str, struct in_addr* addr, char* proto);
+static void ParseArgs (int argc, char** argv);
+static void FlushPacketBuffer (int fd);
+
+/*
+ * Globals.
+ */
+
+static int verbose;
+static int background;
+static int running;
+static int assignAliasAddr;
+static char* ifName;
+static int ifIndex;
+static int inPort;
+static int outPort;
+static int inOutPort;
+static struct in_addr aliasAddr;
+static int dynamicMode;
+static int ifMTU;
+static int aliasOverhead;
+static int icmpSock;
+static char packetBuf[IP_MAXPACKET];
+static int packetLen;
+static struct sockaddr_in packetAddr;
+static int packetSock;
+
+int main (int argc, char** argv)
+{
+ int divertIn;
+ int divertOut;
+ int divertInOut;
+ int routeSock;
+ struct sockaddr_in addr;
+ fd_set readMask;
+ fd_set writeMask;
+ int fdMax;
+/*
+ * Initialize packet aliasing software.
+ * Done already here to be able to alter option bits
+ * during command line and configuration file processing.
+ */
+ PacketAliasInit ();
+/*
+ * Parse options.
+ */
+ inPort = 0;
+ outPort = 0;
+ verbose = 0;
+ inOutPort = 0;
+ ifName = NULL;
+ ifMTU = -1;
+ background = 0;
+ running = 1;
+ assignAliasAddr = 0;
+ aliasAddr.s_addr = INADDR_NONE;
+ aliasOverhead = 12;
+ dynamicMode = 0;
+/*
+ * Mark packet buffer empty.
+ */
+ packetSock = -1;
+
+ ParseArgs (argc, argv);
+/*
+ * Check that valid aliasing address has been given.
+ */
+ if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL) {
+
+ fprintf (stderr, "Aliasing address not given.\n");
+ exit (1);
+ }
+
+ if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL) {
+
+ fprintf (stderr, "Both alias address and interface name "
+ "are not allowed.\n");
+ exit (1);
+ }
+/*
+ * Check that valid port number is known.
+ */
+ if (inPort != 0 || outPort != 0)
+ if (inPort == 0 || outPort == 0) {
+
+ fprintf (stderr, "Both input and output ports"
+ " are required.\n");
+ exit (1);
+ }
+
+ if (inPort == 0 && outPort == 0 && inOutPort == 0)
+ ParseOption ("port", DEFAULT_SERVICE, 0);
+
+/*
+ * Create divert sockets. Use only one socket if -p was specified
+ * on command line. Otherwise, create separate sockets for
+ * outgoing and incoming connnections.
+ */
+ if (inOutPort) {
+
+ divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ if (divertInOut == -1)
+ Quit ("Unable to create divert socket.");
+
+ divertIn = -1;
+ divertOut = -1;
+/*
+ * Bind socket.
+ */
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = inOutPort;
+
+ if (bind (divertInOut,
+ (struct sockaddr*) &addr,
+ sizeof addr) == -1)
+ Quit ("Unable to bind divert socket.");
+ }
+ else {
+
+ divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ if (divertIn == -1)
+ Quit ("Unable to create incoming divert socket.");
+
+ divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ if (divertOut == -1)
+ Quit ("Unable to create outgoing divert socket.");
+
+ divertInOut = -1;
+
+/*
+ * Bind divert sockets.
+ */
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = inPort;
+
+ if (bind (divertIn,
+ (struct sockaddr*) &addr,
+ sizeof addr) == -1)
+ Quit ("Unable to bind incoming divert socket.");
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = outPort;
+
+ if (bind (divertOut,
+ (struct sockaddr*) &addr,
+ sizeof addr) == -1)
+ Quit ("Unable to bind outgoing divert socket.");
+ }
+/*
+ * Create routing socket if interface name specified.
+ */
+ if (ifName && dynamicMode) {
+
+ routeSock = socket (PF_ROUTE, SOCK_RAW, 0);
+ if (routeSock == -1)
+ Quit ("Unable to create routing info socket.");
+ }
+ else
+ routeSock = -1;
+/*
+ * Create socket for sending ICMP messages.
+ */
+ icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (icmpSock == -1)
+ Quit ("Unable to create ICMP socket.");
+/*
+ * Become a daemon unless verbose mode was requested.
+ */
+ if (!verbose)
+ DaemonMode ();
+/*
+ * Catch signals to manage shutdown and
+ * refresh of interface address.
+ */
+ signal (SIGTERM, InitiateShutdown);
+ signal (SIGHUP, RefreshAddr);
+/*
+ * Set alias address if it has been given.
+ */
+ if (aliasAddr.s_addr != INADDR_NONE)
+ PacketAliasSetAddress (aliasAddr);
+
+/*
+ * We need largest descriptor number for select.
+ */
+
+ fdMax = -1;
+
+ if (divertIn > fdMax)
+ fdMax = divertIn;
+
+ if (divertOut > fdMax)
+ fdMax = divertOut;
+
+ if (divertInOut > fdMax)
+ fdMax = divertInOut;
+
+ if (routeSock > fdMax)
+ fdMax = routeSock;
+
+ while (running) {
+
+ if (divertInOut != -1 && !ifName && packetSock == -1) {
+/*
+ * When using only one socket, just call
+ * DoAliasing repeatedly to process packets.
+ */
+ DoAliasing (divertInOut);
+ continue;
+ }
+/*
+ * Build read mask from socket descriptors to select.
+ */
+ FD_ZERO (&readMask);
+ FD_ZERO (&writeMask);
+
+/*
+ * If there is unsent packet in buffer, use select
+ * to check when socket comes writable again.
+ */
+ if (packetSock != -1) {
+
+ FD_SET (packetSock, &writeMask);
+ }
+ else {
+/*
+ * No unsent packet exists - safe to check if
+ * new ones are available.
+ */
+ if (divertIn != -1)
+ FD_SET (divertIn, &readMask);
+
+ if (divertOut != -1)
+ FD_SET (divertOut, &readMask);
+
+ if (divertInOut != -1)
+ FD_SET (divertInOut, &readMask);
+ }
+/*
+ * Routing info is processed always.
+ */
+ if (routeSock != -1)
+ FD_SET (routeSock, &readMask);
+
+ if (select (fdMax + 1,
+ &readMask,
+ &writeMask,
+ NULL,
+ NULL) == -1) {
+
+ if (errno == EINTR)
+ continue;
+
+ Quit ("Select failed.");
+ }
+
+ if (packetSock != -1)
+ if (FD_ISSET (packetSock, &writeMask))
+ FlushPacketBuffer (packetSock);
+
+ if (divertIn != -1)
+ if (FD_ISSET (divertIn, &readMask))
+ DoAliasing (divertIn);
+
+ if (divertOut != -1)
+ if (FD_ISSET (divertOut, &readMask))
+ DoAliasing (divertOut);
+
+ if (divertInOut != -1)
+ if (FD_ISSET (divertInOut, &readMask))
+ DoAliasing (divertInOut);
+
+ if (routeSock != -1)
+ if (FD_ISSET (routeSock, &readMask))
+ HandleRoutingInfo (routeSock);
+ }
+
+ if (background)
+ unlink (PIDFILE);
+
+ return 0;
+}
+
+static void DaemonMode ()
+{
+ FILE* pidFile;
+
+ daemon (0, 0);
+ background = 1;
+
+ pidFile = fopen (PIDFILE, "w");
+ if (pidFile) {
+
+ fprintf (pidFile, "%d\n", getpid ());
+ fclose (pidFile);
+ }
+}
+
+static void ParseArgs (int argc, char** argv)
+{
+ int arg;
+ char* parm;
+ char* opt;
+ char parmBuf[256];
+
+ for (arg = 1; arg < argc; arg++) {
+
+ opt = argv[arg];
+ if (*opt != '-') {
+
+ fprintf (stderr, "Invalid option %s.\n", opt);
+ Usage ();
+ }
+
+ parm = NULL;
+ parmBuf[0] = '\0';
+
+ while (arg < argc - 1) {
+
+ if (argv[arg + 1][0] == '-')
+ break;
+
+ if (parm)
+ strcat (parmBuf, " ");
+
+ ++arg;
+ parm = parmBuf;
+ strcat (parmBuf, argv[arg]);
+ }
+
+ ParseOption (opt + 1, parm, 1);
+ }
+}
+
+static void DoAliasing (int fd)
+{
+ int bytes;
+ int origBytes;
+ int addrSize;
+ struct ip* ip;
+
+ if (assignAliasAddr) {
+
+ SetAliasAddressFromIfName (ifName);
+ assignAliasAddr = 0;
+ }
+/*
+ * Get packet from socket.
+ */
+ addrSize = sizeof packetAddr;
+ origBytes = recvfrom (fd,
+ packetBuf,
+ sizeof packetBuf,
+ 0,
+ (struct sockaddr*) &packetAddr,
+ &addrSize);
+
+ if (origBytes == -1) {
+
+ if (errno != EINTR)
+ Warn ("Read from divert socket failed.");
+
+ return;
+ }
+/*
+ * This is a IP packet.
+ */
+ ip = (struct ip*) packetBuf;
+
+ if (verbose) {
+
+/*
+ * Print packet direction and protocol type.
+ */
+
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY)
+ printf ("Out ");
+ else
+ printf ("In ");
+
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ printf ("[TCP] ");
+ break;
+
+ case IPPROTO_UDP:
+ printf ("[UDP] ");
+ break;
+
+ case IPPROTO_ICMP:
+ printf ("[ICMP] ");
+ break;
+
+ default:
+ printf ("[?] ");
+ break;
+ }
+/*
+ * Print addresses.
+ */
+ PrintPacket (ip);
+ }
+
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY) {
+/*
+ * Outgoing packets. Do aliasing.
+ */
+ PacketAliasOut (packetBuf, IP_MAXPACKET);
+ }
+ else {
+/*
+ * Do aliasing.
+ */
+ PacketAliasIn (packetBuf, IP_MAXPACKET);
+ }
+/*
+ * Length might have changed during aliasing.
+ */
+ bytes = ntohs (ip->ip_len);
+/*
+ * Update alias overhead size for outgoing packets.
+ */
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY &&
+ bytes - origBytes > aliasOverhead)
+ aliasOverhead = bytes - origBytes;
+
+ if (verbose) {
+
+/*
+ * Print addresses after aliasing.
+ */
+ printf (" aliased to\n");
+ printf (" ");
+ PrintPacket (ip);
+ printf ("\n");
+ }
+
+ packetLen = bytes;
+ packetSock = fd;
+ FlushPacketBuffer (fd);
+}
+
+static void FlushPacketBuffer (int fd)
+{
+ int wrote;
+ char msgBuf[80];
+/*
+ * Put packet back for processing.
+ */
+ wrote = sendto (fd,
+ packetBuf,
+ packetLen,
+ 0,
+ (struct sockaddr*) &packetAddr,
+ sizeof packetAddr);
+
+ if (wrote != packetLen) {
+/*
+ * If buffer space is not available,
+ * just return. Main loop will take care of
+ * retrying send when space becomes available.
+ */
+ if (errno == ENOBUFS)
+ return;
+
+ if (errno == EMSGSIZE) {
+
+ if (packetAddr.sin_addr.s_addr == INADDR_ANY &&
+ ifMTU != -1)
+ SendNeedFragIcmp (icmpSock,
+ (struct ip*) packetBuf,
+ ifMTU - aliasOverhead);
+ }
+ else {
+
+ sprintf (msgBuf, "Failed to write packet back.");
+ Warn (msgBuf);
+ }
+ }
+
+ packetSock = -1;
+}
+
+static void HandleRoutingInfo (int fd)
+{
+ int bytes;
+ struct if_msghdr ifMsg;
+/*
+ * Get packet from socket.
+ */
+ bytes = read (fd, &ifMsg, sizeof ifMsg);
+ if (bytes == -1) {
+
+ Warn ("Read from routing socket failed.");
+ return;
+ }
+
+ if (ifMsg.ifm_version != RTM_VERSION) {
+
+ Warn ("Unexpected packet read from routing socket.");
+ return;
+ }
+
+ if (verbose)
+ printf ("Routing message %X received.\n", ifMsg.ifm_type);
+
+ if (ifMsg.ifm_type != RTM_NEWADDR)
+ return;
+
+ if (verbose && ifMsg.ifm_index == ifIndex)
+ printf ("Interface address has changed.\n");
+
+ if (ifMsg.ifm_index == ifIndex)
+ assignAliasAddr = 1;
+}
+
+static void PrintPacket (struct ip* ip)
+{
+ struct tcphdr* tcphdr;
+
+ if (ip->ip_p == IPPROTO_TCP)
+ tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2));
+ else
+ tcphdr = NULL;
+
+ printf ("%s", inet_ntoa (ip->ip_src));
+ if (tcphdr)
+ printf (":%d", ntohs (tcphdr->th_sport));
+
+ printf (" -> ");
+ printf ("%s", inet_ntoa (ip->ip_dst));
+ if (tcphdr)
+ printf (":%d", ntohs (tcphdr->th_dport));
+}
+
+static void SetAliasAddressFromIfName (char* ifName)
+{
+ struct ifconf cf;
+ struct ifreq buf[32];
+ char msg[80];
+ struct ifreq* ifPtr;
+ int extra;
+ int helperSock;
+ int bytes;
+ struct sockaddr_in* addr;
+ int found;
+ struct ifreq req;
+ char last[10];
+/*
+ * Create a dummy socket to access interface information.
+ */
+ helperSock = socket (AF_INET, SOCK_DGRAM, 0);
+ if (helperSock == -1) {
+
+ Quit ("Failed to create helper socket.");
+ exit (1);
+ }
+
+ cf.ifc_len = sizeof (buf);
+ cf.ifc_req = buf;
+/*
+ * Get interface data.
+ */
+ if (ioctl (helperSock, SIOCGIFCONF, &cf) == -1) {
+
+ Quit ("Ioctl SIOCGIFCONF failed.");
+ exit (1);
+ }
+
+ ifIndex = 0;
+ ifPtr = buf;
+ bytes = cf.ifc_len;
+ found = 0;
+ last[0] = '\0';
+/*
+ * Loop through interfaces until one with
+ * given name is found. This is done to
+ * find correct interface index for routing
+ * message processing.
+ */
+ while (bytes) {
+
+ if (ifPtr->ifr_addr.sa_family == AF_INET &&
+ !strcmp (ifPtr->ifr_name, ifName)) {
+
+ found = 1;
+ break;
+ }
+
+ if (strcmp (last, ifPtr->ifr_name)) {
+
+ strcpy (last, ifPtr->ifr_name);
+ ++ifIndex;
+ }
+
+ extra = ifPtr->ifr_addr.sa_len - sizeof (struct sockaddr);
+
+ ifPtr++;
+ ifPtr = (struct ifreq*) ((char*) ifPtr + extra);
+ bytes -= sizeof (struct ifreq) + extra;
+ }
+
+ if (!found) {
+
+ close (helperSock);
+ sprintf (msg, "Unknown interface name %s.\n", ifName);
+ Quit (msg);
+ }
+/*
+ * Get MTU size.
+ */
+ strcpy (req.ifr_name, ifName);
+
+ if (ioctl (helperSock, SIOCGIFMTU, &req) == -1)
+ Quit ("Cannot get interface mtu size.");
+
+ ifMTU = req.ifr_mtu;
+/*
+ * Get interface address.
+ */
+ if (ioctl (helperSock, SIOCGIFADDR, &req) == -1)
+ Quit ("Cannot get interface address.");
+
+ addr = (struct sockaddr_in*) &req.ifr_addr;
+ SetPacketAliasAddress (addr->sin_addr);
+ syslog (LOG_INFO, "Aliasing to %s, mtu %d bytes",
+ inet_ntoa (addr->sin_addr),
+ ifMTU);
+
+ close (helperSock);
+}
+
+void Quit (char* msg)
+{
+ Warn (msg);
+ exit (1);
+}
+
+void Warn (char* msg)
+{
+ if (background)
+ syslog (LOG_ALERT, "%s (%m)", msg);
+ else
+ perror (msg);
+}
+
+static void RefreshAddr ()
+{
+ signal (SIGHUP, RefreshAddr);
+ if (ifName)
+ assignAliasAddr = 1;
+}
+
+static void InitiateShutdown ()
+{
+/*
+ * Start timer to allow kernel gracefully
+ * shutdown existing connections when system
+ * is shut down.
+ */
+ signal (SIGALRM, Shutdown);
+ alarm (10);
+}
+
+static void Shutdown ()
+{
+ running = 0;
+}
+
+/*
+ * Different options recognized by this program.
+ */
+
+enum Option {
+
+ PacketAliasOption,
+ Verbose,
+ InPort,
+ OutPort,
+ Port,
+ AliasAddress,
+ InterfaceName,
+ PermanentLink,
+ RedirectPort,
+ RedirectAddress,
+ ConfigFile,
+ DynamicMode
+};
+
+enum Param {
+
+ YesNo,
+ Numeric,
+ String,
+ None,
+ Address,
+ Service
+};
+
+/*
+ * Option information structure (used by ParseOption).
+ */
+
+struct OptionInfo {
+
+ enum Option type;
+ int packetAliasOpt;
+ enum Param parm;
+ char* parmDescription;
+ char* description;
+ char* name;
+ char* shortName;
+};
+
+/*
+ * Table of known options.
+ */
+
+static struct OptionInfo optionTable[] = {
+
+ { PacketAliasOption,
+ PKT_ALIAS_UNREGISTERED_ONLY,
+ YesNo,
+ "[yes|no]",
+ "alias only unregistered addresses",
+ "unregistered_only",
+ "u" },
+
+ { PacketAliasOption,
+ PKT_ALIAS_LOG,
+ YesNo,
+ "[yes|no]",
+ "enable logging",
+ "log",
+ "l" },
+
+ { PacketAliasOption,
+ PKT_ALIAS_DENY_INCOMING,
+ YesNo,
+ "[yes|no]",
+ "allow incoming connections",
+ "deny_incoming",
+ "d" },
+
+ { PacketAliasOption,
+ PKT_ALIAS_USE_SOCKETS,
+ YesNo,
+ "[yes|no]",
+ "use sockets to inhibit port conflict",
+ "use_sockets",
+ "s" },
+
+ { PacketAliasOption,
+ PKT_ALIAS_SAME_PORTS,
+ YesNo,
+ "[yes|no]",
+ "try to keep original port numbers for connections",
+ "same_ports",
+ "m" },
+
+ { Verbose,
+ 0,
+ YesNo,
+ "[yes|no]",
+ "verbose mode, dump packet information",
+ "verbose",
+ "v" },
+
+ { DynamicMode,
+ 0,
+ YesNo,
+ "[yes|no]",
+ "dynamic mode, automatically detect interface address changes",
+ "dynamic",
+ NULL },
+
+ { InPort,
+ 0,
+ Service,
+ "number|service_name",
+ "set port for incoming packets",
+ "in_port",
+ "i" },
+
+ { OutPort,
+ 0,
+ Service,
+ "number|service_name",
+ "set port for outgoing packets",
+ "out_port",
+ "o" },
+
+ { Port,
+ 0,
+ Service,
+ "number|service_name",
+ "set port (defaults to natd/divert)",
+ "port",
+ "p" },
+
+ { AliasAddress,
+ 0,
+ Address,
+ "x.x.x.x",
+ "address to use for aliasing",
+ "alias_address",
+ "a" },
+
+ { InterfaceName,
+ 0,
+ String,
+ "network_if_name",
+ "take aliasing address from interface",
+ "interface",
+ "n" },
+
+ { PermanentLink,
+ 0,
+ String,
+ "tcp|udp src:port dst:port alias",
+ "define permanent link for incoming connection",
+ "permanent_link",
+ NULL },
+
+ { RedirectPort,
+ 0,
+ String,
+ "tcp|udp local_addr:local_port [public_addr:]public_port"
+ " [remote_addr[:remote_port]]",
+ "redirect a port for incoming traffic",
+ "redirect_port",
+ NULL },
+
+ { RedirectAddress,
+ 0,
+ String,
+ "local_addr public_addr",
+ "define mapping between local and public addresses",
+ "redirect_address",
+ NULL },
+
+ { ConfigFile,
+ 0,
+ String,
+ "file_name",
+ "read options from configuration file",
+ "config",
+ "f" }
+};
+
+static void ParseOption (char* option, char* parms, int cmdLine)
+{
+ int i;
+ struct OptionInfo* info;
+ int yesNoValue;
+ int aliasValue;
+ int numValue;
+ char* strValue;
+ struct in_addr addrValue;
+ int max;
+ char* end;
+/*
+ * Find option from table.
+ */
+ max = sizeof (optionTable) / sizeof (struct OptionInfo);
+ for (i = 0, info = optionTable; i < max; i++, info++) {
+
+ if (!strcmp (info->name, option))
+ break;
+
+ if (info->shortName)
+ if (!strcmp (info->shortName, option))
+ break;
+ }
+
+ if (i >= max) {
+
+ fprintf (stderr, "Unknown option %s.\n", option);
+ Usage ();
+ }
+
+ yesNoValue = 0;
+ numValue = 0;
+ strValue = NULL;
+/*
+ * Check parameters.
+ */
+ switch (info->parm) {
+ case YesNo:
+ if (!parms)
+ parms = "yes";
+
+ if (!strcmp (parms, "yes"))
+ yesNoValue = 1;
+ else
+ if (!strcmp (parms, "no"))
+ yesNoValue = 0;
+ else {
+
+ fprintf (stderr, "%s needs yes/no parameter.\n",
+ option);
+ exit (1);
+ }
+ break;
+
+ case Service:
+ if (!parms) {
+
+ fprintf (stderr, "%s needs service name or "
+ "port number parameter.\n",
+ option);
+ exit (1);
+ }
+
+ numValue = StrToPort (parms, "divert");
+ break;
+
+ case Numeric:
+ if (parms)
+ numValue = strtol (parms, &end, 10);
+ else
+ end = parms;
+
+ if (end == parms) {
+
+ fprintf (stderr, "%s needs numeric parameter.\n",
+ option);
+ exit (1);
+ }
+ break;
+
+ case String:
+ strValue = parms;
+ if (!strValue) {
+
+ fprintf (stderr, "%s needs parameter.\n",
+ option);
+ exit (1);
+ }
+ break;
+
+ case None:
+ if (parms) {
+
+ fprintf (stderr, "%s does not take parameters.\n",
+ option);
+ exit (1);
+ }
+ break;
+
+ case Address:
+ if (!parms) {
+
+ fprintf (stderr, "%s needs address/host parameter.\n",
+ option);
+ exit (1);
+ }
+
+ StrToAddr (parms, &addrValue);
+ break;
+ }
+
+ switch (info->type) {
+ case PacketAliasOption:
+
+ aliasValue = yesNoValue ? info->packetAliasOpt : 0;
+ PacketAliasSetMode (aliasValue, info->packetAliasOpt);
+ break;
+
+ case Verbose:
+ verbose = yesNoValue;
+ break;
+
+ case DynamicMode:
+ dynamicMode = yesNoValue;
+ break;
+
+ case InPort:
+ inPort = numValue;
+ break;
+
+ case OutPort:
+ outPort = numValue;
+ break;
+
+ case Port:
+ inOutPort = numValue;
+ break;
+
+ case AliasAddress:
+ memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr));
+ break;
+
+ case PermanentLink:
+ SetupPermanentLink (strValue);
+ break;
+
+ case RedirectPort:
+ SetupPortRedirect (strValue);
+ break;
+
+ case RedirectAddress:
+ SetupAddressRedirect (strValue);
+ break;
+
+ case InterfaceName:
+ if (ifName)
+ free (ifName);
+
+ ifName = strdup (strValue);
+ assignAliasAddr = 1;
+ break;
+
+ case ConfigFile:
+ ReadConfigFile (strValue);
+ break;
+ }
+}
+
+void ReadConfigFile (char* fileName)
+{
+ FILE* file;
+ char buf[128];
+ char* ptr;
+ char* option;
+
+ file = fopen (fileName, "r");
+ if (!file) {
+
+ sprintf (buf, "Cannot open config file %s.\n", fileName);
+ Quit (buf);
+ }
+
+ while (fgets (buf, sizeof (buf), file)) {
+
+ ptr = strchr (buf, '\n');
+ if (!ptr) {
+
+ fprintf (stderr, "config line too link: %s\n", buf);
+ exit (1);
+ }
+
+ *ptr = '\0';
+ if (buf[0] == '#')
+ continue;
+
+ ptr = buf;
+/*
+ * Skip white space at beginning of line.
+ */
+ while (*ptr && isspace (*ptr))
+ ++ptr;
+
+ if (*ptr == '\0')
+ continue;
+/*
+ * Extract option name.
+ */
+ option = ptr;
+ while (*ptr && !isspace (*ptr))
+ ++ptr;
+
+ if (*ptr != '\0') {
+
+ *ptr = '\0';
+ ++ptr;
+ }
+/*
+ * Skip white space between name and parms.
+ */
+ while (*ptr && isspace (*ptr))
+ ++ptr;
+
+ ParseOption (option, *ptr ? ptr : NULL, 0);
+ }
+
+ fclose (file);
+}
+
+static void Usage ()
+{
+ int i;
+ int max;
+ struct OptionInfo* info;
+
+ fprintf (stderr, "Recognized options:\n\n");
+
+ max = sizeof (optionTable) / sizeof (struct OptionInfo);
+ for (i = 0, info = optionTable; i < max; i++, info++) {
+
+ fprintf (stderr, "-%-20s %s\n", info->name,
+ info->parmDescription);
+
+ if (info->shortName)
+ fprintf (stderr, "-%-20s %s\n", info->shortName,
+ info->parmDescription);
+
+ fprintf (stderr, " %s\n\n", info->description);
+ }
+
+ exit (1);
+}
+
+void SetupPermanentLink (char* parms)
+{
+ char buf[128];
+ char* ptr;
+ struct in_addr srcAddr;
+ struct in_addr dstAddr;
+ int srcPort;
+ int dstPort;
+ int aliasPort;
+ int proto;
+ char* protoName;
+
+ strcpy (buf, parms);
+/*
+ * Extract protocol.
+ */
+ protoName = strtok (buf, " \t");
+ if (!protoName) {
+
+ fprintf (stderr, "permanent_link: missing protocol.\n");
+ exit (1);
+ }
+
+ proto = StrToProto (protoName);
+/*
+ * Extract source address.
+ */
+ ptr = strtok (NULL, " \t");
+ if (!ptr) {
+
+ fprintf (stderr, "permanent_link: missing src address.\n");
+ exit (1);
+ }
+
+ srcPort = StrToAddrAndPort (ptr, &srcAddr, protoName);
+/*
+ * Extract destination address.
+ */
+ ptr = strtok (NULL, " \t");
+ if (!ptr) {
+
+ fprintf (stderr, "permanent_link: missing dst address.\n");
+ exit (1);
+ }
+
+ dstPort = StrToAddrAndPort (ptr, &dstAddr, protoName);
+/*
+ * Export alias port.
+ */
+ ptr = strtok (NULL, " \t");
+ if (!ptr) {
+
+ fprintf (stderr, "permanent_link: missing alias port.\n");
+ exit (1);
+ }
+
+ aliasPort = StrToPort (ptr, protoName);
+
+ PacketAliasPermanentLink (srcAddr,
+ srcPort,
+ dstAddr,
+ dstPort,
+ aliasPort,
+ proto);
+}
+
+void SetupPortRedirect (char* parms)
+{
+ char buf[128];
+ char* ptr;
+ struct in_addr localAddr;
+ struct in_addr publicAddr;
+ struct in_addr remoteAddr;
+ int localPort;
+ int publicPort;
+ int remotePort;
+ int proto;
+ char* protoName;
+ char* separator;
+
+ strcpy (buf, parms);
+/*
+ * Extract protocol.
+ */
+ protoName = strtok (buf, " \t");
+ if (!protoName) {
+
+ fprintf (stderr, "redirect_port: missing protocol.\n");
+ exit (1);
+ }
+
+ proto = StrToProto (protoName);
+/*
+ * Extract local address.
+ */
+ ptr = strtok (NULL, " \t");
+ if (!ptr) {
+
+ fprintf (stderr, "redirect_port: missing local address.\n");
+ exit (1);
+ }
+
+ localPort = StrToAddrAndPort (ptr, &localAddr, protoName);
+/*
+ * Extract public port and optinally address.
+ */
+ ptr = strtok (NULL, " \t");
+ if (!ptr) {
+
+ fprintf (stderr, "redirect_port: missing public port.\n");
+ exit (1);
+ }
+
+ separator = strchr (ptr, ':');
+ if (separator)
+ publicPort = StrToAddrAndPort (ptr, &publicAddr, protoName);
+ else {
+
+ publicAddr.s_addr = INADDR_ANY;
+ publicPort = StrToPort (ptr, protoName);
+ }
+
+/*
+ * Extract remote address and optionally port.
+ */
+ ptr = strtok (NULL, " \t");
+ if (ptr) {
+
+
+ separator = strchr (ptr, ':');
+ if (separator)
+ remotePort = StrToAddrAndPort (ptr,
+ &remoteAddr,
+ protoName);
+ else {
+
+ remotePort = 0;
+ StrToAddr (ptr, &remoteAddr);
+ }
+ }
+ else {
+
+ remotePort = 0;
+ remoteAddr.s_addr = INADDR_ANY;
+ }
+
+ PacketAliasRedirectPort (localAddr,
+ localPort,
+ remoteAddr,
+ remotePort,
+ publicAddr,
+ publicPort,
+ proto);
+}
+
+void SetupAddressRedirect (char* parms)
+{
+ char buf[128];
+ char* ptr;
+ struct in_addr localAddr;
+ struct in_addr publicAddr;
+
+ strcpy (buf, parms);
+/*
+ * Extract local address.
+ */
+ ptr = strtok (buf, " \t");
+ if (!ptr) {
+
+ fprintf (stderr, "redirect_address: missing local address.\n");
+ exit (1);
+ }
+
+ StrToAddr (ptr, &localAddr);
+/*
+ * Extract public address.
+ */
+ ptr = strtok (NULL, " \t");
+ if (!ptr) {
+
+ fprintf (stderr, "redirect_address: missing public address.\n");
+ exit (1);
+ }
+
+ StrToAddr (ptr, &publicAddr);
+ PacketAliasRedirectAddr (localAddr, publicAddr);
+}
+
+void StrToAddr (char* str, struct in_addr* addr)
+{
+ struct hostent* hp;
+
+ if (inet_aton (str, addr))
+ return;
+
+ hp = gethostbyname (str);
+ if (!hp) {
+
+ fprintf (stderr, "Unknown host %s.\n", str);
+ exit (1);
+ }
+
+ memcpy (addr, hp->h_addr, sizeof (struct in_addr));
+}
+
+int StrToPort (char* str, char* proto)
+{
+ int port;
+ struct servent* sp;
+ char* end;
+
+ port = strtol (str, &end, 10);
+ if (end != str)
+ return htons (port);
+
+ sp = getservbyname (str, proto);
+ if (!sp) {
+
+ fprintf (stderr, "Unknown service %s/%s.\n",
+ str, proto);
+ exit (1);
+ }
+
+ return sp->s_port;
+}
+
+int StrToProto (char* str)
+{
+ if (!strcmp (str, "tcp"))
+ return IPPROTO_TCP;
+
+ if (!strcmp (str, "udp"))
+ return IPPROTO_UDP;
+
+ fprintf (stderr, "Unknown protocol %s. Expected tcp or udp.\n", str);
+ exit (1);
+}
+
+int StrToAddrAndPort (char* str, struct in_addr* addr, char* proto)
+{
+ char* ptr;
+
+ ptr = strchr (str, ':');
+ if (!ptr) {
+
+ fprintf (stderr, "%s is missing port number.\n", str);
+ exit (1);
+ }
+
+ *ptr = '\0';
+ ++ptr;
+
+ StrToAddr (str, addr);
+ return StrToPort (ptr, proto);
+}
+
diff --git a/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4 b/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4
new file mode 100644
index 000000000000..ebce4991def7
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4
@@ -0,0 +1,16 @@
+#
+# SCO UnixWare 2.1.2 ostype file
+#
+# Contributed by Christopher Durham <chrisdu@SCO.COM> of SCO.
+#
+divert(0)
+VERSIONID(`@(#)sco-uw-2.1.m4 8.1 (Berkeley) 7/6/97')
+
+define(`ALIAS_FILE', /usr/lib/mail/aliases)dnl
+ifdef(`HELP_FILE',,`define(`HELP_FILE', /usr/ucblib/sendmail.hf)')dnl
+ifdef(`STATUS_FILE',,`define(`STATUS_FILE', /usr/ucblib/sendmail.st)')dnl
+define(`LOCAL_MAILER_PATH', `/usr/bin/rmail')dnl
+define(`LOCAL_MAILER_FLAGS', `fhCEn9')dnl
+define(`LOCAL_SHELL_FLAGS', `ehuP')dnl
+define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gmedium $h!rmail ($u)')dnl
+define(`LOCAL_MAILER_ARGS',`rmail $u')dnl
diff --git a/usr.sbin/sendmail/contrib/passwd-to-alias.pl b/usr.sbin/sendmail/contrib/passwd-to-alias.pl
new file mode 100644
index 000000000000..05a51b93496f
--- /dev/null
+++ b/usr.sbin/sendmail/contrib/passwd-to-alias.pl
@@ -0,0 +1,30 @@
+#!/bin/perl
+
+#
+# Convert GECOS information in password files to alias syntax.
+#
+# Contributed by Kari E. Hurtta <Kari.Hurtta@ozone.fmi.fi>
+#
+
+print "# Generated from passwd by $0\n";
+
+while (@a = getpwent) {
+ ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = @a;
+
+ ($fullname = $gcos) =~ s/,.*$//;
+
+ if (!-d $dir || !-x $shell) {
+ print "$name: root\n";
+ }
+
+ $fullname =~ s/\.*[ _]+\.*/./g;
+ $fullname =~ tr [åäöÅÄÖé] [aaoAAOe]; # <hakan@af.lu.se> 1997-06-15
+ if ($fullname =~ /^[a-zA-Z][a-zA-Z-]+(\.[a-zA-Z][a-zA-Z-]+)+$/) {
+# if ($fullname =~ /^[a-zA-Z]+(\.[a-zA-Z]+)+$/) { # Kari E. Hurtta
+ print "$fullname: $name\n";
+ } else {
+ print "# $fullname: $name\n";
+ }
+};
+
+endpwent;
diff --git a/usr.sbin/sendmail/src/safefile.c b/usr.sbin/sendmail/src/safefile.c
new file mode 100644
index 000000000000..842a09f8ca86
--- /dev/null
+++ b/usr.sbin/sendmail/src/safefile.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright (c) 1983, 1995-1997 Eric P. Allman
+ * Copyright (c) 1988, 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.
+ * 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 lint
+static char sccsid[] = "@(#)safefile.c 8.18 (Berkeley) 8/1/97";
+#endif /* not lint */
+
+# include "sendmail.h"
+ /*
+** SAFEFILE -- return true if a file exists and is safe for a user.
+**
+** Parameters:
+** fn -- filename to check.
+** uid -- user id to compare against.
+** gid -- group id to compare against.
+** uname -- user name to compare against (used for group
+** sets).
+** flags -- modifiers:
+** SFF_MUSTOWN -- "uid" must own this file.
+** SFF_NOSLINK -- file cannot be a symbolic link.
+** mode -- mode bits that must match.
+** st -- if set, points to a stat structure that will
+** get the stat info for the file.
+**
+** Returns:
+** 0 if fn exists, is owned by uid, and matches mode.
+** An errno otherwise. The actual errno is cleared.
+**
+** Side Effects:
+** none.
+*/
+
+#include <grp.h>
+
+#ifndef S_IXOTH
+# define S_IXOTH (S_IEXEC >> 6)
+#endif
+
+#ifndef S_IXGRP
+# define S_IXGRP (S_IEXEC >> 3)
+#endif
+
+#ifndef S_IXUSR
+# define S_IXUSR (S_IEXEC)
+#endif
+
+int
+safefile(fn, uid, gid, uname, flags, mode, st)
+ char *fn;
+ UID_T uid;
+ GID_T gid;
+ char *uname;
+ int flags;
+ int mode;
+ struct stat *st;
+{
+ register char *p;
+ register struct group *gr = NULL;
+ int file_errno = 0;
+ bool checkpath;
+ struct stat stbuf;
+ struct stat fstbuf;
+ char fbuf[MAXPATHLEN + 1];
+
+ if (tTd(44, 4))
+ printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n",
+ fn, (int) uid, (int) gid, flags, mode);
+ errno = 0;
+ if (st == NULL)
+ st = &fstbuf;
+ if (strlen(fn) > sizeof fbuf - 1)
+ {
+ if (tTd(44, 4))
+ printf("\tpathname too long\n");
+ return ENAMETOOLONG;
+ }
+ strcpy(fbuf, fn);
+ fn = fbuf;
+
+ /* ignore SFF_SAFEDIRPATH if we are debugging */
+ if (RealUid != 0 && RunAsUid == RealUid)
+ flags &= ~SFF_SAFEDIRPATH;
+
+ /* first check to see if the file exists at all */
+#ifdef HASLSTAT
+ if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st)
+ : stat(fn, st)) < 0)
+#else
+ if (stat(fn, st) < 0)
+#endif
+ {
+ file_errno = errno;
+ }
+ else if (bitset(SFF_SETUIDOK, flags) &&
+ !bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) &&
+ S_ISREG(st->st_mode))
+ {
+ /*
+ ** If final file is setuid, run as the owner of that
+ ** file. Gotta be careful not to reveal anything too
+ ** soon here!
+ */
+
+#ifdef SUID_ROOT_FILES_OK
+ if (bitset(S_ISUID, st->st_mode))
+#else
+ if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0)
+#endif
+ {
+ uid = st->st_uid;
+ uname = NULL;
+ }
+#ifdef SUID_ROOT_FILES_OK
+ if (bitset(S_ISGID, st->st_mode))
+#else
+ if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0)
+#endif
+ gid = st->st_gid;
+ }
+
+ checkpath = !bitset(SFF_NOPATHCHECK, flags) ||
+ (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags));
+ if (bitset(SFF_NOWLINK, flags) && !bitset(SFF_SAFEDIRPATH, flags))
+ {
+ int ret;
+
+ /* check the directory */
+ p = strrchr(fn, '/');
+ if (p == NULL)
+ {
+ ret = safedirpath(".", uid, gid, uname, flags|SFF_SAFEDIRPATH);
+ }
+ else
+ {
+ *p = '\0';
+ ret = safedirpath(fn, uid, gid, uname, flags|SFF_SAFEDIRPATH);
+ *p = '/';
+ }
+ if (ret == 0)
+ {
+ /* directory is safe */
+ checkpath = FALSE;
+ }
+ else
+ {
+ /* directory is writable: disallow links */
+ flags |= SFF_NOLINK;
+ }
+ }
+
+ if (checkpath)
+ {
+ int ret;
+
+ p = strrchr(fn, '/');
+ if (p == NULL)
+ {
+ ret = safedirpath(".", uid, gid, uname, flags);
+ }
+ else
+ {
+ *p = '\0';
+ ret = safedirpath(fn, uid, gid, uname, flags);
+ *p = '/';
+ }
+ if (ret != 0)
+ return ret;
+ }
+
+ /*
+ ** If the target file doesn't exist, check the directory to
+ ** ensure that it is writable by this user.
+ */
+
+ if (file_errno != 0)
+ {
+ int ret = file_errno;
+ char *dir = fn;
+
+ if (tTd(44, 4))
+ printf("\t%s\n", errstring(ret));
+
+ errno = 0;
+ if (!bitset(SFF_CREAT, flags) || file_errno != ENOENT)
+ return ret;
+
+ /* check to see if legal to create the file */
+ p = strrchr(dir, '/');
+ if (p == NULL)
+ dir = ".";
+ else if (p == dir)
+ dir = "/";
+ else
+ *p = '\0';
+ if (stat(dir, &stbuf) >= 0)
+ {
+ int md = S_IWRITE|S_IEXEC;
+ if (stbuf.st_uid != uid)
+ md >>= 6;
+ if ((stbuf.st_mode & md) != md)
+ errno = EACCES;
+ }
+ ret = errno;
+ if (tTd(44, 4))
+ printf("\t[final dir %s uid %d mode %lo] %s\n",
+ dir, (int) stbuf.st_uid, (u_long) stbuf.st_mode,
+ errstring(ret));
+ if (p != NULL)
+ *p = '/';
+ st->st_mode = ST_MODE_NOFILE;
+ return ret;
+ }
+
+#ifdef S_ISLNK
+ if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[slink mode %o]\tE_SM_NOSLINK\n",
+ st->st_mode);
+ return E_SM_NOSLINK;
+ }
+#endif
+ if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[non-reg mode %o]\tE_SM_REGONLY\n",
+ st->st_mode);
+ return E_SM_REGONLY;
+ }
+ if (bitset(SFF_NOWFILES, flags) &&
+ bitset(S_IWOTH | (UnsafeGroupWrites ? S_IWGRP : 0), st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[write bits %o]\tE_SM_%cWFILE\n",
+ st->st_mode,
+ bitset(S_IWOTH, st->st_mode) ? 'W' : 'G');
+ return bitset(S_IWOTH, st->st_mode) ? E_SM_WWFILE : E_SM_GWFILE;
+ }
+ if (bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) &&
+ bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[exec bits %o]\tE_SM_ISEXEC]\n",
+ st->st_mode);
+ return E_SM_ISEXEC;
+ }
+ if (bitset(SFF_NOHLINK, flags) && st->st_nlink != 1)
+ {
+ if (tTd(44, 4))
+ printf("\t[link count %d]\tE_SM_NOHLINK\n",
+ st->st_nlink);
+ return E_SM_NOHLINK;
+ }
+
+ if (uid == 0 && bitset(SFF_OPENASROOT, flags))
+ ;
+ else if (uid == 0 && !bitset(SFF_ROOTOK, flags))
+ mode >>= 6;
+ else if (st->st_uid != uid)
+ {
+ mode >>= 3;
+ if (st->st_gid == gid)
+ ;
+#ifndef NO_GROUP_SET
+ else if (uname != NULL && !DontInitGroups &&
+ ((gr != NULL && gr->gr_gid == st->st_gid) ||
+ (gr = getgrgid(st->st_gid)) != NULL))
+ {
+ register char **gp;
+
+ for (gp = gr->gr_mem; *gp != NULL; gp++)
+ if (strcmp(*gp, uname) == 0)
+ break;
+ if (*gp == NULL)
+ mode >>= 3;
+ }
+#endif
+ else
+ mode >>= 3;
+ }
+ if (tTd(44, 4))
+ printf("\t[uid %d, nlink %d, stat %lo, mode %lo] ",
+ (int) st->st_uid, (int) st->st_nlink,
+ (u_long) st->st_mode, (u_long) mode);
+ if ((st->st_uid == uid || st->st_uid == 0 ||
+ !bitset(SFF_MUSTOWN, flags)) &&
+ (st->st_mode & mode) == mode)
+ {
+ if (tTd(44, 4))
+ printf("\tOK\n");
+ return 0;
+ }
+ if (tTd(44, 4))
+ printf("\tEACCES\n");
+ return EACCES;
+}
+ /*
+** SAFEDIRPATH -- check to make sure a path to a directory is safe
+**
+** Safe means not writable and owned by the right folks.
+**
+** Parameters:
+** fn -- filename to check.
+** uid -- user id to compare against.
+** gid -- group id to compare against.
+** uname -- user name to compare against (used for group
+** sets).
+** flags -- modifiers:
+** SFF_ROOTOK -- ok to use root permissions to open.
+** SFF_SAFEDIRPATH -- writable directories are considered
+** to be fatal errors.
+**
+** Returns:
+** 0 -- if the directory path is "safe".
+** else -- an error number associated with the path.
+*/
+
+int
+safedirpath(fn, uid, gid, uname, flags)
+ char *fn;
+ UID_T uid;
+ GID_T gid;
+ char *uname;
+ int flags;
+{
+ char *p;
+ register struct group *gr = NULL;
+ int ret = 0;
+ struct stat stbuf;
+
+ /* special case root directory */
+ if (*fn == '\0')
+ fn = "/";
+
+ if (tTd(44, 4))
+ printf("safedirpath(%s, uid=%ld, gid=%ld, flags=%x):\n",
+ fn, (long) uid, (long) gid, flags);
+
+ p = fn;
+ do
+ {
+ if (*p == '\0')
+ *p = '/';
+ p = strchr(++p, '/');
+ if (p != NULL)
+ *p = '\0';
+ if (stat(fn, &stbuf) < 0)
+ {
+ ret = errno;
+ break;
+ }
+ if ((uid == 0 || bitset(SFF_SAFEDIRPATH, flags)) &&
+ bitset(S_IWGRP|S_IWOTH, stbuf.st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[dir %s] mode %o\n",
+ fn, stbuf.st_mode);
+ if (bitset(SFF_SAFEDIRPATH, flags))
+ {
+ if (bitset(S_IWOTH, stbuf.st_mode))
+ ret = E_SM_WWDIR;
+ else
+ ret = E_SM_GWDIR;
+ break;
+ }
+ if (Verbose > 1)
+ message("051 WARNING: writable directory %s", fn);
+ }
+ if (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags))
+ {
+ if (bitset(S_IXOTH, stbuf.st_mode))
+ continue;
+ ret = EACCES;
+ break;
+ }
+ if (stbuf.st_uid == uid &&
+ bitset(S_IXUSR, stbuf.st_mode))
+ continue;
+ if (stbuf.st_gid == gid &&
+ bitset(S_IXGRP, stbuf.st_mode))
+ continue;
+#ifndef NO_GROUP_SET
+ if (uname != NULL && !DontInitGroups &&
+ ((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
+ (gr = getgrgid(stbuf.st_gid)) != NULL))
+ {
+ register char **gp;
+
+ for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++)
+ if (strcmp(*gp, uname) == 0)
+ break;
+ if (gp != NULL && *gp != NULL &&
+ bitset(S_IXGRP, stbuf.st_mode))
+ continue;
+ }
+#endif
+ if (!bitset(S_IXOTH, stbuf.st_mode))
+ {
+ ret = EACCES;
+ break;
+ }
+ } while (p != NULL);
+ if (ret != 0 && tTd(44, 4))
+ printf("\t[dir %s] %s\n", fn, errstring(ret));
+ if (p != NULL)
+ *p = '/';
+ return ret;
+}
+ /*
+** SAFEOPEN -- do a file open with extra checking
+**
+** Parameters:
+** fn -- the file name to open.
+** omode -- the open-style mode flags.
+** cmode -- the create-style mode flags.
+** sff -- safefile flags.
+**
+** Returns:
+** Same as open.
+*/
+
+#ifndef O_ACCMODE
+# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
+int
+safeopen(fn, omode, cmode, sff)
+ char *fn;
+ int omode;
+ int cmode;
+ int sff;
+{
+ int rval;
+ int fd;
+ int smode;
+ struct stat stb;
+
+ if (bitset(O_CREAT, omode))
+ sff |= SFF_CREAT;
+ omode &= ~O_CREAT;
+ smode = 0;
+ switch (omode & O_ACCMODE)
+ {
+ case O_RDONLY:
+ smode = S_IREAD;
+ break;
+
+ case O_WRONLY:
+ smode = S_IWRITE;
+ break;
+
+ case O_RDWR:
+ smode = S_IREAD|S_IWRITE;
+ break;
+
+ default:
+ smode = 0;
+ break;
+ }
+ if (bitset(SFF_OPENASROOT, sff))
+ rval = safefile(fn, RunAsUid, RunAsGid, RunAsUserName,
+ sff, smode, &stb);
+ else
+ rval = safefile(fn, RealUid, RealGid, RealUserName,
+ sff, smode, &stb);
+ if (rval != 0)
+ {
+ errno = rval;
+ return -1;
+ }
+ if (stb.st_mode == ST_MODE_NOFILE && bitset(SFF_CREAT, sff))
+ omode |= O_EXCL|O_CREAT;
+
+ fd = dfopen(fn, omode, cmode, sff);
+ if (fd < 0)
+ return fd;
+ if (filechanged(fn, fd, &stb, sff))
+ {
+ syserr("554 cannot open: file %s changed after open", fn);
+ close(fd);
+ errno = E_SM_FILECHANGE;
+ return -1;
+ }
+ return fd;
+}
+ /*
+** SAFEFOPEN -- do a file open with extra checking
+**
+** Parameters:
+** fn -- the file name to open.
+** omode -- the open-style mode flags.
+** cmode -- the create-style mode flags.
+** sff -- safefile flags.
+**
+** Returns:
+** Same as fopen.
+*/
+
+FILE *
+safefopen(fn, omode, cmode, sff)
+ char *fn;
+ int omode;
+ int cmode;
+ int sff;
+{
+ int fd;
+ FILE *fp;
+ char *fmode;
+
+ switch (omode & O_ACCMODE)
+ {
+ case O_RDONLY:
+ fmode = "r";
+ break;
+
+ case O_WRONLY:
+ if (bitset(O_APPEND, omode))
+ fmode = "a";
+ else
+ fmode = "w";
+ break;
+
+ case O_RDWR:
+ if (bitset(O_TRUNC, omode))
+ fmode = "w+";
+ else if (bitset(O_APPEND, omode))
+ fmode = "a+";
+ else
+ fmode = "r+";
+ break;
+
+ default:
+ syserr("safefopen: unknown omode %o", omode);
+ fmode = "x";
+ }
+ fd = safeopen(fn, omode, cmode, sff);
+ if (fd < 0)
+ {
+ if (tTd(44, 10))
+ printf("safefopen: safeopen failed: %s\n",
+ errstring(errno));
+ return NULL;
+ }
+ fp = fdopen(fd, fmode);
+ if (fp != NULL)
+ return fp;
+
+ if (tTd(44, 10))
+ {
+ printf("safefopen: fdopen(%s, %s) failed: omode=%x, sff=%x, err=%s\n",
+ fn, fmode, omode, sff, errstring(errno));
+#ifndef NOT_SENDMAIL
+ dumpfd(fd, TRUE, FALSE);
+#endif
+ }
+ (void) close(fd);
+ return NULL;
+}
+ /*
+** FILECHANGED -- check to see if file changed after being opened
+**
+** Parameters:
+** fn -- pathname of file to check.
+** fd -- file descriptor to check.
+** stb -- stat structure from before open.
+** sff -- safe file flags.
+**
+** Returns:
+** TRUE -- if a problem was detected.
+** FALSE -- if this file is still the same.
+*/
+
+bool
+filechanged(fn, fd, stb, sff)
+ char *fn;
+ int fd;
+ struct stat *stb;
+ int sff;
+{
+ struct stat sta;
+
+ if (stb->st_mode == ST_MODE_NOFILE)
+ {
+#if HASLSTAT && BOGUS_O_EXCL
+ /* only necessary if exclusive open follows symbolic links */
+ if (lstat(fn, stb) < 0 || stb->st_nlink != 1)
+ return TRUE;
+#else
+ return FALSE;
+#endif
+ }
+ if (fstat(fd, &sta) < 0)
+ return TRUE;
+
+ if (sta.st_nlink != stb->st_nlink ||
+ sta.st_dev != stb->st_dev ||
+ sta.st_ino != stb->st_ino ||
+#if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */
+ sta.st_gen != stb->st_gen ||
+#endif
+ sta.st_uid != stb->st_uid ||
+ sta.st_gid != stb->st_gid)
+ {
+ if (tTd(44, 8))
+ {
+ printf("File changed after opening:\n");
+ printf(" nlink = %ld/%ld\n",
+ (long) stb->st_nlink, (long) sta.st_nlink);
+ printf(" dev = %ld/%ld\n",
+ (long) stb->st_dev, (long) sta.st_dev);
+ printf(" ino = %ld/%ld\n",
+ (long) stb->st_ino, (long) sta.st_ino);
+#if HAS_ST_GEN
+ printf(" gen = %ld/%ld\n",
+ (long) stb->st_gen, (long) sta.st_gen);
+#endif
+ printf(" uid = %ld/%ld\n",
+ (long) stb->st_uid, (long) sta.st_uid);
+ printf(" gid = %ld/%ld\n",
+ (long) stb->st_gid, (long) sta.st_gid);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+ /*
+** DFOPEN -- determined file open
+**
+** This routine has the semantics of open, except that it will
+** keep trying a few times to make this happen. The idea is that
+** on very loaded systems, we may run out of resources (inodes,
+** whatever), so this tries to get around it.
+*/
+
+int
+dfopen(filename, omode, cmode, sff)
+ char *filename;
+ int omode;
+ int cmode;
+ int sff;
+{
+ register int tries;
+ int fd;
+ struct stat st;
+
+ for (tries = 0; tries < 10; tries++)
+ {
+ sleep((unsigned) (10 * tries));
+ errno = 0;
+ fd = open(filename, omode, cmode);
+ if (fd >= 0)
+ break;
+ switch (errno)
+ {
+ case ENFILE: /* system file table full */
+ case EINTR: /* interrupted syscall */
+#ifdef ETXTBSY
+ case ETXTBSY: /* Apollo: net file locked */
+#endif
+ continue;
+ }
+ break;
+ }
+ if (!bitset(SFF_NOLOCK, sff) &&
+ fd >= 0 &&
+ fstat(fd, &st) >= 0 &&
+ S_ISREG(st.st_mode))
+ {
+ int locktype;
+
+ /* lock the file to avoid accidental conflicts */
+ if ((omode & O_ACCMODE) != O_RDONLY)
+ locktype = LOCK_EX;
+ else
+ locktype = LOCK_SH;
+ (void) lockfile(fd, filename, NULL, locktype);
+ errno = 0;
+ }
+ return fd;
+}
diff --git a/usr.sbin/sendmail/test/t_exclopen.c b/usr.sbin/sendmail/test/t_exclopen.c
new file mode 100644
index 000000000000..54f7873f4b33
--- /dev/null
+++ b/usr.sbin/sendmail/test/t_exclopen.c
@@ -0,0 +1,91 @@
+/*
+** This program tests your system to see if you have the lovely
+** security-defeating semantics that an open with O_CREAT|O_EXCL
+** set will successfully open a file named by a symbolic link that
+** points to a non-existent file. Sadly, Posix is mute on what
+** should happen in this situation.
+**
+** Results to date:
+** AIX 3.2 OK
+** BSD family OK
+** BSD/OS 2.1 OK
+** FreeBSD 2.1 OK
+** DEC OSF/1 3.0 OK
+** HP-UX 9.04 FAIL
+** HP-UX 9.05 FAIL
+** HP-UX 9.07 OK
+** HP-UX 10.01 OK
+** HP-UX 10.10 OK
+** HP-UX 10.20 OK
+** Irix 5.3 OK
+** Irix 6.2 OK
+** Linux OK
+** NeXT 2.1 OK
+** Solaris 2.x OK
+** SunOS 4.x OK
+** Ultrix 4.3 OK
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+char Attacker[128];
+char Attackee[128];
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct stat st;
+
+ sprintf(Attacker, "/tmp/attacker.%d.%ld", getpid(), time(NULL));
+ sprintf(Attackee, "/tmp/attackee.%d.%ld", getpid(), time(NULL));
+
+ if (symlink(Attackee, Attacker) < 0)
+ {
+ printf("Could not create %s->%s symlink: %d\n",
+ Attacker, Attackee, errno);
+ bail(1);
+ }
+ (void) unlink(Attackee);
+ if (stat(Attackee, &st) >= 0)
+ {
+ printf("%s already exists -- remove and try again.\n",
+ Attackee);
+ bail(1);
+ }
+ if (open(Attacker, O_WRONLY|O_CREAT|O_EXCL, 0644) < 0)
+ {
+ int saveerr = errno;
+
+ if (stat(Attackee, &st) >= 0)
+ {
+ printf("Weird. Open failed but %s was created anyhow (errno = %d)\n",
+ Attackee, saveerr);
+ bail(1);
+ }
+ printf("Good show! Exclusive open works properly with symbolic links (errno = %d).\n",
+ saveerr);
+ bail(0);
+ }
+ if (stat(Attackee, &st) < 0)
+ {
+ printf("Weird. Open succeeded but %s was not created\n",
+ Attackee);
+ bail(2);
+ }
+ printf("Bad news: you can do an exclusive open through a symbolic link\n");
+ printf("\tBe sure you #define BOGUS_O_EXCL in conf.h\n");
+ bail(1);
+}
+
+bail(stat)
+ int stat;
+{
+ (void) unlink(Attacker);
+ (void) unlink(Attackee);
+ exit(stat);
+}
diff --git a/usr.sbin/wlconfig/wlconfig.8 b/usr.sbin/wlconfig/wlconfig.8
new file mode 100644
index 000000000000..a16db4e94103
--- /dev/null
+++ b/usr.sbin/wlconfig/wlconfig.8
@@ -0,0 +1,131 @@
+.Dd December 26 1996
+.Os
+.Dt WLCONFIG 8
+.Sh NAME
+.Nm wlconfig
+.Nd read/write wavelan config parameters
+.Sh SYNOPSIS
+.Nm wlconfig
+.Ar ifname
+.Op Ar param value ...
+.Sh DESCRIPTION
+The
+.Nm wlconfig
+command can be used to read and set parameters for the NCR/AT&T Wavelan
+radio LAN card. Various parameters stored in the nonvolatile Parameter
+Storage Area (PSA) on the card can be modified with this program, which
+obviates the need for the DOS-based
+.Nm instconf.exe
+program. It can also be used to interrogate the optional signal
+strength cache which may have been compiled into the driver.
+.Pp
+The
+.Ar ifname
+parameter specifies the wavelan interface name (eg.
+.Pa wl0
+). If no other arguments are supplied, the current contents of the PSA
+are interpreted and displayed.
+.Pp
+The
+.Ar param
+and
+.Ar value
+arguments can be used to change the value of several parameters.
+Any number of
+.Ar param value
+pairs may be supplied.
+.Bl -tag -width 15n -compat -offset indent
+.It Va param
+.Va value
+.It irq
+IRQ value (used at next reset), may be one of 3,4,5,6,10,11,12,15
+.It mac
+Local MAC value (ethernet address)
+.It macsel
+.Sq soft
+(as set by the
+.Sq mac
+parameter) or
+.Sq default
+(as set at the factory).
+.It nwid
+The NWID is a 2-byte parameter passed to the card's radio modem.
+NWIDs allow multiple logically discrete networks to operate
+independantly whilse occupying the same airspace.
+Packets with a different NWID are simply ignored by the modem.
+In the hardware, NWIDs are stored long-term in non-volative memory
+(called the PSA or programmable storage area), and are loaded by
+software into the radio modem when the driver is
+initialized. This sets the default NWID loaded at startup.
+.It curnwid
+This sets the current operating NWID (but does not save it to the
+PSA).
+.It cache
+The driver may maintain a per interface fixed size cache of signal strength,
+silence, and quality levels, which are indexed by sender MAC addresses.
+Input packets are stored in the cache, and when received, the values
+stored in the radio modem are interrogated and stored.
+There are also two sysctl values (iponly and multicast only) which
+can be used for filtering out some input packets. By default, the
+cache mechanism stores only non-unicast IP packets, but this can
+be changed with sysctl(8). Each non-filtered
+input packet causes a cache update, hence one can monitor
+the antennae signal strength to a remote system.
+There are three commands that can be given as values:
+.Sq raw ,
+which prints out the raw signal strength data as found in the radio
+modem hardware value,
+.Sq scale ,
+which scales the raw hardware values to 0..100%, and
+.Sq zero
+which clears out the cache in case you want to store new samples.
+.El
+.Pp
+Note that if the IRQ on the Wavelan card is incorrect, the interface
+will be configured, but will not function. The
+.Nm wlconfig
+program should then be used to reconfigure the card to a sensible
+value.
+.Sh EXAMPLES
+Set the NWID to 0x1234 :
+.Bd -literal -offset
+# wlconfig wl0 nwid 0x1234
+.Ed
+.Pp
+Show the current settings :
+.Bd -literal -offset
+# wlconfig wl0
+Board type : ISA
+Base address options : 0x300, 0x390, 0x3c0, 0x3e0
+Waitstates : 0
+Bus mode : ISA
+IRQ : 10
+Default MAC address : 08:00:0e:20:3d:4b
+Soft MAC address : 00:00:00:00:00:00
+Current MAC address : Default
+Adapter compatability : PC-AT 2.4GHz
+Threshold preset : 1
+Call code required : NO
+Subband : 2425MHz
+Quality threshold : 3
+Hardware version : 0 (Rel1/Rel2)
+Network ID enable : YES
+NWID : 0xdead
+Datalink security : NO
+Databus width : 16 (variable)
+Configuration state : unconfigured
+CRC-16 : 0x3c26
+CRC status : OK
+.Pp
+Print a scaled version of the signal strength cache :
+.Bd -literal -offset
+# wlconfig wl0 cache scale
+.Ed
+.Sh SEE ALSO
+.Xr wl 4,
+.Xr sysctl 8 .
+.Sh HISTORY
+This implementation of the
+.Nm wlconfig
+command is completely new, written for Hilink Internet by Michael Smith,
+and updated by Jim Binkley &c.
diff --git a/usr.sbin/wlconfig/wlconfig.c b/usr.sbin/wlconfig/wlconfig.c
new file mode 100644
index 000000000000..51153f9291f9
--- /dev/null
+++ b/usr.sbin/wlconfig/wlconfig.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 1996
+ * Michael Smith. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Michael Smith 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 Michael Smith 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.
+ *
+ * $Id: wlconfig.c,v 1.3 1997/08/01 03:50:23 msmith Exp $
+ *
+ */
+/*
+ * wlconfig.c
+ *
+ * utility to read out and change various WAVELAN parameters.
+ * Currently supports NWID and IRQ values.
+ *
+ * The NWID is used by 2 or more wavelan controllers to determine
+ * if packets should be received or not. It is a filter that
+ * is roughly analogous to the "channel" setting with a garage
+ * door controller. Two companies side by side with wavelan devices
+ * that could actually hear each other can use different NWIDs
+ * and ignore packets. In truth however, the air space is shared,
+ * and the NWID is a virtual filter.
+ *
+ * In the current set of wavelan drivers, ioctls changed only
+ * the runtime radio modem registers which act in a manner analogous
+ * to an ethernet transceiver. The ioctls do not change the
+ * stored nvram PSA (or parameter storage area). At boot, the PSA
+ * values are stored in the radio modem. Thus when the
+ * system reboots it will restore the wavelan NWID to the value
+ * stored in the PSA. The NCR/ATT dos utilities must be used to
+ * change the initial NWID values in the PSA. The wlconfig utility
+ * may be used to set a different NWID at runtime; this is only
+ * permitted while the interface is up and running.
+ *
+ * By contrast, the IRQ value can only be changed while the
+ * Wavelan card is down and unconfigured, and it will remain
+ * disabled after an IRQ change until reboot.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <machine/if_wl_wavelan.h>
+
+#include <net/if.h>
+#if __FreeBSD__ >= 3
+#include <net/if_var.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+extern struct ether_addr *ether_aton(char *a);
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+/* translate IRQ bit to number */
+/* array for maping irq numbers to values for the irq parameter register */
+static int irqvals[16] = {
+ 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80
+};
+
+/* cache */
+static int w_sigitems; /* count of valid items */
+static struct w_sigcache wsc[MAXCACHEITEMS];
+
+int
+wlirq(int irqval)
+{
+ int irq;
+
+ for(irq = 0; irq < 16; irq++)
+ if(irqvals[irq] == irqval)
+ return(irq);
+ return 0;
+}
+
+char *compat_type[] = {
+ "PC-AT 915MHz",
+ "PC-MC 915MHz",
+ "PC-AT 2.4GHz",
+ "PC-MC 2.4GHz",
+ "PCCARD or 1/2 size AT, 915MHz or 2.4GHz"
+};
+
+char *subband[] = {
+ "915MHz/see WaveModem",
+ "2425MHz",
+ "2460MHz",
+ "2484MHz",
+ "2430.5MHz"
+};
+
+
+/*
+** print_psa
+**
+** Given a pointer to a PSA structure, print it out
+*/
+void
+print_psa(u_char *psa, int currnwid)
+{
+ int nwid;
+
+ /*
+ ** Work out what sort of board we have
+ */
+ if (psa[0] == 0x14) {
+ printf("Board type : Microchannel\n");
+ } else {
+ if (psa[1] == 0) {
+ printf("Board type : PCCARD\n");
+ } else {
+ printf("Board type : ISA");
+ if ((psa[4] == 0) &&
+ (psa[5] == 0) &&
+ (psa[6] == 0))
+ printf(" (DEC OEM)");
+ printf("\n");
+ printf("Base address options : 0x300, 0x%02x0, 0x%02x0, 0x%02x0\n",
+ (int)psa[1], (int)psa[2], (int)psa[3]);
+ printf("Waitstates : %d\n",psa[7] & 0xf);
+ printf("Bus mode : %s\n",(psa[7] & 0x10) ? "EISA" : "ISA");
+ printf("IRQ : %d\n",wlirq(psa[8]));
+ }
+ }
+ printf("Default MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ psa[0x10],psa[0x11],psa[0x12],psa[0x13],psa[0x14],psa[0x15]);
+ printf("Soft MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n",
+ psa[0x16],psa[0x17],psa[0x18],psa[0x19],psa[0x1a],psa[0x1b]);
+ printf("Current MAC address : %s\n",(psa[0x1c] & 0x1) ? "Soft" : "Default");
+ printf("Adapter compatability : ");
+ if (psa[0x1d] < 5) {
+ printf("%s\n",compat_type[psa[0x1d]]);
+ } else {
+ printf("unknown\n");
+ }
+ printf("Threshold preset : %d\n",psa[0x1e]);
+ printf("Call code required : %s\n",(psa[0x1f] & 0x1) ? "YES" : "NO");
+ if (psa[0x1f] & 0x1)
+ printf("Call code : 0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ psa[0x30],psa[0x31],psa[0x32],psa[0x33],psa[0x34],psa[0x35],psa[0x36],psa[0x37]);
+ printf("Subband : %s\n",subband[psa[0x20] & 0xf]);
+ printf("Quality threshold : %d\n",psa[0x21]);
+ printf("Hardware version : %d (%s)\n",psa[0x22],psa[0x22] ? "Rel3" : "Rel1/Rel2");
+ printf("Network ID enable : %s\n",(psa[0x25] & 0x1) ? "YES" : "NO");
+ if (psa[0x25] & 0x1) {
+ nwid = (psa[0x23] << 8) + psa[0x24];
+ printf("NWID : 0x%04x\n",nwid);
+ if (nwid != currnwid) {
+ printf("Current NWID : 0x%04x\n",currnwid);
+ }
+ }
+ printf("Datalink security : %s\n",(psa[0x26] & 0x1) ? "YES" : "NO");
+ if (psa[0x26] & 0x1) {
+ printf("Encryption key : ");
+ if (psa[0x27] == 0) {
+ printf("DENIED\n");
+ } else {
+ printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ psa[0x27],psa[0x28],psa[0x29],psa[0x2a],psa[0x2b],psa[0x2c],psa[0x2d],psa[0x2e]);
+ }
+ }
+ printf("Databus width : %d (%s)\n",
+ (psa[0x2f] & 0x1) ? 16 : 8, (psa[0x2f] & 0x80) ? "fixed" : "variable");
+ printf("Configuration state : %sconfigured\n",(psa[0x38] & 0x1) ? "" : "un");
+ printf("CRC-16 : 0x%02x%02x\n",psa[0x3e],psa[0x3d]);
+ printf("CRC status : ");
+ switch(psa[0x3f]) {
+ case 0xaa:
+ printf("OK\n");
+ break;
+ case 0x55:
+ printf("BAD\n");
+ break;
+ default:
+ printf("Error\n");
+ break;
+ }
+}
+
+
+void
+syntax(char *pname)
+{
+ fprintf(stderr,"Usage: %s <ifname> [<param> <value> ...]\n",pname);
+ fprintf(stderr," <ifname> Wavelan interface name.\n");
+ fprintf(stderr," <param> Parameter name (see below)\n");
+ fprintf(stderr," <value> New value for parameter.\n");
+ fprintf(stderr," Parameter name: Value:\n");
+ fprintf(stderr," irq 3,4,5,6,10,11,12,15\n");
+ fprintf(stderr," mac soft ethernet address\n");
+ fprintf(stderr," macsel soft or default\n");
+ fprintf(stderr," nwid default NWID (0x0-0xffff)\n");
+ fprintf(stderr," currnwid current NWID (0x0-0xffff) or 'get'\n");
+ fprintf(stderr," cache signal strength cache\n");
+ fprintf(stderr," cache values = { raw, scale, zero }\n");
+ exit(1);
+}
+
+
+void
+get_cache(int sd, struct ifreq *ifr)
+{
+ /* get the cache count */
+ if (ioctl(sd, SIOCGWLCITEM, (caddr_t)ifr)) {
+ perror("SIOCGWLCITEM - get cache count");
+ exit(1);
+ }
+ w_sigitems = (int) ifr->ifr_data;
+
+ ifr->ifr_data = (caddr_t) &wsc;
+ /* get the cache */
+ if (ioctl(sd, SIOCGWLCACHE, (caddr_t)ifr)) {
+ perror("SIOCGWLCACHE - get cache count");
+ exit(1);
+ }
+}
+
+static int
+scale_value(int value, int max)
+{
+ double dmax = (double) max;
+ if (value > max)
+ return(100);
+ return((value/dmax) * 100);
+}
+
+static void
+dump_cache(int rawFlag)
+{
+ int i;
+ int signal, silence, quality;
+
+ if (rawFlag)
+ printf("signal range 0..63: silence 0..63: quality 0..15\n");
+ else
+ printf("signal range 0..100: silence 0..100: quality 0..100\n");
+
+ /* after you read it, loop through structure,i.e. wsc
+ * print each item:
+ */
+ for(i = 0; i < w_sigitems; i++) {
+ printf("[%d:%d]>\n", i+1, w_sigitems);
+ printf("\tip: %d.%d.%d.%d,",((wsc[i].ipsrc >> 0) & 0xff),
+ ((wsc[i].ipsrc >> 8) & 0xff),
+ ((wsc[i].ipsrc >> 16) & 0xff),
+ ((wsc[i].ipsrc >> 24) & 0xff));
+ printf(" mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ wsc[i].macsrc[0]&0xff,
+ wsc[i].macsrc[1]&0xff,
+ wsc[i].macsrc[2]&0xff,
+ wsc[i].macsrc[3]&0xff,
+ wsc[i].macsrc[4]&0xff,
+ wsc[i].macsrc[5]&0xff);
+ if (rawFlag) {
+ signal = wsc[i].signal;
+ silence = wsc[i].silence;
+ quality = wsc[i].quality;
+ }
+ else {
+ signal = scale_value(wsc[i].signal, 63);
+ silence = scale_value(wsc[i].silence, 63);
+ quality = scale_value(wsc[i].quality, 15);
+ }
+ printf("\tsignal: %d, silence: %d, quality: %d, ",
+ signal,
+ silence,
+ quality);
+ printf("snr: %d\n", signal - silence);
+ }
+}
+
+#define raw_cache() dump_cache(1)
+#define scale_cache() dump_cache(0)
+
+void
+main(int argc, char *argv[])
+{
+ int sd;
+ struct ifreq ifr;
+ u_char psabuf[0x40];
+ int val, argind, i;
+ char *cp, *param, *value;
+ struct ether_addr *ea;
+ int work = 0;
+ int currnwid;
+
+ if ((argc < 2) || (argc % 2))
+ syntax(argv[0]);
+
+ /* get a socket */
+ sd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sd < 0)
+ err(1,"socket");
+ strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name));
+ ifr.ifr_addr.sa_family = AF_INET;
+
+ /* get the PSA */
+ ifr.ifr_data = (caddr_t)psabuf;
+ if (ioctl(sd, SIOCGWLPSA, (caddr_t)&ifr))
+ err(1,"Get PSA");
+
+ /* get the current NWID */
+ if (ioctl(sd, SIOCGWLCNWID, (caddr_t)&ifr))
+ err(1,"Get NWID");
+ currnwid = (int)ifr.ifr_data;
+
+ /* just dump and exit? */
+ if (argc == 2) {
+ print_psa(psabuf, currnwid);
+ exit(0);
+ }
+
+ /* loop reading arg pairs */
+ for (argind = 2; argind < argc; argind += 2) {
+
+ param = argv[argind];
+ value = argv[argind+1];
+
+ /* What to do? */
+
+ if (!strcasecmp(param,"currnwid")) { /* set current NWID */
+ val = strtol(value,&cp,0);
+ if ((val < 0) || (val > 0xffff) || (cp == value))
+ errx(1,"Bad NWID '%s'",value);
+
+ ifr.ifr_data = (caddr_t)val;
+ if (ioctl(sd, SIOCSWLCNWID, (caddr_t)&ifr))
+ err(1,"Set NWID (interface not up?)");
+ continue ;
+ }
+
+ if (!strcasecmp(param,"irq")) {
+ val = strtol(value,&cp,0);
+ val = irqvals[val];
+ if ((val == 0) || (cp == value))
+ errx(1,"Bad IRQ '%s'",value);
+ psabuf[WLPSA_IRQNO] = (u_char)val;
+ work = 1;
+ continue;
+ }
+
+ if (!strcasecmp(param,"mac")) {
+ if ((ea = ether_aton(value)) == NULL)
+ errx(1,"Bad ethernet address '%s'",value);
+ for (i = 0; i < 6; i++)
+ psabuf[WLPSA_LOCALMAC + i] = ea->octet[i];
+ work = 1;
+ continue;
+ }
+
+ if (!strcasecmp(param,"macsel")) {
+ if (!strcasecmp(value,"local")) {
+ psabuf[WLPSA_MACSEL] |= 0x1;
+ work = 1;
+ continue;
+ }
+ if (!strcasecmp(value,"universal")) {
+ psabuf[WLPSA_MACSEL] &= ~0x1;
+ work = 1;
+ continue;
+ }
+ errx(1,"Bad macsel value '%s'",value);
+ }
+
+ if (!strcasecmp(param,"nwid")) {
+ val = strtol(value,&cp,0);
+ if ((val < 0) || (val > 0xffff) || (cp == value))
+ errx(1,"Bad NWID '%s'",value);
+ psabuf[WLPSA_NWID] = (val >> 8) & 0xff;
+ psabuf[WLPSA_NWID+1] = val & 0xff;
+ work = 1;
+ continue;
+ }
+ if (!strcasecmp(param,"cache")) {
+
+ /* raw cache dump
+ */
+ if (!strcasecmp(value,"raw")) {
+ get_cache(sd, &ifr);
+ raw_cache();
+ continue;
+ }
+ /* scaled cache dump
+ */
+ else if (!strcasecmp(value,"scale")) {
+ get_cache(sd, &ifr);
+ scale_cache();
+ continue;
+ }
+ /* zero out cache
+ */
+ else if (!strcasecmp(value,"zero")) {
+ if (ioctl(sd, SIOCDWLCACHE, (caddr_t)&ifr))
+ err(1,"Zero cache");
+ continue;
+ }
+ errx(1,"Unknown value '%s'", value);
+ }
+ errx(1,"Unknown parameter '%s'",param);
+ }
+ if (work) {
+ ifr.ifr_data = (caddr_t)psabuf;
+ if (ioctl(sd, SIOCSWLPSA, (caddr_t)&ifr))
+ err(1,"Set PSA");
+ }
+}