Compare commits

...
Author SHA1 Message Date
cvs2svn a3ab491d64 This commit was manufactured by cvs2svn to create tag
'RELENG_2_1_0_RELEASE'.
1996-01-01 11:01:15 +00:00
66 changed files with 10169 additions and 3471 deletions

No files matched your search

+156
View File
@@ -0,0 +1,156 @@
#!/usr/local/bin/perl
# Merge conflicted ChangeLogs
# tromey Mon Aug 15 1994
# Due to popular demand, I'm posting my ChangeLog auto-merge tool. Run
# this on your ChangeLog files when an update leaves them conflicted.
# The code is appended.
#
# Usage is:
#
# cl-merge [-i] file ...
#
# With -i, it works in place (backups put in a ~ file). Otherwise the
# merged ChangeLog is printed to stdout.
#
# Style comments are welcome. This is my third perl program ever.
#
# Please report any bugs to me. I wrote this yesterday, so there are no
# guarantees about its performance. I recommend checking its output
# carefully. If you do send a bug report, please includie the failing
# ChangeLog, so I can include it in my test suite.
#
# Tom
# ---
# [email protected] Member, League for Programming Freedom
# Sadism and farce are always inexplicably linked.
# -- Alexander Theroux
# If '-i' is given, do it in-place.
if ($ARGV[0] eq '-i') {
shift (@ARGV);
$^I = '~';
}
$lastkey = '';
$lastval = '';
$conf = 0;
%conflist = ();
$tjd = 0;
# Simple state machine. The states:
#
# 0 Not in conflict. Just copy input to output.
# 1 Beginning an entry. Next non-blank line is key.
# 2 In entry. Entry beginner transitions to state 1.
while (<>) {
if (/^<<<</ || /^====/) {
# Start of a conflict.
# Copy last key into array.
if ($lastkey ne '') {
$conflist{$lastkey} = $lastval;
$lastkey = '';
$lastval = '';
}
$conf = 1;
} elsif (/^>>>>/) {
# End of conflict. Output.
# Copy last key into array.
if ($lastkey ne '') {
$conflist{$lastkey} = $lastval;
$lastkey = '';
$lastval = '';
}
foreach (reverse sort clcmp keys %conflist) {
print STDERR "doing $_" if $tjd;
print $_;
print $conflist{$_};
}
$lastkey = '';
$lastval = '';
$conf = 0;
%conflist = ();
} elsif ($conf == 1) {
# Beginning an entry. Skip empty lines. Error if not a real
# beginner.
if (/^$/) {
# Empty line; just skip at this point.
} elsif (/^[MTWFS]/) {
# Looks like the name of a day; assume opener and move to
# "in entry" state.
$lastkey = $_;
$conf = 2;
print STDERR "found $_" if $tjd;
} else {
die ("conflict crosses entry boundaries: $_");
}
} elsif ($conf == 2) {
# In entry. Copy into variable until we see beginner line.
if (/^[MTWFS]/) {
# Entry beginner line.
# Copy last key into array.
if ($lastkey ne '') {
$conflist{$lastkey} = $lastval;
$lastkey = '';
$lastval = '';
}
$lastkey = $_;
print STDERR "found $_" if $tjd;
$lastval = '';
} else {
$lastval .= $_;
}
} else {
# Just copy.
print;
}
}
%months = ('Jan', 0,
'Feb', 1,
'Mar', 2,
'Apr', 3,
'May', 4,
'Jun', 5,
'Jul', 6,
'Aug', 7,
'Sep', 8,
'Oct', 9,
'Nov', 10,
'Dec', 11);
# Compare ChangeLog time strings like <=>.
#
# 0 1 2 3
# Thu Aug 11 13:22:42 1994 Tom Tromey ([email protected])
# 0123456789012345678901234567890
#
sub clcmp {
# First check year.
$r = substr ($a, 20, 4) <=> substr ($b, 20, 4);
# Now check month.
$r = $months{$a} <=> $months{$b} if !$r;
# Now check day.
$r = substr ($a, 8, 2) <=> substr ($b, 8, 2) if !$r;
# Now check time (3 parts).
$r = substr ($a, 11, 2) <=> substr ($b, 11, 2) if !$r;
$r = substr ($a, 14, 2) <=> substr ($b, 14, 2) if !$r;
$r = substr ($a, 17, 2) <=> substr ($b, 17, 2) if !$r;
$r;
}
+84
View File
@@ -0,0 +1,84 @@
#! /bin/sh
# $Id: cvscheck,v 1.2 1992/04/10 03:04:19 berliner Exp $
#
# cvscheck - identify files added, changed, or removed
# in CVS working directory
#
# Contributed by Lowell Skoog <[email protected]>
#
# This program should be run in a working directory that has been
# checked out using CVS. It identifies files that have been added,
# changed, or removed in the working directory, but not "cvs
# committed". It also determines whether the files have been "cvs
# added" or "cvs removed". For directories, it is only practical to
# determine whether they have been added.
name=cvscheck
changes=0
# If we can't run CVS commands in this directory
cvs status . > /dev/null 2>&1
if [ $? != 0 ] ; then
# Bail out
echo "$name: there is no version here; bailing out" 1>&2
exit 1
fi
# Identify files added to working directory
for file in .* * ; do
# Skip '.' and '..'
if [ $file = '.' -o $file = '..' ] ; then
continue
fi
# If a regular file
if [ -f $file ] ; then
if cvs status $file | grep -s '^From:[ ]*New file' ; then
echo "file added: $file - not CVS committed"
changes=`expr $changes + 1`
elif cvs status $file | grep -s '^From:[ ]*no entry for' ; then
echo "file added: $file - not CVS added, not CVS committed"
changes=`expr $changes + 1`
fi
# Else if a directory
elif [ -d $file -a $file != CVS.adm ] ; then
# Move into it
cd $file
# If CVS commands don't work inside
cvs status . > /dev/null 2>&1
if [ $? != 0 ] ; then
echo "directory added: $file - not CVS added"
changes=`expr $changes + 1`
fi
# Move back up
cd ..
fi
done
# Identify changed files
changedfiles=`cvs diff | egrep '^diff' | awk '{print $3}'`
for file in $changedfiles ; do
echo "file changed: $file - not CVS committed"
changes=`expr $changes + 1`
done
# Identify files removed from working directory
removedfiles=`cvs status | egrep '^File:[ ]*no file' | awk '{print $4}'`
# Determine whether each file has been cvs removed
for file in $removedfiles ; do
if cvs status $file | grep -s '^From:[ ]*-' ; then
echo "file removed: $file - not CVS committed"
else
echo "file removed: $file - not CVS removed, not CVS committed"
fi
changes=`expr $changes + 1`
done
exit $changes
+116
View File
@@ -0,0 +1,116 @@
#! /bin/sh
# $Id: descend,v 1.1 1992/04/03 05:22:52 berliner Exp $
#
# descend - walk down a directory tree and execute a command at each node
fullname=$0
name=descend
usage="Usage: $name [-afqrv] command [directory ...]\n
\040\040-a\040\040All: descend into directories starting with '.'\n
\040\040-f\040\040Force: ignore errors during descent\n
\040\040-q\040\040Quiet: don't print directory names\n
\040\040-r\040\040Restricted: don't descend into RCS, CVS.adm, SCCS directories\n
\040\040-v\040\040Verbose: print command before executing it"
# Scan for options
while getopts afqrv option; do
case $option in
a)
alldirs=$option
options=$options" "-$option
;;
f)
force=$option
options=$options" "-$option
;;
q)
verbose=
quiet=$option
options=$options" "-$option
;;
r)
restricted=$option
options=$options" "-$option
;;
v)
verbose=$option
quiet=
options=$options" "-$option
;;
\?)
/usr/5bin/echo $usage 1>&2
exit 1
;;
esac
done
shift `expr $OPTIND - 1`
# Get command to execute
if [ $# -lt 1 ] ; then
/usr/5bin/echo $usage 1>&2
exit 1
else
command=$1
shift
fi
# If no directory specified, use '.'
if [ $# -lt 1 ] ; then
default_dir=.
fi
# For each directory specified
for dir in $default_dir "$@" ; do
# Spawn sub-shell so we return to starting directory afterward
(cd $dir
# Execute specified command
if [ -z "$quiet" ] ; then
echo In directory `hostname`:`pwd`
fi
if [ -n "$verbose" ] ; then
echo $command
fi
eval "$command" || if [ -z "$force" ] ; then exit 1; fi
# Collect dot file names if necessary
if [ -n "$alldirs" ] ; then
dotfiles=.*
else
dotfiles=
fi
# For each file in current directory
for file in $dotfiles * ; do
# Skip '.' and '..'
if [ "$file" = "." -o "$file" = ".." ] ; then
continue
fi
# If a directory but not a symbolic link
if [ -d "$file" -a ! -h "$file" ] ; then
# If not skipping this type of directory
if [ \( "$file" != "RCS" -a \
"$file" != "SCCS" -a \
"$file" != "CVS" -a \
"$file" != "CVS.adm" \) \
-o -z "$restricted" ] ; then
# Recursively descend into it
$fullname $options "$command" "$file" \
|| if [ -z "$force" ] ; then exit 1; fi
fi
# Else if a directory AND a symbolic link
elif [ -d "$file" -a -h "$file" ] ; then
if [ -z "$quiet" ] ; then
echo In directory `hostname`:`pwd`/$file: symbolic link: skipping
fi
fi
done
) || if [ -z "$force" ] ; then exit 1; fi
done
+481
View File
@@ -0,0 +1,481 @@
echo 'directory.3':
sed 's/^X//' >'directory.3' <<'!'
X.TH DIRECTORY 3 imported
X.DA 9 Oct 1985
X.SH NAME
Xopendir, readdir, telldir, seekdir, rewinddir, closedir \- high-level directory operations
X.SH SYNOPSIS
X.B #include <sys/types.h>
X.br
X.B #include <ndir.h>
X.PP
X.SM
X.B DIR
X.B *opendir(filename)
X.br
X.B char *filename;
X.PP
X.SM
X.B struct direct
X.B *readdir(dirp)
X.br
X.B DIR *dirp;
X.PP
X.SM
X.B long
X.B telldir(dirp)
X.br
X.B DIR *dirp;
X.PP
X.SM
X.B seekdir(dirp, loc)
X.br
X.B DIR *dirp;
X.br
X.B long loc;
X.PP
X.SM
X.B rewinddir(dirp)
X.br
X.B DIR *dirp;
X.PP
X.SM
X.B closedir(dirp)
X.br
X.B DIR *dirp;
X.SH DESCRIPTION
XThis library provides high-level primitives for directory scanning,
Xsimilar to those available for 4.2BSD's (very different) directory system.
X.\"The purpose of this library is to simulate
X.\"the new flexible length directory names of 4.2bsd UNIX
X.\"on top of the old directory structure of v7.
XIt incidentally provides easy portability to and from 4.2BSD (insofar
Xas such portability is not compromised by other 4.2/VAX dependencies).
X.\"It allows programs to be converted immediately
X.\"to the new directory access interface,
X.\"so that they need only be relinked
X.\"when moved to 4.2bsd.
X.\"It is obtained with the loader option
X.\".BR \-lndir .
X.PP
X.I Opendir
Xopens the directory named by
X.I filename
Xand associates a
X.I directory stream
Xwith it.
X.I Opendir
Xreturns a pointer to be used to identify the
X.I directory stream
Xin subsequent operations.
XThe pointer
X.SM
X.B NULL
Xis returned if
X.I filename
Xcannot be accessed or is not a directory.
X.PP
X.I Readdir
Xreturns a pointer to the next directory entry.
XIt returns
X.B NULL
Xupon reaching the end of the directory or detecting
Xan invalid
X.I seekdir
Xoperation.
X.PP
X.I Telldir
Xreturns the current location associated with the named
X.I directory stream.
X.PP
X.I Seekdir
Xsets the position of the next
X.I readdir
Xoperation on the
X.I directory stream.
XThe new position reverts to the one associated with the
X.I directory stream
Xwhen the
X.I telldir
Xoperation was performed.
XValues returned by
X.I telldir
Xare good only for the lifetime of the DIR pointer from
Xwhich they are derived.
XIf the directory is closed and then reopened,
Xthe
X.I telldir
Xvalue may be invalidated
Xdue to undetected directory compaction in 4.2BSD.
XIt is safe to use a previous
X.I telldir
Xvalue immediately after a call to
X.I opendir
Xand before any calls to
X.I readdir.
X.PP
X.I Rewinddir
Xresets the position of the named
X.I directory stream
Xto the beginning of the directory.
X.PP
X.I Closedir
Xcauses the named
X.I directory stream
Xto be closed,
Xand the structure associated with the DIR pointer to be freed.
X.PP
XA
X.I direct
Xstructure is as follows:
X.PP
X.RS
X.nf
Xstruct direct {
X /* unsigned */ long d_ino; /* inode number of entry */
X unsigned short d_reclen; /* length of this record */
X unsigned short d_namlen; /* length of string in d_name */
X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
X};
X.fi
X.RE
X.PP
XThe
X.I d_reclen
Xfield is meaningless in non-4.2BSD systems and should be ignored.
XThe use of a
X.I long
Xfor
X.I d_ino
Xis also a 4.2BSDism;
X.I ino_t
X(see
X.IR types (5))
Xshould be used elsewhere.
XThe macro
X.I DIRSIZ(dp)
Xgives the minimum memory size needed to hold the
X.I direct
Xvalue pointed to by
X.IR dp ,
Xwith the minimum necessary allocation for
X.IR d_name .
X.PP
XThe preferred way to search the current directory for entry ``name'' is:
X.PP
X.RS
X.nf
X len = strlen(name);
X dirp = opendir(".");
X if (dirp == NULL) {
X fprintf(stderr, "%s: can't read directory .\\n", argv[0]);
X return NOT_FOUND;
X }
X while ((dp = readdir(dirp)) != NULL)
X if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) {
X closedir(dirp);
X return FOUND;
X }
X closedir(dirp);
X return NOT_FOUND;
X.RE
X.\".SH LINKING
X.\"This library is accessed by specifying ``-lndir'' as the
X.\"last argument to the compile line, e.g.:
X.\".PP
X.\" cc -I/usr/include/ndir -o prog prog.c -lndir
X.SH "SEE ALSO"
Xopen(2),
Xclose(2),
Xread(2),
Xlseek(2)
X.SH HISTORY
XWritten by
XKirk McKusick at Berkeley (ucbvax!mckusick).
XMiscellaneous bug fixes from elsewhere.
XThe size of the data structure has been decreased to avoid excessive
Xspace waste under V7 (where filenames are 14 characters at most).
XFor obscure historical reasons, the include file is also available
Xas
X.IR <ndir/sys/dir.h> .
XThe Berkeley version lived in a separate library (\fI\-lndir\fR),
Xwhereas ours is
Xpart of the C library, although the separate library is retained to
Xmaximize compatibility.
X.PP
XThis manual page has been substantially rewritten to be informative in
Xthe absence of a 4.2BSD manual.
X.SH BUGS
XThe
X.I DIRSIZ
Xmacro actually wastes a bit of space due to some padding requirements
Xthat are an artifact of 4.2BSD.
X.PP
XThe returned value of
X.I readdir
Xpoints to a static area that will be overwritten by subsequent calls.
X.PP
XThere are some unfortunate name conflicts with the \fIreal\fR V7
Xdirectory structure definitions.
!
echo 'dir.h':
sed 's/^X//' >'dir.h' <<'!'
X/* dir.h 4.4 82/07/25 */
X
X/*
X * A directory consists of some number of blocks of DIRBLKSIZ
X * bytes, where DIRBLKSIZ is chosen such that it can be transferred
X * to disk in a single atomic operation (e.g. 512 bytes on most machines).
X *
X * Each DIRBLKSIZ byte block contains some number of directory entry
X * structures, which are of variable length. Each directory entry has
X * a struct direct at the front of it, containing its inode number,
X * the length of the entry, and the length of the name contained in
X * the entry. These are followed by the name padded to a 4 byte boundary
X * with null bytes. All names are guaranteed null terminated.
X * The maximum length of a name in a directory is MAXNAMLEN.
X *
X * The macro DIRSIZ(dp) gives the amount of space required to represent
X * a directory entry. Free space in a directory is represented by
X * entries which have dp->d_reclen >= DIRSIZ(dp). All DIRBLKSIZ bytes
X * in a directory block are claimed by the directory entries. This
X * usually results in the last entry in a directory having a large
X * dp->d_reclen. When entries are deleted from a directory, the
X * space is returned to the previous entry in the same directory
X * block by increasing its dp->d_reclen. If the first entry of
X * a directory block is free, then its dp->d_ino is set to 0.
X * Entries other than the first in a directory do not normally have
X * dp->d_ino set to 0.
X */
X#define DIRBLKSIZ 512
X#ifdef VMUNIX
X#define MAXNAMLEN 255
X#else
X#define MAXNAMLEN 14
X#endif
X
Xstruct direct {
X /* unsigned */ long d_ino; /* inode number of entry */
X unsigned short d_reclen; /* length of this record */
X unsigned short d_namlen; /* length of string in d_name */
X char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
X};
X
X/*
X * The DIRSIZ macro gives the minimum record length which will hold
X * the directory entry. This requires the amount of space in struct direct
X * without the d_name field, plus enough space for the name with a terminating
X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
X */
X#undef DIRSIZ
X#define DIRSIZ(dp) \
X ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
X
X#ifndef KERNEL
X/*
X * Definitions for library routines operating on directories.
X */
Xtypedef struct _dirdesc {
X int dd_fd;
X long dd_loc;
X long dd_size;
X char dd_buf[DIRBLKSIZ];
X} DIR;
X#ifndef NULL
X#define NULL 0
X#endif
Xextern DIR *opendir();
Xextern struct direct *readdir();
Xextern long telldir();
X#ifdef void
Xextern void seekdir();
Xextern void closedir();
X#endif
X#define rewinddir(dirp) seekdir((dirp), (long)0)
X#endif KERNEL
!
echo 'makefile':
sed 's/^X//' >'makefile' <<'!'
XDIR = closedir.o opendir.o readdir.o seekdir.o telldir.o
XCFLAGS=-O -I. -Dvoid=int
XDEST=..
X
Xall: $(DIR)
X
Xmv: $(DIR)
X mv $(DIR) $(DEST)
X
Xcpif: dir.h
X cp dir.h /usr/include/ndir.h
X
Xclean:
X rm -f *.o
!
echo 'closedir.c':
sed 's/^X//' >'closedir.c' <<'!'
Xstatic char sccsid[] = "@(#)closedir.c 4.2 3/10/82";
X
X#include <sys/types.h>
X#include <dir.h>
X
X/*
X * close a directory.
X */
Xvoid
Xclosedir(dirp)
X register DIR *dirp;
X{
X close(dirp->dd_fd);
X dirp->dd_fd = -1;
X dirp->dd_loc = 0;
X free((char *)dirp);
X}
!
echo 'opendir.c':
sed 's/^X//' >'opendir.c' <<'!'
X/* Copyright (c) 1982 Regents of the University of California */
X
Xstatic char sccsid[] = "@(#)opendir.c 4.4 11/12/82";
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <dir.h>
X
X/*
X * open a directory.
X */
XDIR *
Xopendir(name)
X char *name;
X{
X register DIR *dirp;
X register int fd;
X struct stat statbuf;
X char *malloc();
X
X if ((fd = open(name, 0)) == -1)
X return NULL;
X if (fstat(fd, &statbuf) == -1 || !(statbuf.st_mode & S_IFDIR)) {
X close(fd);
X return NULL;
X }
X if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
X close (fd);
X return NULL;
X }
X dirp->dd_fd = fd;
X dirp->dd_loc = 0;
X dirp->dd_size = 0; /* so that telldir will work before readdir */
X return dirp;
X}
!
echo 'readdir.c':
sed 's/^X//' >'readdir.c' <<'!'
X/* Copyright (c) 1982 Regents of the University of California */
X
Xstatic char sccsid[] = "@(#)readdir.c 4.3 8/8/82";
X
X#include <sys/types.h>
X#include <dir.h>
X
X/*
X * read an old stlye directory entry and present it as a new one
X */
X#define ODIRSIZ 14
X
Xstruct olddirect {
X ino_t od_ino;
X char od_name[ODIRSIZ];
X};
X
X/*
X * get next entry in a directory.
X */
Xstruct direct *
Xreaddir(dirp)
X register DIR *dirp;
X{
X register struct olddirect *dp;
X static struct direct dir;
X
X for (;;) {
X if (dirp->dd_loc == 0) {
X dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
X DIRBLKSIZ);
X if (dirp->dd_size <= 0) {
X dirp->dd_size = 0;
X return NULL;
X }
X }
X if (dirp->dd_loc >= dirp->dd_size) {
X dirp->dd_loc = 0;
X continue;
X }
X dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
X dirp->dd_loc += sizeof(struct olddirect);
X if (dp->od_ino == 0)
X continue;
X dir.d_ino = dp->od_ino;
X strncpy(dir.d_name, dp->od_name, ODIRSIZ);
X dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
X dir.d_namlen = strlen(dir.d_name);
X dir.d_reclen = DIRBLKSIZ;
X return (&dir);
X }
X}
!
echo 'seekdir.c':
sed 's/^X//' >'seekdir.c' <<'!'
Xstatic char sccsid[] = "@(#)seekdir.c 4.9 3/25/83";
X
X#include <sys/param.h>
X#include <dir.h>
X
X/*
X * seek to an entry in a directory.
X * Only values returned by "telldir" should be passed to seekdir.
X */
Xvoid
Xseekdir(dirp, loc)
X register DIR *dirp;
X long loc;
X{
X long curloc, base, offset;
X struct direct *dp;
X extern long lseek();
X
X curloc = telldir(dirp);
X if (loc == curloc)
X return;
X base = loc & ~(DIRBLKSIZ - 1);
X offset = loc & (DIRBLKSIZ - 1);
X (void) lseek(dirp->dd_fd, base, 0);
X dirp->dd_size = 0;
X dirp->dd_loc = 0;
X while (dirp->dd_loc < offset) {
X dp = readdir(dirp);
X if (dp == NULL)
X return;
X }
X}
!
echo 'telldir.c':
sed 's/^X//' >'telldir.c' <<'!'
Xstatic char sccsid[] = "@(#)telldir.c 4.1 2/21/82";
X
X#include <sys/types.h>
X#include <dir.h>
X
X/*
X * return a pointer into a directory
X */
Xlong
Xtelldir(dirp)
X DIR *dirp;
X{
X long lseek();
X
X return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc);
X}
!
echo done
+388
View File
@@ -0,0 +1,388 @@
#!/usr/bin/perl
#
# Support for importing a source collection into CVS.
# Tries to prevent the user from the most common pitfalls (like creating
# new top-level repositories or second-level areas accidentally), and
# cares to do some of the `dirty' work like maintaining the modules
# database accordingly.
#
# Written by Jörg Wunsch, 95/03/07, and placed in the public domain.
#
# $Id: easy-import.perl,v 1.3 1995/07/23 17:34:00 joerg Exp $
require "complete.pl";
require "getopts.pl";
sub scan_opts
{
local($status);
$status = &Getopts("nv");
$dont_do_it = "-n" if $opt_n;
if($opt_v) {
print STDERR '$Source: /home/ncvs/src/gnu/usr.bin/cvs/contrib/easy-import.perl,v $ $Revision: 1.3 $' . "\n"; # 'emacs kludge
exit 0;
}
die "usage: $0 [-v] [-n] [moduledir]\n" .
" -n: don't do any commit, show only\n" .
" -v: show program version\n"
unless $status && $#ARGV <= 0;
if($#ARGV == 0) {
$moduledir = $ARGV[0];
shift;
}
}
sub lsdir
{
# find all subdirectories under @_
# ignore all CVS entries, dot entries, and non-directories
local($base) = @_;
local(@ls, @rv, $fname);
opendir(DIR, $base) || die "Cannot find dir $base.\n";
@ls = readdir(DIR);
closedir(DIR);
@rv = ();
foreach $fname (@ls) {
next if $fname =~ /^CVS/ || $fname eq "Attic"
|| $fname =~ /^\./ || ! -d "$base/$fname";
@rv = (@rv, $fname);
}
return sort(@rv);
}
sub contains
{
# look if the first parameter is contained in the list following it
local($item, @list) = @_;
local($found, $i);
$found = 0;
foreach $i (@list) {
return 1 if $i eq $item;
}
return 0;
}
sub term_init
{
# first, get some terminal attributes
# try bold mode first
$so = `tput md`; $se = `tput me`;
# if no bold mode available, use standout mode
if ($so eq "") {
$so = `tput so`; $se = `tput se`;
}
# try if we can underscore
$us = `tput us`; $ue = `tput ue`;
# if we don't have it available, or same as bold/standout, disable it
if ($us eq "" || $us eq $so) {
$us = $ue = "";
}
# look how many columns we've got
if($ENV{'COLUMNS'} ne "") {
$columns = $ENV{'COLUMNS'};
} elsif(-t STDIN) { # if we operate on a terminal...
local($word, $tmp);
open(STTY, "stty -a|");
$_ = <STTY>; # try getting the tty win structure value
close(STTY);
chop;
$columns = 0;
foreach $word (split) {
$columns = $tmp if $word eq "columns;"; # the number preceding
$tmp = $word;
}
} else {
$columns = 80;
}
# sanity
$columns = 80 unless $columns >= 5;
}
sub list
{
# pretty-print a list
# imports: global variable $columns
local(@items) = @_;
local($longest,$i,$item,$cols,$width);
# find the longest item
$longest = 0;
foreach $item (@items) {
$i = length($item);
$longest = $i if $longest < $i;
}
$width = $longest + 1;
$cols = int($columns / $width);
$i = 0;
foreach $item (@items) {
print $item;
if(++$i == $cols) {
$i = 0; print "\n";
} else {
print ' ' x ($width - length($item));
}
}
print "\n" unless $i == 0;
}
sub cvs_init
{
# get the CVS repository(s)
die "You need to have the \$CVSROOT variable set.\n"
unless $ENV{'CVSROOT'} ne "";
# get the list of available repositories
$cvsroot = $ENV{'CVSROOT'};
@reps = &lsdir($cvsroot);
}
sub lsmodules
{
# list all known CVS modules
local(@rv, $mname, $_);
@rv = ();
open(CVS, "cvs co -c|");
while($_ = <CVS>) {
chop;
($mname) = split;
next if $mname eq "";
@rv = (@rv, $mname);
}
close(CVS);
return @rv;
}
sub checktag
{
# check a given string for tag rules
local($s, $name) = @_;
local($regexp);
if($name eq "vendor") { $regexp = '^[A-Z][A-Z0-9_]*$'; }
elsif($name eq "release") { $regexp = '^[a-z][a-z0-9_]*$'; }
else {
print STDERR "Internal error: unknown tag name $name\n";
exit(2);
}
if($s !~ /$regexp/) {
print "\a${us}Valid $name tags must match the regexp " .
"$regexp.${ue}\n";
return 0;
}
if($s =~ /^RELENG/) {
print "\a${us}Tags must not start with the word \"RELENG\".${ue}\n";
return 0;
}
return 1;
}
&scan_opts;
&term_init;
&cvs_init;
if(! $moduledir) {
@dirs = &lsdir(".");
print "${so}Import from which directory?${se}\n";
@dirs = (@dirs, ".");
&list(@dirs);
$moduledir = &Complete("Which? [.]: ", @dirs);
$moduledir = "." unless $moduledir ne "";
}
chdir $moduledir || die "Cannot chdir to $moduledir\n";
print "${so}Available repositories:${se}\n";
&list(@reps);
# the following kludge prevents the Complete package from starting
# over with the string just selected; Complete should better provide
# some reinitialize method
$Complete'return = ""; $Complete'r = 0;
$selected =
&Complete("Enter repository (<TAB>=complete, ^D=show): ",
@reps);
die "\aYou cannot create new repositories with this script.\n"
unless &contains($selected, @reps);
$rep = $selected;
print "\n${so}Selected repository:${se} ${us}$rep${ue}\n";
@areas = &lsdir("$cvsroot/$rep");
print "${so}Existent areas in this repository:${se}\n";
&list(@areas);
$Complete'return = ""; $Complete'r = 0;
$selected =
&Complete("Enter area name (<TAB>=complete, ^D=show): ",
@areas);
print "\a${us}Warning: this will create a new area.${ue}\n"
unless &contains($selected, @areas);
$area = "$rep/$selected";
print "\n${so}[Working on:${se} ${us}$area${ue}${so}]${se}\n";
for(;;) {
$| = 1;
print "${so}Enter the module path:${se} $area/";
$| = 0;
$modpath = <>;
chop $modpath;
if ($modpath eq "") {
print "\a${us}You cannot use an empty module path.${ue}\n";
next;
}
last if ! -d "$cvsroot/$area/$modpath";
print "\a${us}This module path does already exist; " .
"choose another one.${ue}\n";
}
@newdirs = ();
$dir1 = "$cvsroot/$area";
$dir2 = "$area";
@newdirs = (@newdirs, "$dir2") if ! -d $dir1;
foreach $ele (split(/\//, $modpath)) {
$dir1 = "$dir1/$ele";
$dir2 = "$dir2/$ele";
@newdirs = (@newdirs, "$dir2") if ! -d $dir1;
}
print "${so}You're going to create the following new directories:${se}\n";
&list(@newdirs);
@cvsmods = &lsmodules();
for(;;) {
$| = 1;
print "${so}Gimme the module name:${se} ";
$| = 0;
$modname = <>;
chop $modname;
if ($modname eq "") {
print "\a${us}You cannot use an empty module name.${ue}\n";
next;
}
last if !&contains($modname, @cvsmods);
print "\a${us}This module name does already exist; " .
"choose another one.${ue}\n";
}
for(;;) {
$| = 1;
print "${so}Enter a \`vendor\' tag (e. g. the authors ID):${se} ";
$| = 0;
$vtag = <>;
chop $vtag;
last if &checktag($vtag, "vendor");
}
for(;;) {
$| = 1;
print "${so}Enter a \`release\' tag (e. g. the version #):${se} ";
$| = 0;
$rtag = <>;
chop $rtag;
last if &checktag($rtag, "release");
}
$| = 1;
print "${so}This is your last chance to interrupt, " .
"hit <return> to go on:${se} ";
$| = 0;
<>;
$mod = "";
foreach $tmp (@cvsmods) {
if($tmp gt $modname) {
$mod = $tmp;
last;
}
}
if($mod eq "") {
# we are going to append our module
$cmd = "\$\na\n";
} else {
# we can insert it
$cmd = "/^${mod}[ \t]/\ni\n";
}
print "${so}Checking out the modules database...${se}\n";
system("cvs co modules") && die "${us}failed.\n${ue}";
print "${so}Inserting new module...${se}\n";
open(ED, "|ed modules/modules") || die "${us}Cannot start ed${ue}\n";
print(ED "${cmd}${modname}" . ' ' x (16 - length($modname)) .
"$area/${modpath}\n.\nw\nq\n");
close(ED);
print "${so}Commiting new modules database...${se}\n";
system("cvs $dont_do_it commit -m \" " .
"${modname} --> $area/${modpath}\" modules")
&& die "Commit failed\n";
system("cvs $dont_do_it release -dQ modules");
print "${so}Importing source. Enter a commit message in the editor.${se}\n";
system("cvs $dont_do_it import $area/$modpath $vtag $rtag");
print "${so}You are done now. Go to a different directory, perform a${se}\n".
"${us}cvs co ${modname}${ue} ${so}command, and see if your new module" .
" builds ok.${se}\n";
if($dont_do_it) {
print <<END
${so}Since you did not allow to commit anything, you'll have${se}
${so}to remove the edited modules' database yourself.${se}
${so}To do this, perform a${se}
${us}cd ${moduledir}; cvs release -dQ modules${ue}
${so}command.${se}
END
;
}
+884
View File
@@ -0,0 +1,884 @@
;;; cookie.el,v 1.2 1992/04/07 20:49:12 berliner Exp
;;; cookie.el -- Utility to display cookies in buffers
;;; Copyright (C) 1991, 1992 Per Cederqvist
;;;
;;; This program is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2 of the License, or
;;; (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, write to the Free Software
;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;;; TO-DO: Byt namn! tin -> wrapper (eller n}got b{ttre).
;;; Note that this file is still under development. Comments,
;;; enhancements and bug fixes are welcome.
;;; Send them to [email protected].
(defun impl nil (error "Not yet implemented!"))
;;; Cookie is a package that imlements a connection between an
;;; elib-dll and the contents of a buffer. Possible uses are dired
;;; (have all files in a list, and show them), buffer-list,
;;; kom-prioritize (in the LysKOM elisp client) and others. pcl-cvs.el
;;; uses cookie.el.
;;;
;;; A cookie buffer contains a header, any number of cookies, and a
;;; footer. The header and footer are constant strings that are given
;;; to cookie-create when the buffer is placed under cookie. Each cookie
;;; is displayed in the buffer by calling a user-supplied function
;;; that takes a cookie and returns a string. The string may be
;;; empty, or contain any number of lines. An extra newline is always
;;; appended unless the string is empty.
;;;
;;; Cookie does not affect the mode of the buffer in any way. It
;;; merely makes it easy to connect an underlying data representation
;;; to the buffer contents.
;;;
;;; The cookie-node data type:
;;; start-marker
;;; ;; end-marker This field is no longer present.
;;; cookie The user-supplied element.
;;;
;;; A dll of cookie-nodes are held in the buffer local variable
;;; cake-tin.
;;;
;;; A tin is an object that contains one cookie. You can get the next
;;; and previous tin.
;;;
(require 'elib-dll)
(provide 'cookie)
(defvar cookies nil
"A doubly linked list that contains the underlying data representation
for the contents of a cookie buffer. The package elib-dll is used to
manipulate this list.")
(defvar cookie-pretty-printer nil
"The function that is used to pretty-print a cookie in this buffer.")
(defvar cookie-header nil
"The tin that holds the header cookie.")
(defvar cookie-footer nil
"The tin that holds the footer cookie.")
(defvar cookie-last-tin nil
"The tin the cursor was positioned at, the last time the cookie
package checked the cursor position. Buffer local in all buffers
the cookie package works on. You may set this if your package
thinks it knows where the cursor will be the next time this
package is called. It can speed things up.
It must never be set to a tin that has been deleted.")
;;; ================================================================
;;; Internal functions for use in the cookie package
(put 'cookie-set-buffer 'lisp-indent-hook 1)
(defmacro cookie-set-buffer (buffer &rest forms)
;; Execute FORMS with BUFFER selected as current buffer.
;; Return value of last form in FORMS. INTERNAL USE ONLY.
(let ((old-buffer (make-symbol "old-buffer")))
(` (let (((, old-buffer) (current-buffer)))
(set-buffer (get-buffer-create (, buffer)))
(unwind-protect
(progn (,@ forms))
(set-buffer (, old-buffer)))))))
(defmacro cookie-filter-hf (tin)
;; Evaluate TIN once and return it. BUT if it is
;; equal to cookie-header or cookie-footer return nil instead.
;; INTERNAL USE ONLY.
(let ((tempvar (make-symbol "tin")))
(` (let (((, tempvar) (, tin)))
(if (or (eq (, tempvar) cookie-header)
(eq (, tempvar) cookie-footer))
nil
(, tempvar))))))
;;; cookie-tin
;;; Constructor:
(defun cookie-create-tin (start-marker
cookie)
;; Create a tin. INTERNAL USE ONLY.
(cons 'COOKIE-TIN (vector start-marker nil cookie)))
;;; Selectors:
(defun cookie-tin-start-marker (cookie-tin)
;; Get start-marker from cookie-tin. INTERNAL USE ONLY.
(elt (cdr cookie-tin) 0))
;(defun cookie-tin-end-marker (cookie-tin)
; ;;Get end-marker from cookie-tin. INTERNAL USE ONLY.
; (elt (cdr cookie-tin) 1))
(defun cookie-tin-cookie-safe (cookie-tin)
;; Get cookie from cookie-tin. INTERNAL USE ONLY.
;; Returns nil if given nil as input.
;; This is the same as cookie-tin-cookie in version 18.57
;; of emacs, but elt should signal an error when given nil
;; as input (according to the info files).
(elt (cdr cookie-tin) 2))
(defun cookie-tin-cookie (cookie-tin)
;; Get cookie from cookie-tin. INTERNAL USE ONLY.
(elt (cdr cookie-tin) 2))
;;; Modifiers:
(defun set-cookie-tin-start-marker (cookie-tin newval)
;; Set start-marker in cookie-tin to NEWVAL. INTERNAL USE ONLY.
(aset (cdr cookie-tin) 0 newval))
;(defun set-cookie-tin-end-marker (cookie-tin newval)
; ;; Set end-marker in cookie-tin to NEWVAL. INTERNAL USE ONLY.
; (aset (cdr cookie-tin) 1 newval))
(defun set-cookie-tin-cookie (cookie-tin newval)
;; Set cookie in cookie-tin to NEWVAL. INTERNAL USE ONLY.
(aset (cdr cookie-tin) 2 newval))
;;; Predicate:
(defun cookie-tin-p (object)
;; Return t if OBJECT is a tin. INTERNAL USE ONLY.
(eq (car-safe object) 'COOKIE-TIN))
;;; end of cookie-tin data type.
(defun cookie-create-tin-and-insert (cookie string pos)
;; Insert STRING at POS in current buffer. Remember start
;; position. Create a tin containing them and the COOKIE.
;; INTERNAL USE ONLY.
(save-excursion
(goto-char pos)
;; Remember the position as a number so that it doesn't move
;; when we insert the string.
(let ((start (if (markerp pos)
(marker-position pos)
pos)))
;; Use insert-before-markers so that the marker for the
;; next cookie is updated.
(insert-before-markers string)
(insert-before-markers ?\n)
(cookie-create-tin (copy-marker start) cookie))))
(defun cookie-delete-tin-internal (tin)
;; Delete a cookie from the buffer. INTERNAL USE ONLY.
;; Can not be used on the footer.
(delete-region (cookie-tin-start-marker (dll-element cookies tin))
(cookie-tin-start-marker
(dll-element cookies
(dll-next cookies tin)))))
(defun cookie-refresh-tin (tin)
;; Redisplay the cookie represented by TIN. INTERNAL USE ONLY.
;; Can not be used on the footer.
(save-excursion
;; First, remove the string:
(delete-region (cookie-tin-start-marker (dll-element cookies tin))
(1- (marker-position
(cookie-tin-start-marker
(dll-element cookies
(dll-next cookies tin))))))
;; Calculate and insert the string.
(goto-char (cookie-tin-start-marker (dll-element cookies tin)))
(insert
(funcall cookie-pretty-printer
(cookie-tin-cookie (dll-element cookies tin))))))
;;; ================================================================
;;; The public members of the cookie package
(defun cookie-cookie (buffer tin)
"Get the cookie from a TIN. Args: BUFFER TIN."
(cookie-set-buffer buffer
(cookie-tin-cookie (dll-element cookies tin))))
(defun cookie-create (buffer pretty-printer &optional header footer)
"Start to use the cookie package in BUFFER.
BUFFER may be a buffer or a buffer name. It is created if it does not exist.
Beware that the entire contents of the buffer will be erased.
PRETTY-PRINTER is a function that takes one cookie and returns a string
to be displayed in the buffer. The string may be empty. If it is not
empty a newline will be added automatically. It may span several lines.
Optional third argument HEADER is a string that will always be present
at the top of the buffer. HEADER should end with a newline. Optionaly
fourth argument FOOTER is similar, and will always be inserted at the
bottom of the buffer."
(cookie-set-buffer buffer
(erase-buffer)
(make-local-variable 'cookie-last-tin)
(make-local-variable 'cookie-pretty-printer)
(make-local-variable 'cookie-header)
(make-local-variable 'cookie-footer)
(make-local-variable 'cookies)
(setq cookie-last-tin nil)
(setq cookie-pretty-printer pretty-printer)
(setq cookies (dll-create))
(dll-enter-first cookies
(cookie-create-tin-and-insert
header header 0))
(setq cookie-header (dll-nth cookies 0))
(dll-enter-last cookies
(cookie-create-tin-and-insert
footer footer (point-max)))
(setq cookie-footer (dll-nth cookies -1))
(goto-char (point-min))
(forward-line 1)))
(defun cookie-set-header (buffer header)
"Change the header. Args: BUFFER HEADER."
(impl))
(defun cookie-set-footer (buffer header)
"Change the footer. Args: BUFFER FOOTER."
(impl))
(defun cookie-enter-first (buffer cookie)
"Enter a COOKIE first in BUFFER.
Args: BUFFER COOKIE."
(cookie-set-buffer buffer
;; It is always safe to insert an element after the first element,
;; because the header is always present. (dll-nth cookies 0) should
;; never return nil.
(dll-enter-after
cookies
(dll-nth cookies 0)
(cookie-create-tin-and-insert
cookie
(funcall cookie-pretty-printer cookie)
(cookie-tin-start-marker
(dll-element cookies (dll-nth cookies 1)))))))
(defun cookie-enter-last (buffer cookie)
"Enter a COOKIE last in BUFFER.
Args: BUFFER COOKIE."
(cookie-set-buffer buffer
;; Remember that the header and footer are always present. There
;; is no need to check if (dll-nth cookies -2) returns nil.
(dll-enter-before
cookies
(dll-nth cookies -1)
(cookie-create-tin-and-insert
cookie
(funcall cookie-pretty-printer cookie)
(cookie-tin-start-marker (dll-last cookies))))))
(defun cookie-enter-after (buffer node cookie)
(impl))
(defun cookie-enter-before (buffer node cookie)
(impl))
(defun cookie-next (buffer tin)
"Get the next tin. Args: BUFFER TIN.
Returns nil if TIN is nil or the last cookie."
(if tin
(cookie-set-buffer buffer
(cookie-filter-hf (dll-next cookies tin)))))
(defun cookie-previous (buffer tin)
"Get the previous tin. Args: BUFFER TIN.
Returns nil if TIN is nil or the first cookie."
(if tin
(cookie-set-buffer buffer
(cookie-filter-hf (dll-previous cookies tin)))))
(defun cookie-nth (buffer n)
"Return the Nth tin. Args: BUFFER N.
N counts from zero. Nil is returned if there is less than N cookies.
If N is negative, return the -(N+1)th last element.
Thus, (cookie-nth dll 0) returns the first node,
and (cookie-nth dll -1) returns the last node.
Use cookie-cookie to extract the cookie from the tin."
(cookie-set-buffer buffer
;; Skip the header (or footer, if n is negative).
(if (< n 0)
(setq n (1- n))
(setq n (1+ n)))
(cookie-filter-hf (dll-nth cookies n))))
(defun cookie-delete (buffer tin)
"Delete a cookie. Args: BUFFER TIN."
(cookie-set-buffer buffer
(if (eq cookie-last-tin tin)
(setq cookie-last-tin nil))
(cookie-delete-tin-internal tin)
(dll-delete cookies tin)))
(defun cookie-delete-first (buffer)
"Delete first cookie and return it. Args: BUFFER.
Returns nil if there is no cookie left."
(cookie-set-buffer buffer
;; We have to check that we do not try to delete the footer.
(let ((tin (dll-nth cookies 1))) ;Skip the header.
(if (eq tin cookie-footer)
nil
(cookie-delete-tin-internal tin)
(cookie-tin-cookie (dll-delete cookies tin))))))
(defun cookie-delete-last (buffer)
"Delete last cookie and return it. Args: BUFFER.
Returns nil if there is no cookie left."
(cookie-set-buffer buffer
;; We have to check that we do not try to delete the header.
(let ((tin (dll-nth cookies -2))) ;Skip the footer.
(if (eq tin cookie-header)
nil
(cookie-delete-tin-internal tin)
(cookie-tin-cookie (dll-delete cookies tin))))))
(defun cookie-first (buffer)
"Return the first cookie in BUFFER. The cookie is not removed."
(cookie-set-buffer buffer
(let ((tin (cookie-filter-hf (dll-nth cookies -1))))
(if tin
(cookie-tin-cookie-safe
(dll-element cookies tin))))))
(defun cookie-last (buffer)
"Return the last cookie in BUFFER. The cookie is not removed."
(cookie-set-buffer buffer
(let ((tin (cookie-filter-hf (dll-nth cookies -2))))
(if tin
(cookie-tin-cookie-safe
(dll-element cookies tin))))))
(defun cookie-empty (buffer)
"Return true if there are no cookies in BUFFER."
(cookie-set-buffer buffer
(eq (dll-nth cookies 1) cookie-footer)))
(defun cookie-length (buffer)
"Return number of cookies in BUFFER."
;; Don't count the footer and header.
(cookie-set-buffer buffer
(- (dll-length cookies) 2)))
(defun cookie-all (buffer)
"Return a list of all cookies in BUFFER."
(cookie-set-buffer buffer
(let (result
(tin (dll-nth cookies -2)))
(while (not (eq tin cookie-header))
(setq result (cons (cookie-tin-cookie (dll-element cookies tin))
result))
(setq tin (dll-previous cookies tin)))
result)))
(defun cookie-clear (buffer)
"Remove all cookies in buffer."
(cookie-set-buffer buffer
(cookie-create buffer cookie-pretty-printer
(cookie-tin-cookie (dll-element cookies cookie-header))
(cookie-tin-cookie (dll-element cookies cookie-footer)))))
(defun cookie-map (map-function buffer &rest map-args)
"Apply MAP-FUNCTION to all cookies in BUFFER.
MAP-FUNCTION is applied to the first element first.
If MAP-FUNCTION returns non-nil the cookie will be refreshed.
Note that BUFFER will be current buffer when MAP-FUNCTION is called.
If more than two arguments are given to cookie-map, remaining
arguments will be passed to MAP-FUNCTION."
(cookie-set-buffer buffer
(let ((tin (dll-nth cookies 1))
result)
(while (not (eq tin cookie-footer))
(if (apply map-function
(cookie-tin-cookie (dll-element cookies tin))
map-args)
(cookie-refresh-tin tin))
(setq tin (dll-next cookies tin))))))
(defun cookie-map-reverse (map-function buffer &rest map-args)
"Apply MAP-FUNCTION to all cookies in BUFFER.
MAP-FUNCTION is applied to the last cookie first.
If MAP-FUNCTION returns non-nil the cookie will be refreshed.
Note that BUFFER will be current buffer when MAP-FUNCTION is called.
If more than two arguments are given to cookie-map, remaining
arguments will be passed to MAP-FUNCTION."
(cookie-set-buffer buffer
(let ((tin (dll-nth cookies -2))
result)
(while (not (eq tin cookie-header))
(if (apply map-function
(cookie-tin-cookie (dll-element cookies tin))
map-args)
(cookie-refresh-tin tin))
(setq tin (dll-previous cookies tin))))))
(defun cookie-enter-cookies (buffer cookie-list)
"Insert all cookies in the list COOKIE-LIST last in BUFFER.
Args: BUFFER COOKIE-LIST."
(while cookie-list
(cookie-enter-last buffer (car cookie-list))
(setq cookie-list (cdr cookie-list))))
(defun cookie-filter (buffer predicate)
"Remove all cookies in BUFFER for which PREDICATE returns nil.
Note that BUFFER will be current-buffer when PREDICATE is called.
The PREDICATE is called with one argument, the cookie."
(cookie-set-buffer buffer
(let ((tin (dll-nth cookies 1))
next)
(while (not (eq tin cookie-footer))
(setq next (dll-next cookies tin))
(if (funcall predicate (cookie-tin-cookie (dll-element cookies tin)))
nil
(cookie-delete-tin-internal tin)
(dll-delete cookies tin))
(setq tin next)))))
(defun cookie-filter-tins (buffer predicate)
"Remove all cookies in BUFFER for which PREDICATE returns nil.
Note that BUFFER will be current-buffer when PREDICATE is called.
The PREDICATE is called with one argument, the tin."
(cookie-set-buffer buffer
(let ((tin (dll-nth cookies 1))
next)
(while (not (eq tin cookie-footer))
(setq next (dll-next cookies tin))
(if (funcall predicate tin)
nil
(cookie-delete-tin-internal tin)
(dll-delete cookies tin))
(setq tin next)))))
(defun cookie-pos-before-middle-p (pos tin1 tin2)
"Return true if POS is in the first half of the region defined by TIN1 and
TIN2."
(< pos (/ (+ (cookie-tin-start-marker (dll-element cookeis tin1))
(cookie-tin-start-marker (dll-element cookeis tin2)))
2)))
(defun cookie-get-selection (buffer pos &optional guess force-guess)
"Return the tin the POS is within.
Args: BUFFER POS &optional GUESS FORCE-GUESS.
GUESS should be a tin that it is likely that POS is near. If FORCE-GUESS
is non-nil GUESS is always used as a first guess, otherwise the first
guess is the first tin, last tin, or GUESS, whichever is nearest to
pos in the BUFFER.
If pos points within the header, the first cookie is returned.
If pos points within the footer, the last cookie is returned.
Nil is returned if there is no cookie.
It is often good to specify cookie-last-tin as GUESS, but remember
that cookie-last-tin is buffer local in all buffers that cookie
operates on."
(cookie-set-buffer buffer
(cond
; No cookies present?
((eq (dll-nth cookies 1) (dll-nth cookies -1))
nil)
; Before first cookie?
((< pos (cookie-tin-start-marker
(dll-element cookies (dll-nth cookies 1))))
(dll-nth cookies 1))
; After last cookie?
((>= pos (cookie-tin-start-marker (dll-last cookies)))
(dll-nth cookies -2))
; We now now that pos is within a cookie.
(t
; Make an educated guess about which of the three known
; cookies (the first, the last, or GUESS) is nearest.
(setq
guess
(cond
(force-guess guess)
(guess
(cond
;; Closest to first cookie?
((cookie-pos-before-middle-p
pos guess
(dll-nth cookies 1))
(dll-nth cookies 1))
;; Closest to GUESS?
((cookie-pos-before-middle-p
pos guess
cookie-footer)
guess)
;; Closest to last cookie.
(t (dll-previous cookies cookie-footer))))
(t
;; No guess given.
(cond
;; First half?
((cookie-pos-before-middle-p
pos (dll-nth cookies 1)
cookie-footer)
(dll-nth cookies 1))
(t (dll-previous cookies cookie-footer))))))
;; GUESS is now a "best guess".
;; Find the correct cookie. First determine in which direction
;; it lies, and then move in that direction until it is found.
(cond
;; Is pos after the guess?
((>= pos (cookie-tin-start-marker (dll-element cookiess guess)))
;; Loop until we are exactly one cookie too far down...
(while (>= pos (cookie-tin-start-marker (dll-element cookiess guess)))
(setq guess (dll-next cookies guess)))
;; ...and return the previous cookie.
(dll-previous cookies guess))
;; Pos is before guess
(t
(while (< pos (cookie-tin-start-marker (dll-element cookiess guess)))
(setq guess (dll-previous cookies guess)))
guess))))))
(defun cookie-start-marker (buffer tin)
"Return start-position of a cookie in BUFFER.
Args: BUFFER TIN.
The marker that is returned should not be modified in any way,
and is only valid until the contents of the cookie buffer changes."
(cookie-set-buffer buffer
(cookie-tin-start-marker (dll-element cookies tin))))
(defun cookie-end-marker (buffer tin)
"Return end-position of a cookie in BUFFER.
Args: BUFFER TIN.
The marker that is returned should not be modified in any way,
and is only valid until the contents of the cookie buffer changes."
(cookie-set-buffer buffer
(cookie-tin-start-marker
(dll-element cookies (dll-next cookies tin)))))
(defun cookie-refresh (buffer)
"Refresh all cookies in BUFFER.
Cookie-pretty-printer will be called for all cookies and the new result
displayed.
See also cookie-invalidate-tins."
(cookie-set-buffer buffer
(erase-buffer)
(set-marker (cookie-tin-start-marker (dll-element cookies cookie-header))
(point) buffer)
(insert (cookie-tin-cookie (dll-element cookies cookie-header)))
(insert "\n")
(let ((tin (dll-nth cookies 1)))
(while (not (eq tin cookie-footer))
(set-marker (cookie-tin-start-marker (dll-element cookies tin))
(point) buffer)
(insert
(funcall cookie-pretty-printer
(cookie-tin-cookie (dll-element cookies tin))))
(insert "\n")
(setq tin (dll-next cookies tin))))
(set-marker (cookie-tin-start-marker (dll-element cookies cookie-footer))
(point) buffer)
(insert (cookie-tin-cookie (dll-element cookies cookie-footer)))
(insert "\n")))
(defun cookie-invalidate-tins (buffer &rest tins)
"Refresh some cookies.
Args: BUFFER &rest TINS."
(cookie-set-buffer buffer
(while tins
(cookie-refresh-tin (car tins))
(setq tins (cdr tins)))))
;;; Cookie movement commands.
(defun cookie-set-goal-column (buffer goal)
"Set goal-column for BUFFER.
Args: BUFFER GOAL.
goal-column is made buffer-local."
(cookie-set-buffer buffer
(make-local-variable 'goal-column)
(setq goal-column goal)))
(defun cookie-previous-cookie (buffer pos arg)
"Move point to the ARGth previous cookie.
Don't move if we are at the first cookie.
ARG is the prefix argument when called interactively.
Args: BUFFER POS ARG.
Sets cookie-last-tin to the cookie we move to."
(interactive (list (current-buffer) (point)
(prefix-numeric-value current-prefix-arg)))
(cookie-set-buffer buffer
(setq cookie-last-tin
(cookie-get-selection buffer pos cookie-last-tin))
(while (and cookie-last-tin (> arg 0))
(setq arg (1- arg))
(setq cookie-last-tin
(dll-previous cookies cookie-last-tin)))
;; Never step above the first cookie.
(if (null (cookie-filter-hf cookie-last-tin))
(setq cookie-last-tin (dll-nth cookies 1)))
(goto-char
(cookie-tin-start-marker
(dll-element cookies cookie-last-tin)))
(if goal-column
(move-to-column goal-column))))
(defun cookie-next-cookie (buffer pos arg)
"Move point to the ARGth next cookie.
Don't move if we are at the last cookie.
ARG is the prefix argument when called interactively.
Args: BUFFER POS ARG.
Sets cookie-last-tin to the cookie we move to."
(interactive (list (current-buffer) (point)
(prefix-numeric-value current-prefix-arg)))
(cookie-set-buffer buffer
(setq cookie-last-tin
(cookie-get-selection buffer pos cookie-last-tin))
(while (and cookie-last-tin (> arg 0))
(setq arg (1- arg))
(setq cookie-last-tin
(dll-next cookies cookie-last-tin)))
(if (null (cookie-filter-hf cookie-last-tin))
(setq cookie-last-tin (dll-nth cookies -2)))
(goto-char
(cookie-tin-start-marker
(dll-element cookies cookie-last-tin)))
(if goal-column
(move-to-column goal-column))))
(defun cookie-collect-tins (buffer predicate &rest predicate-args)
"Return a list of all tins in BUFFER whose cookie PREDICATE
returns true for.
PREDICATE is a function that takes a cookie as its argument.
The tins on the returned list will appear in the same order
as in the buffer. You should not rely on in which order PREDICATE
is called. Note that BUFFER is current-buffer when PREDICATE
is called. (If you call cookie-collect with another buffer set
as current-buffer and need to access buffer-local variables
from that buffer within PREDICATE you must send them via
PREDICATE-ARGS).
If more than two arguments are given to cookie-collect the remaining
arguments will be passed to PREDICATE.
Use cookie-cookie to get the cookie from the tin."
(cookie-set-buffer buffer
(let ((tin (dll-nth cookies -2))
result)
(while (not (eq tin cookie-header))
(if (apply predicate
(cookie-tin-cookie (dll-element cookies tin))
predicate-args)
(setq result (cons tin result)))
(setq tin (dll-previous cookies tin)))
result)))
(defun cookie-collect-cookies (buffer predicate &rest predicate-args)
"Return a list of all cookies in BUFFER that PREDICATE
returns true for.
PREDICATE is a function that takes a cookie as its argument.
The cookie on the returned list will appear in the same order
as in the buffer. You should not rely on in which order PREDICATE
is called. Note that BUFFER is current-buffer when PREDICATE
is called. (If you call cookie-collect with another buffer set
as current-buffer and need to access buffer-local variables
from that buffer within PREDICATE you must send them via
PREDICATE-ARGS).
If more than two arguments are given to cookie-collect the remaining
arguments will be passed to PREDICATE."
(cookie-set-buffer buffer
(let ((tin (dll-nth cookies -2))
result)
(while (not (eq tin cookie-header))
(if (apply predicate
(cookie-tin-cookie (dll-element cookies tin))
predicate-args)
(setq result (cons (cookie-tin-cookie (dll-element cookies tin))
result)))
(setq tin (dll-previous cookies tin)))
result)))
@@ -0,0 +1,298 @@
;;; elib-dll-debug -- A slow implementation of elib-dll for debugging.
;;; elib-dll-debug.el,v 1.2 1992/04/07 20:49:13 berliner Exp
;;; Copyright (C) 1991,1992 Per Cederqvist
;;;
;;; This program is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2 of the License, or
;;; (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, write to the Free Software
;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;; This is a plug-in replacement for elib-dll.el. It is dreadfully
;;; slow, but it facilitates debugging. Don't trust the comments in
;;; this file too much.
(provide 'elib-dll)
;;;
;;; A doubly linked list consists of one cons cell which holds the tag
;;; 'DL-LIST in the car cell and the list in the cdr
;;; cell. The doubly linked list is implemented as a normal list. You
;;; should use elib-dll.el and not this package in debugged code. This
;;; package is not written for speed...
;;;
;;; ================================================================
;;; Internal functions for use in the doubly linked list package
(defun dll-get-dummy-node (dll)
;; Return the dummy node. INTERNAL USE ONLY.
dll)
(defun dll-list-nodes (dll)
;; Return a list of all nodes in DLL. INTERNAL USE ONLY.
(cdr dll))
(defun dll-set-from-node-list (dll list)
;; Set the contents of DLL to the nodes in LIST.
;; INTERNAL USE ONLY.
(setcdr dll list))
(defun dll-get-node-before (dll node)
;; Return the node in DLL that points to NODE. Use
;; (dll-get-node-before some-list nil) to get the last node.
;; INTERNAL USE ONLY.
(while (and dll (not (eq (cdr dll) node)))
(setq dll (cdr dll)))
(if (not dll)
(error "Node not on list"))
dll)
(defmacro dll-insert-after (node element)
(let ((node-v (make-symbol "node"))
(element-v (make-symbol "element")))
(` (let (((, node-v) (, node))
((, element-v) (, element)))
(setcdr (, node-v) (cons (, element-v) (cdr (, node-v))))))))
;;; ===================================================================
;;; The public functions which operate on doubly linked lists.
(defmacro dll-element (dll node)
"Get the element of a NODE in a doubly linked list DLL.
Args: DLL NODE."
(` (car (, node))))
(defun dll-create ()
"Create an empty doubly linked list."
(cons 'DL-LIST nil))
(defun dll-p (object)
"Return t if OBJECT is a doubly linked list, otherwise return nil."
(eq (car-safe object) 'DL-LIST))
(defun dll-enter-first (dll element)
"Add an element first on a doubly linked list.
Args: DLL ELEMENT."
(setcdr dll (cons element (cdr dll))))
(defun dll-enter-last (dll element)
"Add an element last on a doubly linked list.
Args: DLL ELEMENT."
(dll-insert-after (dll-get-node-before dll nil) element))
(defun dll-enter-after (dll node element)
"In the doubly linked list DLL, insert a node containing ELEMENT after NODE.
Args: DLL NODE ELEMENT."
(dll-get-node-before dll node)
(dll-insert-after node element))
(defun dll-enter-before (dll node element)
"In the doubly linked list DLL, insert a node containing ELEMENT before NODE.
Args: DLL NODE ELEMENT."
(dll-insert-after (dll-get-node-before dll node) element))
(defun dll-next (dll node)
"Return the node after NODE, or nil if NODE is the last node.
Args: DLL NODE."
(dll-get-node-before dll node)
(cdr node))
(defun dll-previous (dll node)
"Return the node before NODE, or nil if NODE is the first node.
Args: DLL NODE."
(dll-get-node-before dll node))
(defun dll-delete (dll node)
"Delete NODE from the doubly linked list DLL.
Args: DLL NODE. Return the element of node."
;; This is a no-op when applied to the dummy node. This will return
;; nil if applied to the dummy node since it always contains nil.
(setcdr (dll-get-node-before dll node) (cdr node)))
(defun dll-delete-first (dll)
"Delete the first NODE from the doubly linked list DLL.
Return the element. Args: DLL. Returns nil if the DLL was empty."
;; Relies on the fact that dll-delete does nothing and
;; returns nil if given the dummy node.
(setcdr dll (cdr (cdr dll))))
(defun dll-delete-last (dll)
"Delete the last NODE from the doubly linked list DLL.
Return the element. Args: DLL. Returns nil if the DLL was empty."
;; Relies on the fact that dll-delete does nothing and
;; returns nil if given the dummy node.
(setcdr dll (dll-get-node-before dll nil) nil))
(defun dll-first (dll)
"Return the first element on the doubly linked list DLL.
Return nil if the list is empty. The element is not removed."
(car (cdr dll)))
(defun dll-last (dll)
"Return the last element on the doubly linked list DLL.
Return nil if the list is empty. The element is not removed."
(car (dll-get-node-before dll nil)))
(defun dll-nth (dll n)
"Return the Nth node from the doubly linked list DLL.
Args: DLL N
N counts from zero. If DLL is not that long, nil is returned.
If N is negative, return the -(N+1)th last element.
Thus, (dll-nth dll 0) returns the first node,
and (dll-nth dll -1) returns the last node."
;; Branch 0 ("follow left pointer") is used when n is negative.
;; Branch 1 ("follow right pointer") is used otherwise.
(if (>= n 0)
(nthcdr n (cdr dll))
(unwind-protect
(progn (setcdr dll (nreverse (cdr dll)))
(nthcdr (- n) dll))
(setcdr dll (nreverse (cdr dll))))))
(defun dll-empty (dll)
"Return t if the doubly linked list DLL is empty, nil otherwise"
(not (cdr dll)))
(defun dll-length (dll)
"Returns the number of elements in the doubly linked list DLL."
(length (cdr dll)))
(defun dll-copy (dll &optional element-copy-fnc)
"Return a copy of the doubly linked list DLL.
If optional second argument ELEMENT-COPY-FNC is non-nil it should be
a function that takes one argument, an element, and returns a copy of it.
If ELEMENT-COPY-FNC is not given the elements are not copied."
(if element-copy-fnc
(cons 'DL-LIST (mapcar element-copy-fnc (cdr dll)))
(copy-sequence dll)))
(defun dll-all (dll)
"Return all elements on the double linked list DLL as an ordinary list."
(cdr dll))
(defun dll-clear (dll)
"Clear the doubly linked list DLL, i.e. make it completely empty."
(setcdr dll nil))
(defun dll-map (map-function dll)
"Apply MAP-FUNCTION to all elements in the doubly linked list DLL.
The function is applied to the first element first."
(mapcar map-function (cdr dll)))
(defun dll-map-reverse (map-function dll)
"Apply MAP-FUNCTION to all elements in the doubly linked list DLL.
The function is applied to the last element first."
(unwind-protect
(setcdr dll (nreverse (cdr dll)))
(mapcar map-function (cdr dll))
(setcdr dll (nreverse (cdr dll)))))
(defun dll-create-from-list (list)
"Given an elisp LIST create a doubly linked list with the same elements."
(cons 'DL-LIST list))
(defun dll-sort (dll predicate)
"Sort the doubly linked list DLL, stably, comparing elements using PREDICATE.
Returns the sorted list. DLL is modified by side effects.
PREDICATE is called with two elements of DLL, and should return T
if the first element is \"less\" than the second."
(setcdr dll (sort (cdr dll) predicate))
dll)
(defun dll-filter (dll predicate)
"Remove all elements in the doubly linked list DLL for which PREDICATE
return nil."
(let* ((prev dll)
(node (cdr dll)))
(while node
(cond
((funcall predicate (car node))
(setq prev node))
(t
(setcdr prev (cdr node))))
(setq node (cdr node)))))
+386
View File
@@ -0,0 +1,386 @@
;;; elib-dll.el,v 1.2 1992/04/07 20:49:15 berliner Exp
;;; elib-dll.el -- Some primitives for Doubly linked lists.
;;; Copyright (C) 1991, 1992 Per Cederqvist
;;;
;;; This program is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2 of the License, or
;;; (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, write to the Free Software
;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;; Mail bug reports to [email protected].
(require 'elib-node)
(provide 'elib-dll)
;;;
;;; A doubly linked list consists of one cons cell which holds the tag
;;; 'DL-LIST in the car cell and a pointer to a dummy node in the cdr
;;; cell. The doubly linked list is implemented as a circular list
;;; with the dummy node first and last. The dummy node is recognized
;;; by comparing it to the node which the cdr of the cons cell points
;;; to.
;;;
;;; ================================================================
;;; Internal functions for use in the doubly linked list package
(defun dll-get-dummy-node (dll)
;; Return the dummy node. INTERNAL USE ONLY.
(cdr dll))
(defun dll-list-nodes (dll)
;; Return a list of all nodes in DLL. INTERNAL USE ONLY.
(let* ((result nil)
(dummy (dll-get-dummy-node dll))
(node (elib-node-left dummy)))
(while (not (eq node dummy))
(setq result (cons node result))
(setq node (elib-node-left node)))
result))
(defun dll-set-from-node-list (dll list)
;; Set the contents of DLL to the nodes in LIST.
;; INTERNAL USE ONLY.
(dll-clear dll)
(let* ((dummy (dll-get-dummy-node dll))
(left dummy))
(while list
(elib-node-set-left (car list) left)
(elib-node-set-right left (car list))
(setq left (car list))
(setq list (cdr list)))
(elib-node-set-right left dummy)
(elib-node-set-left dummy left)))
;;; ===================================================================
;;; The public functions which operate on doubly linked lists.
(defmacro dll-element (dll node)
"Get the element of a NODE in a doubly linked list DLL.
Args: DLL NODE."
(` (elib-node-data (, node))))
(defun dll-create ()
"Create an empty doubly linked list."
(let ((dummy-node (elib-node-create nil nil nil)))
(elib-node-set-right dummy-node dummy-node)
(elib-node-set-left dummy-node dummy-node)
(cons 'DL-LIST dummy-node)))
(defun dll-p (object)
"Return t if OBJECT is a doubly linked list, otherwise return nil."
(eq (car-safe object) 'DL-LIST))
(defun dll-enter-first (dll element)
"Add an element first on a doubly linked list.
Args: DLL ELEMENT."
(dll-enter-after
dll
(dll-get-dummy-node dll)
element))
(defun dll-enter-last (dll element)
"Add an element last on a doubly linked list.
Args: DLL ELEMENT."
(dll-enter-before
dll
(dll-get-dummy-node dll)
element))
(defun dll-enter-after (dll node element)
"In the doubly linked list DLL, insert a node containing ELEMENT after NODE.
Args: DLL NODE ELEMENT."
(let ((new-node (elib-node-create
node (elib-node-right node)
element)))
(elib-node-set-left (elib-node-right node) new-node)
(elib-node-set-right node new-node)))
(defun dll-enter-before (dll node element)
"In the doubly linked list DLL, insert a node containing ELEMENT before NODE.
Args: DLL NODE ELEMENT."
(let ((new-node (elib-node-create
(elib-node-left node) node
element)))
(elib-node-set-right (elib-node-left node) new-node)
(elib-node-set-left node new-node)))
(defun dll-next (dll node)
"Return the node after NODE, or nil if NODE is the last node.
Args: DLL NODE."
(if (eq (elib-node-right node) (dll-get-dummy-node dll))
nil
(elib-node-right node)))
(defun dll-previous (dll node)
"Return the node before NODE, or nil if NODE is the first node.
Args: DLL NODE."
(if (eq (elib-node-left node) (dll-get-dummy-node dll))
nil
(elib-node-left node)))
(defun dll-delete (dll node)
"Delete NODE from the doubly linked list DLL.
Args: DLL NODE. Return the element of node."
;; This is a no-op when applied to the dummy node. This will return
;; nil if applied to the dummy node since it always contains nil.
(elib-node-set-right (elib-node-left node) (elib-node-right node))
(elib-node-set-left (elib-node-right node) (elib-node-left node))
(dll-element dll node))
(defun dll-delete-first (dll)
"Delete the first NODE from the doubly linked list DLL.
Return the element. Args: DLL. Returns nil if the DLL was empty."
;; Relies on the fact that dll-delete does nothing and
;; returns nil if given the dummy node.
(dll-delete dll (elib-node-right (dll-get-dummy-node dll))))
(defun dll-delete-last (dll)
"Delete the last NODE from the doubly linked list DLL.
Return the element. Args: DLL. Returns nil if the DLL was empty."
;; Relies on the fact that dll-delete does nothing and
;; returns nil if given the dummy node.
(dll-delete dll (elib-node-left (dll-get-dummy-node dll))))
(defun dll-first (dll)
"Return the first element on the doubly linked list DLL.
Return nil if the list is empty. The element is not removed."
(if (eq (elib-node-right (dll-get-dummy-node dll))
(dll-get-dummy-node dll))
nil
(elib-node-data (elib-node-right (dll-get-dummy-node dll)))))
(defun dll-last (dll)
"Return the last element on the doubly linked list DLL.
Return nil if the list is empty. The element is not removed."
(if (eq (elib-node-left (dll-get-dummy-node dll))
(dll-get-dummy-node dll))
nil
(elib-node-data (elib-node-left (dll-get-dummy-node dll)))))
(defun dll-nth (dll n)
"Return the Nth node from the doubly linked list DLL.
Args: DLL N
N counts from zero. If DLL is not that long, nil is returned.
If N is negative, return the -(N+1)th last element.
Thus, (dll-nth dll 0) returns the first node,
and (dll-nth dll -1) returns the last node."
;; Branch 0 ("follow left pointer") is used when n is negative.
;; Branch 1 ("follow right pointer") is used otherwise.
(let* ((dummy (dll-get-dummy-node dll))
(branch (if (< n 0) 0 1))
(node (elib-node-branch dummy branch)))
(if (< n 0)
(setq n (- -1 n)))
(while (and (not (eq dummy node))
(> n 0))
(setq node (elib-node-branch node branch))
(setq n (1- n)))
(if (eq dummy node)
nil
node)))
(defun dll-empty (dll)
"Return t if the doubly linked list DLL is empty, nil otherwise"
(eq (elib-node-left (dll-get-dummy-node dll))
(dll-get-dummy-node dll)))
(defun dll-length (dll)
"Returns the number of elements in the doubly linked list DLL."
(let* ((dummy (dll-get-dummy-node dll))
(node (elib-node-right dummy))
(n 0))
(while (not (eq node dummy))
(setq node (elib-node-right node))
(setq n (1+ n)))
n))
(defun dll-copy (dll &optional element-copy-fnc)
"Return a copy of the doubly linked list DLL.
If optional second argument ELEMENT-COPY-FNC is non-nil it should be
a function that takes one argument, an element, and returns a copy of it.
If ELEMENT-COPY-FNC is not given the elements are not copied."
(let ((result (dll-create))
(node (dll-nth dll 0)))
(if element-copy-fnc
;; Copy the elements with the user-supplied function.
(while node
(dll-enter-last result
(funcall element-copy-fnc
(dll-element dll node)))
(setq node (dll-next dll node)))
;; Don't try to copy the elements - they might be
;; circular lists, or anything at all...
(while node
(dll-enter-last result (dll-element dll node))
(setq node (dll-next dll node))))
result))
(defun dll-all (dll)
"Return all elements on the double linked list DLL as an ordinary list."
(let* ((result nil)
(dummy (dll-get-dummy-node dll))
(node (elib-node-left dummy)))
(while (not (eq node dummy))
(setq result (cons (dll-element dll node) result))
(setq node (elib-node-left node)))
result))
(defun dll-clear (dll)
"Clear the doubly linked list DLL, i.e. make it completely empty."
(elib-node-set-left (dll-get-dummy-node dll) (dll-get-dummy-node dll))
(elib-node-set-right (dll-get-dummy-node dll) (dll-get-dummy-node dll)))
(defun dll-map (map-function dll)
"Apply MAP-FUNCTION to all elements in the doubly linked list DLL.
The function is applied to the first element first."
(let* ((dummy (dll-get-dummy-node dll))
(node (elib-node-right dummy)))
(while (not (eq node dummy))
(funcall map-function (dll-element dll node))
(setq node (elib-node-right node)))))
(defun dll-map-reverse (map-function dll)
"Apply MAP-FUNCTION to all elements in the doubly linked list DLL.
The function is applied to the last element first."
(let* ((dummy (dll-get-dummy-node dll))
(node (elib-node-left dummy)))
(while (not (eq node dummy))
(funcall map-function (dll-element dll node))
(setq node (elib-node-left node)))))
(defun dll-create-from-list (list)
"Given an elisp LIST create a doubly linked list with the same elements."
(let ((dll (dll-create)))
(while list
(dll-enter-last dll (car list))
(setq list (cdr list)))
dll))
(defun dll-sort (dll predicate)
"Sort the doubly linked list DLL, stably, comparing elements using PREDICATE.
Returns the sorted list. DLL is modified by side effects.
PREDICATE is called with two elements of DLL, and should return T
if the first element is \"less\" than the second."
(dll-set-from-node-list
dll (sort (dll-list-nodes dll)
(function (lambda (x1 x2)
(funcall predicate
(dll-element dll x1)
(dll-element dll x2))))))
dll)
(defun dll-filter (dll predicate)
"Remove all elements in the doubly linked list DLL for which PREDICATE
return nil."
(let* ((dummy (dll-get-dummy-node dll))
(node (elib-node-right dummy))
next)
(while (not (eq node dummy))
(setq next (elib-node-right node))
(if (funcall predicate (dll-element dll node))
nil
(dll-delete dll node))
(setq node next))))
@@ -0,0 +1,89 @@
;;;; elib-node.el,v 1.2 1992/04/07 20:49:16 berliner Exp
;;;; This file implements the nodes used in binary trees and
;;;; doubly linked lists
;;;;
;;;; Copyright (C) 1991 Inge Wallin
;;;;
;;;; This file is part of the GNU Emacs lisp library, Elib.
;;;;
;;;; GNU Elib 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 1, or (at your option)
;;;; any later version.
;;;;
;;;; GNU Elib 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 GNU Emacs; see the file COPYING. If not, write to
;;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
;;;;
;;;; Author: Inge Wallin
;;;;
;;;
;;; A node is implemented as an array with three elements, using
;;; (elt node 0) as the left pointer
;;; (elt node 1) as the right pointer
;;; (elt node 2) as the data
;;;
;;; Some types of trees, e.g. AVL trees, need bigger nodes, but
;;; as long as the first three parts are the left pointer, the
;;; right pointer and the data field, these macros can be used.
;;;
(provide 'elib-node)
(defmacro elib-node-create (left right data)
"Create a tree node from LEFT, RIGHT and DATA."
(` (vector (, left) (, right) (, data))))
(defmacro elib-node-left (node)
"Return the left pointer of NODE."
(` (aref (, node) 0)))
(defmacro elib-node-right (node)
"Return the right pointer of NODE."
(` (aref (, node) 1)))
(defmacro elib-node-data (node)
"Return the data of NODE."
(` (aref (, node) 2)))
(defmacro elib-node-set-left (node newleft)
"Set the left pointer of NODE to NEWLEFT."
(` (aset (, node) 0 (, newleft))))
(defmacro elib-node-set-right (node newright)
"Set the right pointer of NODE to NEWRIGHT."
(` (aset (, node) 1 (, newright))))
(defmacro elib-node-set-data (node newdata)
"Set the data of NODE to NEWDATA."
(` (aset (, node) 2 (, newdata))))
(defmacro elib-node-branch (node branch)
"Get value of a branch of a node.
NODE is the node, and BRANCH is the branch.
0 for left pointer, 1 for right pointer and 2 for the data."
(` (aref (, node) (, branch))))
(defmacro elib-node-set-branch (node branch newval)
"Set value of a branch of a node.
NODE is the node, and BRANCH is the branch.
0 for left pointer, 1 for the right pointer and 2 for the data.
NEWVAL is new value of the branch."
(` (aset (, node) (, branch) (, newval))))
+184
View File
@@ -0,0 +1,184 @@
#!/bin/sh
#
# $Id: rcs-to-cvs,v 1.4 1994/09/21 07:23:16 berliner Exp $
# Based on the CVS 1.0 checkin csh script.
# Contributed by Per Cederqvist <[email protected]>.
# Rewritten in sh by David MacKenzie <[email protected]>.
#
# Copyright (c) 1989, Brian Berliner
#
# You may distribute under the terms of the GNU General Public License.
#
#############################################################################
#
# Check in sources that previously were under RCS or no source control system.
#
# The repository is the directory where the sources should be deposited.
#
# Traverses the current directory, ensuring that an
# identical directory structure exists in the repository directory. It
# then checks the files in in the following manner:
#
# 1) If the file doesn't yet exist, check it in as revision 1.1
#
# The script also is somewhat verbose in letting the user know what is
# going on. It prints a diagnostic when it creates a new file, or updates
# a file that has been modified on the trunk.
#
# Bugs: doesn't put the files in branch 1.1.1
# doesn't put in release and vendor tags
#
#############################################################################
usage="Usage: rcs-to-cvs [-v] [-m message] [-f message_file] repository"
vbose=0
message=""
message_file=/usr/tmp/checkin.$$
got_one=0
if [ $# -lt 1 ]; then
echo "$usage" >&2
exit 1
fi
while [ $# -ne 0 ]; do
case "$1" in
-v)
vbose=1
;;
-m)
shift
echo $1 > $message_file
got_one=1
;;
-f)
shift
message_file=$1
got_one=2
;;
*)
break
esac
shift
done
if [ $# -lt 1 ]; then
echo "$usage" >&2
exit 1
fi
repository=$1
shift
if [ -z "$CVSROOT" ]; then
echo "Please the environmental variable CVSROOT to the root" >&2
echo " of the tree you wish to update" >&2
exit 1
fi
if [ $got_one -eq 0 ]; then
echo "Please Edit this file to contain the RCS log information" >$message_file
echo "to be associated with this directory (please remove these lines)">>$message_file
${EDITOR-/usr/ucb/vi} $message_file
got_one=1
fi
umask 22
update_dir=${CVSROOT}/${repository}
[ ! -d ${update_dir} ] && mkdir $update_dir
if [ -d SCCS ]; then
echo SCCS files detected! >&2
exit 1
fi
if [ -d RCS ]; then
co RCS/*
fi
for name in * .[a-zA-Z0-9]*
do
case "$name" in
RCS | \* | .\[a-zA-Z0-9\]\* ) continue ;;
esac
echo $name
if [ $vbose -ne 0 ]; then
echo "Updating ${repository}/${name}"
fi
if [ -d "$name" ]; then
if [ ! -d "${update_dir}/${name}" ]; then
echo "WARNING: Creating new directory ${repository}/${name}"
mkdir "${update_dir}/${name}"
if [ $? -ne 0 ]; then
echo "ERROR: mkdir failed - aborting" >&2
exit 1
fi
fi
cd "$name"
if [ $? -ne 0 ]; then
echo "ERROR: Couldn\'t cd to $name - aborting" >&2
exit 1
fi
if [ $vbose -ne 0 ]; then
$0 -v -f $message_file "${repository}/${name}"
else
$0 -f $message_file "${repository}/${name}"
fi
if [ $? -ne 0 ]; then
exit 1
fi
cd ..
else # if not directory
if [ ! -f "$name" ]; then
echo "WARNING: $name is neither a regular file"
echo " nor a directory - ignored"
continue
fi
file="${update_dir}/${name},v"
comment=""
if grep -s '\$Log.*\$' "${name}"; then # If $Log keyword
myext=`echo $name | sed 's,.*\.,,'`
[ "$myext" = "$name" ] && myext=
case "$myext" in
c | csh | e | f | h | l | mac | me | mm | ms | p | r | red | s | sh | sl | cl | ml | el | tex | y | ye | yr | "" )
;;
* )
echo "For file ${file}:"
grep '\$Log.*\$' "${name}"
echo -n "Please insert a comment leader for file ${name} > "
read comment
;;
esac
fi
if [ ! -f "$file" ]; then # If not exists in repository
if [ ! -f "${update_dir}/Attic/${name},v" ]; then
echo "WARNING: Creating new file ${repository}/${name}"
if [ -f RCS/"${name}",v ]; then
echo "MSG: Copying old rcs file."
cp RCS/"${name}",v "$file"
else
if [ -n "${comment}" ]; then
rcs -q -i -c"${comment}" -t${message_file} -m'.' "$file"
fi
ci -q -u1.1 -t${message_file} -m'.' "$file"
if [ $? -ne 0 ]; then
echo "ERROR: Initial check-in of $file failed - aborting" >&2
exit 1
fi
fi
else
file="${update_dir}/Attic/${name},v"
echo "WARNING: IGNORED: ${repository}/Attic/${name}"
continue
fi
else # File existed
echo "ERROR: File exists in repository: Ignored: $file"
continue
fi
fi
done
[ $got_one -eq 1 ] && rm -f $message_file
exit 0
+326
View File
@@ -0,0 +1,326 @@
#!/bin/sh
# RCS to ChangeLog generator
# Generate a change log prefix from RCS/* and the existing ChangeLog (if any).
# Output the new prefix to standard output.
# You can edit this prefix by hand, and then prepend it to ChangeLog.
# Ignore log entries that start with `#'.
# Clump together log entries that start with `{topic} ',
# where `topic' contains neither white space nor `}'.
# Author: Paul Eggert <[email protected]>
# OrigId: rcs2log,v 1.9 1993/01/15 05:33:29 eggert Exp
# Copyright 1992, 1993 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
# Parse options.
# defaults
indent=8 # indent of log line
length=79 # suggested max width of log line
tabwidth=8 # width of horizontal tab
while :
do
case $1 in
-i) indent=${2?};;
-l) length=${2?};;
-t) tabwidth=${2?};;
-*) echo >&2 "$0: usage: $0 [-i indent] [-l length] [-t tabwidth] [file ...]"
exit 1;;
*) break
esac
shift; shift
done
# Log into $rlogout the revisions checked in since the first ChangeLog entry.
date=1970
if test -s ChangeLog
then
# Add 1 to seconds to avoid duplicating most recent log.
# It's a good thing `rlog' doesn't mind a time ending in `:60'.
e='
/^... ... [ 0-9][0-9] [ 0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9]+ /{
printf "%s%02d %s\n", substr($0,1,17), substr($0,18,2)+1, $5
exit
}
'
d=`awk "$e" <ChangeLog` || exit
case $d in
?*) date=$d
esac
fi
datearg="-d>$date"
rlogout=/tmp/chg$$
trap exit 1 2 13 15
trap 'rm -f $rlogout; exit 1' 0
case $# in
0) set RCS/*
esac
rlog "$datearg" "$@" >$rlogout || exit
# Get the full name of each author the logs mention, and set initialize_fullname
# to awk code that initializes the `fullname' awk associative array.
# Warning: foreign authors (i.e. not known in the passwd file) are mishandled;
# you have to fix the resulting output by hand.
initialize_fullname=
authors=`
sed -n 's|^date: *[0-9]*/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]; *author: *\([^; ]*\).*|\1|p' <$rlogout |
sort -u
`
case $authors in
?*)
initialize_author=
for author in $authors
do
initialize_author="$initialize_author
author[\"$author\"] = 1
"
done
awkscript='
BEGIN {
alphabet = "abcdefghijklmnopqrstuvwxyz"
ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
'"$initialize_author"'
}
{
if (author[$1]) {
fullname = $5
abbr = index(fullname, "&")
if (abbr) {
a = substr($1, 1, 1)
A = a
i = index(alphabet, a)
if (i) A = substr(ALPHABET, i, 1)
fullname = substr(fullname, 1, abbr-1) A substr($1, 2) substr(fullname, abbr+1)
}
printf "fullname[\"%s\"] = \"%s\"\n", $1, fullname
author[$1] = 0
}
}
'
initialize_fullname=`
(cat /etc/passwd; ypmatch $authors passwd) 2>/dev/null |
awk -F: "$awkscript"
`
esac
# Function to print a single log line.
# We don't use awk functions, to stay compatible with old awk versions.
# `Log' is the log message (with \n replaced by \r).
# `files' contains the affected files.
printlogline='{
# Following the GNU coding standards, rewrite
# * file: (function): comment
# to
# * file (function): comment
if (Log ~ /^\([^)]*\): /) {
i = index(Log, ")")
files = files " " substr(Log, 1, i)
Log = substr(Log, i+3)
}
# If "label: comment" is too long, break the line after the ":".
sep = " "
if ('"$length"' <= '"$indent"' + 1 + length(files) + index(Log, "\r")) sep = "\n" indent_string
# Print the label.
printf "%s*%s:", indent_string, files
# Print each line of the log, transliterating \r to \n.
while ((i = index(Log, "\r")) != 0) {
printf "%s%s\n", sep, substr(Log, 1, i-1)
sep = indent_string
Log = substr(Log, i+1)
}
}'
hostname=`(
hostname || cat /etc/whoami || uuname -l || uname -n
) 2>/dev/null` || {
echo >&2 "$0: cannot deduce hostname"
exit 1
}
# Process the rlog output, generating ChangeLog style entries.
# First, reformat the rlog output so that each line contains one log entry.
# Transliterate \n to \r so that multiline entries fit on a single line.
# Discard irrelevant rlog output.
awk <$rlogout '
/^Working file:/ { filename = $3 }
/^date: /, /^(-----------*|===========*)$/ {
if ($0 ~ /^branches: /) { next }
if ($0 ~ /^date: [0-9][ /0-9:]*;/) {
time = substr($3, 1, length($3)-1)
author = substr($5, 1, length($5)-1)
printf "%s %s %s %s \r", filename, $2, time, author
next
}
if ($0 ~ /^(-----------*|===========*)$/) { print ""; next }
printf "%s\r", $0
}
' |
# Now each line is of the form
# FILENAME YYYY/MM/DD HH:MM:SS AUTHOR \rLOG
# where \r stands for a carriage return,
# and each line of the log is terminated by \r instead of \n.
# Sort the log entries, first by date+time (in reverse order),
# then by author, then by log entry, and finally by file name (just in case).
sort +1 -3r +3 +0 |
# Finally, reformat the sorted log entries.
awk '
BEGIN {
# Initialize the fullname associative array.
'"$initialize_fullname"'
# Initialize indent string.
indent_string = ""
i = '"$indent"'
if (0 < '"$tabwidth"')
for (; '"$tabwidth"' <= i; i -= '"$tabwidth"')
indent_string = indent_string "\t"
while (1 <= i--)
indent_string = indent_string " "
# Set up date conversion tables.
# RCS uses a nice, clean, sortable format,
# but ChangeLog wants the traditional, ugly ctime format.
# January 1, 0 AD (Gregorian) was Saturday = 6
EPOCH_WEEKDAY = 6
# Of course, there was no 0 AD, but the algorithm works anyway.
w[0]="Sun"; w[1]="Mon"; w[2]="Tue"; w[3]="Wed"
w[4]="Thu"; w[5]="Fri"; w[6]="Sat"
m[0]="Jan"; m[1]="Feb"; m[2]="Mar"
m[3]="Apr"; m[4]="May"; m[5]="Jun"
m[6]="Jul"; m[7]="Aug"; m[8]="Sep"
m[9]="Oct"; m[10]="Nov"; m[11]="Dec"
# days in non-leap year thus far, indexed by month (0-12)
mo[0]=0; mo[1]=31; mo[2]=59; mo[3]=90
mo[4]=120; mo[5]=151; mo[6]=181; mo[7]=212
mo[8]=243; mo[9]=273; mo[10]=304; mo[11]=334
mo[12]=365
}
{
newlog = substr($0, 1 + index($0, "\r"))
# Ignore log entries prefixed by "#".
if (newlog ~ /^#/) { next }
if (Log != newlog || date != $2 || author != $4) {
# The previous log and this log differ.
# Print the old log.
if (date != "") '"$printlogline"'
# Logs that begin with "{clumpname} " should be grouped together,
# and the clumpname should be removed.
# Extract the new clumpname from the log header,
# and use it to decide whether to output a blank line.
newclumpname = ""
sep = "\n"
if (date == "") sep = ""
if (newlog ~ /^{[^ }]*}[ ]/) {
i = index(newlog, "}")
newclumpname = substr(newlog, 1, i)
while (substr(newlog, i+1) ~ /^[ ]/) i++
newlog = substr(newlog, i+1)
if (clumpname == newclumpname) sep = ""
}
printf sep
clumpname = newclumpname
# Get ready for the next log.
Log = newlog
if (files != "")
for (i in filesknown)
filesknown[i] = 0
files = ""
}
if (date != $2 || author != $4) {
# The previous date+author and this date+author differ.
# Print the new one.
date = $2
author = $4
# Convert nice RCS date like "1992/01/03 00:03:44"
# into ugly ctime date like "Fri Jan 3 00:03:44 1992".
# Calculate day of week from Gregorian calendar.
i = index($2, "/")
year = substr($2, 1, i-1) + 0
monthday = substr($2, i+1)
i = index(monthday, "/")
month = substr(monthday, 1, i-1) + 0
day = substr(monthday, i+1) + 0
leap = 0
if (2 < month && year%4 == 0 && (year%100 != 0 || year%400 == 0)) leap = 1
days_since_Sunday_before_epoch = EPOCH_WEEKDAY + year * 365 + int((year + 3) / 4) - int((year + 99) / 100) + int((year + 399) / 400) + mo[month-1] + leap + day - 1
# Print "date fullname (email address)" if the fullname is known;
# print "date author" otherwise.
# Get the fullname from the associative array.
# The email address is just author@thishostname.
printf "%s %s %2d %s %d ", w[days_since_Sunday_before_epoch%7], m[month-1], day, $3, year
if (fullname[author])
printf "%s (%s@%s)\n\n", fullname[author], author, "'"$hostname"'"
else
printf "%s\n\n", author
}
if (! filesknown[$1]) {
filesknown[$1] = 1
if (files == "") files = " " $1
else files = files ", " $1
}
}
END {
# Print the last log.
if (date != "") {
'"$printlogline"'
printf "\n"
}
}
' &&
# Exit successfully.
exec rm -f $rlogout
+143
View File
@@ -0,0 +1,143 @@
#!/bin/sh
#
#
# OrigId: rcs2sccs,v 1.12 90/10/04 20:52:23 kenc Exp Locker: kenc
# $Id: rcs2sccs,v 1.1 1993/12/06 06:37:14 berliner Exp $
############################################################
# Error checking
#
if [ ! -d SCCS ] ; then
mkdir SCCS
fi
logfile=/tmp/rcs2sccs_$$_log
rm -f $logfile
tmpfile=/tmp/rcs2sccs_$$_tmp
rm -f $tmpfile
emptyfile=/tmp/rcs2sccs_$$_empty
echo -n "" > $emptyfile
initialfile=/tmp/rcs2sccs_$$_init
echo "Initial revision" > $initialfile
sedfile=/tmp/rcs2sccs_$$_sed
rm -f $sedfile
revfile=/tmp/rcs2sccs_$$_rev
rm -f $revfile
commentfile=/tmp/rcs2sccs_$$_comment
rm -f $commentfile
# create the sed script
cat > $sedfile << EOF
s,;Id;,%Z%%M% %I% %E%,g
s,;SunId;,%Z%%M% %I% %E%,g
s,;RCSfile;,%M%,g
s,;Revision;,%I%,g
s,;Date;,%E%,g
s,;Id:.*;,%Z%%M% %I% %E%,g
s,;SunId:.*;,%Z%%M% %I% %E%,g
s,;RCSfile:.*;,%M%,g
s,;Revision:.*;,%I%,g
s,;Date:.*;,%E%,g
EOF
sed -e 's/;/\\$/g' $sedfile > $tmpfile
cp $tmpfile $sedfile
############################################################
# Loop over every RCS file in RCS dir
#
for vfile in *,v; do
# get rid of the ",v" at the end of the name
file=`echo $vfile | sed -e 's/,v$//'`
# work on each rev of that file in ascending order
firsttime=1
rlog $file | grep "^revision [0-9][0-9]*\." | awk '{print $2}' | sed -e 's/\./ /g' | sort -n -u +0 +1 +2 +3 +4 +5 +6 +7 +8 | sed -e 's/ /./g' > $revfile
for rev in `cat $revfile`; do
if [ $? != 0 ]; then
echo ERROR - revision
exit
fi
# get file into current dir and get stats
date=`rlog -r$rev $file | grep "^date: " | awk '{print $2; exit}' | sed -e 's/^19//'`
time=`rlog -r$rev $file | grep "^date: " | awk '{print $3; exit}' | sed -e 's/;//'`
author=`rlog -r$rev $file | grep "^date: " | awk '{print $5; exit}' | sed -e 's/;//'`
date="$date $time"
echo ""
rlog -r$rev $file | sed -e '/^branches: /d' -e '1,/^date: /d' -e '/^===========/d' -e 's/$/\\/' | awk '{if ((total += length($0) + 1) < 510) print $0}' > $commentfile
echo "==> file $file, rev=$rev, date=$date, author=$author"
rm -f $file
co -r$rev $file >> $logfile 2>&1
if [ $? != 0 ]; then
echo ERROR - co
exit
fi
echo checked out of RCS
# add SCCS keywords in place of RCS keywords
sed -f $sedfile $file > $tmpfile
if [ $? != 0 ]; then
echo ERROR - sed
exit
fi
echo performed keyword substitutions
rm -f $file
cp $tmpfile $file
# check file into SCCS
if [ "$firsttime" = "1" ]; then
firsttime=0
echo about to do sccs admin
echo sccs admin -n -i$file $file < $commentfile
sccs admin -n -i$file $file < $commentfile >> $logfile 2>&1
if [ $? != 0 ]; then
echo ERROR - sccs admin
exit
fi
echo initial rev checked into SCCS
else
case $rev in
*.*.*.*)
brev=`echo $rev | sed -e 's/\.[0-9]*$//'`
sccs admin -fb $file 2>>$logfile
echo sccs get -e -p -r$brev $file
sccs get -e -p -r$brev $file >/dev/null 2>>$logfile
;;
*)
echo sccs get -e -p $file
sccs get -e -p $file >/dev/null 2>> $logfile
;;
esac
if [ $? != 0 ]; then
echo ERROR - sccs get
exit
fi
sccs delta $file < $commentfile >> $logfile 2>&1
if [ $? != 0 ]; then
echo ERROR - sccs delta -r$rev $file
exit
fi
echo checked into SCCS
fi
sed -e "s;^d D $rev ../../.. ..:..:.. [^ ][^ ]*;d D $rev $date $author;" SCCS/s.$file > $tmpfile
rm -f SCCS/s.$file
cp $tmpfile SCCS/s.$file
chmod 444 SCCS/s.$file
sccs admin -z $file
if [ $? != 0 ]; then
echo ERROR - sccs admin -z
exit
fi
done
rm -f $file
done
############################################################
# Clean up
#
echo cleaning up...
rm -f $tmpfile $emptyfile $initialfile $sedfile $commentfile
echo ===================================================
echo " Conversion Completed Successfully"
echo ===================================================
rm -f *,v
+277
View File
@@ -0,0 +1,277 @@
#!/bin/csh -f
#
# Sccs2rcs is a script to convert an existing SCCS
# history into an RCS history without losing any of
# the information contained therein.
# It has been tested under the following OS's:
# SunOS 3.5, 4.0.3, 4.1
# Ultrix-32 2.0, 3.1
#
# Things to note:
# + It will NOT delete or alter your ./SCCS history under any circumstances.
#
# + Run in a directory where ./SCCS exists and where you can
# create ./RCS
#
# + /usr/local/bin is put in front of the default path.
# (SCCS under Ultrix is set-uid sccs, bad bad bad, so
# /usr/local/bin/sccs here fixes that)
#
# + Date, time, author, comments, branches, are all preserved.
#
# + If a command fails somewhere in the middle, it bombs with
# a message -- remove what it's done so far and try again.
# "rm -rf RCS; sccs unedit `sccs tell`; sccs clean"
# There is no recovery and exit is far from graceful.
# If a particular module is hanging you up, consider
# doing it separately; move it from the current area so that
# the next run will have a better chance or working.
# Also (for the brave only) you might consider hacking
# the s-file for simpler problems: I've successfully changed
# the date of a delta to be in sync, then run "sccs admin -z"
# on the thing.
#
# + After everything finishes, ./SCCS will be moved to ./old-SCCS.
#
# This file may be copied, processed, hacked, mutilated, and
# even destroyed as long as you don't tell anyone you wrote it.
#
# Ken Cox
# Viewlogic Systems, Inc.
# [email protected]
# ...!harvard!cg-atla!viewlog!kenstir
#
# Various hacks made by Brian Berliner before inclusion in CVS contrib area.
#
# $Id: sccs2rcs,v 1.1 1992/04/10 03:04:26 berliner Exp $
#we'll assume the user set up the path correctly
# for the Pmax, /usr/ucb/sccs is suid sccs, what a pain
# /usr/local/bin/sccs should override /usr/ucb/sccs there
set path = (/usr/local/bin $path)
############################################################
# Error checking
#
if (! -w .) then
echo "Error: ./ not writeable by you."
exit 1
endif
if (! -d SCCS) then
echo "Error: ./SCCS directory not found."
exit 1
endif
set edits = (`sccs tell`)
if ($#edits) then
echo "Error: $#edits file(s) out for edit...clean up before converting."
exit 1
endif
if (-d RCS) then
echo "Warning: RCS directory exists"
if (`ls -a RCS | wc -l` > 2) then
echo "Error: RCS directory not empty
exit 1
endif
else
mkdir RCS
endif
sccs clean
set logfile = /tmp/sccs2rcs_$$_log
rm -f $logfile
set tmpfile = /tmp/sccs2rcs_$$_tmp
rm -f $tmpfile
set emptyfile = /tmp/sccs2rcs_$$_empty
echo -n "" > $emptyfile
set initialfile = /tmp/sccs2rcs_$$_init
echo "Initial revision" > $initialfile
set sedfile = /tmp/sccs2rcs_$$_sed
rm -f $sedfile
set revfile = /tmp/sccs2rcs_$$_rev
rm -f $revfile
# the quotes surround the dollar signs to fool RCS when I check in this script
set sccs_keywords = (\
'%W%[ ]*%G%'\
'%W%[ ]*%E%'\
'%W%'\
'%Z%%M%[ ]*%I%[ ]*%G%'\
'%Z%%M%[ ]*%I%[ ]*%E%'\
'%M%[ ]*%I%[ ]*%G%'\
'%M%[ ]*%I%[ ]*%E%'\
'%M%'\
'%I%'\
'%G%'\
'%E%'\
'%U%')
set rcs_keywords = (\
'$'Id'$'\
'$'Id'$'\
'$'Id'$'\
'$'SunId'$'\
'$'SunId'$'\
'$'Id'$'\
'$'Id'$'\
'$'RCSfile'$'\
'$'Revision'$'\
'$'Date'$'\
'$'Date'$'\
'')
############################################################
# Get some answers from user
#
echo ""
echo "Do you want to be prompted for a description of each"
echo "file as it is checked in to RCS initially?"
echo -n "(y=prompt for description, n=null description) [y] ?"
set ans = $<
if ((_$ans == _) || (_$ans == _y) || (_$ans == _Y)) then
set nodesc = 0
else
set nodesc = 1
endif
echo ""
echo "The default keyword substitutions are as follows and are"
echo "applied in the order specified:"
set i = 1
while ($i <= $#sccs_keywords)
# echo ' '\"$sccs_keywords[$i]\"' ==> '\"$rcs_keywords[$i]\"
echo " $sccs_keywords[$i] ==> $rcs_keywords[$i]"
@ i = $i + 1
end
echo ""
echo -n "Do you want to change them [n] ?"
set ans = $<
if ((_$ans != _) && (_$ans != _n) && (_$ans != _N)) then
echo "You can't always get what you want."
echo "Edit this script file and change the variables:"
echo ' $sccs_keywords'
echo ' $rcs_keywords'
else
echo "good idea."
endif
# create the sed script
set i = 1
while ($i <= $#sccs_keywords)
echo "s,$sccs_keywords[$i],$rcs_keywords[$i],g" >> $sedfile
@ i = $i + 1
end
onintr ERROR
############################################################
# Loop over every s-file in SCCS dir
#
foreach sfile (SCCS/s.*)
# get rid of the "s." at the beginning of the name
set file = `echo $sfile:t | sed -e "s/^..//"`
# work on each rev of that file in ascending order
set firsttime = 1
sccs prs $file | grep "^D " | awk '{print $2}' | sed -e 's/\./ /g' | sort -n -u +0 +1 +2 +3 +4 +5 +6 +7 +8 | sed -e 's/ /./g' > $revfile
foreach rev (`cat $revfile`)
if ($status != 0) goto ERROR
# get file into current dir and get stats
set date = `sccs prs -r$rev $file | grep "^D " | awk '{printf("19%s %s", $3, $4); exit}'`
set author = `sccs prs -r$rev $file | grep "^D " | awk '{print $5; exit}'`
echo ""
echo "==> file $file, rev=$rev, date=$date, author=$author"
sccs edit -r$rev $file >>& $logfile
if ($status != 0) goto ERROR
echo checked out of SCCS
# add RCS keywords in place of SCCS keywords
sed -f $sedfile $file > $tmpfile
if ($status != 0) goto ERROR
echo performed keyword substitutions
cp $tmpfile $file
# check file into RCS
if ($firsttime) then
set firsttime = 0
if ($nodesc) then
echo about to do ci
echo ci -f -r$rev -d"$date" -w$author -t$emptyfile $file
ci -f -r$rev -d"$date" -w$author -t$emptyfile $file < $initialfile >>& $logfile
if ($status != 0) goto ERROR
echo initial rev checked into RCS without description
else
echo ""
echo Enter a brief description of the file $file \(end w/ Ctrl-D\):
cat > $tmpfile
ci -f -r$rev -d"$date" -w$author -t$tmpfile $file < $initialfile >>& $logfile
if ($status != 0) goto ERROR
echo initial rev checked into RCS
endif
else
# get RCS lock
set lckrev = `echo $rev | sed -e 's/\.[0-9]*$//'`
if ("$lckrev" =~ [0-9]*.*) then
# need to lock the brach -- it is OK if the lock fails
rcs -l$lckrev $file >>& $logfile
else
# need to lock the trunk -- must succeed
rcs -l $file >>& $logfile
if ($status != 0) goto ERROR
endif
echo got lock
sccs prs -r$rev $file | grep "." > $tmpfile
# it's OK if grep fails here and gives status == 1
# put the delta message in $tmpfile
ed $tmpfile >>& $logfile <<EOF
/COMMENTS
1,.d
w
q
EOF
ci -f -r$rev -d"$date" -w$author $file < $tmpfile >>& $logfile
if ($status != 0) goto ERROR
echo checked into RCS
endif
sccs unedit $file >>& $logfile
if ($status != 0) goto ERROR
end
rm -f $file
end
############################################################
# Clean up
#
echo cleaning up...
mv SCCS old-SCCS
rm -f $tmpfile $emptyfile $initialfile $sedfile
echo ===================================================
echo " Conversion Completed Successfully"
echo ""
echo " SCCS history now in old-SCCS/"
echo ===================================================
set exitval = 0
goto cleanup
ERROR:
foreach f (`sccs tell`)
sccs unedit $f
end
echo ""
echo ""
echo Danger\! Danger\!
echo Some command exited with a non-zero exit status.
echo Log file exists in $logfile.
echo ""
echo Incomplete history in ./RCS -- remove it
echo Original unchanged history in ./SCCS
set exitval = 1
cleanup:
# leave log file
rm -f $tmpfile $emptyfile $initialfile $sedfile $revfile
exit $exitval
+533
View File
@@ -0,0 +1,533 @@
#!/bin/sh
# Submit a problem report to a GNATS site.
# Copyright (C) 1993 Free Software Foundation, Inc.
# Contributed by Brendan Kehoe ([email protected]), based on a
# version written by Heinz G. Seidl ([email protected]).
#
# This file is part of GNU GNATS.
# Modified by Berliner for CVS.
# $CVSid: @(#)cvsbug.sh 1.2 94/10/22 $
#
# GNU GNATS 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.
#
# GNU GNATS 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 GNU GNATS; see the file COPYING. If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
# The version of this send-pr.
VERSION=3.2
# The submitter-id for your site.
SUBMITTER=net
## # Where the GNATS directory lives, if at all.
## [ -z "$GNATS_ROOT" ] &&
## GNATS_ROOT=/usr/local/lib/gnats/gnats-db
# The default mail address for PR submissions.
GNATS_ADDR=[email protected]
## # Where the gnats category tree lives.
## DATADIR=/usr/local/lib
## # If we've been moved around, try using GCC_EXEC_PREFIX.
## [ ! -d $DATADIR/gnats -a -d "$GCC_EXEC_PREFIX" ] && DATADIR=${GCC_EXEC_PREFIX}..
# The default release for this host.
DEFAULT_RELEASE="cvs-1.4A2"
# The default organization.
DEFAULT_ORGANIZATION="net"
## # The default site to look for.
## GNATS_SITE=unknown
## # Newer config information?
## [ -f ${GNATS_ROOT}/gnats-adm/config ] && . ${GNATS_ROOT}/gnats-adm/config
# What mailer to use. This must come after the config file, since it is
# host-dependent.
MAIL_AGENT="/usr/lib/sendmail -oi -t"
MAILER=`echo $MAIL_AGENT | sed -e 's, .*,,'`
if [ ! -f "$MAILER" ] ; then
echo "$COMMAND: Cannot file mail program \"$MAILER\"."
echo "$COMMAND: Please fix the MAIL_AGENT entry in the $COMMAND file."
exit 1
fi
if test "`echo -n foo`" = foo ; then
ECHON=bsd
elif test "`echo 'foo\c'`" = foo ; then
ECHON=sysv
else
ECHON=none
fi
if [ $ECHON = bsd ] ; then
ECHON1="echo -n"
ECHON2=
elif [ $ECHON = sysv ] ; then
ECHON1=echo
ECHON2='\c'
else
ECHON1=echo
ECHON2=
fi
#
[ -z "$TMPDIR" ] && TMPDIR=/tmp
TEMP=$TMPDIR/p$$
BAD=$TMPDIR/pbad$$
REF=$TMPDIR/pf$$
if [ -z "$LOGNAME" -a -n "$USER" ]; then
LOGNAME=$USER
fi
FROM="$LOGNAME"
REPLY_TO="$LOGNAME"
# Find out the name of the originator of this PR.
if [ -n "$NAME" ]; then
ORIGINATOR="$NAME"
elif [ -f $HOME/.fullname ]; then
ORIGINATOR="`sed -e '1q' $HOME/.fullname`"
elif [ -f /bin/domainname ]; then
if [ "`/bin/domainname`" != "" -a -f /usr/bin/ypcat ]; then
# Must use temp file due to incompatibilities in quoting behavior
# and to protect shell metacharacters in the expansion of $LOGNAME
/usr/bin/ypcat passwd 2>/dev/null | cat - /etc/passwd | grep "^$LOGNAME:" |
cut -f5 -d':' | sed -e 's/,.*//' > $TEMP
ORIGINATOR="`cat $TEMP`"
rm -f $TEMP
fi
fi
if [ "$ORIGINATOR" = "" ]; then
grep "^$LOGNAME:" /etc/passwd | cut -f5 -d':' | sed -e 's/,.*//' > $TEMP
ORIGINATOR="`cat $TEMP`"
rm -f $TEMP
fi
if [ -n "$ORGANIZATION" ]; then
if [ -f "$ORGANIZATION" ]; then
ORGANIZATION="`cat $ORGANIZATION`"
fi
else
if [ -n "$DEFAULT_ORGANIZATION" ]; then
ORGANIZATION="$DEFAULT_ORGANIZATION"
elif [ -f $HOME/.organization ]; then
ORGANIZATION="`cat $HOME/.organization`"
elif [ -f $HOME/.signature ]; then
ORGANIZATION="`cat $HOME/.signature`"
fi
fi
# If they don't have a preferred editor set, then use
if [ -z "$VISUAL" ]; then
if [ -z "$EDITOR" ]; then
EDIT=vi
else
EDIT="$EDITOR"
fi
else
EDIT="$VISUAL"
fi
# Find out some information.
SYSTEM=`( [ -f /bin/uname ] && /bin/uname -a ) || \
( [ -f /usr/bin/uname ] && /usr/bin/uname -a ) || echo ""`
ARCH=`[ -f /bin/arch ] && /bin/arch`
MACHINE=`[ -f /bin/machine ] && /bin/machine`
COMMAND=`echo $0 | sed -e 's,.*/,,'`
## USAGE="Usage: $COMMAND [-PVL] [-t address] [-f filename] [--request-id]
USAGE="Usage: $COMMAND [-PVL]
[--version]"
REMOVE=
BATCH=
while [ $# -gt 0 ]; do
case "$1" in
-r) ;; # Ignore for backward compat.
## -t | --to) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
## shift ; GNATS_ADDR="$1"
## EXPLICIT_GNATS_ADDR=true
## ;;
## -f | --file) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
## shift ; IN_FILE="$1"
## if [ "$IN_FILE" != "-" -a ! -r "$IN_FILE" ]; then
## echo "$COMMAND: cannot read $IN_FILE"
## exit 1
## fi
## ;;
-b | --batch) BATCH=true ;;
-p | -P | --print) PRINT=true ;;
-L | --list) FORMAT=norm ;;
-l | -CL | --lisp) FORMAT=lisp ;;
## --request-id) REQUEST_ID=true ;;
-h | --help) echo "$USAGE"; exit 0 ;;
-V | --version) echo "$VERSION"; exit 0 ;;
-*) echo "$USAGE" ; exit 1 ;;
*) echo "$USAGE" ; exit 1
## if [ -z "$USER_GNATS_SITE" ]; then
## if [ ! -r "$DATADIR/gnats/$1" ]; then
## echo "$COMMAND: the GNATS site $1 does not have a categories list."
## exit 1
## else
## # The site name is the alias they'll have to have created.
## USER_GNATS_SITE=$1
## fi
## else
## echo "$USAGE" ; exit 1
## fi
;;
esac
shift
done
if [ -n "$USER_GNATS_SITE" ]; then
GNATS_SITE=$USER_GNATS_SITE
GNATS_ADDR=$USER_GNATS_SITE-gnats
fi
if [ "$SUBMITTER" = "unknown" -a -z "$REQUEST_ID" -a -z "$IN_FILE" ]; then
cat << '__EOF__'
It seems that send-pr is not installed with your unique submitter-id.
You need to run
install-sid YOUR-SID
where YOUR-SID is the identification code you received with `send-pr'.
`send-pr' will automatically insert this value into the template field
`>Submitter-Id'. If you've downloaded `send-pr' from the Net, use `net'
for this value. If you do not know your id, run `send-pr --request-id' to
get one from your support site.
__EOF__
exit 1
fi
## if [ -r "$DATADIR/gnats/$GNATS_SITE" ]; then
## CATEGORIES=`grep -v '^#' $DATADIR/gnats/$GNATS_SITE | sort`
## else
## echo "$COMMAND: could not read $DATADIR/gnats/$GNATS_SITE for categories list."
## exit 1
## fi
CATEGORIES="contrib cvs doc pcl-cvs portability"
if [ -z "$CATEGORIES" ]; then
echo "$COMMAND: the categories list for $GNATS_SITE was empty!"
exit 1
fi
case "$FORMAT" in
lisp) echo "$CATEGORIES" | \
awk 'BEGIN {printf "( "} {printf "(\"%s\") ",$0} END {printf ")\n"}'
exit 0
;;
norm) l=`echo "$CATEGORIES" | \
awk 'BEGIN {max = 0; } { if (length($0) > max) { max = length($0); } }
END {print max + 1;}'`
c=`expr 70 / $l`
if [ $c -eq 0 ]; then c=1; fi
echo "$CATEGORIES" | \
awk 'BEGIN {print "Known categories:"; i = 0 }
{ printf ("%-'$l'.'$l's", $0); if ((++i % '$c') == 0) { print "" } }
END { print ""; }'
exit 0
;;
esac
ORIGINATOR_C='<name of the PR author (one line)>'
ORGANIZATION_C='<organization of PR author (multiple lines)>'
CONFIDENTIAL_C='<[ yes | no ] (one line)>'
SYNOPSIS_C='<synopsis of the problem (one line)>'
SEVERITY_C='<[ non-critical | serious | critical ] (one line)>'
PRIORITY_C='<[ low | medium | high ] (one line)>'
CATEGORY_C='<name of the product (one line)>'
CLASS_C='<[ sw-bug | doc-bug | change-request | support ] (one line)>'
RELEASE_C='<release number or tag (one line)>'
ENVIRONMENT_C='<machine, os, target, libraries (multiple lines)>'
DESCRIPTION_C='<precise description of the problem (multiple lines)>'
HOW_TO_REPEAT_C='<code/input/activities to reproduce the problem (multiple lines)>'
FIX_C='<how to correct or work around the problem, if known (multiple lines)>'
# Catch some signals. ($xs kludge needed by Sun /bin/sh)
xs=0
trap 'rm -f $REF $TEMP; exit $xs' 0
trap 'echo "$COMMAND: Aborting ..."; rm -f $REF $TEMP; xs=1; exit' 1 2 3 13 15
# If they told us to use a specific file, then do so.
if [ -n "$IN_FILE" ]; then
if [ "$IN_FILE" = "-" ]; then
# The PR is coming from the standard input.
if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" > $TEMP
else
cat > $TEMP
fi
else
# Use the file they named.
if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" $IN_FILE > $TEMP
else
cat $IN_FILE > $TEMP
fi
fi
else
if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
# If their PR_FORM points to a bogus entry, then bail.
if [ ! -f "$PR_FORM" -o ! -r "$PR_FORM" -o ! -s "$PR_FORM" ]; then
echo "$COMMAND: can't seem to read your template file (\`$PR_FORM'), ignoring PR_FORM"
sleep 1
PRINT_INTERN=bad_prform
fi
fi
if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
cp $PR_FORM $TEMP ||
( echo "$COMMAND: could not copy $PR_FORM" ; xs=1; exit )
else
for file in $TEMP $REF ; do
cat > $file << '__EOF__'
SEND-PR: -*- send-pr -*-
SEND-PR: Lines starting with `SEND-PR' will be removed automatically, as
SEND-PR: will all comments (text enclosed in `<' and `>').
SEND-PR:
SEND-PR: Choose from the following categories:
SEND-PR:
__EOF__
# Format the categories so they fit onto lines.
l=`echo "$CATEGORIES" | \
awk 'BEGIN {max = 0; } { if (length($0) > max) { max = length($0); } }
END {print max + 1;}'`
c=`expr 61 / $l`
if [ $c -eq 0 ]; then c=1; fi
echo "$CATEGORIES" | \
awk 'BEGIN {printf "SEND-PR: "; i = 0 }
{ printf ("%-'$l'.'$l's", $0);
if ((++i % '$c') == 0) { printf "\nSEND-PR: " } }
END { printf "\nSEND-PR:\n"; }' >> $file
cat >> $file << __EOF__
To: $GNATS_ADDR
Subject:
From: $FROM
Reply-To: $REPLY_TO
X-send-pr-version: $VERSION
>Submitter-Id: $SUBMITTER
>Originator: $ORIGINATOR
>Organization:
`
if [ -n "$ORGANIZATION" ]; then
echo "$ORGANIZATION"
else
echo " $ORGANIZATION_C" ;
fi ;
`
>Confidential: $CONFIDENTIAL_C
>Synopsis: $SYNOPSIS_C
>Severity: $SEVERITY_C
>Priority: $PRIORITY_C
>Category: $CATEGORY_C
>Class: $CLASS_C
>Release: `if [ -n "$DEFAULT_RELEASE" ]; then
echo "$DEFAULT_RELEASE"
else
echo " $RELEASE_C"
fi; `
>Environment:
$ENVIRONMENT_C
`[ -n "$SYSTEM" ] && echo System: $SYSTEM`
`[ -n "$ARCH" ] && echo Architecture: $ARCH`
`[ -n "$MACHINE" ] && echo Machine: $MACHINE`
>Description:
$DESCRIPTION_C
>How-To-Repeat:
$HOW_TO_REPEAT_C
>Fix:
$FIX_C
__EOF__
done
fi
if [ "$PRINT" = true -o "$PRINT_INTERN" = true ]; then
cat $TEMP
xs=0; exit
fi
chmod u+w $TEMP
if [ -z "$REQUEST_ID" ]; then
eval $EDIT $TEMP
else
ed -s $TEMP << '__EOF__'
/^Subject/s/^Subject:.*/Subject: request for a customer id/
/^>Category/s/^>Category:.*/>Category: send-pr/
w
q
__EOF__
fi
if cmp -s $REF $TEMP ; then
echo "$COMMAND: problem report not filled out, therefore not sent"
xs=1; exit
fi
fi
#
# Check the enumeration fields
# This is a "sed-subroutine" with one keyword parameter
# (with workaround for Sun sed bug)
#
SED_CMD='
/$PATTERN/{
s|||
s|<.*>||
s|^[ ]*||
s|[ ]*$||
p
q
}'
while [ -z "$REQUEST_ID" ]; do
CNT=0
# 1) Confidential
#
PATTERN=">Confidential:"
CONFIDENTIAL=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
case "$CONFIDENTIAL" in
""|yes|no) CNT=`expr $CNT + 1` ;;
*) echo "$COMMAND: \`$CONFIDENTIAL' is not a valid value for \`Confidential'." ;;
esac
#
# 2) Severity
#
PATTERN=">Severity:"
SEVERITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
case "$SEVERITY" in
""|non-critical|serious|critical) CNT=`expr $CNT + 1` ;;
*) echo "$COMMAND: \`$SEVERITY' is not a valid value for \`Severity'."
esac
#
# 3) Priority
#
PATTERN=">Priority:"
PRIORITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
case "$PRIORITY" in
""|low|medium|high) CNT=`expr $CNT + 1` ;;
*) echo "$COMMAND: \`$PRIORITY' is not a valid value for \`Priority'."
esac
#
# 4) Category
#
PATTERN=">Category:"
CATEGORY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
FOUND=
for C in $CATEGORIES
do
if [ "$C" = "$CATEGORY" ]; then FOUND=true ; break ; fi
done
if [ -n "$FOUND" ]; then
CNT=`expr $CNT + 1`
else
if [ -z "$CATEGORY" ]; then
echo "$COMMAND: you must include a Category: field in your report."
else
echo "$COMMAND: \`$CATEGORY' is not a known category."
fi
fi
#
# 5) Class
#
PATTERN=">Class:"
CLASS=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
case "$CLASS" in
""|sw-bug|doc-bug|change-request|support) CNT=`expr $CNT + 1` ;;
*) echo "$COMMAND: \`$CLASS' is not a valid value for \`Class'."
esac
[ $CNT -lt 5 -a -z "$BATCH" ] &&
echo "Errors were found with the problem report."
while true; do
if [ -z "$BATCH" ]; then
$ECHON1 "a)bort, e)dit or s)end? $ECHON2"
read input
else
if [ $CNT -eq 5 ]; then
input=s
else
input=a
fi
fi
case "$input" in
a*)
if [ -z "$BATCH" ]; then
echo "$COMMAND: the problem report remains in $BAD and is not sent."
mv $TEMP $BAD
else
echo "$COMMAND: the problem report is not sent."
fi
xs=1; exit
;;
e*)
eval $EDIT $TEMP
continue 2
;;
s*)
break 2
;;
esac
done
done
#
# Remove comments and send the problem report
# (we have to use patterns, where the comment contains regex chars)
#
# /^>Originator:/s;$ORIGINATOR;;
sed -e "
/^SEND-PR:/d
/^>Organization:/,/^>[A-Za-z-]*:/s;$ORGANIZATION_C;;
/^>Confidential:/s;<.*>;;
/^>Synopsis:/s;$SYNOPSIS_C;;
/^>Severity:/s;<.*>;;
/^>Priority:/s;<.*>;;
/^>Category:/s;$CATEGORY_C;;
/^>Class:/s;<.*>;;
/^>Release:/,/^>[A-Za-z-]*:/s;$RELEASE_C;;
/^>Environment:/,/^>[A-Za-z-]*:/s;$ENVIRONMENT_C;;
/^>Description:/,/^>[A-Za-z-]*:/s;$DESCRIPTION_C;;
/^>How-To-Repeat:/,/^>[A-Za-z-]*:/s;$HOW_TO_REPEAT_C;;
/^>Fix:/,/^>[A-Za-z-]*:/s;$FIX_C;;
" $TEMP > $REF
if $MAIL_AGENT < $REF; then
echo "$COMMAND: problem report sent"
xs=0; exit
else
echo "$COMMAND: mysterious mail failure."
if [ -z "$BATCH" ]; then
echo "$COMMAND: the problem report remains in $BAD and is not sent."
mv $REF $BAD
else
echo "$COMMAND: the problem report is not sent."
fi
xs=1; exit
fi
+18
View File
@@ -0,0 +1,18 @@
;;;; -*- lisp-interaction -*-
;;;; Time-stamp: <29 Nov 93 14:25:28, by [email protected]>
(defun reset-fail-counter (arg)
(interactive "p")
(setq fail-counter arg)
(message (concat "fail-counter = " (int-to-string arg))))
(defun inc-next-fail-counter nil
(interactive)
(search-forward "failed test ")
(kill-word 1)
(insert-string fail-counter)
(setq fail-counter (+ 1 fail-counter)))
(global-set-key [f15] 'reset-fail-counter)
(global-set-key [f16] 'inc-next-fail-counter)
+191
View File
@@ -0,0 +1,191 @@
/*
alloca -- (mostly) portable public-domain implementation -- D A Gwyn
last edit: 86/05/30 rms
include config.h, since on VMS it renames some symbols.
Use xmalloc instead of malloc.
This implementation of the PWB library alloca() function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
It should work under any C implementation that uses an
actual procedure stack (as opposed to a linked list of
frames). There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca()-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection.
*/
#ifndef lint
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
#if defined(emacs) || defined(HAVE_CONFIG_H)
#include "config.h"
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif /* static */
#endif /* emacs || HAVE_CONFIG_H*/
#if __STDC__
typedef void *pointer; /* generic pointer type */
#else
typedef char *pointer; /* generic pointer type */
#endif
#define NULL 0 /* null pointer constant */
extern void free();
extern pointer xmalloc();
/*
Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* direction unknown */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* known at compile-time */
#else /* STACK_DIRECTION == 0; need run-time code */
static int stack_dir; /* 1 or -1 once known */
#define STACK_DIR stack_dir
static void
find_stack_direction (/* void */)
{
static char *addr = NULL; /* address of first
`dummy', once known */
auto char dummy; /* to get stack address */
if (addr == NULL)
{ /* initial entry */
addr = &dummy;
find_stack_direction (); /* recurse once */
}
else /* second entry */
if (&dummy > addr)
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
#endif /* STACK_DIRECTION == 0 */
/*
An "alloca header" is used to:
(a) chain together all alloca()ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc()
alignment chunk size. The following default should work okay.
*/
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* to force sizeof(header) */
struct
{
union hdr *next; /* for chaining headers */
char *deep; /* for stack depth measure */
} h;
} header;
/*
alloca( size ) returns a pointer to at least `size' bytes of
storage which will be automatically reclaimed upon exit from
the procedure that called alloca(). Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32.
*/
static header *last_alloca_header = NULL; /* -> last alloca header */
pointer
alloca (size) /* returns pointer to storage */
unsigned size; /* # bytes to allocate */
{
auto char probe; /* probes stack depth: */
register char *depth = &probe;
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* unknown growth direction */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca()ed storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* traverses linked list */
for (hp = last_alloca_header; hp != NULL;)
if (STACK_DIR > 0 && hp->h.deep > depth
|| STACK_DIR < 0 && hp->h.deep < depth)
{
register header *np = hp->h.next;
free ((pointer) hp); /* collect garbage */
hp = np; /* -> next header */
}
else
break; /* rest are not deeper */
last_alloca_header = hp; /* -> last valid storage */
}
if (size == 0)
return NULL; /* no allocation required */
/* Allocate combined header + user data storage. */
{
register pointer new = xmalloc (sizeof (header) + size);
/* address of header */
((header *)new)->h.next = last_alloca_header;
((header *)new)->h.deep = depth;
last_alloca_header = (header *)new;
/* User storage begins just after header. */
return (pointer)((char *)new + sizeof(header));
}
}
+40
View File
@@ -0,0 +1,40 @@
/*
dup2 -- 7th Edition UNIX system call emulation for UNIX System V
last edit: 11-Feb-1987 D A Gwyn
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h>
#include <fcntl.h>
extern int close(), fcntl();
int
dup2( oldfd, newfd )
int oldfd; /* already-open file descriptor */
int newfd; /* desired duplicate descriptor */
{
register int ret; /* for fcntl() return value */
register int save; /* for saving entry errno */
if ( oldfd == newfd )
return oldfd; /* be careful not to close() */
save = errno; /* save entry errno */
(void) close( newfd ); /* in case newfd is open */
/* (may have just clobbered the original errno value) */
ret = fcntl( oldfd, F_DUPFD, newfd ); /* dupe it */
if ( ret >= 0 )
errno = save; /* restore entry errno */
else /* fcntl() returned error */
if ( errno == EINVAL )
errno = EBADF; /* we think of everything */
return ret; /* return file descriptor */
}
+183
View File
@@ -0,0 +1,183 @@
/* Copyright (C) 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
/* Modified slightly by Brian Berliner <[email protected]> for CVS use */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* IGNORE(@ */
/* #include <ansidecl.h> */
/* @) */
#include <errno.h>
#include <fnmatch.h>
#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
extern int errno;
#endif
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */
int
#if __STDC__
fnmatch (const char *pattern, const char *string, int flags)
#else
fnmatch (pattern, string, flags)
char *pattern;
char *string;
int flags;
#endif
{
register const char *p = pattern, *n = string;
register char c;
if ((flags & ~__FNM_FLAGS) != 0)
{
errno = EINVAL;
return -1;
}
while ((c = *p++) != '\0')
{
switch (c)
{
case '?':
if (*n == '\0')
return FNM_NOMATCH;
else if ((flags & FNM_PATHNAME) && *n == '/')
return FNM_NOMATCH;
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return FNM_NOMATCH;
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
c = *p++;
if (*n != c)
return FNM_NOMATCH;
break;
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return FNM_NOMATCH;
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
if (((flags & FNM_PATHNAME) && *n == '/') ||
(c == '?' && *n == '\0'))
return FNM_NOMATCH;
if (c == '\0')
return 0;
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
for (--p; *n != '\0'; ++n)
if ((c == '[' || *n == c1) &&
fnmatch(p, n, flags & ~FNM_PERIOD) == 0)
return 0;
return FNM_NOMATCH;
}
case '[':
{
/* Nonzero if the sense of the character class is inverted. */
register int not;
if (*n == '\0')
return FNM_NOMATCH;
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return FNM_NOMATCH;
not = (*p == '!' || *p == '^');
if (not)
++p;
c = *p++;
for (;;)
{
register char cstart = c, cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
cstart = cend = *p++;
if (c == '\0')
/* [ (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
if ((flags & FNM_PATHNAME) && c == '/')
/* [/] can never match. */
return FNM_NOMATCH;
if (c == '-' && *p != ']')
{
cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return FNM_NOMATCH;
c = *p++;
}
if (*n >= cstart && *n <= cend)
goto matched;
if (c == ']')
break;
}
if (!not)
return FNM_NOMATCH;
break;
matched:;
/* Skip the rest of the [...] that already matched. */
while (c != ']')
{
if (c == '\0')
/* [... (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
/* 1003.2d11 is unclear if this is right. %%% */
++p;
}
if (not)
return FNM_NOMATCH;
}
break;
default:
if (c != *n)
return FNM_NOMATCH;
}
++n;
}
if (*n == '\0')
return 0;
return FNM_NOMATCH;
}
+45
View File
@@ -0,0 +1,45 @@
/* Copyright (C) 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _FNMATCH_H
#define _FNMATCH_H 1
/* Bits set in the FLAGS argument to `fnmatch'. */
#undef FNM_PATHNAME
#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match `/'. */
#undef FNM_NOESCAPE
#define FNM_NOESCAPE (1 << 1)/* Backslashes don't quote special chars. */
#undef FNM_PERIOD
#define FNM_PERIOD (1 << 2)/* Leading `.' is matched only explicitly. */
#undef __FNM_FLAGS
#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
#undef FNM_NOMATCH
#define FNM_NOMATCH 1
/* Match STRING against the filename pattern PATTERN,
returning zero if it matches, FNM_NOMATCH if not. */
#if __STDC__
extern int fnmatch (const char *pattern, const char *string, int flags);
#else
extern int fnmatch ();
#endif
#endif /* fnmatch.h */
+76
View File
@@ -0,0 +1,76 @@
/* ftruncate emulations that work on some System V's.
This file is in the public domain. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <fcntl.h>
#ifdef F_CHSIZE
int
ftruncate (fd, length)
int fd;
off_t length;
{
return fcntl (fd, F_CHSIZE, length);
}
#else
#ifdef F_FREESP
/* The following function was written by
[email protected] (William Kucharski) */
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
int
ftruncate (fd, length)
int fd;
off_t length;
{
struct flock fl;
struct stat filebuf;
if (fstat (fd, &filebuf) < 0)
return -1;
if (filebuf.st_size < length)
{
/* Extend file length. */
if (lseek (fd, (length - 1), SEEK_SET) < 0)
return -1;
/* Write a "0" byte. */
if (write (fd, "", 1) != 1)
return -1;
}
else
{
/* Truncate length. */
fl.l_whence = 0;
fl.l_len = 0;
fl.l_start = length;
fl.l_type = F_WRLCK; /* Write lock on file space. */
/* This relies on the UNDOCUMENTED F_FREESP argument to
fcntl, which truncates the file so that it ends at the
position indicated by fl.l_start.
Will minor miracles never cease? */
if (fcntl (fd, F_FREESP, &fl) < 0)
return -1;
}
return 0;
}
#else
int
ftruncate (fd, length)
int fd;
off_t length;
{
return chsize (fd, length);
}
#endif
#endif
+35
View File
@@ -0,0 +1,35 @@
/* getwd.c -- get current working directory pathname
Copyright (C) 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Some systems which include both getwd() and getcwd() have an implementation
of getwd() which is much faster than getcwd(). As a result, we use the
system's getwd() if it is available */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "system.h"
/* Get the current working directory into PATHNAME */
char *
getwd (pathname)
char *pathname;
{
return (getcwd(pathname, PATH_MAX));
}
+49
View File
@@ -0,0 +1,49 @@
/* hostname.c -- use uname() to get the name of the host
Copyright (C) 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(STDC_HEADERS) || defined(USG)
#include <string.h>
#ifndef index
#define index strchr
#endif
#else
#include <strings.h>
#endif
#include <sys/utsname.h>
/* Put this host's name into NAME, using at most NAMELEN characters */
int
gethostname(name, namelen)
char *name;
int namelen;
{
struct utsname ugnm;
if (uname(&ugnm) < 0)
return (-1);
(void) strncpy(name, ugnm.nodename, namelen-1);
name[namelen-1] = '\0';
return (0);
}
+57
View File
@@ -0,0 +1,57 @@
/* memmove -- copy memory regions of arbitary length
Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
/*
NAME
memmove -- copy memory regions of arbitary length
SYNOPSIS
void memmove (void *out, const void *in, size_t n);
DESCRIPTION
Copy LENGTH bytes from memory region pointed to by IN to memory
region pointed to by OUT.
Regions can be overlapping.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef __STDC__
#include <stddef.h>
#else
#define size_t unsigned long
#endif
void *
memmove (out, in, length)
void *out;
const void* in;
size_t length;
{
bcopy(in, out, length);
return out;
}
+129
View File
@@ -0,0 +1,129 @@
/* mkrmdir.c -- BSD compatible directory functions for System V
Copyright (C) 1988, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
/* mkdir and rmdir adapted from GNU tar. */
/* Make directory DPATH, with permission mode DMODE.
Written by Robert Rother, Mariah Corporation, August 1985
(sdcsvax!rmr or rmr@uscd). If you want it, it's yours.
Severely hacked over by John Gilmore to make a 4.2BSD compatible
subroutine. 11Mar86; hoptoad!gnu
Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
subroutine didn't return EEXIST. It does now. */
int
mkdir (dpath, dmode)
char *dpath;
int dmode;
{
int cpid, status;
struct stat statbuf;
if (stat (dpath, &statbuf) == 0)
{
errno = EEXIST; /* stat worked, so it already exists. */
return -1;
}
/* If stat fails for a reason other than non-existence, return error. */
if (errno != ENOENT)
return -1;
cpid = fork ();
switch (cpid)
{
case -1: /* Cannot fork. */
return -1; /* errno is set already. */
case 0: /* Child process. */
/* Cheap hack to set mode of new directory. Since this child
process is going away anyway, we zap its umask.
This won't suffice to set SUID, SGID, etc. on this
directory, so the parent process calls chmod afterward. */
status = umask (0); /* Get current umask. */
umask (status | (0777 & ~dmode)); /* Set for mkdir. */
execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
_exit (1);
default: /* Parent process. */
while (wait (&status) != cpid) /* Wait for kid to finish. */
/* Do nothing. */ ;
if (status & 0xFFFF)
{
errno = EIO; /* /bin/mkdir failed. */
return -1;
}
return chmod (dpath, dmode);
}
}
/* Remove directory DPATH.
Return 0 if successful, -1 if not. */
int
rmdir (dpath)
char *dpath;
{
int cpid, status;
struct stat statbuf;
if (stat (dpath, &statbuf) != 0)
return -1; /* stat set errno. */
if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
{
errno = ENOTDIR;
return -1;
}
cpid = fork ();
switch (cpid)
{
case -1: /* Cannot fork. */
return -1; /* errno is set already. */
case 0: /* Child process. */
execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
_exit (1);
default: /* Parent process. */
while (wait (&status) != cpid) /* Wait for kid to finish. */
/* Do nothing. */ ;
if (status & 0xFFFF)
{
errno = EIO; /* /bin/rmdir failed. */
return -1;
}
return 0;
}
}
+72
View File
@@ -0,0 +1,72 @@
/* rename.c -- BSD compatible directory function for System V
Copyright (C) 1988, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#ifndef STDC_HEADERS
extern int errno;
#endif
/* Rename file FROM to file TO.
Return 0 if successful, -1 if not. */
int
rename (from, to)
char *from;
char *to;
{
struct stat from_stats;
int pid, status;
if (stat (from, &from_stats) == 0)
{
if (unlink (to) && errno != ENOENT)
return -1;
if ((from_stats.st_mode & S_IFMT) == S_IFDIR)
{
/* Need a setuid root process to link and unlink directories. */
pid = fork ();
switch (pid)
{
case -1: /* Error. */
error (1, errno, "cannot fork");
case 0: /* Child. */
execl (MVDIR, "mvdir", from, to, (char *) 0);
error (255, errno, "cannot run `%s'", MVDIR);
default: /* Parent. */
while (wait (&status) != pid)
/* Do nothing. */ ;
errno = 0; /* mvdir printed the system error message. */
return status != 0 ? -1 : 0;
}
}
else
{
if (link (from, to) == 0 && (unlink (from) == 0 || errno == ENOENT))
return 0;
}
}
return -1;
}
+43
View File
@@ -0,0 +1,43 @@
/* strdup.c -- return a newly allocated copy of a string
Copyright (C) 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef STDC_HEADERS
#include <string.h>
#include <stdlib.h>
#else
char *malloc ();
char *strcpy ();
#endif
/* Return a newly allocated copy of STR,
or 0 if out of memory. */
char *
strdup (str)
char *str;
{
char *newstr;
newstr = (char *) malloc (strlen (str) + 1);
if (newstr)
strcpy (newstr, str);
return newstr;
}
+813
View File
@@ -0,0 +1,813 @@
/* Extended support for using errno values.
Copyright (C) 1992 Free Software Foundation, Inc.
Written by Fred Fish. [email protected]
This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include "config.h"
#ifndef NEED_sys_errlist
/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
might declare sys_errlist in a way that the compiler might consider
incompatible with our later declaration, perhaps by using const
attributes. So we hide the declaration in errno.h (if any) using a
macro. */
#define sys_errlist sys_errlist__
#endif
#include <stdio.h>
#include <errno.h>
#ifndef NEED_sys_errlist
#undef sys_errlist
#endif
/* Routines imported from standard C runtime libraries. */
#ifdef __STDC__
#include <stddef.h>
extern void *malloc (size_t size); /* 4.10.3.3 */
extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */
#else /* !__STDC__ */
extern char *malloc (); /* Standard memory allocater */
extern char *memset ();
#endif /* __STDC__ */
#ifndef MAX
# define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
/* Translation table for errno values. See intro(2) in most UNIX systems
Programmers Reference Manuals.
Note that this table is generally only accessed when it is used at runtime
to initialize errno name and message tables that are indexed by errno
value.
Not all of these errnos will exist on all systems. This table is the only
thing that should have to be updated as new error numbers are introduced.
It's sort of ugly, but at least its portable. */
struct error_info
{
int value; /* The numeric value from <errno.h> */
char *name; /* The equivalent symbolic value */
#ifdef NEED_sys_errlist
char *msg; /* Short message about this value */
#endif
};
#ifdef NEED_sys_errlist
# define ENTRY(value, name, msg) {value, name, msg}
#else
# define ENTRY(value, name, msg) {value, name}
#endif
static const struct error_info error_table[] =
{
#if defined (EPERM)
ENTRY(EPERM, "EPERM", "Not owner"),
#endif
#if defined (ENOENT)
ENTRY(ENOENT, "ENOENT", "No such file or directory"),
#endif
#if defined (ESRCH)
ENTRY(ESRCH, "ESRCH", "No such process"),
#endif
#if defined (EINTR)
ENTRY(EINTR, "EINTR", "Interrupted system call"),
#endif
#if defined (EIO)
ENTRY(EIO, "EIO", "I/O error"),
#endif
#if defined (ENXIO)
ENTRY(ENXIO, "ENXIO", "No such device or address"),
#endif
#if defined (E2BIG)
ENTRY(E2BIG, "E2BIG", "Arg list too long"),
#endif
#if defined (ENOEXEC)
ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
#endif
#if defined (EBADF)
ENTRY(EBADF, "EBADF", "Bad file number"),
#endif
#if defined (ECHILD)
ENTRY(ECHILD, "ECHILD", "No child processes"),
#endif
#if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */
ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
#endif
#if defined (EAGAIN)
ENTRY(EAGAIN, "EAGAIN", "No more processes"),
#endif
#if defined (ENOMEM)
ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
#endif
#if defined (EACCES)
ENTRY(EACCES, "EACCES", "Permission denied"),
#endif
#if defined (EFAULT)
ENTRY(EFAULT, "EFAULT", "Bad address"),
#endif
#if defined (ENOTBLK)
ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
#endif
#if defined (EBUSY)
ENTRY(EBUSY, "EBUSY", "Device busy"),
#endif
#if defined (EEXIST)
ENTRY(EEXIST, "EEXIST", "File exists"),
#endif
#if defined (EXDEV)
ENTRY(EXDEV, "EXDEV", "Cross-device link"),
#endif
#if defined (ENODEV)
ENTRY(ENODEV, "ENODEV", "No such device"),
#endif
#if defined (ENOTDIR)
ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
#endif
#if defined (EISDIR)
ENTRY(EISDIR, "EISDIR", "Is a directory"),
#endif
#if defined (EINVAL)
ENTRY(EINVAL, "EINVAL", "Invalid argument"),
#endif
#if defined (ENFILE)
ENTRY(ENFILE, "ENFILE", "File table overflow"),
#endif
#if defined (EMFILE)
ENTRY(EMFILE, "EMFILE", "Too many open files"),
#endif
#if defined (ENOTTY)
ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
#endif
#if defined (ETXTBSY)
ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
#endif
#if defined (EFBIG)
ENTRY(EFBIG, "EFBIG", "File too large"),
#endif
#if defined (ENOSPC)
ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
#endif
#if defined (ESPIPE)
ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
#endif
#if defined (EROFS)
ENTRY(EROFS, "EROFS", "Read-only file system"),
#endif
#if defined (EMLINK)
ENTRY(EMLINK, "EMLINK", "Too many links"),
#endif
#if defined (EPIPE)
ENTRY(EPIPE, "EPIPE", "Broken pipe"),
#endif
#if defined (EDOM)
ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
#endif
#if defined (ERANGE)
ENTRY(ERANGE, "ERANGE", "Math result not representable"),
#endif
#if defined (ENOMSG)
ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
#endif
#if defined (EIDRM)
ENTRY(EIDRM, "EIDRM", "Identifier removed"),
#endif
#if defined (ECHRNG)
ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
#endif
#if defined (EL2NSYNC)
ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
#endif
#if defined (EL3HLT)
ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
#endif
#if defined (EL3RST)
ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
#endif
#if defined (ELNRNG)
ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
#endif
#if defined (EUNATCH)
ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
#endif
#if defined (ENOCSI)
ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
#endif
#if defined (EL2HLT)
ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
#endif
#if defined (EDEADLK)
ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
#endif
#if defined (ENOLCK)
ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
#endif
#if defined (EBADE)
ENTRY(EBADE, "EBADE", "Invalid exchange"),
#endif
#if defined (EBADR)
ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
#endif
#if defined (EXFULL)
ENTRY(EXFULL, "EXFULL", "Exchange full"),
#endif
#if defined (ENOANO)
ENTRY(ENOANO, "ENOANO", "No anode"),
#endif
#if defined (EBADRQC)
ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
#endif
#if defined (EBADSLT)
ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
#endif
#if defined (EDEADLOCK)
ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
#endif
#if defined (EBFONT)
ENTRY(EBFONT, "EBFONT", "Bad font file format"),
#endif
#if defined (ENOSTR)
ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
#endif
#if defined (ENODATA)
ENTRY(ENODATA, "ENODATA", "No data available"),
#endif
#if defined (ETIME)
ENTRY(ETIME, "ETIME", "Timer expired"),
#endif
#if defined (ENOSR)
ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
#endif
#if defined (ENONET)
ENTRY(ENONET, "ENONET", "Machine is not on the network"),
#endif
#if defined (ENOPKG)
ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
#endif
#if defined (EREMOTE)
ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
#endif
#if defined (ENOLINK)
ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
#endif
#if defined (EADV)
ENTRY(EADV, "EADV", "Advertise error"),
#endif
#if defined (ESRMNT)
ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
#endif
#if defined (ECOMM)
ENTRY(ECOMM, "ECOMM", "Communication error on send"),
#endif
#if defined (EPROTO)
ENTRY(EPROTO, "EPROTO", "Protocol error"),
#endif
#if defined (EMULTIHOP)
ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
#endif
#if defined (EDOTDOT)
ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
#endif
#if defined (EBADMSG)
ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
#endif
#if defined (ENAMETOOLONG)
ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
#endif
#if defined (EOVERFLOW)
ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
#endif
#if defined (ENOTUNIQ)
ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
#endif
#if defined (EBADFD)
ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
#endif
#if defined (EREMCHG)
ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
#endif
#if defined (ELIBACC)
ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
#endif
#if defined (ELIBBAD)
ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
#endif
#if defined (ELIBSCN)
ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
#endif
#if defined (ELIBMAX)
ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
#endif
#if defined (ELIBEXEC)
ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
#endif
#if defined (EILSEQ)
ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
#endif
#if defined (ENOSYS)
ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
#endif
#if defined (ELOOP)
ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
#endif
#if defined (ERESTART)
ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
#endif
#if defined (ESTRPIPE)
ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
#endif
#if defined (ENOTEMPTY)
ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
#endif
#if defined (EUSERS)
ENTRY(EUSERS, "EUSERS", "Too many users"),
#endif
#if defined (ENOTSOCK)
ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
#endif
#if defined (EDESTADDRREQ)
ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
#endif
#if defined (EMSGSIZE)
ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
#endif
#if defined (EPROTOTYPE)
ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
#endif
#if defined (ENOPROTOOPT)
ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
#endif
#if defined (EPROTONOSUPPORT)
ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
#endif
#if defined (ESOCKTNOSUPPORT)
ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
#endif
#if defined (EOPNOTSUPP)
ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
#endif
#if defined (EPFNOSUPPORT)
ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
#endif
#if defined (EAFNOSUPPORT)
ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
#endif
#if defined (EADDRINUSE)
ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
#endif
#if defined (EADDRNOTAVAIL)
ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
#endif
#if defined (ENETDOWN)
ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
#endif
#if defined (ENETUNREACH)
ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
#endif
#if defined (ENETRESET)
ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
#endif
#if defined (ECONNABORTED)
ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
#endif
#if defined (ECONNRESET)
ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
#endif
#if defined (ENOBUFS)
ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
#endif
#if defined (EISCONN)
ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
#endif
#if defined (ENOTCONN)
ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
#endif
#if defined (ESHUTDOWN)
ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
#endif
#if defined (ETOOMANYREFS)
ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
#endif
#if defined (ETIMEDOUT)
ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
#endif
#if defined (ECONNREFUSED)
ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
#endif
#if defined (EHOSTDOWN)
ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
#endif
#if defined (EHOSTUNREACH)
ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
#endif
#if defined (EALREADY)
ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
#endif
#if defined (EINPROGRESS)
ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
#endif
#if defined (ESTALE)
ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
#endif
#if defined (EUCLEAN)
ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
#endif
#if defined (ENOTNAM)
ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
#endif
#if defined (ENAVAIL)
ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
#endif
#if defined (EISNAM)
ENTRY(EISNAM, "EISNAM", "Is a named type file"),
#endif
#if defined (EREMOTEIO)
ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
#endif
ENTRY(0, NULL, NULL)
};
/* Translation table allocated and initialized at runtime. Indexed by the
errno value to find the equivalent symbolic value. */
static char **error_names;
static int num_error_names = 0;
/* Translation table allocated and initialized at runtime, if it does not
already exist in the host environment. Indexed by the errno value to find
the descriptive string.
We don't export it for use in other modules because even though it has the
same name, it differs from other implementations in that it is dynamically
initialized rather than statically initialized. */
#ifdef NEED_sys_errlist
static int sys_nerr;
static char **sys_errlist;
#else
extern int sys_nerr;
extern char *sys_errlist[];
#endif
/*
NAME
init_error_tables -- initialize the name and message tables
SYNOPSIS
static void init_error_tables ();
DESCRIPTION
Using the error_table, which is initialized at compile time, generate
the error_names and the sys_errlist (if needed) tables, which are
indexed at runtime by a specific errno value.
BUGS
The initialization of the tables may fail under low memory conditions,
in which case we don't do anything particularly useful, but we don't
bomb either. Who knows, it might succeed at a later point if we free
some memory in the meantime. In any case, the other routines know
how to deal with lack of a table after trying to initialize it. This
may or may not be considered to be a bug, that we don't specifically
warn about this particular failure mode.
*/
static void
init_error_tables ()
{
const struct error_info *eip;
int nbytes;
/* If we haven't already scanned the error_table once to find the maximum
errno value, then go find it now. */
if (num_error_names == 0)
{
for (eip = error_table; eip -> name != NULL; eip++)
{
if (eip -> value >= num_error_names)
{
num_error_names = eip -> value + 1;
}
}
}
/* Now attempt to allocate the error_names table, zero it out, and then
initialize it from the statically initialized error_table. */
if (error_names == NULL)
{
nbytes = num_error_names * sizeof (char *);
if ((error_names = (char **) malloc (nbytes)) != NULL)
{
memset (error_names, 0, nbytes);
for (eip = error_table; eip -> name != NULL; eip++)
{
error_names[eip -> value] = eip -> name;
}
}
}
#ifdef NEED_sys_errlist
/* Now attempt to allocate the sys_errlist table, zero it out, and then
initialize it from the statically initialized error_table. */
if (sys_errlist == NULL)
{
nbytes = num_error_names * sizeof (char *);
if ((sys_errlist = (char **) malloc (nbytes)) != NULL)
{
memset (sys_errlist, 0, nbytes);
sys_nerr = num_error_names;
for (eip = error_table; eip -> name != NULL; eip++)
{
sys_errlist[eip -> value] = eip -> msg;
}
}
}
#endif
}
/*
NAME
errno_max -- return the max errno value
SYNOPSIS
int errno_max ();
DESCRIPTION
Returns the maximum errno value for which a corresponding symbolic
name or message is available. Note that in the case where
we use the sys_errlist supplied by the system, it is possible for
there to be more symbolic names than messages, or vice versa.
In fact, the manual page for perror(3C) explicitly warns that one
should check the size of the table (sys_nerr) before indexing it,
since new error codes may be added to the system before they are
added to the table. Thus sys_nerr might be smaller than value
implied by the largest errno value defined in <errno.h>.
We return the maximum value that can be used to obtain a meaningful
symbolic name or message.
*/
int
errno_max ()
{
int maxsize;
if (error_names == NULL)
{
init_error_tables ();
}
maxsize = MAX (sys_nerr, num_error_names);
return (maxsize - 1);
}
/*
NAME
strerror -- map an error number to an error message string
SYNOPSIS
char *strerror (int errnoval)
DESCRIPTION
Maps an errno number to an error message string, the contents of
which are implementation defined. On systems which have the external
variables sys_nerr and sys_errlist, these strings will be the same
as the ones used by perror().
If the supplied error number is within the valid range of indices
for the sys_errlist, but no message is available for the particular
error number, then returns the string "Error NUM", where NUM is the
error number.
If the supplied error number is not a valid index into sys_errlist,
returns NULL.
The returned string is only guaranteed to be valid only until the
next call to strerror.
*/
char *
strerror (errnoval)
int errnoval;
{
char *msg;
static char buf[32];
#ifdef NEED_sys_errlist
if (error_names == NULL)
{
init_error_tables ();
}
#endif
if ((errnoval < 0) || (errnoval >= sys_nerr))
{
/* Out of range, just return NULL */
msg = NULL;
}
else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
{
/* In range, but no sys_errlist or no entry at this index. */
sprintf (buf, "Error %d", errnoval);
msg = buf;
}
else
{
/* In range, and a valid message. Just return the message. */
msg = sys_errlist[errnoval];
}
return (msg);
}
/*
NAME
strerrno -- map an error number to a symbolic name string
SYNOPSIS
char *strerrno (int errnoval)
DESCRIPTION
Given an error number returned from a system call (typically
returned in errno), returns a pointer to a string containing the
symbolic name of that error number, as found in <errno.h>.
If the supplied error number is within the valid range of indices
for symbolic names, but no name is available for the particular
error number, then returns the string "Error NUM", where NUM is
the error number.
If the supplied error number is not within the range of valid
indices, then returns NULL.
BUGS
The contents of the location pointed to are only guaranteed to be
valid until the next call to strerrno.
*/
char *
strerrno (errnoval)
int errnoval;
{
char *name;
static char buf[32];
if (error_names == NULL)
{
init_error_tables ();
}
if ((errnoval < 0) || (errnoval >= num_error_names))
{
/* Out of range, just return NULL */
name = NULL;
}
else if ((error_names == NULL) || (error_names[errnoval] == NULL))
{
/* In range, but no error_names or no entry at this index. */
sprintf (buf, "Error %d", errnoval);
name = buf;
}
else
{
/* In range, and a valid name. Just return the name. */
name = error_names[errnoval];
}
return (name);
}
/*
NAME
strtoerrno -- map a symbolic errno name to a numeric value
SYNOPSIS
int strtoerrno (char *name)
DESCRIPTION
Given the symbolic name of a error number, map it to an errno value.
If no translation is found, returns 0.
*/
int
strtoerrno (name)
char *name;
{
int errnoval = 0;
if (name != NULL)
{
if (error_names == NULL)
{
init_error_tables ();
}
for (errnoval = 0; errnoval < num_error_names; errnoval++)
{
if ((error_names[errnoval] != NULL) &&
(strcmp (name, error_names[errnoval]) == 0))
{
break;
}
}
if (errnoval == num_error_names)
{
errnoval = 0;
}
}
return (errnoval);
}
/* A simple little main that does nothing but print all the errno translations
if MAIN is defined and this file is compiled and linked. */
#ifdef MAIN
main ()
{
int errn;
int errnmax;
char *name;
char *msg;
char *strerrno ();
char *strerror ();
errnmax = errno_max ();
printf ("%d entries in names table.\n", num_error_names);
printf ("%d entries in messages table.\n", sys_nerr);
printf ("%d is max useful index.\n", errnmax);
/* Keep printing values until we get to the end of *both* tables, not
*either* table. Note that knowing the maximum useful index does *not*
relieve us of the responsibility of testing the return pointer for
NULL. */
for (errn = 0; errn <= errnmax; errn++)
{
name = strerrno (errn);
name = (name == NULL) ? "<NULL>" : name;
msg = strerror (errn);
msg = (msg == NULL) ? "<NULL>" : msg;
printf ("%-4d%-18s%s\n", errn, name, msg);
}
}
#endif
-30
View File
@@ -1,30 +0,0 @@
# $Id$
# This may become bsd.shprog.mk. The general version would have to handle:
# - arbitrary sed substitutions.
# - programs without man pages.
# - programs with man pages in sections other than section 1.
MAN1= ${SHPROG:S/$/.1/g}
CLEANFILES+= ${SHPROG} ${MAN1}
all: ${SHPROG}
.sh:
sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \
-e 's,%pager%,${pager},' \
${.ALLSRC} > ${.TARGET}
.SUFFIXES: .man .1
.man.1:
sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \
-e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \
-e 's,%manpath_config_file%,${manpath_config_file},' \
${.ALLSRC} > ${.TARGET}
beforeinstall:
${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${SHPROG} ${DESTDIR}${BINDIR}
.include <bsd.prog.mk>
+201
View File
@@ -0,0 +1,201 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Paul Borman at Krystal Technologies.
*
* 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93";
#endif /* LIBC_SCCS and not lint */
#include <limits.h>
#include <locale.h>
#include <rune.h>
#include <stdlib.h>
#include <string.h>
#include "common_setlocale.h"
#include "common_rune.h"
char *_PathLocale;
static char *loadlocale __P((int));
char *
setlocale(category, locale)
int category;
const char *locale;
{
int found, i, len;
char *env, *r;
if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
PathLocale = _PATH_LOCALE;
if (category < 0 || category >= _LC_LAST)
return (NULL);
if (!locale)
return (category ?
current_categories[category] : currentlocale());
/*
* Default to the current locale for everything.
*/
for (i = 1; i < _LC_LAST; ++i)
(void)strcpy(new_categories[i], current_categories[i]);
/*
* Now go fill up new_categories from the locale argument
*/
if (!*locale) {
env = getenv(categories[category]);
if (!env)
env = getenv(categories[0]);
if (!env)
env = getenv("LANG");
if (!env)
env = "C";
(void) strncpy(new_categories[category], env, 31);
new_categories[category][31] = 0;
if (!category) {
for (i = 1; i < _LC_LAST; ++i) {
if (!(env = getenv(categories[i])))
env = new_categories[0];
(void)strncpy(new_categories[i], env, 31);
new_categories[i][31] = 0;
}
}
} else if (category) {
(void)strncpy(new_categories[category], locale, 31);
new_categories[category][31] = 0;
} else {
if ((r = strchr(locale, '/')) == 0) {
for (i = 1; i < _LC_LAST; ++i) {
(void)strncpy(new_categories[i], locale, 31);
new_categories[i][31] = 0;
}
} else {
for (i = 1; r[1] == '/'; ++r);
if (!r[1])
return (NULL); /* Hmm, just slashes... */
do {
len = r - locale > 31 ? 31 : r - locale;
(void)strncpy(new_categories[i++], locale, len);
new_categories[i++][len] = 0;
locale = r;
while (*locale == '/')
++locale;
while (*++r && *r != '/');
} while (*locale);
while (i < _LC_LAST)
(void)strcpy(new_categories[i],
new_categories[i-1]);
}
}
if (category)
return (loadlocale(category));
found = 0;
for (i = 1; i < _LC_LAST; ++i)
if (loadlocale(i) != NULL)
found = 1;
if (found)
return (currentlocale());
return (NULL);
}
static char *
loadlocale(category)
int category;
{
#if 0
char name[PATH_MAX];
#endif
if (strcmp(new_categories[category],
current_categories[category]) == 0)
return (current_categories[category]);
if (category == LC_CTYPE) {
if (setrunelocale(new_categories[LC_CTYPE]))
return (NULL);
(void)strcpy(current_categories[LC_CTYPE],
new_categories[LC_CTYPE]);
return (current_categories[LC_CTYPE]);
}
if (category == LC_COLLATE) {
if (__collate_load_tables(new_categories[LC_COLLATE]) < 0)
return (NULL);
(void)strcpy(current_categories[LC_COLLATE],
new_categories[LC_COLLATE]);
return (current_categories[LC_COLLATE]);
}
if (category == LC_TIME) {
if (__time_load_locale(new_categories[LC_TIME]) < 0)
return (NULL);
(void)strcpy(current_categories[LC_TIME],
new_categories[LC_TIME]);
return (current_categories[LC_TIME]);
}
if (!strcmp(new_categories[category], "C") ||
!strcmp(new_categories[category], "POSIX")) {
/*
* Some day this will need to reset the locale to the default
* C locale. Since we have no way to change them as of yet,
* there is no need to reset them.
*/
(void)strcpy(current_categories[category],
new_categories[category]);
return (current_categories[category]);
}
#if 0
/*
* Some day we will actually look at this file.
*/
(void)snprintf(name, sizeof(name), "%s/%s/%s",
PathLocale, new_categories[category], categories[category]);
#endif
switch (category) {
case LC_MONETARY:
case LC_NUMERIC:
return (NULL);
}
}
-23
View File
@@ -1,23 +0,0 @@
LIB= disk
SRCS= blocks.c disklabel.c dkcksum.c chunk.c disk.c change.c \
create_chunk.c rules.c write_disk.c data.c
CFLAGS+= -Wall -g
CLEANFILES+= tmp.c tst01 tst01.o data.c
VPATH= ${.CURDIR}/../../sbin/disklabel
NOPROFILE= yes
NOSHARED= yes
.include <bsd.lib.mk>
BOOTS=/usr/mdec
data.c: libdisk.h ${BOOTS}/boot1 ${BOOTS}/boot2
file2c 'const unsigned char boot1[] = {' '};' \
< ${BOOTS}/boot1 > tmp.c
file2c 'const unsigned char boot2[] = {' '};' \
< ${BOOTS}/boot2 >> tmp.c
mv tmp.c data.c
tst01: tst01.o libdisk.a
cc ${CFLAGS} -static tst01.o -o tst01 libdisk.a
-41
View File
@@ -1,41 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: blocks.c,v 1.2 1995/04/29 01:55:17 phk Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <err.h>
#include "libdisk.h"
void *
read_block(int fd, daddr_t block)
{
void *foo;
foo = malloc(512);
if (!foo)
err(1,"malloc");
if (-1 == lseek(fd,block * 512,SEEK_SET))
err(1,"lseek");
if (512 != read(fd,foo, 512))
err(1,"read");
return foo;
}
void
write_block(int fd, daddr_t block, void *foo)
{
if (-1 == lseek(fd,block * 512,SEEK_SET))
err(1,"lseek");
if (512 != write(fd,foo, 512))
err(1,"write");
}
-62
View File
@@ -1,62 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: change.c,v 1.9 1995/06/11 19:29:31 rgrimes Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <err.h>
#include <sys/types.h>
#include "libdisk.h"
#if 0
struct disk *
Set_Phys_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect)
{
struct disk *d = Int_Open_Disk(disk->name,cyl*hd*sect);
d->real_cyl = cyl;
d->real_hd = hd;
d->real_sect = sect;
d->bios_cyl = disk->bios_cyl;
d->bios_hd = disk->bios_hd;
d->bios_sect = disk->bios_sect;
d->flags = disk->flags;
Free_Disk(disk);
return d;
}
#endif
void
Set_Bios_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect)
{
disk->bios_cyl = cyl;
disk->bios_hd = hd;
disk->bios_sect = sect;
Bios_Limit_Chunk(disk->chunks,1024*hd*sect);
}
void
All_FreeBSD(struct disk *d, int force_all)
{
struct chunk *c;
again:
for (c=d->chunks->part;c;c=c->next)
if (c->type != unused) {
Delete_Chunk(d,c);
goto again;
}
c=d->chunks;
Create_Chunk(d,c->offset,c->size,freebsd,0xa5,
force_all? CHUNK_FORCE_ALL: 0);
}
-433
View File
@@ -1,433 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: chunk.c,v 1.14.2.2 1995/06/05 02:24:25 jkh Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <err.h>
#include "libdisk.h"
#define new_chunk() memset(malloc(sizeof(struct chunk)), 0, sizeof(struct chunk))
/* Is c2 completely inside c1 ? */
static int
Chunk_Inside(struct chunk *c1, struct chunk *c2)
{
/* if c1 ends before c2 do */
if (c1->end < c2->end)
return 0;
/* if c1 starts after c2 do */
if (c1->offset > c2->offset)
return 0;
return 1;
}
struct chunk *
Find_Mother_Chunk(struct chunk *chunks, u_long offset, u_long end, chunk_e type)
{
struct chunk *c1,*c2,ct;
ct.offset = offset;
ct.end = end;
switch (type) {
case whole:
if (Chunk_Inside(chunks,&ct))
return chunks;
case extended:
for(c1=chunks->part;c1;c1=c1->next) {
if (c1->type != type)
continue;
if (Chunk_Inside(c1,&ct))
return c1;
}
return 0;
case freebsd:
for(c1=chunks->part;c1;c1=c1->next) {
if (c1->type == type)
if (Chunk_Inside(c1,&ct))
return c1;
if (c1->type != extended)
continue;
for(c2=c1->part;c2;c2=c2->next)
if (c2->type == type
&& Chunk_Inside(c2,&ct))
return c2;
}
return 0;
default:
warn("Unsupported mother (0x%x) in Find_Mother_Chunk");
return 0;
}
}
void
Free_Chunk(struct chunk *c1)
{
if(!c1) return;
if(c1->private && c1->private_free)
(*c1->private_free)(c1->private);
if(c1->part)
Free_Chunk(c1->part);
if(c1->next)
Free_Chunk(c1->next);
free(c1->name);
free(c1);
}
struct chunk *
Clone_Chunk(struct chunk *c1)
{
struct chunk *c2;
if(!c1)
return 0;
c2 = new_chunk();
if (!c2) err(1,"malloc failed");
*c2 = *c1;
if (c1->private && c1->private_clone)
c2->private = c2->private_clone(c2->private);
c2->name = strdup(c2->name);
c2->next = Clone_Chunk(c2->next);
c2->part = Clone_Chunk(c2->part);
return c2;
}
int
Insert_Chunk(struct chunk *c2, u_long offset, u_long size, char *name, chunk_e type, int subtype, u_long flags)
{
struct chunk *ct,*cs;
/* We will only insert into empty spaces */
if (c2->type != unused)
return __LINE__;
ct = new_chunk();
if (!ct) err(1,"malloc failed");
memset(ct,0,sizeof *ct);
ct->disk = c2->disk;
ct->offset = offset;
ct->size = size;
ct->end = offset + size - 1;
ct->type = type;
ct->name = strdup(name);
ct->subtype = subtype;
ct->flags = flags;
if (!Chunk_Inside(c2,ct)) {
Free_Chunk(ct);
return __LINE__;
}
if(type==freebsd || type==extended) {
cs = new_chunk();
if (!cs) err(1,"malloc failed");
memset(cs,0,sizeof *cs);
cs->disk = c2->disk;
cs->offset = offset;
cs->size = size;
cs->end = offset + size - 1;
cs->type = unused;
cs->name = strdup("-");
ct->part = cs;
}
/* Make a new chunk for any trailing unused space */
if (c2->end > ct->end) {
cs = new_chunk();
if (!cs) err(1,"malloc failed");
*cs = *c2;
cs->disk = c2->disk;
cs->offset = ct->end + 1;
cs->size = c2->end - ct->end;
if(c2->name)
cs->name = strdup(c2->name);
c2->next = cs;
c2->size -= c2->end - ct->end;
c2->end = ct->end;
}
/* If no leading unused space just occupy the old chunk */
if (c2->offset == ct->offset) {
c2->name = ct->name;
c2->type = ct->type;
c2->part = ct->part;
c2->subtype = ct->subtype;
c2->flags = ct->flags;
ct->name = 0;
ct->part = 0;
Free_Chunk(ct);
return 0;
}
/* else insert new chunk and adjust old one */
c2->end = ct->offset - 1;
c2->size -= ct->size;
ct->next = c2->next;
c2->next = ct;
return 0;
}
int
Add_Chunk(struct disk *d, long offset, u_long size, char *name, chunk_e type,
int subtype, u_long flags)
{
struct chunk *c1,*c2,ct;
u_long end = offset + size - 1;
ct.offset = offset;
ct.end = end;
ct.size = size;
if (type == whole) {
d->chunks = c1 = new_chunk();
if (!c1) err(1,"malloc failed");
memset(c1,0,sizeof *c1);
c2 = c1->part = new_chunk();
if (!c2) err(1,"malloc failed");
memset(c2,0,sizeof *c2);
c2->disk = c1->disk = d;
c2->offset = c1->offset = offset;
c2->size = c1->size = size;
c2->end = c1->end = end;
c1->name = strdup(name);
c2->name = strdup("-");
c1->type = type;
c2->type = unused;
c1->flags = flags;
c1->subtype = subtype;
return 0;
}
if (type == freebsd)
subtype = 0xa5;
c1 = 0;
if(!c1 && (type == freebsd || type == fat || type == unknown))
c1 = Find_Mother_Chunk(d->chunks,offset,end,extended);
if(!c1 && (type == freebsd || type == fat || type == unknown))
c1 = Find_Mother_Chunk(d->chunks,offset,end,whole);
if(!c1 && type == extended)
c1 = Find_Mother_Chunk(d->chunks,offset,end,whole);
if(!c1 && type == part)
c1 = Find_Mother_Chunk(d->chunks,offset,end,freebsd);
if(!c1)
return __LINE__;
for(c2=c1->part;c2;c2=c2->next) {
if (c2->type != unused)
continue;
if(Chunk_Inside(c2,&ct)) {
if (type != freebsd)
goto doit;
if (!(flags & CHUNK_ALIGN))
goto doit;
if (offset == d->chunks->offset
&& end == d->chunks->end)
goto doit;
/* Round down to prev cylinder */
offset = Prev_Cyl_Aligned(d,offset);
/* Stay inside the parent */
if (offset < c2->offset)
offset = c2->offset;
/* Round up to next cylinder */
offset = Next_Cyl_Aligned(d,offset);
/* Keep one track clear in front of parent */
if (offset == c1->offset)
offset = Next_Track_Aligned(d,offset+1);
/* Work on the (end+1) */
size += offset;
/* Round up to cylinder */
size = Next_Cyl_Aligned(d,size);
/* Stay inside parent */
if ((size-1) > c2->end)
size = c2->end+1;
/* Round down to cylinder */
size = Prev_Cyl_Aligned(d,size);
/* Convert back to size */
size -= offset;
doit:
return Insert_Chunk(c2,offset,size,name,
type,subtype,flags);
}
}
return __LINE__;
}
char *
ShowChunkFlags(struct chunk *c)
{
static char ret[10];
int i=0;
if (c->flags & CHUNK_BSD_COMPAT) ret[i++] = 'C';
if (c->flags & CHUNK_ACTIVE) ret[i++] = 'A';
if (c->flags & CHUNK_ALIGN) ret[i++] = '=';
if (c->flags & CHUNK_PAST_1024) ret[i++] = '>';
if (c->flags & CHUNK_IS_ROOT) ret[i++] = 'R';
if (c->flags & CHUNK_BAD144) ret[i++] = 'B';
ret[i++] = '\0';
return ret;
}
void
Print_Chunk(struct chunk *c1,int offset)
{
int i;
if(!c1) return;
for(i=0;i<offset-2;i++) putchar(' ');
for(;i<offset;i++) putchar('-');
putchar('>');
for(;i<10;i++) putchar(' ');
printf("%p %8ld %8lu %8lu %-8s %-8s 0x%02x %s",
c1, c1->offset, c1->size, c1->end, c1->name,
chunk_n[c1->type],c1->subtype,
ShowChunkFlags(c1));
putchar('\n');
Print_Chunk(c1->part,offset + 2);
Print_Chunk(c1->next,offset);
}
void
Debug_Chunk(struct chunk *c1)
{
Print_Chunk(c1,2);
}
void
Bios_Limit_Chunk(struct chunk *c1, u_long limit)
{
if (c1->part)
Bios_Limit_Chunk(c1->part,limit);
if (c1->next)
Bios_Limit_Chunk(c1->next,limit);
if (c1->end >= limit) {
c1->flags |= CHUNK_PAST_1024;
} else {
c1->flags &= ~CHUNK_PAST_1024;
}
}
int
Delete_Chunk(struct disk *d, struct chunk *c)
{
struct chunk *c1=0,*c2,*c3;
chunk_e type = c->type;
if(type == whole)
return 1;
if(!c1 && (type == freebsd || type == fat || type == unknown))
c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,extended);
if(!c1 && (type == freebsd || type == fat || type == unknown))
c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,whole);
if(!c1 && type == extended)
c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,whole);
if(!c1 && type == part)
c1 = Find_Mother_Chunk(d->chunks,c->offset,c->end,freebsd);
if(!c1)
return 1;
for(c2=c1->part;c2;c2=c2->next) {
if (c2 == c) {
c2->type = unused;
c2->subtype = 0;
c2->flags = 0;
free(c2->name);
c2->name = strdup("-");
Free_Chunk(c2->part);
c2->part =0;
goto scan;
}
}
return 1;
scan:
for(c2=c1->part;c2;c2=c2->next) {
if (c2->type != unused)
continue;
if (!c2->next)
continue;
if (c2->next->type != unused)
continue;
c3 = c2->next;
c2->size += c3->size;
c2->end = c3->end;
c2->next = c3->next;
c3->next = 0;
Free_Chunk(c3);
goto scan;
}
Fixup_Names(d);
return 0;
}
#if 0
int
Collapse_Chunk(struct disk *d, struct chunk *c1)
{
struct chunk *c2, *c3;
if(c1->next && Collapse_Chunk(d,c1->next))
return 1;
if(c1->type == unused && c1->next && c1->next->type == unused) {
c3 = c1->next;
c1->size += c3->size;
c1->end = c3->end;
c1->next = c3->next;
c3->next = 0;
Free_Chunk(c3);
return 1;
}
c3 = c1->part;
if(!c3)
return 0;
if (Collapse_Chunk(d,c1->part))
return 1;
if (c1->type == whole)
return 0;
if(c3->type == unused && c3->size == c1->size) {
Delete_Chunk(d,c1);
return 1;
}
if(c3->type == unused) {
c2 = new_chunk();
if (!c2) err(1,"malloc failed");
*c2 = *c1;
c1->next = c2;
c1->disk = d;
c1->name = strdup("-");
c1->part = 0;
c1->type = unused;
c1->flags = 0;
c1->subtype = 0;
c1->size = c3->size;
c1->end = c3->end;
c2->offset += c1->size;
c2->size -= c1->size;
c2->part = c3->next;
c3->next = 0;
Free_Chunk(c3);
return 1;
}
for(c2=c3;c2->next;c2 = c2->next)
c3 = c2;
if (c2 && c2->type == unused) {
c3->next = 0;
c2->next = c1->next;
c1->next = c2;
c1->size -= c2->size;
c1->end -= c2->size;
return 1;
}
return 0;
}
#endif
-359
View File
@@ -1,359 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: create_chunk.c,v 1.21.2.5 1995/11/17 23:04:04 jkh Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/disklabel.h>
#include <sys/diskslice.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <err.h>
#include "libdisk.h"
/* Clone these two from sysinstall because we need our own copies
* due to link order problems with `crunch'. Feh!
*/
static int
isDebug()
{
static int debug = 0; /* Allow debugger to tweak it */
return debug;
}
/* Write something to the debugging port */
static void
msgDebug(char *fmt, ...)
{
va_list args;
char *dbg;
static int DebugFD = -1;
if (DebugFD == -1)
DebugFD = open("/dev/ttyv1", O_RDWR);
dbg = (char *)alloca(FILENAME_MAX);
strcpy(dbg, "DEBUG: ");
va_start(args, fmt);
vsnprintf((char *)(dbg + strlen(dbg)), FILENAME_MAX, fmt, args);
va_end(args);
write(DebugFD, dbg, strlen(dbg));
}
void
Fixup_FreeBSD_Names(struct disk *d, struct chunk *c)
{
struct chunk *c1, *c3;
int j;
if (!strcmp(c->name, "X")) return;
/* reset all names to "X" */
for (c1 = c->part; c1 ; c1 = c1->next) {
c1->oname = c1->name;
c1->name = malloc(12);
if(!c1->name) err(1,"Malloc failed");
strcpy(c1->name,"X");
}
/* Allocate the first swap-partition we find */
for (c1 = c->part; c1 ; c1 = c1->next) {
if (c1->type == unused) continue;
if (c1->subtype != FS_SWAP) continue;
sprintf(c1->name,"%s%c",c->name,SWAP_PART+'a');
break;
}
/* Allocate the first root-partition we find */
for (c1 = c->part; c1 ; c1 = c1->next) {
if (c1->type == unused) continue;
if (!(c1->flags & CHUNK_IS_ROOT)) continue;
sprintf(c1->name,"%s%c",c->name,0+'a');
break;
}
/* Try to give them the same as they had before */
for (c1 = c->part; c1 ; c1 = c1->next) {
if (strcmp(c1->name,"X")) continue;
for(c3 = c->part; c3 ; c3 = c3->next)
if (c1 != c3 && !strcmp(c3->name, c1->oname)) {
goto newname;
}
strcpy(c1->name,c1->oname);
newname:
}
/* Allocate the rest sequentially */
for (c1 = c->part; c1 ; c1 = c1->next) {
const char order[] = "efghabd";
if (c1->type == unused) continue;
if (strcmp("X",c1->name)) continue;
for(j=0;j<strlen(order);j++) {
sprintf(c1->name,"%s%c",c->name,order[j]);
for(c3 = c->part; c3 ; c3 = c3->next)
if (c1 != c3 && !strcmp(c3->name, c1->name))
goto match;
break;
match:
strcpy(c1->name,"X");
continue;
}
}
for (c1 = c->part; c1 ; c1 = c1->next) {
free(c1->oname);
c1->oname = 0;
}
}
void
Fixup_Extended_Names(struct disk *d, struct chunk *c)
{
struct chunk *c1;
int j=5;
for (c1 = c->part; c1 ; c1 = c1->next) {
if (c1->type == unused) continue;
free(c1->name);
c1->name = malloc(12);
if(!c1->name) err(1,"malloc failed");
sprintf(c1->name,"%ss%d",d->chunks->name,j++);
if (c1->type == freebsd)
Fixup_FreeBSD_Names(d,c1);
}
}
void
Fixup_Names(struct disk *d)
{
struct chunk *c1, *c2, *c3;
int i,j;
c1 = d->chunks;
for(i=1,c2 = c1->part; c2 ; c2 = c2->next) {
c2->flags &= ~CHUNK_BSD_COMPAT;
if (c2->type == unused)
continue;
if (strcmp(c2->name,"X"))
continue;
c2->oname = malloc(12);
if(!c2->oname) err(1,"malloc failed");
for(j=1;j<=NDOSPART;j++) {
sprintf(c2->oname,"%ss%d",c1->name,j);
for(c3 = c1->part; c3 ; c3 = c3->next)
if (c3 != c2 && !strcmp(c3->name, c2->oname))
goto match;
free(c2->name);
c2->name = c2->oname;
c2->oname = 0;
break;
match:
continue;
}
if (c2->oname)
free(c2->oname);
}
for(c2 = c1->part; c2 ; c2 = c2->next) {
if (c2->type == freebsd) {
c2->flags |= CHUNK_BSD_COMPAT;
break;
}
}
for(c2 = c1->part; c2 ; c2 = c2->next) {
if (c2->type == freebsd)
Fixup_FreeBSD_Names(d,c2);
if (c2->type == extended)
Fixup_Extended_Names(d,c2);
}
}
int
Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags)
{
int i;
u_long l;
if(!(flags & CHUNK_FORCE_ALL))
{
/* Never use the first track */
if (!offset) {
offset += d->bios_sect;
size -= d->bios_sect;
}
/* Always end on cylinder boundary */
l = (offset+size) % (d->bios_sect * d->bios_hd);
size -= l;
}
i = Add_Chunk(d,offset,size,"X",type,subtype,flags);
Fixup_Names(d);
return i;
}
struct chunk *
Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags)
{
int i;
struct chunk *c1;
u_long offset,edge;
if (!parent)
parent = d->chunks;
for (c1=parent->part; c1 ; c1 = c1->next) {
if (c1->type != unused) continue;
if (c1->size < size) continue;
offset = c1->offset;
goto found;
}
warn("Not enough unused space");
return 0;
found:
if (parent->flags & CHUNK_BAD144) {
edge = c1->end - d->bios_sect - 127;
if (offset > edge)
return 0;
if (offset + size > edge)
size = edge - offset + 1;
}
i = Add_Chunk(d,offset,size,"X",type,subtype,flags);
if (i) {
warn("Didn't cut it");
return 0;
}
Fixup_Names(d);
for (c1=parent->part; c1 ; c1 = c1->next)
if (c1->offset == offset)
return c1;
err(1,"Serious internal trouble");
}
int
MakeDev(struct chunk *c1, char *path)
{
char *p = c1->name;
u_long cmaj, bmaj, min, unit, part, slice;
char buf[BUFSIZ], buf2[BUFSIZ];
*buf2 = '\0';
if (isDebug())
msgDebug("MakeDev: Called with %s on path %s\n", p, path);
if (!strcmp(p, "X"))
return 0;
if (!strncmp(p, "wd", 2))
bmaj = 0, cmaj = 3;
else if (!strncmp(p, "sd", 2))
bmaj = 4, cmaj = 13;
else {
return 0;
}
p += 2;
if (!isdigit(*p)) {
msgDebug("MakeDev: Invalid disk unit passed: %s\n", p);
return 0;
}
unit = *p - '0';
p++;
if (!*p) {
slice = 1;
part = 2;
goto done;
}
else if (isdigit(*p)) {
unit *= 10;
unit += (*p - '0');
p++;
}
if (*p != 's') {
msgDebug("MakeDev: `%s' is not a valid slice delimiter\n", p);
return 0;
}
p++;
if (!isdigit(*p)) {
msgDebug("MakeDev: `%s' is an invalid slice number\n", p);
return 0;
}
slice = *p - '0';
p++;
if (isdigit(*p)) {
slice *= 10;
slice += (*p - '0');
p++;
}
slice = slice + 1;
if (!*p) {
part = 2;
if(c1->type == freebsd)
sprintf(buf2, "%sc", c1->name);
goto done;
}
if (*p < 'a' || *p > 'h') {
msgDebug("MakeDev: `%s' is not a valid partition name.\n", p);
return 0;
}
part = *p - 'a';
done:
if (isDebug())
msgDebug("MakeDev: Unit %d, Slice %d, Part %d\n", unit, slice, part);
if (unit > 32)
return 0;
if (slice > 32)
return 0;
min = unit * 8 + 65536 * slice + part;
sprintf(buf, "%s/r%s", path, c1->name);
unlink(buf);
if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
msgDebug("mknod of %s returned failure status!\n", buf);
return 0;
}
if (*buf2) {
sprintf(buf, "%s/r%s", path, buf2);
unlink(buf);
if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
msgDebug("mknod of %s returned failure status!\n", buf);
return 0;
}
}
sprintf(buf, "%s/%s", path, c1->name);
unlink(buf);
if (mknod(buf, S_IFBLK|0640, makedev(bmaj,min)) == -1) {
msgDebug("mknod of %s returned failure status!\n", buf);
return 0;
}
return 1;
}
int
MakeDevChunk(struct chunk *c1, char *path)
{
int i;
i = MakeDev(c1, path);
if (c1->next)
MakeDevChunk(c1->next, path);
if (c1->part)
MakeDevChunk(c1->part, path);
return i;
}
int
MakeDevDisk(struct disk *d, char *path)
{
return MakeDevChunk(d->chunks, path);
}
-327
View File
@@ -1,327 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: disk.c,v 1.19.2.2 1995/06/05 02:24:27 jkh Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <err.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/diskslice.h>
#include "libdisk.h"
#define DOSPTYP_EXTENDED 5
#define DOSPTYP_ONTRACK 84
char *chunk_n[] = {
"whole",
"unknown",
"fat",
"freebsd",
"extended",
"part",
"unused",
NULL
};
struct disk *
Open_Disk(char *name)
{
return Int_Open_Disk(name,0);
}
struct disk *
Int_Open_Disk(char *name, u_long size)
{
int i,fd;
struct diskslices ds;
struct disklabel dl;
char device[64];
struct disk *d;
struct dos_partition *dp;
void *p;
u_long offset = 0;
strcpy(device,"/dev/r");
strcat(device,name);
d = (struct disk *)malloc(sizeof *d);
if(!d) err(1,"malloc failed");
memset(d,0,sizeof *d);
fd = open(device,O_RDONLY);
if (fd < 0) {
warn("open(%s) failed",device);
return 0;
}
memset(&dl,0,sizeof dl);
ioctl(fd,DIOCGDINFO,&dl);
i = ioctl(fd,DIOCGSLICEINFO,&ds);
if (i < 0) {
warn("DIOCGSLICEINFO(%s) failed",device);
close(fd);
return 0;
}
#ifdef DEBUG
for(i=0;i<ds.dss_nslices;i++)
if(ds.dss_slices[i].ds_openmask)
printf(" open(%d)=0x%2x",
i,ds.dss_slices[i].ds_openmask);
printf("\n");
#endif
if (!size)
size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size;
p = read_block(fd,0);
dp = (struct dos_partition*)(p+DOSPARTOFF);
for(i=0;i<NDOSPART;i++) {
if (dp->dp_start >= size) continue;
if (dp->dp_start+dp->dp_size >= size) continue;
if (!dp->dp_size) continue;
if (dp->dp_typ == DOSPTYP_ONTRACK) {
d->flags |= DISK_ON_TRACK;
offset = 63;
}
}
free(p);
d->bios_sect = dl.d_nsectors;
d->bios_hd = dl.d_ntracks;
d->name = strdup(name);
if (dl.d_ntracks && dl.d_nsectors)
d->bios_cyl = size/(dl.d_ntracks*dl.d_nsectors);
if (Add_Chunk(d, -offset, size, name,whole,0,0))
warn("Failed to add 'whole' chunk");
for(i=BASE_SLICE;i<ds.dss_nslices;i++) {
char sname[20];
chunk_e ce;
u_long flags=0;
int subtype=0;
if (! ds.dss_slices[i].ds_size)
continue;
ds.dss_slices[i].ds_offset -= offset;
sprintf(sname,"%ss%d",name,i-1);
subtype = ds.dss_slices[i].ds_type;
switch (ds.dss_slices[i].ds_type) {
case 0xa5:
ce = freebsd;
break;
case 0x1:
case 0x6:
case 0x4:
ce = fat;
break;
case DOSPTYP_EXTENDED:
ce = extended;
break;
default:
ce = unknown;
break;
}
if (Add_Chunk(d,ds.dss_slices[i].ds_offset,
ds.dss_slices[i].ds_size, sname,ce,subtype,flags))
warn("failed to add chunk for slice %d",i - 1);
if (ds.dss_slices[i].ds_type != 0xa5)
continue;
{
struct disklabel dl;
char pname[20];
int j,k;
strcpy(pname,"/dev/r");
strcat(pname,sname);
j = open(pname,O_RDONLY);
if (j < 0) {
warn("open(%s)",pname);
continue;
}
k = ioctl(j,DIOCGDINFO,&dl);
if (k < 0) {
warn("ioctl(%s,DIOCGDINFO)",pname);
close(j);
continue;
}
close(j);
for(j=0; j <= dl.d_npartitions; j++) {
if (j == RAW_PART)
continue;
if (j == 3)
continue;
if (j == dl.d_npartitions) {
j = 3;
dl.d_npartitions=0;
}
if (!dl.d_partitions[j].p_size)
continue;
if (dl.d_partitions[j].p_size +
dl.d_partitions[j].p_offset >
ds.dss_slices[i].ds_size)
continue;
sprintf(pname,"%s%c",sname,j+'a');
if (Add_Chunk(d,
dl.d_partitions[j].p_offset +
ds.dss_slices[i].ds_offset,
dl.d_partitions[j].p_size,
pname,part,
dl.d_partitions[j].p_fstype,
0) && j != 3)
warn(
"Failed to add chunk for partition %c [%lu,%lu]",
j + 'a',dl.d_partitions[j].p_offset,
dl.d_partitions[j].p_size);
}
}
}
close(fd);
Fixup_Names(d);
Bios_Limit_Chunk(d->chunks,1024*d->bios_hd*d->bios_sect);
return d;
}
void
Debug_Disk(struct disk *d)
{
printf("Debug_Disk(%s)",d->name);
printf(" flags=%lx",d->flags);
#if 0
printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect);
#endif
printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect);
printf(" boot1=%p, boot2=%p, bootmgr=%p\n",
d->boot1,d->boot2,d->bootmgr);
Debug_Chunk(d->chunks);
}
void
Free_Disk(struct disk *d)
{
if(d->chunks) Free_Chunk(d->chunks);
if(d->name) free(d->name);
if(d->bootmgr) free(d->bootmgr);
if(d->boot1) free(d->boot1);
if(d->boot2) free(d->boot2);
free(d);
}
struct disk *
Clone_Disk(struct disk *d)
{
struct disk *d2;
d2 = (struct disk*) malloc(sizeof *d2);
if(!d2) err(1,"malloc failed");
*d2 = *d;
d2->name = strdup(d2->name);
d2->chunks = Clone_Chunk(d2->chunks);
if(d2->bootmgr) {
d2->bootmgr = malloc(DOSPARTOFF);
memcpy(d2->bootmgr,d->bootmgr,DOSPARTOFF);
}
if(d2->boot1) {
d2->boot1 = malloc(512);
memcpy(d2->boot1,d->boot1,512);
}
if(d2->boot2) {
d2->boot2 = malloc(512*15);
memcpy(d2->boot2,d->boot2,512*15);
}
return d2;
}
#if 0
void
Collapse_Disk(struct disk *d)
{
while(Collapse_Chunk(d,d->chunks))
;
}
#endif
static char * device_list[] = {"wd","sd",0};
char **
Disk_Names()
{
int i,j,k;
char disk[25];
char diskname[25];
struct stat st;
struct diskslices ds;
int fd;
static char **disks;
disks = malloc(sizeof *disks * (1 + MAX_NO_DISKS));
memset(disks,0,sizeof *disks * (1 + MAX_NO_DISKS));
k = 0;
for (j = 0; device_list[j]; j++) {
for (i = 0; i < 10; i++) {
sprintf(diskname, "%s%d", device_list[j], i);
sprintf(disk, "/dev/r%s", diskname);
if (stat(disk, &st) || !(st.st_mode & S_IFCHR))
continue;
if ((fd = open(disk, O_RDWR)) == -1)
continue;
if (ioctl(fd, DIOCGSLICEINFO, &ds) == -1) {
close(fd);
continue;
}
disks[k++] = strdup(diskname);
if(k == MAX_NO_DISKS)
return disks;
}
}
return disks;
}
void
Set_Boot_Mgr(struct disk *d, u_char *b)
{
if (d->bootmgr)
free(d->bootmgr);
if (!b) {
d->bootmgr = 0;
} else {
d->bootmgr = malloc(DOSPARTOFF);
if(!d->bootmgr) err(1,"malloc failed");
memcpy(d->bootmgr,b,DOSPARTOFF);
}
}
void
Set_Boot_Blocks(struct disk *d, u_char *b1, u_char *b2)
{
if (d->boot1) free(d->boot1);
d->boot1 = malloc(512);
if(!d->boot1) err(1,"malloc failed");
memcpy(d->boot1,b1,512);
if (d->boot2) free(d->boot2);
d->boot2 = malloc(15*512);
if(!d->boot2) err(1,"malloc failed");
memcpy(d->boot2,b2,15*512);
}
-33
View File
@@ -1,33 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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$
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <err.h>
#include <sys/disklabel.h>
#include "libdisk.h"
struct disklabel *
read_disklabel(int fd, daddr_t block)
{
struct disklabel *dp;
dp = (struct disklabel *) read_block(fd,block);
if (dp->d_magic != DISKMAGIC)
return 0;
if (dp->d_magic2 != DISKMAGIC)
return 0;
if (dkcksum(dp) != 0)
return 0;
return dp;
}
-324
View File
@@ -1,324 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: libdisk.h,v 1.19.2.1 1995/09/20 10:43:03 jkh Exp $
*
*/
#define MAX_NO_DISKS 20
/* Max # of disks Disk_Names() will return */
typedef enum {
whole,
unknown,
fat,
freebsd,
extended,
part,
unused,
} chunk_e;
extern char *chunk_n[];
struct disk {
char *name;
u_long flags;
# define DISK_ON_TRACK 1
#if 0
u_long real_cyl;
u_long real_hd;
u_long real_sect;
#endif
u_long bios_cyl;
u_long bios_hd;
u_long bios_sect;
u_char *bootmgr;
u_char *boot1;
u_char *boot2;
struct chunk *chunks;
};
struct chunk {
struct chunk *next;
struct chunk *part;
struct disk *disk;
long offset;
u_long size;
u_long end;
char *name;
char *oname;
/* Used during Fixup_Names() to avoid renaming more than
* absolutely needed.
*/
chunk_e type;
int subtype;
u_long flags;
# define CHUNK_PAST_1024 1
/* this chunk cannot be booted from because it
* extends past cylinder 1024
*/
# define CHUNK_BSD_COMPAT 2
/* this chunk is in the BSD-compatibility, and has a
* short name too, ie wd0s4f -> wd0f
*/
# define CHUNK_BAD144 4
/* this chunk has bad144 mapping */
# define CHUNK_ALIGN 8
/* This chunk should be aligned */
# define CHUNK_IS_ROOT 16
/* This 'part' is a rootfs, allocate 'a' */
# define CHUNK_ACTIVE 32
/* This is the active slice in the MBR */
# define CHUNK_FORCE_ALL 64
/* Force a dedicated disk for FreeBSD, bypassing
* all BIOS geometry considerations
*/
void (*private_free)(void*);
void *(*private_clone)(void*);
void *private;
/* For data private to the application, and the management
* thereof. If the functions are not provided, no storage
* management is done, Cloning will just copy the pointer
* and freeing will just forget it.
*/
};
struct disk *
Open_Disk(char *devname);
/* Will open the named disk, and return populated tree.
*/
struct disk *
Clone_Disk(struct disk *disk);
/* Clone a copy of a tree. Useful for "Undo" functionality
*/
void
Free_Disk(struct disk *disk);
/* Free a tree made with Open_Disk() or Clone_Disk()
*/
void
Debug_Disk(struct disk *disk);
/* Print the content of the tree to stdout
*/
#if 0
struct disk *
Set_Phys_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
/* Use a different physical geometry. Makes sense for ST506 disks only.
* The tree returned is read from the disk, using this geometry.
*/
#endif
void
Set_Bios_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
/* Set the geometry the bios uses.
*/
int
Delete_Chunk(struct disk *disk, struct chunk *);
/* Free a chunk of disk_space
*/
void
Collapse_Disk(struct disk *disk);
/* Experimental, do not use.
*/
int
Collapse_Chunk(struct disk *disk, struct chunk *chunk);
/* Experimental, do not use.
*/
int
Create_Chunk(struct disk *disk, u_long offset, u_long size, chunk_e type, int subtype, u_long flags);
/* Create a chunk with the specified paramters
*/
void
All_FreeBSD(struct disk *d, int force_all);
/* Make one FreeBSD chunk covering the entire disk;
* if force_all is set, bypass all BIOS geometry
* considerations.
*/
char *
CheckRules(struct disk *);
/* Return char* to warnings about broken design rules in this disklayout
*/
char **
Disk_Names();
/* Return char** with all disk's names (wd0, wd1 ...). You must free
* each pointer, as well as the array by hand
*/
void
Set_Boot_Mgr(struct disk *d, u_char *bootmgr);
/* Use this boot-manager on this disk. Gets written when Write_Disk()
* is called
*/
void
Set_Boot_Blocks(struct disk *d, u_char *boot1, u_char *boot2);
/* Use these boot-blocks on this disk. Gets written when Write_Disk()
* is called
*/
int
Write_Disk(struct disk *d);
/* Write all the MBRs, disklabels, bootblocks and boot managers
*/
int
Cyl_Aligned(struct disk *d, u_long offset);
/* Check if offset is aligned on a cylinder according to the
* bios geometry
*/
u_long
Next_Cyl_Aligned(struct disk *d, u_long offset);
/* Round offset up to next cylinder according to the bios-geometry
*/
u_long
Prev_Cyl_Aligned(struct disk *d, u_long offset);
/* Round offset down to previous cylinder according to the bios-
* geometry
*/
int
Track_Aligned(struct disk *d, u_long offset);
/* Check if offset is aligned on a track according to the
* bios geometry
*/
u_long
Next_Track_Aligned(struct disk *d, u_long offset);
/* Round offset up to next track according to the bios-geometry
*/
u_long
Prev_Track_Aligned(struct disk *d, u_long offset);
/* Check if offset is aligned on a track according to the
* bios geometry
*/
struct chunk *
Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags);
/* This one creates a partition inside the given parent of the given
* size, and returns a pointer to it. The first unused chunk big
* enough is used.
*/
int
MakeDev(struct chunk *c, char *path);
int
MakeDevDisk(struct disk *d,char *path);
/* Make device nodes for all chunks on this disk */
char *
ShowChunkFlags(struct chunk *c);
/* Return string to show flags. */
char *
ChunkCanBeRoot(struct chunk *c);
/* Return NULL if chunk can be /, explanation otherwise */
/*
* Implementation details >>> DO NOT USE <<<
*/
void Debug_Chunk(struct chunk *);
void Free_Chunk(struct chunk *);
struct chunk * Clone_Chunk(struct chunk *);
int Add_Chunk(struct disk *, long , u_long , char *, chunk_e, int , u_long);
void Bios_Limit_Chunk(struct chunk *, u_long);
void * read_block(int, daddr_t );
void write_block(int fd, daddr_t block, void *foo);
struct disklabel * read_disklabel(int, daddr_t);
u_short dkcksum(struct disklabel *);
struct chunk * Find_Mother_Chunk(struct chunk *, u_long , u_long , chunk_e);
struct disk * Int_Open_Disk(char *name, u_long size);
void Fixup_Names(struct disk *);
#define dprintf printf
/* TODO
*
* Need a error string mechanism from the functions instead of warn()
*
* Make sure only FreeBSD start at offset==0
*
* Collapse must align.
*
* Make Write_Disk(struct disk*)
*
* Consider booting from OnTrack'ed disks.
*
* Get Bios-geom, ST506 & OnTrack from driver (or otherwise)
*
* Make Create_DWIM().
*
* Make Is_Unchanged(struct disk *d1, struct chunk *c1)
*
* don't rename slices unless we have to
*
*Sample output from tst01:
*
* Debug_Disk(wd0) flags=0 real_geom=0/0/0 bios_geom=0/0/0
* >> 0x3d040 0 1411200 1411199 wd0 0 whole 0 0
* >>>> 0x3d080 0 960120 960119 wd0s1 3 freebsd 0 8
* >>>>>> 0x3d100 0 40960 40959 wd0s1a 5 part 0 0
* >>>>>> 0x3d180 40960 131072 172031 wd0s1b 5 part 0 0
* >>>>>> 0x3d1c0 172032 409600 581631 wd0s1e 5 part 0 0
* >>>>>> 0x3d200 581632 378488 960119 wd0s1f 5 part 0 0
* >>>> 0x3d140 960120 5670 965789 wd0s2 4 extended 0 8
* >>>>>> 0x3d2c0 960120 63 960182 - 6 unused 0 0
* >>>>>> 0x3d0c0 960183 5607 965789 wd0s5 2 fat 0 8
* >>>> 0x3d280 965790 1890 967679 wd0s3 1 foo -2 8
* >>>> 0x3d300 967680 443520 1411199 wd0s4 3 freebsd 0 8
* >>>>>> 0x3d340 967680 443520 1411199 wd0s4a 5 part 0 0
*
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
* level chunkptr start size end name type subtype flags
*
* Underlying data structure:
*
* Legend:
* <struct chunk> --> part
* |
* v next
*
* <wd0> --> <wd0s1> --> <wd0s1a>
* | |
* | v
* | <wd0s1b>
* | |
* | v
* | <wd0s1e>
* | |
* | v
* | <wd0s1f>
* |
* v
* <wd0s2> --> <unused>
* | |
* | v
* | <wd0s5>
* |
* v
* <wd0s3>
* |
* v
* <wd0s4> --> <wd0s4a>
*
*
*/
-316
View File
@@ -1,316 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: rules.c,v 1.10.2.1 1995/06/03 08:40:33 jkh Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/diskslice.h>
#include <sys/disklabel.h>
#include <err.h>
#include "libdisk.h"
int
Track_Aligned(struct disk *d, u_long offset)
{
if (!d->bios_sect)
return 1;
if (offset % d->bios_sect)
return 0;
return 1;
}
u_long
Prev_Track_Aligned(struct disk *d, u_long offset)
{
if (!d->bios_sect)
return offset;
return (offset / d->bios_sect) * d->bios_sect;
}
u_long
Next_Track_Aligned(struct disk *d, u_long offset)
{
if (!d->bios_sect)
return offset;
return Prev_Track_Aligned(d,offset + d->bios_sect-1);
}
int
Cyl_Aligned(struct disk *d, u_long offset)
{
if (!d->bios_sect || !d->bios_hd)
return 1;
if (offset % (d->bios_sect * d->bios_hd))
return 0;
return 1;
}
u_long
Prev_Cyl_Aligned(struct disk *d, u_long offset)
{
if (!d->bios_sect || !d->bios_hd)
return offset;
return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd;
}
u_long
Next_Cyl_Aligned(struct disk *d, u_long offset)
{
if (!d->bios_sect || !d->bios_hd)
return offset;
return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1);
}
/*
* Rule#0:
* Chunks of type 'whole' can have max NDOSPART children.
* Only one of them can have the "active" flag
*/
void
Rule_000(struct disk *d, struct chunk *c, char *msg)
{
int i=0,j=0;
struct chunk *c1;
if (c->type != whole)
return;
for (c1=c->part; c1; c1=c1->next) {
if (c1->type != unused) continue;
if (c1->flags & CHUNK_ACTIVE)
j++;
i++;
}
if (i > NDOSPART)
sprintf(msg+strlen(msg),
"%d is too many children of the 'whole' chunk. Max is %d\n",
i, NDOSPART);
if (j > 1)
sprintf(msg+strlen(msg),
"Too many active children of 'whole'");
}
/*
* Rule#1:
* All children of 'whole' and 'extended' must be track-aligned.
* Exception: the end can be unaligned if it matches the end of 'whole'
*/
void
Rule_001(struct disk *d, struct chunk *c, char *msg)
{
int i;
struct chunk *c1;
if (c->type != whole && c->type != extended)
return;
for (i=0, c1=c->part; c1; c1=c1->next) {
if (c1->type == unused) continue;
c1->flags |= CHUNK_ALIGN;
if (!Track_Aligned(d,c1->offset))
sprintf(msg+strlen(msg),
"chunk '%s' [%ld..%ld] does not start on a track boundary\n",
c1->name,c1->offset,c1->end);
if ((c->type == whole || c->end == c1->end)
|| Cyl_Aligned(d,c1->end+1))
;
else
sprintf(msg+strlen(msg),
"chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n",
c1->name,c1->offset,c1->end);
}
}
/*
* Rule#2:
* Max one 'fat' as child of 'whole'
*/
void
Rule_002(struct disk *d, struct chunk *c, char *msg)
{
int i;
struct chunk *c1;
if (c->type != whole)
return;
for (i=0, c1=c->part; c1; c1=c1->next) {
if (c1->type != fat)
continue;
i++;
}
if (i > 1) {
sprintf(msg+strlen(msg),
"Max one 'fat' allowed as child of 'whole'\n");
}
}
/*
* Rule#3:
* Max one extended as child of 'whole'
*/
void
Rule_003(struct disk *d, struct chunk *c, char *msg)
{
int i;
struct chunk *c1;
if (c->type != whole)
return;
for (i=0, c1=c->part; c1; c1=c1->next) {
if (c1->type != extended)
continue;
i++;
}
if (i > 1) {
sprintf(msg+strlen(msg),
"Max one 'extended' allowed as child of 'whole'\n");
}
}
/*
* Rule#4:
* Max seven 'part' as children of 'freebsd'
* Max one CHUNK_IS_ROOT child per 'freebsd'
* If Bad144, space for table must exist.
* If Bad144 & root, bad144 table must be inside 1024
*/
void
Rule_004(struct disk *d, struct chunk *c, char *msg)
{
int i=0,k=0;
struct chunk *c1;
u_long l;
if (c->type != freebsd)
return;
if (c->flags & CHUNK_BAD144) {
l = c->end - 127 - d->bios_sect + 1;
for (c1=c->part; c1; c1=c1->next) {
if (c1->end < l || c1->type == unused)
continue;
sprintf(msg+strlen(msg),
"Blocks %lu to %lu are needed for bad144 information, but isn't unused.\n",
l, c->end);
break;
}
if (c->flags & CHUNK_PAST_1024) {
for (c1=c->part; c1; c1=c1->next) {
if (c1->flags & CHUNK_IS_ROOT) {
sprintf(msg+strlen(msg),
"You have assigned root to a slice which uses bad144, and\n extends past the first 1023 cylinders, and thus cannot be booted from.\n");
break;
}
}
}
}
for (c1=c->part; c1; c1=c1->next) {
if (c1->type != part)
continue;
if (c1->flags & CHUNK_IS_ROOT) {
k++;
if (c1->flags & CHUNK_PAST_1024)
sprintf(msg+strlen(msg),
"Root filesystem extends past cylinder 1024, and cannot be booted from\n");
}
i++;
}
if (i > 7) {
sprintf(msg+strlen(msg),
"Max seven partitions per freebsd slice\n");
}
if (k > 1) {
sprintf(msg+strlen(msg),
"Max one root partition child per freebsd slice\n");
}
}
void
Check_Chunk(struct disk *d, struct chunk *c, char *msg)
{
Rule_000(d,c,msg);
Rule_001(d,c,msg);
Rule_002(d,c,msg);
Rule_003(d,c,msg);
Rule_004(d,c,msg);
if (c->part)
Check_Chunk(d,c->part,msg);
if (c->next)
Check_Chunk(d,c->next,msg);
if (c->end >= 1024*d->bios_hd*d->bios_sect)
c->flags |= CHUNK_PAST_1024;
else
c->flags &= ~CHUNK_PAST_1024;
}
char *
CheckRules(struct disk *d)
{
char msg[BUFSIZ];
*msg = '\0';
Check_Chunk(d,d->chunks,msg);
if (*msg)
return strdup(msg);
return 0;
}
char *
ChunkCanBeRoot(struct chunk *c)
{
struct chunk *c1;
struct disk *d = c->disk;
char msg[BUFSIZ];
*msg = '\0';
if (c->flags & CHUNK_PAST_1024) {
strcat(msg,
"The root partition must end before cylinder 1024 seen from\n");
strcat(msg,
"the BIOS' point of view, or it cannot be booted from.\n");
return strdup(msg);
}
for (c1=d->chunks->part;;) {
for (; c1; c1=c1->next)
if (c1->offset <= c->offset && c1->end >= c->end)
break;
if (!c1) {
strcat(msg,
"Internal trouble, cannot find this chunk in the chunk-tree\n");
return strdup(msg);
}
if (c1->type == freebsd)
break;
c1 = c1->part;
}
if (c1->type != freebsd) {
strcat(msg,
"The root partition must be in a FreeBSD slice, otherwise\n");
strcat(msg,
"the kernel cannot be booted from it\n");
return strdup(msg);
}
if ((c1->flags & CHUNK_BAD144) && (c1->flags & CHUNK_PAST_1024)) {
strcat(msg,
"This partition is unsuitable for root, because the FreeBSD slice\n");
strcat(msg,
"it is inside has bad144 enabled, but the badblock data lives past\n");
strcat(msg,
"the 1024th cylinder, and the bootblocks cannot get to it there.\n");
return strdup(msg);
}
return NULL;
}
-313
View File
@@ -1,313 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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: tst01.c,v 1.15 1995/06/11 19:29:37 rgrimes Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <err.h>
#ifdef READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#include <sys/types.h>
#include "libdisk.h"
u_char mbr[] = {
250,51,192,142,208,188,0,124,139,244,80,7,80,31,251,252,191,0,6,185,0,1,
242,165,234,29,6,0,0,190,190,7,179,4,128,60,128,116,14,128,60,0,117,28,
131,198,16,254,203,117,239,205,24,139,20,139,76,2,139,238,131,198,16,254,
203,116,26,128,60,0,116,244,190,139,6,172,60,0,116,11,86,187,7,0,180,14,
205,16,94,235,240,235,254,191,5,0,187,0,124,184,1,2,87,205,19,95,115,12,
51,192,205,19,79,117,237,190,163,6,235,211,190,194,6,191,254,125,129,61,
85,170,117,199,139,245,234,0,124,0,0,73,110,118,97,108,105,100,32,112,97,
114,116,105,116,105,111,110,32,116,97,98,108,101,0,69,114,114,111,114,32,
108,111,97,100,105,110,103,32,111,112,101,114,97,116,105,110,103,32,115,
121,115,116,101,109,0,77,105,115,115,105,110,103,32,111,112,101,114,97,
116,105,110,103,32,115,121,115,116,101,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,
1,1,0,4,15,63,60,63,0,0,0,241,239,0,0,0,0,1,61,5,15,63,243,48,240,0,0,144,
208,2,0,0,0,1,244,165,15,63,170,192,192,3,0,144,208,2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,85,170
};
u_char bteasy17[] = {
51,192,142,192,142,216,142,208,188,0,124,252,139,244,191,0,6,185,0,1,242,
165,234,96,6,0,0,139,213,88,162,72,7,60,53,116,28,180,16,246,228,5,174,
4,150,246,68,4,255,116,62,198,4,128,232,218,0,138,116,1,139,76,2,235,8,
232,207,0,185,1,0,50,209,187,0,124,184,1,2,205,19,114,30,129,191,254,1,
85,170,117,22,234,0,124,0,0,128,250,129,116,2,178,128,139,234,66,128,242,
179,136,22,58,7,191,190,7,185,4,0,198,6,45,7,49,50,246,136,45,138,69,4,
60,0,116,35,60,5,116,31,254,198,190,42,7,232,113,0,190,72,7,70,70,139,28,
10,255,116,5,50,125,4,117,243,141,183,114,7,232,90,0,131,199,16,254,6,45,
7,226,203,128,62,117,4,2,116,11,190,59,7,10,246,117,10,205,24,235,172,190,
42,7,232,57,0,232,54,0,50,228,205,26,139,218,131,195,96,180,1,205,22,180,
0,117,11,205,26,59,211,114,242,160,72,7,235,10,205,22,138,196,60,28,116,
243,4,246,60,49,114,214,60,53,119,210,80,190,40,7,187,27,6,83,252,172,80,
36,127,180,14,205,16,88,168,128,116,242,195,86,184,1,3,187,0,6,185,1,0,
50,246,205,19,94,198,6,72,7,63,195,13,138,13,10,70,48,32,46,32,46,32,46,
160,100,105,115,107,32,49,13,10,10,68,101,102,97,117,108,116,58,32,70,63,
160,0,1,0,4,0,6,3,7,7,10,10,99,14,100,14,101,20,128,20,129,25,130,30,147,
36,165,39,159,43,117,47,82,47,219,50,64,55,242,61,0,100,111,243,72,80,70,
211,79,115,178,85,110,105,248,78,111,118,101,108,236,77,105,110,105,248,
76,105,110,117,248,65,109,111,101,98,225,66,83,196,66,83,68,233,80,67,73,
216,67,80,205,86,101,110,105,248,68,111,115,115,101,227,63,191,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,85,170
};
int
scan_block(int fd, daddr_t block)
{
u_char foo[512];
if (-1 == lseek(fd,block * 512,SEEK_SET))
err(1,"lseek");
if (512 != read(fd,foo, 512))
return 1;
return 0;
}
void
Scan_Disk(struct disk *d)
{
char device[64];
u_long l;
int i,j,fd;
strcpy(device,"/dev/r");
strcat(device,d->name);
fd = open(device,O_RDWR);
if (fd < 0) {
warn("open(%s) failed",device);
return;
}
for(i=-1,l=0;;l++) {
j = scan_block(fd,l);
if (j != i) {
if (i == -1) {
printf("%c: %lu.",j ? 'B' : 'G', l);
fflush(stdout);
} else if (i == 0) {
printf(".%lu\nB: %lu.",l-1,l);
fflush(stdout);
} else {
printf(".%lu\nG: %lu.",l-1,l);
fflush(stdout);
}
i = j;
}
}
close(fd);
}
int
main(int argc, char **argv)
{
struct disk *d,*db;
char myprompt[BUFSIZ];
#ifndef READLINE
char input[BUFSIZ];
#endif
char *p,*q=0;
char **cp,*cmds[200];
int ncmd,i;
if (argc < 2) {
fprintf(stderr,"Usage:\n\t%s diskname\n",argv[0]);
exit(1);
}
d = Open_Disk(argv[1]);
if (!d)
err(1,"Couldn't open disk %s",argv[1]);
sprintf(myprompt,"%s %s> ",argv[0],argv[1]);
while(1) {
printf("--==##==--\n");
p = CheckRules(d);
Debug_Disk(d);
if (p) {
printf("%s",p);
free(p);
}
#ifdef READLINE
if (q)
free(q);
q = p = readline(myprompt);
#else
printf(myprompt);
fflush(stdout);
q = p = fgets(input,sizeof(input),stdin);
#endif
if(!p)
break;
for(cp = cmds; (*cp = strsep(&p, " \t\n")) != NULL;)
if (**cp != '\0')
cp++;
ncmd = cp - cmds;
if(!ncmd)
continue;
if (!strcasecmp(*cmds,"quit")) { break; }
if (!strcasecmp(*cmds,"exit")) { break; }
if (!strcasecmp(*cmds,"q")) { break; }
if (!strcasecmp(*cmds,"x")) { break; }
if (!strcasecmp(*cmds,"dwim") && ncmd == 6) {
printf("dwim = %p\n",
Create_Chunk_DWIM(d,
(struct chunk *)strtol(cmds[1],0,0),
strtol(cmds[2],0,0),
strtol(cmds[3],0,0),
strtol(cmds[4],0,0),
strtol(cmds[5],0,0)));
continue;
}
if (!strcasecmp(*cmds,"mknod")) {
MakeDevDisk(d,"/tmp");
continue;
}
if (!strcasecmp(*cmds,"delete") && ncmd == 2) {
printf("delete = %d\n",
Delete_Chunk(d,
(struct chunk *)strtol(cmds[1],0,0)));
continue;
}
if (!strcasecmp(*cmds,"allfreebsd")) {
All_FreeBSD(d, 0);
continue;
}
if (!strcasecmp(*cmds,"dedicate")) {
All_FreeBSD(d, 1);
continue;
}
if (!strcasecmp(*cmds,"bios") && ncmd == 4) {
Set_Bios_Geom(d,
strtol(cmds[1],0,0),
strtol(cmds[2],0,0),
strtol(cmds[3],0,0));
continue;
}
#if 0
if (!strcasecmp(*cmds,"phys") && ncmd == 4) {
d = Set_Phys_Geom(d,
strtol(cmds[1],0,0),
strtol(cmds[2],0,0),
strtol(cmds[3],0,0));
continue;
}
#endif
#if 0
if (!strcasecmp(*cmds,"collapse")) {
if (cmds[1])
while (Collapse_Chunk(d,
(struct chunk *)strtol(cmds[1],0,0)))
;
else
Collapse_Disk(d);
continue;
}
#endif
if (!strcasecmp(*cmds,"list")) {
cp = Disk_Names();
printf("Disks:");
for(i=0;cp[i];i++) {
printf(" %s",cp[i]);
free(cp[i]);
}
free(cp);
continue;
}
if (!strcasecmp(*cmds,"create") && ncmd == 6) {
printf("Create=%d\n",
Create_Chunk(d,
strtol(cmds[1],0,0),
strtol(cmds[2],0,0),
strtol(cmds[3],0,0),
strtol(cmds[4],0,0),
strtol(cmds[5],0,0)));
continue;
}
if (!strcasecmp(*cmds,"read")) {
db = d;
if (ncmd > 1)
d = Open_Disk(cmds[1]);
else
d = Open_Disk(argv[1]);
if (d)
Free_Disk(db);
else
d = db;
continue;
}
if (!strcasecmp(*cmds,"scan")) {
Scan_Disk(d);
continue;
}
if (!strcasecmp(*cmds,"bteasy")) {
Set_Boot_Mgr(d,bteasy17);
continue;
}
if (!strcasecmp(*cmds,"mbr")) {
Set_Boot_Mgr(d,mbr);
continue;
}
if (!strcasecmp(*cmds,"boot")) {
extern u_char boot1[],boot2[];
Set_Boot_Blocks(d,boot1,boot2);
continue;
}
if (!strcasecmp(*cmds,"write")) {
printf("Write=%d\n",
Write_Disk(d));
Free_Disk(d);
d = Open_Disk(d->name);
continue;
}
if (strcasecmp(*cmds,"help"))
printf("\007ERROR\n");
printf("CMDS:\n");
printf("\tallfreebsd\n");
printf("\tdedicate\n");
printf("\tbios cyl hd sect\n");
printf("\tboot\n");
printf("\tbteasy17\n");
#if 0
printf("\tcollapse [pointer]\n");
#endif
printf("\tcreate offset size enum subtype flags\n");
printf("\t\tsubtype(part): swap=1, ffs=7\n");
printf("\tdelete pointer\n");
printf("\tlist\n");
printf("\tmbr\n");
#if 0
printf("\tphys cyl hd sect\n");
#endif
printf("\tquit\n");
printf("\tread [disk]\n");
printf("\tscan\n");
printf("\twrite\n");
printf("\nENUM:\n\t");
for(i=0;chunk_n[i];i++)
printf("%d = %s%s",i,chunk_n[i],i == 4 ? "\n\t" : " ");
printf("\n");
}
exit (0);
}
-233
View File
@@ -1,233 +0,0 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <[email protected]> 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_disk.c,v 1.14.2.1 1995/07/21 11:22:38 rgrimes Exp $
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <err.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/diskslice.h>
#include "libdisk.h"
#define DOSPTYP_EXTENDED 5
#define BBSIZE 8192
#define SBSIZE 8192
#define DEF_RPM 3600
#define DEF_INTERLEAVE 1
#define WHERE(offset,disk) (disk->flags & DISK_ON_TRACK ? offset + 63 : offset)
int
Write_FreeBSD(int fd, struct disk *new, struct disk *old, struct chunk *c1)
{
struct disklabel *dl;
struct chunk *c2;
int i,j;
void *p;
u_char buf[BBSIZE];
for(i=0;i<BBSIZE/512;i++) {
p = read_block(fd,WHERE(i + c1->offset,new));
memcpy(buf+512*i,p,512);
free(p);
}
if(new->boot1)
memcpy(buf,new->boot1,512);
if(new->boot2)
memcpy(buf+512,new->boot2,BBSIZE-512);
dl = (struct disklabel *) (buf+512*LABELSECTOR+LABELOFFSET);
memset(dl,0,sizeof *dl);
for(c2=c1->part;c2;c2=c2->next) {
if (c2->type == unused) continue;
if (!strcmp(c2->name,"X")) continue;
j = c2->name[5] - 'a';
if (j < 0 || j >= MAXPARTITIONS || j == RAW_PART) {
warn("Weird parititon letter %c",c2->name[5]);
continue;
}
dl->d_partitions[j].p_size = c2->size;
dl->d_partitions[j].p_offset = c2->offset;
dl->d_partitions[j].p_fstype = c2->subtype;
}
dl->d_bbsize = BBSIZE;
/*
* Add in defaults for superblock size, interleave, and rpms
*/
dl->d_sbsize = SBSIZE;
dl->d_interleave = DEF_INTERLEAVE;
dl->d_rpm = DEF_RPM;
strcpy(dl->d_typename,c1->name);
dl->d_secsize = 512;
dl->d_secperunit = new->chunks->size;
#if 0
dl->d_ncylinders = new->real_cyl ? new->real_cyl : new->bios_cyl;
dl->d_ntracks = new->real_hd ? new->real_hd : new->bios_hd;
dl->d_nsectors = new->real_sect ? new->real_sect : new->bios_sect;
#else
dl->d_ncylinders = new->bios_cyl;
dl->d_ntracks = new->bios_hd;
dl->d_nsectors = new->bios_sect;
#endif
dl->d_secpercyl = dl->d_ntracks * dl->d_nsectors;
dl->d_npartitions = MAXPARTITIONS;
dl->d_type = new->name[0] == 's' ? DTYPE_SCSI : DTYPE_ESDI;
dl->d_partitions[RAW_PART].p_size = c1->size;
dl->d_partitions[RAW_PART].p_offset = c1->offset;
if(new->flags & DISK_ON_TRACK)
for(i=0;i<MAXPARTITIONS;i++)
if (dl->d_partitions[i].p_size)
dl->d_partitions[i].p_offset += 63;
dl->d_magic = DISKMAGIC;
dl->d_magic2 = DISKMAGIC;
dl->d_checksum = dkcksum(dl);
for(i=0;i<BBSIZE/512;i++) {
write_block(fd,WHERE(i + c1->offset,new),buf+512*i);
}
return 0;
}
int
Write_Extended(int fd, struct disk *new, struct disk *old, struct chunk *c1)
{
return 0;
}
int
Write_Disk(struct disk *d1)
{
int fd,i,j;
struct disk *old = 0;
struct chunk *c1;
int ret = 0;
char device[64];
u_char *mbr;
struct dos_partition *dp,work[NDOSPART];
int s[4];
strcpy(device,"/dev/r");
strcat(device,d1->name);
fd = open(device,O_RDWR);
if (fd < 0) {
warn("open(%s) failed",device);
return 1;
}
memset(s,0,sizeof s);
mbr = read_block(fd,WHERE(0,d1));
dp = (struct dos_partition*) (mbr + DOSPARTOFF);
memcpy(work,dp,sizeof work);
dp = work;
free(mbr);
for (c1=d1->chunks->part; c1 ; c1 = c1->next) {
if (c1->type == unused) continue;
if (!strcmp(c1->name,"X")) continue;
j = c1->name[4] - '1';
if (j < 0 || j > 3)
continue;
s[j]++;
if (c1->type == extended)
ret += Write_Extended(fd, d1,old,c1);
if (c1->type == freebsd)
ret += Write_FreeBSD(fd, d1,old,c1);
dp[j].dp_start = c1->offset;
dp[j].dp_size = c1->size;
i = c1->offset;
if (i >= 1024*d1->bios_sect*d1->bios_hd) {
dp[j].dp_ssect = 0xff;
dp[j].dp_shd = 0xff;
dp[j].dp_scyl = 0xff;
} else {
dp[j].dp_ssect = i % d1->bios_sect;
i -= dp[j].dp_ssect++;
i /= d1->bios_sect;
dp[j].dp_shd = i % d1->bios_hd;
i -= dp[j].dp_shd;
i /= d1->bios_hd;
dp[j].dp_scyl = i;
i -= dp[j].dp_scyl;
dp[j].dp_ssect |= i >> 2;
}
#ifdef DEBUG
printf("S:%lu = (%x/%x/%x)",
c1->offset,dp[j].dp_scyl,dp[j].dp_shd,dp[j].dp_ssect);
#endif
i = c1->end;
dp[j].dp_esect = i % d1->bios_sect;
i -= dp[j].dp_esect++;
i /= d1->bios_sect;
dp[j].dp_ehd = i % d1->bios_hd;
i -= dp[j].dp_ehd;
i /= d1->bios_hd;
if (i>1023) i = 1023;
dp[j].dp_ecyl = i;
i -= dp[j].dp_ecyl;
dp[j].dp_esect |= i >> 2;
#ifdef DEBUG
printf(" E:%lu = (%x/%x/%x)\n",
c1->end,dp[j].dp_ecyl,dp[j].dp_ehd,dp[j].dp_esect);
#endif
dp[j].dp_typ = c1->subtype;
if (c1->flags & CHUNK_ACTIVE)
dp[j].dp_flag = 0x80;
else
dp[j].dp_flag = 0;
}
j = 0;
for(i=0;i<NDOSPART;i++) {
if (!s[i])
memset(dp+i,0,sizeof *dp);
if (dp[i].dp_flag)
j++;
}
if (!j)
for(i=0;i<NDOSPART;i++)
if (dp[i].dp_typ == 0xa5)
dp[i].dp_flag = 0x80;
mbr = read_block(fd,WHERE(0,d1));
if (d1->bootmgr)
memcpy(mbr,d1->bootmgr,DOSPARTOFF);
memcpy(mbr+DOSPARTOFF,dp,sizeof *dp * NDOSPART);
mbr[512-2] = 0x55;
mbr[512-1] = 0xaa;
write_block(fd,WHERE(0,d1),mbr);
i = 1;
i = ioctl(fd,DIOCSYNCSLICEINFO,&i);
if (i != 0)
warn("ioctl(DIOCSYNCSLICEINFO)");
close(fd);
return 0;
}
+487
View File
@@ -0,0 +1,487 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: anonFTP.c,v 1.5 1995/11/11 11:56:40 jkh Exp $
*
* Copyright (c) 1995
* Coranth Gryphon. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 Coranth Gryphon
* for the FreeBSD Project.
* 4. The name of Coranth Gryphon or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY CORANTH GRYPHON ``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 CORANTH GRYPHON OR HIS PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <string.h>
#include <dialog.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include "ui_objects.h"
#include "dir.h"
#include "dialog.priv.h"
#include "colors.h"
#include "sysinstall.h"
/* This doesn't change until FTP itself changes */
#define FTP_NAME "ftp"
#define MOTD_FILE "ftpmotd"
/* These change if we want to use different defaults */
#define FTP_UID 14
#define FTP_GID 5
#define FTP_GROUP "operator"
#define FTP_UPLOAD "incoming"
#define FTP_COMMENT "Anonymous FTP Admin"
#define FTP_HOMEDIR "/usr/ftp"
#define ANONFTP_HELPFILE "anonftp"
/* Set up the structure to hold configuration information */
/* Note that this is only what we could fit onto the one screen */
typedef struct
{
char homedir[64]; /* Home Dir for Anon FTP */
char group[32]; /* Group */
char uid[8]; /* UID */
char comment[64]; /* PWD Comment */
char upload[32]; /* Upload Dir */
} FTPConf;
static FTPConf tconf;
#define ANONFTP_HOMEDIR_LEN 64
#define ANONFTP_COMMENT_LEN 64
#define ANONFTP_UPLOAD_LEN 32
#define ANONFTP_GROUP_LEN 32
#define ANONFTP_UID_LEN 8
static int okbutton, cancelbutton;
/* What the screen size is meant to be */
#define ANONFTP_DIALOG_Y 0
#define ANONFTP_DIALOG_X 8
#define ANONFTP_DIALOG_WIDTH COLS - 16
#define ANONFTP_DIALOG_HEIGHT LINES - 2
/* The screen layout structure */
typedef struct _layout {
int y; /* x & Y co-ordinates */
int x;
int len; /* The size of the dialog on the screen */
int maxlen; /* How much the user can type in ... */
char *prompt; /* The string for the prompt */
char *help; /* The display for the help line */
void *var; /* The var to set when this changes */
int type; /* The type of the dialog to create */
void *obj; /* The obj pointer returned by libdialog */
} Layout;
static Layout layout[] = {
{ 2, 3, 8, ANONFTP_UID_LEN - 1,
"UID:", "What user ID to assign to FTP Admin",
tconf.uid, STRINGOBJ, NULL },
#define LAYOUT_UID 1
{ 2, 15, 15, ANONFTP_GROUP_LEN - 1,
"Group:", "Group name that ftp process belongs to",
tconf.group, STRINGOBJ, NULL },
#define LAYOUT_GROUP 2
{ 2, 35, 24, ANONFTP_COMMENT_LEN - 1,
"Comment:", "Password file comment for FTP Admin",
tconf.comment, STRINGOBJ, NULL },
#define LAYOUT_COMMENT 3
{ 9, 10, 43, ANONFTP_HOMEDIR_LEN - 1,
"FTP Root Directory:",
"The top directory to chroot to when doing anonymous ftp",
tconf.homedir, STRINGOBJ, NULL },
#define LAYOUT_HOMEDIR 4
{ 14, 20, 22, ANONFTP_UPLOAD_LEN - 1,
"Upload Subdirectory:", "Designated sub-directory that holds uploads",
tconf.upload, STRINGOBJ, NULL },
#define LAYOUT_UPLOAD 5
{ 19, 15, 0, 0,
"OK", "Select this if you are happy with these settings",
&okbutton, BUTTONOBJ, NULL },
#define LAYOUT_OKBUTTON 6
{ 19, 35, 0, 0,
"CANCEL", "Select this if you wish to cancel this screen",
&cancelbutton, BUTTONOBJ, NULL },
#define LAYOUT_CANCELBUTTON 7
{ NULL },
};
int createFtpUser()
{
struct passwd *tpw;
struct group *tgrp;
char pwline[256];
char *tptr;
int gid;
FILE *fptr;
if ((gid = atoi(tconf.group)) <= 0) {
if (!(tgrp = getgrnam(tconf.group))) {
/* group does not exist, create it by name */
tptr = msgGetInput("14", "What group ID to use for group %s ?", tconf.group);
if (tptr && *tptr && ((gid = atoi(tptr)) > 0)) {
if ((fptr = fopen(_PATH_GROUP,"a"))) {
fprintf(fptr,"%s:*:%d:%s\n",tconf.group,gid,FTP_NAME);
fclose(fptr);
}
}
else
gid = FTP_GID;
}
else
gid = tgrp->gr_gid;
}
else if (!getgrgid(gid)) {
/* group does not exist, create it by number */
tptr = msgGetInput("14", "What group name to use for gid %d ?", gid);
if (tptr && *tptr) {
strcpy(tconf.group, tptr);
if ((tgrp = getgrnam(tconf.group))) {
gid = tgrp->gr_gid;
}
else if ((fptr = fopen(_PATH_GROUP,"a"))) {
fprintf(fptr,"%s:*:%d:%s\n",tconf.group,gid,FTP_NAME);
fclose(fptr);
}
}
}
if ((tpw = getpwnam(FTP_NAME))) {
if (tpw->pw_uid != FTP_UID)
msgConfirm("FTP user already exists with a different uid.");
return (RET_SUCCESS); /* succeeds if already exists */
}
sprintf(pwline, "%s::%s:%d::0:0:%s:%s:/bin/date\n", FTP_NAME, tconf.uid, gid, tconf.comment, tconf.homedir);
fptr = fopen(_PATH_MASTERPASSWD,"a");
if (! fptr) {
msgConfirm("Could not open master password file.");
return (RET_FAIL);
}
fprintf(fptr, pwline);
fclose(fptr);
msgNotify("Remaking password file: %s", _PATH_MASTERPASSWD);
vsystem("pwd_mkdb -p %s", _PATH_MASTERPASSWD);
return (RET_SUCCESS);
}
/* This is it - how to get the setup values */
int
anonftpOpenDialog()
{
WINDOW *ds_win;
ComposeObj *obj = NULL;
ComposeObj *first, *last;
int n=0, quit=FALSE, cancel=FALSE, ret;
int max;
char help[FILENAME_MAX];
char title[80];
/* We need a curses window */
ds_win = newwin(LINES, COLS, 0, 0);
if (ds_win == 0)
{
beep();
msgConfirm("Cannot open anonymous ftp dialog window!!");
return(RET_SUCCESS);
}
/* Say where our help comes from */
systemHelpFile(ANONFTP_HELPFILE, help);
use_helpfile(help);
/* Setup a nice screen for us to splat stuff onto */
draw_box(ds_win, ANONFTP_DIALOG_Y, ANONFTP_DIALOG_X, ANONFTP_DIALOG_HEIGHT, ANONFTP_DIALOG_WIDTH, dialog_attr, border_attr);
wattrset(ds_win, dialog_attr);
mvwaddstr(ds_win, ANONFTP_DIALOG_Y, ANONFTP_DIALOG_X + 20, " Anonymous FTP Configuration ");
draw_box(ds_win, ANONFTP_DIALOG_Y + 7, ANONFTP_DIALOG_X + 8, ANONFTP_DIALOG_HEIGHT - 11, ANONFTP_DIALOG_WIDTH - 17,
dialog_attr, border_attr);
wattrset(ds_win, dialog_attr);
sprintf(title, " Path Configuration ");
mvwaddstr(ds_win, ANONFTP_DIALOG_Y + 7, ANONFTP_DIALOG_X + 22, title);
/** Initialize the config Data Structure **/
bzero(&tconf, sizeof(tconf));
strcpy(tconf.group, FTP_GROUP);
strcpy(tconf.upload, FTP_UPLOAD);
strcpy(tconf.comment, FTP_COMMENT);
strcpy(tconf.homedir, FTP_HOMEDIR);
sprintf(tconf.uid, "%d", FTP_UID);
/* Loop over the layout list, create the objects, and add them
onto the chain of objects that dialog uses for traversal*/
n = 0;
#define lt layout[n]
while (lt.help != NULL) {
switch (lt.type) {
case STRINGOBJ:
lt.obj = NewStringObj(ds_win, lt.prompt, lt.var,
lt.y + ANONFTP_DIALOG_Y, lt.x + ANONFTP_DIALOG_X,
lt.len, lt.maxlen);
break;
case BUTTONOBJ:
lt.obj = NewButtonObj(ds_win, lt.prompt, lt.var,
lt.y + ANONFTP_DIALOG_Y, lt.x + ANONFTP_DIALOG_X);
break;
default:
msgFatal("Don't support this object yet!");
}
AddObj(&obj, lt.type, (void *) lt.obj);
n++;
}
max = n - 1;
/* Find the last object we can traverse to */
last = obj;
while (last->next)
last = last->next;
/* Find the first object in the list */
first = obj;
while (first->prev)
first = first->prev;
/* Some more initialisation before we go into the main input loop */
n = 0;
cancelbutton = 0;
cancel = FALSE;
okbutton = 0;
/* Incoming user data - DUCK! */
while (!quit) {
char help_line[80];
int i, len = strlen(lt.help);
/* Display the help line at the bottom of the screen */
for (i = 0; i < 79; i++)
help_line[i] = (i < len) ? lt.help[i] : ' ';
help_line[i] = '\0';
use_helpline(help_line);
display_helpline(ds_win, LINES - 1, COLS - 1);
/* Ask for libdialog to do its stuff */
ret = PollObj(&obj);
/* Handle special case stuff that libdialog misses. Sigh */
switch (ret) {
/* Bail out */
case SEL_ESC:
quit = TRUE, cancel=TRUE;
break;
/* This doesn't work for list dialogs. Oh well. Perhaps
should special case the move from the OK button ``up''
to make it go to the interface list, but then it gets
awkward for the user to go back and correct screw up's
in the per-interface section */
case KEY_UP:
if (obj->prev !=NULL ) {
obj = obj->prev;
--n;
} else {
obj = last;
n = max;
}
break;
case KEY_DOWN:
if (obj->next != NULL) {
obj = obj->next;
++n;
} else {
obj = first;
n = 0;
}
break;
case SEL_TAB:
if (n < max)
++n;
else
n = 0;
break;
/* The user has pressed enter over a button object */
case SEL_BUTTON:
quit = TRUE;
if (cancelbutton)
cancel = TRUE;
break;
/* Generic CR handler */
case SEL_CR:
if (n < max)
++n;
else
n = 0;
break;
case SEL_BACKTAB:
if (n)
--n;
else
n = max;
break;
case KEY_F(1):
display_helpfile();
/* They tried some key combination we don't support - tell them! */
default:
beep();
}
}
/* Clear this crap off the screen */
dialog_clear();
refresh();
use_helpfile(NULL);
if (cancel)
return RET_FAIL;
return RET_SUCCESS;
}
int
configAnonFTP(char *unused)
{
int i;
/* Be optimistic */
i = RET_SUCCESS;
dialog_clear();
i = anonftpOpenDialog();
if (i != RET_SUCCESS) {
dialog_clear();
msgConfirm("Configuration of Anonymous FTP cancelled per user request.");
return i;
}
/*** Use defaults for any invalid values ***/
if (atoi(tconf.uid) <= 0)
sprintf(tconf.uid, "%d", FTP_UID);
if (!tconf.group[0])
strcpy(tconf.group, FTP_GROUP);
if (!tconf.upload[0])
strcpy(tconf.upload, FTP_UPLOAD);
/*** If the user did not specify a directory, use default ***/
if (tconf.homedir[strlen(tconf.homedir)-1] == '/')
tconf.homedir[strlen(tconf.homedir)-1] = '\0';
if (!tconf.homedir[0])
strcpy(tconf.homedir, FTP_HOMEDIR);
/*** If HomeDir does not exist, create it ***/
if (!directoryExists(tconf.homedir)) {
vsystem("mkdir -p %s" ,tconf.homedir);
}
if (directoryExists(tconf.homedir)) {
msgNotify("Configuring %s for use by anon FTP.", tconf.homedir);
vsystem("chmod 555 %s && chown root.%s %s", tconf.homedir, tconf.group, tconf.homedir);
vsystem("mkdir %s/bin && chmod 555 %s/bin", tconf.homedir, tconf.homedir);
vsystem("cp /bin/ls %s/bin && chmod 111 %s/bin/ls", tconf.homedir, tconf.homedir);
vsystem("cp /bin/date %s/bin && chmod 111 %s/bin/date", tconf.homedir, tconf.homedir);
vsystem("mkdir %s/etc && chmod 555 %s/etc", tconf.homedir, tconf.homedir);
vsystem("mkdir -p %s/pub", tconf.homedir);
vsystem("mkdir -p %s/%s", tconf.homedir, tconf.upload);
vsystem("chmod 1777 %s/%s", tconf.homedir, tconf.upload);
if (createFtpUser() == RET_SUCCESS) {
msgNotify("Copying password information for anon FTP.");
vsystem("cp /etc/pwd.db %s/etc && chmod 444 %s/etc/pwd.db", tconf.homedir, tconf.homedir);
vsystem("cp /etc/passwd %s/etc && chmod 444 %s/etc/passwd",tconf.homedir, tconf.homedir);
vsystem("cp /etc/group %s/etc && chmod 444 %s/etc/group", tconf.homedir, tconf.homedir);
vsystem("chown -R %s.%s %s/pub", FTP_NAME, tconf.group, tconf.homedir);
}
else {
dialog_clear();
msgConfirm("Unable to create FTP user! Anonymous FTP setup failed.");
i = RET_FAIL;
}
dialog_clear();
if (!msgYesNo("Create a welcome message file for anonymous FTP users?")) {
char cmd[256];
dialog_clear();
msgNotify("Uncompressing the editor - please wait..");
vsystem("echo Your welcome message here. > %s/etc/%s", tconf.homedir, MOTD_FILE);
sprintf(cmd, "/stand/ee %s/etc/%s", tconf.homedir, MOTD_FILE);
systemExecute(cmd);
}
}
else {
dialog_clear();
msgConfirm("Invalid Directory: %s\n"
"Anonymous FTP will not be set up.", tconf.homedir);
i = RET_FAIL;
}
return i;
}
+604
View File
@@ -0,0 +1,604 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: apache.c,v 1.11 1995/11/05 01:00:27 jkh Exp $
*
* Copyright (c) 1995
* Coranth Gryphon. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 Coranth Gryphon
* for the FreeBSD Project.
* 4. The name of Coranth Gryphon or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY CORANTH GRYPHON ``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 CORANTH GRYPHON OR HIS PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <string.h>
#include <dialog.h>
#include "ui_objects.h"
#include "dir.h"
#include "dialog.priv.h"
#include "colors.h"
#include "sysinstall.h"
#define APACHE_HELPFILE "apache"
#define APACHE_PACKAGE "apache-0.8.14"
#define FREEBSD_GIF "/stand/power.gif"
/* These change if the package uses different defaults */
#define APACHE_BASE "/usr/local/www"
#define DATA_SUBDIR "data"
#define CONFIG_SUBDIR "config"
/* Set up the structure to hold configuration information */
/* Note that this is only what we could fit onto the one screen */
typedef struct
{
char docroot[128]; /* DocumentRoot */
char userdir[128]; /* UserDir */
char welcome[32]; /* Welcome Doc */
char email[64]; /* ServerAdmin */
char hostname[64]; /* ServerName */
char user[32]; /* User */
char group[32]; /* Group */
char maxcon[8]; /* Max Connections */
} ApacheConf;
static ApacheConf tconf;
#define APACHE_DOCROOT_LEN 128
#define APACHE_USERDIR_LEN 128
#define APACHE_WELCOME_LEN 32
#define APACHE_EMAIL_LEN 64
#define APACHE_HOSTNAME_LEN 64
#define APACHE_USER_LEN 32
#define APACHE_GROUP_LEN 32
#define APACHE_MAXCON_LEN 8
static int okbutton, cancelbutton;
/* What the screen size is meant to be */
#define APACHE_DIALOG_Y 0
#define APACHE_DIALOG_X 8
#define APACHE_DIALOG_WIDTH COLS - 16
#define APACHE_DIALOG_HEIGHT LINES - 2
/* The screen layout structure */
typedef struct _layout {
int y; /* x & Y co-ordinates */
int x;
int len; /* The size of the dialog on the screen */
int maxlen; /* How much the user can type in ... */
char *prompt; /* The string for the prompt */
char *help; /* The display for the help line */
void *var; /* The var to set when this changes */
int type; /* The type of the dialog to create */
void *obj; /* The obj pointer returned by libdialog */
} Layout;
static Layout layout[] = {
{ 1, 2, 24, HOSTNAME_FIELD_LEN - 1,
"Host Name:",
"What name to report this host as to client browsers",
tconf.hostname, STRINGOBJ, NULL },
#define LAYOUT_HOSTNAME 0
{ 1, 30, 30, APACHE_EMAIL_LEN - 1,
"Email Address:",
"The email address of the site maintainer, e.g. [email protected]",
tconf.email, STRINGOBJ, NULL },
#define LAYOUT_EMAIL 1
{ 5, 3, 15, APACHE_USER_LEN - 1,
"Default User:", "Default username for access to web pages",
tconf.user, STRINGOBJ, NULL },
#define LAYOUT_USER 2
{ 5, 22, 15, APACHE_GROUP_LEN - 1,
"Default Group:", "Default group name for access to web pages",
tconf.group, STRINGOBJ, NULL },
#define LAYOUT_GROUP 3
{ 5, 46, 13, APACHE_MAXCON_LEN - 1,
"Max Connect:", "Maximum number of concurrent http connections",
tconf.maxcon, STRINGOBJ, NULL },
#define LAYOUT_MAXCON 4
{ 10, 10, 43, APACHE_DOCROOT_LEN - 1,
"Root Document Path:",
"The top directory that holds the system web pages",
tconf.docroot, STRINGOBJ, NULL },
#define LAYOUT_DOCROOT 5
{ 14, 10, 18, APACHE_USERDIR_LEN - 1,
"User Directory:",
"Personal sub-directory that holds users' web pages (eg. ~/Web)",
tconf.userdir, STRINGOBJ, NULL },
#define LAYOUT_USERDIR 6
{ 14, 35, 18, APACHE_WELCOME_LEN - 1,
"Default Document:",
"The name of the default document found in each directory",
tconf.welcome, STRINGOBJ, NULL },
#define LAYOUT_WELCOME 7
{ 19, 15, 0, 0,
"OK", "Select this if you are happy with these settings",
&okbutton, BUTTONOBJ, NULL },
#define LAYOUT_OKBUTTON 8
{ 19, 35, 0, 0,
"CANCEL", "Select this if you wish to cancel this screen",
&cancelbutton, BUTTONOBJ, NULL },
#define LAYOUT_CANCELBUTTON 9
{ NULL },
};
DMenu MenuApacheLanguages = {
DMENU_MULTIPLE_TYPE | DMENU_SELECTION_RETURNS,
"Apache Languages Menu",
"This allows you to specify which languages are known by your httpd server.",
NULL,
NULL,
{
{ "English", "English",
DMENU_SET_VARIABLE, "APACHE_English=en", 0, 0 },
{ "French", "French",
DMENU_SET_VARIABLE, "APACHE_French=fr", 0, 0 },
{ "German", "German",
DMENU_SET_VARIABLE, "APACHE_German=de", 0, 0 },
{ "Italian", "Italian",
DMENU_SET_VARIABLE, "APACHE_Italian=it", 0, 0 },
{ "Japanese", "Japanese",
DMENU_SET_VARIABLE, "APACHE_Japanese=jp", 0, 0 },
{ NULL } },
};
/* This is it - how to get Apache setup values */
int
apacheOpenDialog()
{
WINDOW *ds_win;
ComposeObj *obj = NULL;
ComposeObj *first, *last;
int n=0, quit=FALSE, cancel=FALSE, ret;
int max;
char *tmp;
char help[FILENAME_MAX];
char title[80];
/* We need a curses window */
ds_win = newwin(LINES, COLS, 0, 0);
if (ds_win == 0)
{
beep();
msgConfirm("Cannot open apache dialog window!!");
return(RET_SUCCESS);
}
/* Say where our help comes from */
systemHelpFile(APACHE_HELPFILE, help);
use_helpfile(help);
/* Setup a nice screen for us to splat stuff onto */
draw_box(ds_win, APACHE_DIALOG_Y, APACHE_DIALOG_X, APACHE_DIALOG_HEIGHT, APACHE_DIALOG_WIDTH, dialog_attr, border_attr);
wattrset(ds_win, dialog_attr);
mvwaddstr(ds_win, APACHE_DIALOG_Y, APACHE_DIALOG_X + 20, " Apache HTTPD Configuration ");
draw_box(ds_win, APACHE_DIALOG_Y + 9, APACHE_DIALOG_X + 8, APACHE_DIALOG_HEIGHT - 13, APACHE_DIALOG_WIDTH - 17,
dialog_attr, border_attr);
wattrset(ds_win, dialog_attr);
sprintf(title, " Path Configuration ");
mvwaddstr(ds_win, APACHE_DIALOG_Y + 9, APACHE_DIALOG_X + 22, title);
/** Initialize the config Data Structure **/
bzero(&tconf, sizeof(tconf));
tmp = variable_get(VAR_DOMAINNAME);
if (tmp)
{
sprintf(tconf.email, "webmaster@%s", tmp);
sprintf(tconf.hostname, "www.%s", tmp);
}
strcpy(tconf.user, "guest");
strcpy(tconf.group, "guest");
strcpy(tconf.userdir, "public_html");
strcpy(tconf.welcome, "index.html");
strcpy(tconf.maxcon, "150");
sprintf(tconf.docroot, "%s/%s", APACHE_BASE, DATA_SUBDIR);
/* Loop over the layout list, create the objects, and add them
onto the chain of objects that dialog uses for traversal*/
n = 0;
#define lt layout[n]
while (lt.help != NULL) {
switch (lt.type) {
case STRINGOBJ:
lt.obj = NewStringObj(ds_win, lt.prompt, lt.var,
lt.y + APACHE_DIALOG_Y, lt.x + APACHE_DIALOG_X,
lt.len, lt.maxlen);
break;
case BUTTONOBJ:
lt.obj = NewButtonObj(ds_win, lt.prompt, lt.var,
lt.y + APACHE_DIALOG_Y, lt.x + APACHE_DIALOG_X);
break;
default:
msgFatal("Don't support this object yet!");
}
AddObj(&obj, lt.type, (void *) lt.obj);
n++;
}
max = n - 1;
/* Find the last object we can traverse to */
last = obj;
while (last->next)
last = last->next;
/* Find the first object in the list */
first = obj;
while (first->prev)
first = first->prev;
/* Some more initialisation before we go into the main input loop */
n = 0;
cancelbutton = 0;
cancel = FALSE;
okbutton = 0;
/* Incoming user data - DUCK! */
while (!quit) {
char help_line[80];
int i, len = strlen(lt.help);
/* Display the help line at the bottom of the screen */
for (i = 0; i < 79; i++)
help_line[i] = (i < len) ? lt.help[i] : ' ';
help_line[i] = '\0';
use_helpline(help_line);
display_helpline(ds_win, LINES - 1, COLS - 1);
/* Ask for libdialog to do its stuff */
ret = PollObj(&obj);
/* We are in the Hostname field - calculate the e-mail addr */
if (n == LAYOUT_HOSTNAME) {
if ((tmp = index(tconf.hostname, '.')) != NULL) {
sprintf(tconf.email,"webmaster@%s",tmp+1);
RefreshStringObj(layout[LAYOUT_EMAIL].obj);
}
}
/* Handle special case stuff that libdialog misses. Sigh */
switch (ret) {
/* Bail out */
case SEL_ESC:
quit = TRUE, cancel=TRUE;
break;
/* This doesn't work for list dialogs. Oh well. Perhaps
should special case the move from the OK button ``up''
to make it go to the interface list, but then it gets
awkward for the user to go back and correct screw up's
in the per-interface section */
case KEY_UP:
if (obj->prev !=NULL ) {
obj = obj->prev;
--n;
} else {
obj = last;
n = max;
}
break;
case KEY_DOWN:
if (obj->next != NULL) {
obj = obj->next;
++n;
} else {
obj = first;
n = 0;
}
break;
case SEL_TAB:
if (n < max)
++n;
else
n = 0;
break;
/* The user has pressed enter over a button object */
case SEL_BUTTON:
quit = TRUE;
if (cancelbutton)
cancel = TRUE;
break;
/* Generic CR handler */
case SEL_CR:
if (n < max)
++n;
else
n = 0;
break;
case SEL_BACKTAB:
if (n)
--n;
else
n = max;
break;
case KEY_F(1):
display_helpfile();
/* They tried some key combination we don't support - tell them! */
default:
beep();
}
}
/* Clear this crap off the screen */
dialog_clear();
refresh();
use_helpfile(NULL);
if (cancel)
return RET_FAIL;
return RET_SUCCESS;
}
int
configApache(char *unused)
{
int i, maxcon;
char company[64], file[128];
char *tptr;
FILE *fptr;
/* Be optimistic */
i = RET_SUCCESS;
dialog_clear();
msgConfirm("Since you elected to install the WEB server, we'll now add the\n"
"Apache HTTPD package and set up a few configuration files.");
i = package_add(APACHE_PACKAGE);
if (i != RET_SUCCESS) {
dialog_clear();
msgConfirm("Hmmmmm. Looks like we weren't able to fetch the Apache WEB server\n"
"package. You may wish to fetch and configure it by hand by looking\n"
"in /usr/ports/net/apache (in the ports collection) or looking for the\n"
"precompiled apache package in packages/networking/%s.", APACHE_PACKAGE);
return (i);
}
i = apacheOpenDialog();
if (i != RET_SUCCESS) {
dialog_clear();
msgConfirm("Configuration of the Apache WEB server was cancelled per\n"
"user request.");
return i;
}
/*** Fix defaults for invalid value ***/
maxcon = atoi(tconf.maxcon);
if (maxcon <= 0)
maxcon = 150;
if (! tconf.group[0])
strcpy(tconf.group, "guest");
if (! tconf.user[0])
strcpy(tconf.user, "nobody");
if (! tconf.welcome[0])
strcpy(tconf.welcome, "index.html");
if (! tconf.userdir[0])
strcpy(tconf.userdir, "public_html");
/*** If the user did not specify a directory, use default ***/
if (tconf.docroot[strlen(tconf.docroot)-1] == '/')
tconf.docroot[strlen(tconf.docroot)-1] = '\0';
if (!tconf.docroot[0])
sprintf(tconf.docroot,"%s/%s",APACHE_BASE, DATA_SUBDIR);
/*** If DocRoot does not exist, create it ***/
if (!directoryExists(tconf.docroot))
vsystem("mkdir -p %s", tconf.docroot);
if (directoryExists(tconf.docroot))
{
sprintf(file,"%s/index.html", tconf.docroot);
if (!file_readable(file))
{
dialog_clear();
tptr = msgGetInput(NULL,
"What is your company name?");
if (tptr && strlen(tptr))
strcpy(company, tptr);
else
strcpy(company, "our Web Page");
msgNotify("Creating sample web page...");
fptr = fopen(file,"w");
if (fptr)
{
fprintf(fptr,"<CENTER>\n<TITLE>Welcome Page</TITLE>\n");
fprintf(fptr,"<H1>Welcome to %s </H1>\n</CENTER>\n",company);
fprintf(fptr,"<P><HR SIZE=4>\n<CENTER>\n");
fprintf(fptr,"<A HREF=\"http://www.FreeBSD.org/What\">\n");
fprintf(fptr,"<IMG SRC=\"./power.gif\" ALIGN=CENTER BORDER=0 ");
fprintf(fptr," ALT=\"Powered by FreeBSD\"></A>\n");
if (! tconf.email[0])
{
if ((tptr = variable_get(VAR_DOMAINNAME)))
sprintf(tconf.email,"root@%s",tptr);
}
if (tconf.email[0])
{
fprintf(fptr,"<ADDRESS><H4>\n");
fprintf(fptr," For questions or comments, please send mail to:\n");
fprintf(fptr," <A HREF=\"mailto:%s\">%s</A>\n",
tconf.email, tconf.email);
fprintf(fptr,"</H4></ADDRESS>\n");
}
fprintf(fptr,"</CENTER>\n\n");
fclose(fptr);
if (file_readable(FREEBSD_GIF))
vsystem("cp %s %s", FREEBSD_GIF, tconf.docroot);
}
else {
msgConfirm("Unable to create sample Web Page.");
i = RET_FAIL;
}
}
}
else {
dialog_clear();
msgConfirm("Unable to create Document Root Directory.");
i = RET_FAIL;
}
msgNotify("Writing configuration files....");
(void)vsystem("mkdir -p %s/config", APACHE_BASE);
sprintf(file, "%s/%s/access.conf", APACHE_BASE,CONFIG_SUBDIR);
if (file_readable(file))
vsystem("mv -f %s %s.ORIG", file, file);
fptr = fopen(file,"w");
if (fptr)
{
fprintf(fptr,"<Directory %s/cgi-bin>\n", APACHE_BASE);
fprintf(fptr,"Options Indexes FollowSymLinks\n</Directory>\n\n");
fprintf(fptr,"<Directory %s>\n", tconf.docroot);
fprintf(fptr,"Options Indexes FollowSymLinks\nAllowOverride All\n");
fprintf(fptr,"</Directory>\n\n");
fclose(fptr);
}
else {
dialog_clear();
msgConfirm("Could not create %s",file);
i = RET_FAIL;
}
sprintf(file, "%s/%s/httpd.conf", APACHE_BASE,CONFIG_SUBDIR);
if (file_readable(file))
vsystem("mv -f %s %s.ORIG", file, file);
fptr = fopen(file,"w");
if (fptr)
{
fprintf(fptr,"ServerType standalone\nPort 80\nTimeOut 400\n");
fprintf(fptr,"ErrorLog logs/error_log\nTransferLog logs/access_log\n");
fprintf(fptr,"PidFile /var/run/httpd.pid\n\nStartServers 5\n");
fprintf(fptr,"MinSpareServers 5\nMaxSpareServers 10\n");
fprintf(fptr,"MaxRequestsPerChild 30\nMaxClients %d\n\n",maxcon);
fprintf(fptr,"User %s\nGroup %s\n\n",tconf.user,tconf.group);
if (tconf.email[0])
fprintf(fptr,"ServerAdmin %s\n",tconf.email);
if (tconf.hostname[0])
fprintf(fptr,"ServerName %s\n",tconf.hostname);
fclose(fptr);
}
else {
dialog_clear();
msgConfirm("Could not create %s",file);
i = RET_FAIL;
}
sprintf(file, "%s/%s/srm.conf", APACHE_BASE,CONFIG_SUBDIR);
if (file_readable(file))
vsystem("mv -f %s %s.ORIG", file, file);
fptr = fopen(file,"w");
if (fptr)
{
fprintf(fptr,"FancyIndexing on\nDefaultType text/plain\n");
fprintf(fptr,"IndexIgnore */.??* *~ *# */HEADER* */README* */RCS\n");
fprintf(fptr,"HeaderName HEADER\nReadmeName README\n");
fprintf(fptr,"AccessFileName .htaccess\n\n");
fprintf(fptr,"AddEncoding x-compress Z\nAddEncoding x-gzip gz\n");
fprintf(fptr,"DefaultIcon /icons/unknown.gif\n\n");
fprintf(fptr,
"AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip\n");
fprintf(fptr,"AddIconByType (TXT,/icons/text.gif) text/*\n");
fprintf(fptr,"AddIconByType (IMG,/icons/image2.gif) image/*\n");
fprintf(fptr,"AddIconByType (SND,/icons/sound2.gif) audio/*\n");
fprintf(fptr,"AddIconByType (VID,/icons/movie.gif) video/*\n\n");
fprintf(fptr,"AddIcon /icons/text.gif .ps .shtml\n");
fprintf(fptr,"AddIcon /icons/movie.gif .mpg .qt\n");
fprintf(fptr,"AddIcon /icons/binary.gif .bin\n");
fprintf(fptr,"AddIcon /icons/burst.gif .wrl\n");
fprintf(fptr,"AddIcon /icons/binhex.gif .hqx .sit\n");
fprintf(fptr,"AddIcon /icons/uu.gif .uu\n");
fprintf(fptr,"AddIcon /icons/tar.gif .tar\n");
fprintf(fptr,"AddIcon /icons/back.gif ..\n");
fprintf(fptr,"AddIcon /icons/dir.gif ^^DIRECTORY^^\n");
fprintf(fptr,"AddIcon /icons/blank.gif ^^BLANKICON^^\n\n");
fprintf(fptr,"ScriptAlias /cgi_bin/ %s/cgi_bin/\n",APACHE_BASE);
fprintf(fptr,"Alias /icons/ %s/icons/\n",APACHE_BASE);
fprintf(fptr,"DocumentRoot %s\n",tconf.docroot);
fprintf(fptr,"UserDir %s\nDirectoryIndex %s\n\n", tconf.userdir,
tconf.welcome);
fclose(fptr);
}
else {
dialog_clear();
msgConfirm("Could not create %s",file);
i = RET_FAIL;
}
if (i != RET_FAIL)
variable_set2("apache_httpd", "YES");
return i;
}
+100
View File
@@ -0,0 +1,100 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: doc.c,v 1.9 1995/11/04 08:47:22 jkh Exp $
*
* Jordan Hubbard
*
* My contributions are in the public domain.
*
*/
#include "sysinstall.h"
/*
* This is called from the main menu. Try to find a copy of Lynx from somewhere
* and fire it up on the first copy of the handbook we can find.
*/
int
docBrowser(char *junk)
{
char *browser = variable_get(VAR_BROWSER_PACKAGE);
if (RunningAsInit && !strstr(variable_get(SYSTEM_STATE), "install")) {
msgConfirm("This option may only be used after the system is installed, sorry!");
return RET_FAIL;
}
/* Make sure we have media available */
if (!mediaVerify())
return RET_FAIL;
/* First, make sure we have whatever browser we've chosen is here */
if (package_add(browser) != RET_SUCCESS) {
dialog_clear();
msgConfirm("Unable to install the %s HTML browser package. You may\n"
"wish to verify that your media is configured correctly and\n"
"try again.", browser);
return RET_FAIL;
}
if (!file_executable(variable_get(VAR_BROWSER_BINARY))) {
dialog_clear();
if (!msgYesNo("Hmmm. The %s package claims to have installed, but I can't\n"
"find its binary in %s! You may wish to try a different\n"
"location to load the package from (go to Media menu) and see if that\n"
"makes a difference.\n\n"
"I suggest that we remove the version that was extracted since it does\n"
"not appear to be correct. Would you like me to do that now?"))
vsystem("pkg_delete %s %s", !strcmp(variable_get(VAR_CPIO_VERBOSITY), "high") ? "-v" : "", browser);
return RET_FAIL;
}
/* Run browser on the appropriate doc */
dmenuOpenSimple(&MenuHTMLDoc);
return RET_SUCCESS;
}
/* Try to show one of the documents requested from the HTML doc menu */
int
docShowDocument(char *str)
{
char tmp[512], target[512];
char *where = NULL;
char *browser = variable_get(VAR_BROWSER_BINARY);
if (!file_executable(browser)) {
dialog_clear();
msgConfirm("Can't find the browser in %s! Please ensure that it's\n"
"properly set in the Options editor.", browser);
return RET_FAIL;
}
if (!strcmp(str, "Home"))
where = "http://www.freebsd.org";
else if (!strcmp(str, "Other"))
where = msgGetInput("http://www.freebsd.org", "Please enter the URL of the location you wish to visit.");
else if (!strcmp(str, "FAQ")) {
strcpy(target, "/usr/share/doc/FAQ/freebsd-faq.html");
if (!file_readable(target))
strcpy(target, "http://www.freebsd.org/FAQ");
where = target;
}
else if (!strcmp(str, "Handbook")) {
strcpy(target, "/usr/share/doc/handbook/handbook.html");
if (!file_readable(target))
strcpy(target, "http://www.freebsd.org/handbook");
where = target;
}
if (where) {
sprintf(tmp, "%s %s", browser, where);
systemExecute(tmp);
return RET_SUCCESS;
}
else {
msgConfirm("Hmmmmm! I can't seem to access the documentation you selected!\n"
"Have you loaded the bin distribution? Is your network connected?");
return RET_FAIL;
}
}
+58
View File
@@ -0,0 +1,58 @@
# This is the installation configuration file for my laptop, fat.cdrom.com.
# It is included here merely as a sort-of-documented example.
# Turn on extra debugging.
debug=yes
# My host specific data
hostname=fat.cdrom.com
domainname=cdrom.com
nameserver=192.216.222.3
defaultrouter=192.216.222.225
ipaddr=192.216.222.227
netmask=255.255.255.240
# Which installation device to use - ftp is pointed directly at my local
# machine and the installation device is my PC CARD ethernet interface.
# the "script" keyword lets mediaSetFTP know that it's being run from
# a script and shouldn't prompt the user for extra details. If you *want*
# it to prompt, you can pass it either "express", "novice" or "custom"
# to set the level of detail for such prompting. This is a general convention
# which you'll see elsewhere in this script file.
ftp=ftp://time.cdrom.com/pub
mediaSetFTP=script
tcpInstallDevice=ze0
# Select which distributions we want.
distSetUser
# Now set the parameters for the partition editor. Set to use all remaining
# free space (could also be "all" or "existing" to use all the disk or an
# existing FreeBSD slice). Pass the script parameter to diskPartitionEditor
# so it's not interactive, as described above.
disk=wd0
diskSpace=free
bootManager=booteasy
diskPartitionEditor=script
# It's bogus that we have to re-enter the label editor for each partition
# we want to create, but it was easier to do it this way (from a programming
# standpoint, not a user standpoint!). This assumes that slice 1 is a DOS
# partition and mounts it as /dos, which is the case on my laptop.
# We can also create a root partition of 20MB in size on the same pass since
# it's in a different slice (s2). All sizes are expressed in 512 byte blocks!
wd0s1=/dos N
wd0s2=partition 40960 /
diskLabelEditor=script
# Now make a 20MB swap partition in the second slice.
wd0s2=swap 40960 none
diskLabelEditor=script
# Size of 0 means allocate the rest of the space to /usr
wd0s2=partition 0 /usr
diskLabelEditor=script
# OK, everything is set. Do it!
installCommit=script
+19
View File
@@ -0,0 +1,19 @@
This screen allows you to configure the anonymous FTP user.
The following configuration values are editable:
UID: The user ID you wish to assign to the anonymous FTP user.
All files uploaded will be owned by this ID.
Group: Which group you wish the anonymous FTP user to be in.
Comment: String describing this user in /etc/passwd
FTP Root Directory:
Where files available for anonymous FTP will be kept.
Upload subdirectory:
Where files uploaded by anonymous FTP users will go.
+51
View File
@@ -0,0 +1,51 @@
There are two sets of options that the Apache HTTP Server needs.
The first set covers how it operates. These are as follows:
The "HostName" field is the name of this host, as it is
reported to each client connection. Normally, the fully
qualified domain name of the host running the server is
returned. If you want this set to something else, however,
(usually "www.my.domain") then this can be entered here.
Additionally, the server needs to know how many connections
are allowed at one time - this is the "Max Connections"
field. If more than this number of clients attempt to connect
at once, the additional connections will be refused. This is
used to limit how much system load will be imposed by the HTTP
server.
The "Email Address" field is the address of the person (or
system alias) who is the administrator for this web site. In
addition to being used by the Apache Server itself, it is also
put at the bottom of the sample web page that is created.
Finally, the "Default User" and "Default Group" fields specify
what user id and group id should be used by the server for
remote connections. Local connections are kept as the UID and
GID of the local process.
The second set of options determine what information is made available
to each client:
The "Document Root Path" is the top of the tree of documents
that are made avaliable. For example, if the value is
"/usr/web", then the URL "http://www.foo.com/doc.html" would
translate as "/usr/web/doc.html".
Similarly, the "User Directory" is the location in each user's
home directory where their public web documents are
stored. Thus if the value if this is "Public", then the URL
"http://www.foo.com/~joe/doc" would translate to the path
"~joe/Public/doc".
Finally, if the URL points to a directory, there is always a
"Default Document" that Apache will use. This field holds the
name (not the path) of this document. By default, Apache uses
the file "index.html". However, some sites may be more used to
using the file "welcome.html".
There are a number of other options that can be configured with
Apache, such as path aliases, masquerading as multiple hosts, server
child process parameters, and so forth. For more information on these,
consult the Apache man pages at http://www.apache.org.
+38
View File
@@ -0,0 +1,38 @@
Welcome to the 2.0.5 -> 2.1 upgrade procedure!
It must first be said that this upgrade DOES NOT take a particularly
sophisticated approach to the upgrade problem, it being more a question
of providing what seemed "good enough" at the time. A truly polished
upgrade that deals properly with the broad spectrum of installed 2.0.5
systems would be nice to have, but until that gets written what you get is
this - the brute-force approach!
What this upgrade will attempt to do is best summarized thusly:
1. fsck and mount all file systems chosen in the label editor.
2. Ask for a location to preserve your /etc directory into and do so.
3. Extract all selected distributions on top of your existing system.
4. Copy certain obvious files back from the preserved /etc, leaving the
rest of the /etc file merge up to the user.
5. Drop user in a shell so that they may perform that merge before
rebooting into the new system.
And that's it! This "upgrade" is not going to hold your hand in all
major respects, it's simply provided to make one PART of the upgrade
easier.
IMPORTANT NOTE: What this upgrade procedure may also do, in fact, is
completely destroy your system (though much more quickly than you
would have been able to destroy it yourself). It is simply impossible
to guarantee that this procedure's crude form of upgrade automation
will work in all cases and if you do this upgrade without proper
BACKUPS for any important data then you really must like living life
close to the edge, that's all we can say!
NOTE to 2.0 users: We're sorry, but the "slice" changes that were
added in FreeBSD 2.0.5 made automated upgrades pretty difficult due to
the fact that a complete reinstall is pretty much called for. Things
may still *work* after a 2.1 upgrade, but you will also no doubt
receive many warnings at boot time about non-aligned slices and such;
we really do recommend a fresh installation for 2.0 systems! (But
back up your user data first :-).
+569
View File
@@ -0,0 +1,569 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: index.c,v 1.19 1995/11/06 22:26:28 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 Jordan Hubbard
* for the FreeBSD Project.
* 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``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 HIS PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ncurses.h>
#include <dialog.h>
#include "sysinstall.h"
/* Macros and magic values */
#define MAX_MENU 13
#define _MAX_DESC 62
/* Smarter strdup */
inline char *
_strdup(char *ptr)
{
return ptr ? strdup(ptr) : NULL;
}
static char *descrs[] = {
"Package Selection", "To mark a package or select a category, move to it and press SPACE.\n"
"To unmark a package, press SPACE again. When you want to commit your\n"
"marks, press [ENTER]. To go to a previous menu, select UP item or Cancel.\n"
"To search for a package by name, press ESC. To extract packages, you\n"
"should Cancel all the way out of any submenus and finally this menu.",
"Package Targets", "These are the packages you've selected for extraction.\n\n"
"If you're sure of these choices, select OK.\n"
"If not, select Cancel to go back to the package selection menu.\n",
"All", "All available packages in all categories.",
"applications", "User application software.",
"archivers", "Utilities for archiving and unarchiving data.",
"audio", "Audio utilities - most require a supported sound card.",
"benchmarks", "Utilities for measuring system performance.",
"benchmarking", "Utilities for measuring system performance.",
"cad", "Computer Aided Design utilities.",
"comms", "Communications utilities.",
"databases", "Database software.",
"devel", "Software development utilities and libraries.",
"development", "Software development utilities and libraries.",
"documentation", "Document preparation utilities.",
"editors", "Common text editors.",
"emulation", "Utilities for emulating other OS types.",
"emulators", "Utilities for emulating other OS types.",
"games", "Various and sundry amusements.",
"graphics", "Graphics libraries and utilities.",
"japanese", "Ported software for the Japanese market.",
"lang", "Computer languages.",
"languages", "Computer languages.",
"libraries", "Software development libraries.",
"mail", "Electronic mail packages and utilities.",
"math", "Mathematical computation software.",
"net", "Networking utilities.",
"networking", "Networking utilities.",
"news", "USENET News support software.",
"numeric", "Mathematical computation software.",
"orphans", "Packages without a home elsewhere.",
"plan9", "Software from the plan9 Operating System.",
"print", "Utilities for dealing with printing.",
"printing", "Utilities for dealing with printing.",
"programming", "Software development utilities and libraries.",
"russian", "Ported software for the Russian market.",
"security", "System security software.",
"shells", "Various shells (tcsh, bash, etc).",
"sysutils", "Various system utilities.",
"troff", "TROFF Text formatting utilities.",
"utils", "Various user utilities.",
"utilities", "Various user utilities.",
"x11", "X Window System based utilities.",
NULL, NULL,
};
static char *
fetch_desc(char *name)
{
int i;
for (i = 0; descrs[i]; i += 2) {
if (!strcmp(descrs[i], name))
return descrs[i + 1];
}
return "No description provided";
}
static PkgNodePtr
new_pkg_node(char *name, node_type type)
{
PkgNodePtr tmp = safe_malloc(sizeof(PkgNode));
tmp->name = _strdup(name);
tmp->type = type;
return tmp;
}
static IndexEntryPtr
new_index(char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint)
{
IndexEntryPtr tmp = safe_malloc(sizeof(IndexEntry));
tmp->name = _strdup(name);
tmp->path = _strdup(pathto);
tmp->prefix = _strdup(prefix);
tmp->comment = _strdup(comment);
tmp->descrfile = _strdup(descr);
tmp->maintainer = _strdup(maint);
return tmp;
}
static void
index_register(PkgNodePtr top, char *where, IndexEntryPtr ptr)
{
PkgNodePtr p, q;
for (q = NULL, p = top->kids; p; p = p->next) {
if (!strcmp(p->name, where)) {
q = p;
break;
}
}
if (!p) {
/* Add new category */
q = new_pkg_node(where, PLACE);
q->desc = fetch_desc(where);
q->next = top->kids;
top->kids = q;
}
p = new_pkg_node(ptr->name, PACKAGE);
p->desc = ptr->comment;
p->data = ptr;
p->next = q->kids;
q->kids = p;
}
static int
copy_to_sep(char *to, char *from, int sep)
{
char *tok;
tok = strchr(from, sep);
if (!tok) {
fprintf(stderr, "missing '%c' token.\n", sep);
*to = '\0';
return 0;
}
*tok = '\0';
strcpy(to, from);
return tok + 1 - from;
}
static int
readline(int fd, char *buf, int max)
{
int rv, i = 0;
char ch;
while ((rv = read(fd, &ch, 1)) == 1 && ch != '\n' && i < max)
buf[i++] = ch;
if (i < max)
buf[i] = '\0';
return rv;
}
int
index_parse(int fd, char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint,
char *cats, char *keys)
{
char line[1024];
char *cp;
int i;
i = readline(fd, line, 1024);
if (i <= 0)
return EOF;
cp = line;
cp += copy_to_sep(name, cp, '|');
cp += copy_to_sep(pathto, cp, '|');
cp += copy_to_sep(prefix, cp, '|');
cp += copy_to_sep(comment, cp, '|');
cp += copy_to_sep(descr, cp, '|');
cp += copy_to_sep(maint, cp, '|');
cp += copy_to_sep(cats, cp, '|');
strcpy(keys, cp);
return 0;
}
int
index_get(char *fname, PkgNodePtr papa)
{
int i, fd;
fd = open(fname, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Unable to open index file `%s' for reading.\n", fname);
i = -1;
}
else
i = index_read(fd, papa);
close(fd);
return i;
}
int
index_read(int fd, PkgNodePtr papa)
{
char name[127], pathto[255], prefix[255], comment[255], descr[127], maint[127], cats[511], keys[511];
while (index_parse(fd, name, pathto, prefix, comment, descr, maint, cats, keys) != EOF) {
char *cp, *cp2, tmp[511];
IndexEntryPtr idx;
idx = new_index(name, pathto, prefix, comment, descr, maint);
/* For now, we only add things to menus if they're in categories. Keywords are ignored */
for (cp = strcpy(tmp, cats); (cp2 = strchr(cp, ' ')) != NULL; cp = cp2 + 1) {
*cp2 = '\0';
index_register(papa, cp, idx);
}
index_register(papa, cp, idx);
/* Add to special "All" category */
index_register(papa, "All", idx);
}
return 0;
}
void
index_init(PkgNodePtr top, PkgNodePtr plist)
{
top->next = top->kids = NULL;
top->name = "Package Selection";
top->type = PLACE;
top->desc = fetch_desc(top->name);
top->data = NULL;
plist->next = plist->kids = NULL;
plist->name = "Package Targets";
plist->type = PLACE;
plist->desc = fetch_desc(plist->name);
plist->data = NULL;
}
void
index_entry_free(IndexEntryPtr top)
{
safe_free(top->name);
safe_free(top->path);
safe_free(top->prefix);
safe_free(top->comment);
safe_free(top->descrfile);
safe_free(top->maintainer);
free(top);
}
void
index_node_free(PkgNodePtr top, PkgNodePtr plist)
{
PkgNodePtr tmp;
tmp = plist;
while (tmp) {
PkgNodePtr tmp2 = tmp->next;
safe_free(tmp);
tmp = tmp2;
}
for (tmp = top; tmp; tmp = tmp->next) {
free(tmp->name);
if (tmp->type == PACKAGE && tmp->data)
index_entry_free((IndexEntryPtr)tmp->data);
if (tmp->kids)
index_node_free(tmp->kids, NULL);
}
}
void
index_print(PkgNodePtr top, int level)
{
int i;
while (top) {
for (i = 0; i < level; i++) putchar('\t');
printf("name [%s]: %s\n", top->type == PLACE ? "place" : "package", top->name);
for (i = 0; i < level; i++) putchar('\t');
printf("desc: %s\n", top->desc);
if (top->kids)
index_print(top->kids, level + 1);
top = top->next;
}
}
/* Swap one node for another */
static void
swap_nodes(PkgNodePtr a, PkgNodePtr b)
{
PkgNode tmp;
tmp = *a;
*a = *b;
a->next = tmp.next;
tmp.next = b->next;
*b = tmp;
}
/* Use a disgustingly simplistic bubble sort to put our lists in order */
void
index_sort(PkgNodePtr top)
{
PkgNodePtr p, q;
/* Sort everything at the top level */
for (p = top->kids; p; p = p->next) {
for (q = top->kids; q; q = q->next) {
if (q->next && strcmp(q->name, q->next->name) > 0)
swap_nodes(q, q->next);
}
}
/* Now sub-sort everything n levels down */
for (p = top->kids; p; p = p->next) {
if (p->kids)
index_sort(p);
}
}
/*
* No, we don't free n because someone else is still pointing at it.
* It's just clone linked from another location, which we're adjusting.
*/
void
index_delete(PkgNodePtr n)
{
if (n->next)
*n = *(n->next);
else /* Kludgy end sentinal */
n->name = NULL;
}
PkgNodePtr
index_search(PkgNodePtr top, char *str, PkgNodePtr *tp)
{
PkgNodePtr p, sp;
for (p = top->kids; p && p->name; p = p->next) {
/* Subtract out the All category from searches */
if (!strcmp(p->name, "All"))
continue;
/* If tp == NULL, we're looking for an exact package match */
if (!tp && !strcmp(p->name, str))
return p;
/* If tp, we're looking for both a package and a pointer to the place it's in */
if (tp && strstr(p->name, str)) {
*tp = top;
return p;
}
/* The usual recursion-out-of-laziness ploy */
if (p->kids)
if ((sp = index_search(p, str, tp)) != NULL)
return sp;
}
if (p && !p->name)
p = NULL;
return p;
}
/* Work function for seeing if name x is in result string y */
static Boolean
is_selected_in(char *name, char *result)
{
Boolean ret = FALSE;
while (*result) {
char *cp;
cp = index(result, '\n');
if (!cp) {
ret = !strcmp(name, result);
break;
}
else {
ret = !strncmp(name, result, cp - result - 1);
if (ret)
break;
}
result = cp + 1;
}
return ret;
}
int
index_menu(PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll)
{
int n, rval, maxname;
int curr, max;
PkgNodePtr sp, kp;
char **nitems;
char result[4096];
Boolean hasPackages;
hasPackages = FALSE;
nitems = NULL;
n = maxname = 0;
/* Figure out if this menu is full of "leaves" or "branches" */
for (kp = top->kids; kp && kp->name; kp = kp->next) {
int len;
++n;
if (kp->type == PACKAGE && plist) {
hasPackages = TRUE;
if ((len = strlen(kp->name)) > maxname)
maxname = len;
}
}
if (!n && plist) {
dialog_clear();
msgConfirm("The %s menu is empty.", top->name);
return RET_DONE;
}
dialog_clear();
while (1) {
n = 0;
curr = max = 0;
kp = top->kids;
if (!hasPackages && kp && kp->name && plist) {
nitems = item_add_pair(nitems, "UP", "<RETURN TO PREVIOUS MENU>", &curr, &max);
++n;
}
while (kp && kp->name) {
/* Brutally adjust description to fit in menu */
if (strlen(kp->desc) > (_MAX_DESC - maxname))
kp->desc[_MAX_DESC - maxname] = '\0';
nitems = item_add_pair(nitems, kp->name, kp->desc, &curr, &max);
if (hasPackages) {
if (kp->type == PACKAGE && plist)
nitems = item_add(nitems, index_search(plist, kp->name, NULL) ? "ON" : "OFF", &curr, &max);
else
nitems = item_add(nitems, "OFF", &curr, &max);
}
++n;
kp = kp->next;
}
nitems = item_add(nitems, NULL, &curr, &max);
if (hasPackages)
rval = dialog_checklist(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, n,
(unsigned char **)nitems, result);
else /* It's a categories menu */
rval = dialog_menu(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, n,
(unsigned char **)nitems, result, pos, scroll);
if (!rval && plist && strcmp(result, "UP")) {
for (kp = top->kids; kp; kp = kp->next) {
if (kp->type == PACKAGE) {
sp = index_search(plist, kp->name, NULL);
if (is_selected_in(kp->name, result)) {
if (!sp) {
PkgNodePtr np = (PkgNodePtr)safe_malloc(sizeof(PkgNode));
*np = *kp;
np->next = plist->kids;
plist->kids = np;
standout();
mvprintw(23, 0, "Selected packages were added to selection list\n", kp->name);
standend();
refresh();
}
}
else if (sp) {
standout();
mvprintw(23, 0, "Deleting unselected packages from selection list\n", kp->name);
standend();
refresh();
index_delete(sp);
}
}
else if (!strcmp(kp->name, result)) { /* Not a package, must be a directory */
int p, s;
p = s = 0;
index_menu(kp, plist, &p, &s);
}
}
}
else if (rval == -1 && plist) {
static char *cp;
PkgNodePtr menu;
/* Search */
if ((cp = msgGetInput(cp, "Search by package name. Please enter search string:")) != NULL) {
PkgNodePtr p = index_search(top, cp, &menu);
if (p) {
int pos, scroll;
/* These need to be set to point at the found item, actually. Hmmm! */
pos = scroll = 0;
index_menu(menu, plist, &pos, &scroll);
}
else {
msgConfirm("Search string: %s yielded no hits.", cp);
}
}
}
else {
dialog_clear();
items_free(nitems, &curr, &max);
return rval ? RET_FAIL : RET_SUCCESS;
}
}
}
int
index_extract(Device *dev, PkgNodePtr plist)
{
PkgNodePtr tmp;
int status = RET_SUCCESS;
for (tmp = plist->kids; tmp; tmp = tmp->next) {
if (package_extract(dev, tmp->name) != RET_SUCCESS)
status = RET_FAIL;
}
return status;
}
+223
View File
@@ -0,0 +1,223 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: installFinal.c,v 1.20 1995/11/12 11:12:25 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard & Coranth Gryphon. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 authors listed above
* for the FreeBSD Project.
* 4. The names of the authors or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``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 OR THEIR PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "sysinstall.h"
#include <sys/disklabel.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mount.h>
/* This file contains all the final configuration thingies */
static DMenu MenuSamba = {
DMENU_MULTIPLE_TYPE | DMENU_SELECTION_RETURNS,
"Samba Services Menu",
"This allows you to configure various aspects of your Samba server.",
NULL,
NULL,
{ { "Homes", "Make home directories available to users.",
DMENU_SET_VARIABLE, "SAMBA_homes=YES", 0, 0, dmenuVarCheck },
{ "Printers", "Allows for sharing of local printers.",
DMENU_SET_VARIABLE, "SAMBA_printers=YES", 0, 0, dmenuVarCheck},
{ "Export Paths", "Specify local directories to make available.",
DMENU_SET_VARIABLE, "SAMBA_export=YES", 0, 0, dmenuVarCheck },
{ NULL } },
};
/* These probably shouldn't be hard-coded, but making them options might prove to be even more confusing! */
#define SMB_CONF "./smb.conf"
/* Load gated package */
int
configGated(char *unused)
{
if (package_add("gated-3.5a11") == RET_SUCCESS)
variable_set2("gated", "YES");
return RET_SUCCESS;
}
/* Load pcnfsd package */
int
configPCNFSD(char *unused)
{
if (package_add("pcnfsd-93.02.16") == RET_SUCCESS)
variable_set2("pcnfsd", "YES");
return RET_SUCCESS;
}
int
configSamba(char *unused)
{
int i = RET_SUCCESS;
if (!dmenuOpenSimple(&MenuSamba))
i = RET_FAIL;
else if (package_add("samba-1.9.14") != RET_SUCCESS)
i = RET_FAIL;
else {
FILE *fptr;
char tbuf[256], *tptr;
int tval;
fptr = fopen("/tmp/smb.conf","w");
if (fptr) {
strcpy(tbuf,"FreeBSD - Samba %v");
if (variable_get("SAMBA_string")) {
tptr = msgGetInput("FreeBSD - Samba %%v", "What should this server list as its description?\n"
"Note that the \"%%v\" refers to the samba version number.");
if (tptr && *tptr)
strcpy(tbuf, tptr);
}
fprintf(fptr, "[global]\n");
fprintf(fptr, "comment = %s\n", tbuf);
fprintf(fptr, "log file = /var/log/samba.log\n");
fprintf(fptr, "dont descend = /dev,/proc,/root,/stand\n\n");
fprintf(fptr, "printing = bsd\n");
fprintf(fptr, "map archive = no\n");
fprintf(fptr, "status = yes\n");
fprintf(fptr, "public = yes\n");
fprintf(fptr, "read only = no\n");
fprintf(fptr, "preserve case = yes\n");
fprintf(fptr, "strip dot = yes\n");
fprintf(fptr, "security = share\n");
fprintf(fptr, "guest ok = yes\n\n");
if (variable_get("SAMBA_homes")) {
fprintf(fptr, "[homes]\n");
fprintf(fptr, "browseable = no\n");
fprintf(fptr, "comment = User Home Directory\n");
fprintf(fptr, "create mode = 0775\n");
fprintf(fptr, "public = no\n\n");
}
if (variable_get("SAMBA_printers")) {
fprintf(fptr, "[printers]\n");
fprintf(fptr, "path = /var/spool\n");
fprintf(fptr, "comment = Printers\n");
fprintf(fptr, "create mode = 0700\n");
fprintf(fptr, "browseable = no\n");
fprintf(fptr, "printable = yes\n");
fprintf(fptr, "read only = yes\n");
fprintf(fptr, "public = no\n\n");
}
if (variable_get("SAMBA_export")) {
for (tval = 0; ! tval; tval = msgYesNo("Another?")) {
tptr = msgGetInput(NULL,"What directory to export?");
if (tptr && *tptr && (tptr[0] == '/')) {
int len = strlen(tbuf);
strcpy(tbuf, tptr);
if (tbuf[len - 1] == '/')
tbuf[len - 1] = '\0';
if (directoryExists(tbuf)) {
tptr = msgGetInput(pathBaseName(tbuf), "What do you want to call this share?");
if (tptr && *tptr) {
fprintf(fptr, "[%s]\npath = %s\n", tptr, tbuf);
tptr = msgGetInput(NULL, "Enter a short description of this share?");
if (tptr && *tptr)
fprintf(fptr, "comment = %s\n", tptr);
if (msgYesNo("Do you want this share to be read only?"))
fprintf(fptr, "read only = no\n\n");
else
fprintf(fptr, "read only = yes\n\n");
}
else {
dialog_clear();
msgConfirm("Invalid Share Name.");
}
}
else {
dialog_clear();
msgConfirm("Directory does not exist.");
}
} /* end if (tptr) */
} /* end for loop */
} /* end if (SAMBA_export) */
fclose(fptr);
vsystem("mv -f /tmp/smb.conf %s", SMB_CONF);
}
else {
dialog_clear();
msgConfirm("Unable to open temporary smb.conf file.\n"
"Samba will have to be configured by hand.");
}
}
return i;
}
int
configNFSServer(char *unused)
{
/* If we're an NFS server, we need an exports file */
if (!file_readable("/etc/exports")) {
dialog_clear();
msgConfirm("Operating as an NFS server means that you must first configure\n"
"an /etc/exports file to indicate which hosts are allowed certain\n"
"kinds of access to your local file systems.\n"
"Press [ENTER] now to invoke an editor on /etc/exports (the editor\n"
"may take a little while to uncompress the first time - please be\n"
"patient!)");
vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
vsystem("echo '#and, finally, /a to 2 privileged machines allowed to write on it as root.' >> /etc/exports");
vsystem("echo '#/usr huey louie dewie' >> /etc/exports");
vsystem("echo '#/home -alldirs janice jimmy frank' >> /etc/exports");
vsystem("echo '#/a -maproot=0 bill albert' >> /etc/exports");
vsystem("echo '#' >> /etc/exports");
vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports");
vsystem("echo >> /etc/exports");
dialog_clear();
systemExecute("/stand/ee /etc/exports");
}
variable_set2("nfs_server", "YES");
return RET_SUCCESS;
}
+221
View File
@@ -0,0 +1,221 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: installPreconfig.c,v 1.16 1995/10/27 17:00:23 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 Jordan Hubbard
* for the FreeBSD Project.
* 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``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 HIS PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "sysinstall.h"
#include <ctype.h>
#include <sys/disklabel.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <sys/param.h>
#define MSDOSFS
#include <sys/mount.h>
#undef MSDOSFS
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mount.h>
static struct _word {
char *name;
int (*handler)(char *str);
} resWords[] = {
{ "configAnonFTP", configAnonFTP },
{ "configApache", configApache },
{ "configGated", configGated },
{ "configNFSServer", configNFSServer },
{ "configSamba", configSamba },
{ "diskPartitionEditor", diskPartitionEditor },
{ "diskPartitionWrite", diskPartitionWrite },
{ "diskLabelEditor", diskLabelEditor },
{ "diskLabelCommit", diskLabelCommit },
{ "distReset", distReset },
{ "distSetCustom", distSetCustom },
{ "distSetDeveloper", distSetDeveloper },
{ "distSetXDeveloper", distSetXDeveloper },
{ "distSetKernDeveloper", distSetKernDeveloper },
{ "distSetUser", distSetUser },
{ "distSetXUser", distSetXUser },
{ "distSetMinimum", distSetMinimum },
{ "distSetEverything", distSetEverything },
{ "distSetDES", distSetDES },
{ "distSetSrc", distSetSrc },
{ "distSetXF86", distSetXF86 },
{ "distExtractAll", distExtractAll },
{ "docBrowser", docBrowser },
{ "docShowDocument", docShowDocument },
{ "installCommit", installCommit },
{ "installExpress", installExpress },
{ "installUpgrade", installUpgrade },
{ "installPreconfig", installPreconfig },
{ "installFixup", installFixup },
{ "installFilesystems", installFilesystems },
{ "mediaSetCDROM", mediaSetCDROM },
{ "mediaSetFloppy", mediaSetFloppy },
{ "mediaSetDOS", mediaSetDOS },
{ "mediaSetTape", mediaSetTape },
{ "mediaSetFTP", mediaSetFTP },
{ "mediaSetFTPActive", mediaSetFTPActive },
{ "mediaSetFTPPassive", mediaSetFTPPassive },
{ "mediaSetUFS", mediaSetUFS },
{ "mediaSetNFS", mediaSetNFS },
{ "mediaSetFtpUserPass", mediaSetFtpUserPass },
{ "mediaSetCPIOVerbosity", mediaSetCPIOVerbosity },
{ "mediaGetType", mediaGetType },
{ "msgConfirm", msgSimpleConfirm },
{ "msgNotify", msgSimpleNotify },
{ "packageAdd", package_add },
{ "system", (int (*)(char *))vsystem },
{ "systemInteractive", systemExecute },
{ "tcpInstallDevice", tcpInstallDevice },
{ NULL, NULL },
};
static int
call_possible_resword(char *name, char *value, int *status)
{
int i, rval;
rval = 0;
for (i = 0; resWords[i].name; i++) {
if (!strcmp(name, resWords[i].name)) {
*status = resWords[i].handler(value);
rval = 1;
break;
}
}
return rval;
}
/* From the top menu - try to mount the floppy and read a configuration file from it */
int
installPreconfig(char *str)
{
struct ufs_args u_args;
struct msdosfs_args m_args;
int fd, i;
char buf[128];
char *cfg_file;
memset(&u_args, 0, sizeof(u_args));
u_args.fspec = "/dev/fd0";
Mkdir("/mnt2", NULL);
memset(&m_args, 0, sizeof(m_args));
m_args.fspec = "/dev/fd0";
m_args.uid = m_args.gid = 0;
m_args.mask = 0777;
i = RET_FAIL;
while (1) {
if (!(cfg_file = variable_get_value(VAR_CONFIG_FILE,
"Please insert the floppy containing this configuration file\n"
"into drive A now and press [ENTER].")))
break;
if (mount(MOUNT_UFS, "/mnt2", MNT_RDONLY, (caddr_t)&u_args) == -1) {
if (mount(MOUNT_MSDOS, "/mnt2", MNT_RDONLY, (caddr_t)&m_args) == -1) {
dialog_clear();
if (msgYesNo("Unable to mount the configuration floppy - do you want to try again?"))
break;
else
continue;
}
}
fnord:
if (!cfg_file)
break;
sprintf(buf, "/mnt2/%s", cfg_file);
msgDebug("Attempting to open configuration file: %s\n", buf);
fd = open(buf, O_RDONLY);
if (fd == -1) {
dialog_clear();
if (msgYesNo("Unable to find the configuration file: %s\n"
"Do you want to try again?", buf)) {
unmount("/mnt2", MNT_FORCE);
break;
}
else
goto fnord;
}
else {
Attribs *cattr = safe_malloc(sizeof(Attribs) * MAX_ATTRIBS);
int i, j;
if (attr_parse(cattr, fd) == RET_FAIL) {
dialog_clear();
msgConfirm("Cannot parse configuration file %s! Please verify your media.", cfg_file);
}
else {
i = RET_SUCCESS;
for (j = 0; cattr[j].name[0]; j++) {
int status;
if (call_possible_resword(cattr[j].name, cattr[j].value, &status)) {
if (status != RET_SUCCESS) {
msgDebug("macro call to %s(%s) returns %d status!\n", cattr[j].name, cattr[j].value,
status);
i = status;
}
}
else
variable_set2(cattr[j].name, cattr[j].value);
}
if (i == RET_SUCCESS) {
dialog_clear();
msgConfirm("Configuration file %s loaded successfully!\n"
"Some parameters may now have new default values.", buf);
}
else if (i == RET_FAIL) {
dialog_clear();
msgConfirm("Configuration file %s loaded with some errors.", buf);
}
}
close(fd);
safe_free(cattr);
unmount("/mnt2", MNT_FORCE);
break;
}
}
return i;
}
+396
View File
@@ -0,0 +1,396 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: installUpgrade.c,v 1.17 1995/11/08 07:09:27 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 Jordan Hubbard
* for the FreeBSD Project.
* 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``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 HIS PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "sysinstall.h"
#include <sys/disklabel.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mount.h>
typedef struct _hitList {
enum { JUST_COPY, CALL_HANDLER } action ;
char *name;
Boolean optional;
void (*handler)(struct _hitList *self);
} HitList;
/* cop-out function for files we can't handle */
static void
doByHand(HitList *h)
{
dialog_clear();
msgConfirm("/etc/%s is one of those files that this upgrade procedure just isn't\n"
"smart enough to deal with right now. You'll need to merge the old and\n"
"new versions by hand when the option to do so manually is later\n"
"presented (in the meantime, you might want to write the name of\n"
"this file down! - the holographic shell on VTY4 is a good place for\n"
"this).", h->name);
}
static void
yellSysconfig(HitList *h)
{
dialog_clear();
msgConfirm("/etc/sysconfig is one of those files that this upgrade procedure just isn't\n"
"smart enough to deal with right now. Unfortunately, your system\n"
"will also come up with a very different \"personality\" than it had\n"
"before if you do not merge at LEAST the hostname and ifconfig lines\n"
"from the old one! This is very important, so please do this merge\n"
"even if you do no others before the system is allowed to reboot.");
}
/* These are the only meaningful files I know about */
static HitList etc_files [] = {
{ JUST_COPY, "Xaccel.ini", TRUE, NULL },
{ JUST_COPY, "adduser.conf", TRUE, NULL },
{ JUST_COPY, "aliases", TRUE, NULL },
{ JUST_COPY, "aliases.db", TRUE, NULL },
{ JUST_COPY, "amd.map", TRUE, NULL },
{ JUST_COPY, "crontab", TRUE, NULL },
{ JUST_COPY, "csh.cshrc", TRUE, NULL },
{ JUST_COPY, "csh.login", TRUE, NULL },
{ JUST_COPY, "csh.logout", TRUE, NULL },
{ JUST_COPY, "daily", TRUE, NULL },
{ JUST_COPY, "disktab", TRUE, NULL },
{ JUST_COPY, "dm.conf", TRUE, NULL },
{ JUST_COPY, "exports", TRUE, NULL },
{ JUST_COPY, "fbtab", TRUE, NULL },
{ CALL_HANDLER, "fstab", FALSE, doByHand },
{ JUST_COPY, "ftpusers", TRUE, NULL },
{ JUST_COPY, "gnats", TRUE, NULL },
{ JUST_COPY, "group", FALSE, NULL },
{ JUST_COPY, "host.conf", TRUE, NULL },
{ JUST_COPY, "hosts", TRUE, NULL },
{ JUST_COPY, "hosts.equiv", TRUE, NULL },
{ JUST_COPY, "hosts.lpd", TRUE, NULL },
{ CALL_HANDLER, "inetd.conf", FALSE, doByHand },
{ CALL_HANDLER, "kerberosIV", TRUE, doByHand },
{ JUST_COPY, "localtime", TRUE, NULL },
{ JUST_COPY, "login.access", TRUE, NULL },
{ JUST_COPY, "mail.rc", TRUE, NULL },
{ JUST_COPY, "make.conf", TRUE, NULL },
{ JUST_COPY, "manpath.config", TRUE, NULL },
{ JUST_COPY, "master.passwd", TRUE, NULL },
{ JUST_COPY, "mib.txt", TRUE, NULL },
{ JUST_COPY, "modems", TRUE, NULL },
{ JUST_COPY, "monthly", TRUE, NULL },
{ JUST_COPY, "motd", TRUE, NULL },
{ JUST_COPY, "namedb", TRUE, NULL },
{ CALL_HANDLER, "netstart", FALSE, doByHand },
{ JUST_COPY, "networks", TRUE, NULL },
{ JUST_COPY, "passwd", FALSE, NULL },
{ JUST_COPY, "phones", TRUE, NULL },
{ JUST_COPY, "ppp", TRUE, NULL },
{ JUST_COPY, "printcap", TRUE, NULL },
{ JUST_COPY, "profile", TRUE, NULL },
{ JUST_COPY, "protocols", TRUE, NULL },
{ JUST_COPY, "pwd.db", TRUE, NULL },
{ CALL_HANDLER, "rc", FALSE, doByHand },
{ CALL_HANDLER, "rc.i386", TRUE, doByHand },
{ JUST_COPY, "rc.local", TRUE, NULL },
{ CALL_HANDLER, "rc.serial", TRUE, doByHand },
{ JUST_COPY, "remote", TRUE, NULL },
{ JUST_COPY, "resolv.conf", TRUE, NULL },
{ JUST_COPY, "rmt", TRUE, NULL },
{ JUST_COPY, "security", TRUE, NULL },
{ JUST_COPY, "sendmail.cf", TRUE, NULL },
{ CALL_HANDLER, "services", TRUE, doByHand },
{ JUST_COPY, "shells", TRUE, NULL },
{ JUST_COPY, "skeykeys", TRUE, NULL },
{ JUST_COPY, "spwd.db", TRUE, NULL },
{ JUST_COPY, "supfile", TRUE, NULL },
{ CALL_HANDLER, "sysconfig", FALSE, yellSysconfig },
{ JUST_COPY, "syslog.conf", TRUE, NULL },
{ JUST_COPY, "termcap", TRUE, NULL },
{ JUST_COPY, "ttys", TRUE, NULL },
{ JUST_COPY, "uucp", TRUE, NULL },
{ JUST_COPY, "weekly", TRUE, NULL },
{ 0 },
};
void
traverseHitlist(HitList *h)
{
while (h->name) {
if (!file_readable(h->name)) {
if (!h->optional) {
dialog_clear();
msgConfirm("Unable to find an old /etc/%s file! That is decidedly non-standard and\n"
"your upgraded system may function a little strangely as a result.");
}
}
else {
if (h->action == JUST_COPY) {
/* Nuke the just-loaded copy thoroughly */
vsystem("rm -rf /etc/%s", h->name);
/* Copy the old one into its place */
msgNotify("Resurrecting %s..", h->name);
/* Do this with tar so that symlinks and such are preserved */
if (vsystem("tar cf - %s | tar xpf - -C /etc", h->name)) {
dialog_clear();
msgConfirm("Unable to resurrect your old /etc/%s! Hmmmm.", h->name);
}
}
else /* call handler */
h->handler(h);
}
++h;
}
}
int
installUpgrade(char *str)
{
char *saved_etc = NULL;
Boolean extractingBin = TRUE;
struct termios foo;
if (!RunningAsInit) {
dialog_clear();
msgConfirm("You can only perform this procedure when booted off the installation\n"
"floppy.");
return RET_FAIL;
}
systemDisplayHelp("upgrade");
if (msgYesNo("Given all that scary stuff you just read, are you sure you want to\n"
"risk it all and proceed with this upgrade?"))
return RET_FAIL;
if (!Dists) {
dialog_clear();
msgConfirm("You haven't specified any distributions yet. The upgrade procedure will\n"
"only upgrade those portions of the system for which a distribution has\n"
"been selected. In the next screen, we'll go to the Distributions menu\n"
"to select those portions of 2.1 you wish to install on top of your 2.0.5\n"
"system.");
if (!dmenuOpenSimple(&MenuDistributions))
return RET_FAIL;
}
/* No bin selected? Not much of an upgrade.. */
if (!(Dists & DIST_BIN)) {
dialog_clear();
if (msgYesNo("You didn't select the bin distribution as one of the distributons to load.\n"
"This one is pretty vital to a successful 2.1 upgrade. Are you SURE you don't\n"
"want to select the bin distribution? Chose _No_ to bring up the Distributions\n"
"menu.")) {
(void)dmenuOpenSimple(&MenuDistributions);
}
}
/* Still?! OK! They must know what they're doing.. */
if (!(Dists & DIST_BIN))
extractingBin = FALSE;
if (!mediaDevice) {
dialog_clear();
msgConfirm("Now you must specify an installation medium for the upgrade.");
if (!dmenuOpenSimple(&MenuMedia) || !mediaDevice)
return RET_FAIL;
}
dialog_clear();
msgConfirm("OK. First, we're going to go to the disk label editor. In this editor\n"
"you will be expected to *Mount* any partitions you're interested in\n"
"upgrading. Don't set the Newfs flag to Y on anything in the label editor\n"
"unless you're absolutely sure you know what you're doing! In this\n"
"instance, you'll be using the label editor as little more than a fancy\n"
"screen-oriented filesystem mounting utility, so think of it that way.\n\n"
"Once you're done in the label editor, press Q to return here for the next\n"
"step.");
if (diskLabelEditor(NULL) == RET_FAIL) {
dialog_clear();
msgConfirm("The disk label editor failed to work properly! Upgrade operation\n"
"aborted.");
return RET_FAIL;
}
/* Don't write out MBR info */
variable_set2(DISK_PARTITIONED, "written");
if (diskLabelCommit("upgrade") == RET_FAIL) {
dialog_clear();
msgConfirm("Not all file systems were properly mounted. Upgrade operation\n"
"aborted.");
variable_unset(DISK_PARTITIONED);
return RET_FAIL;
}
if (!copySelf()) {
dialog_clear();
msgConfirm("Couldn't clone the boot floppy onto the root file system.\n"
"Aborting.");
return RET_FAIL;
}
if (chroot("/mnt") == RET_FAIL) {
dialog_clear();
msgConfirm("Unable to chroot to /mnt - something is wrong with the\n"
"root partition or the way it's mounted if this doesn't work.");
variable_unset(DISK_PARTITIONED);
return RET_FAIL;
}
chdir("/");
systemCreateHoloshell();
if (!rootExtract()) {
dialog_clear();
msgConfirm("Failed to load the ROOT distribution. Please correct\n"
"this problem and try again (the system will now reboot).");
reboot(0);
}
if (extractingBin) {
while (!saved_etc) {
saved_etc = msgGetInput("/usr/tmp/etc", "Under which directory do you wish to save your current /etc?");
if (!saved_etc || !*saved_etc || Mkdir(saved_etc, NULL)) {
dialog_clear();
if (msgYesNo("Directory was not specified, was invalid or user selected Cancel.\n\n"
"Doing an upgrade without first backing up your /etc directory is a very\n"
"bad idea! Do you want to go back and specify the save directory again?"))
break;
}
}
if (saved_etc) {
msgNotify("Preserving /etc directory..");
/* cp returns a bogus status, so we can't check the status meaningfully. Bleah. */
(void)vsystem("cp -pr /etc/* %s", saved_etc);
}
if (file_readable("/kernel")) {
msgNotify("Moving old kernel to /kernel.205");
if (system("chflags noschg /kernel && mv /kernel /kernel.205")) {
dialog_clear();
if (!msgYesNo("Hmmm! I couldn't move the old kernel over! Do you want to\n"
"treat this as a big problem and abort the upgrade? Due to the\n"
"way that this upgrade process works, you will have to reboot\n"
"and start over from the beginning. Select Yes to reboot now")) {
reboot(0);
}
}
}
}
msgNotify("Beginning extraction of distributions..");
if (distExtractAll("upgrade") == RET_FAIL) {
if (extractingBin && (Dists & DIST_BIN)) {
dialog_clear();
msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n"
"should be considered a failure and started from the beginning, sorry!\n"
"The system will reboot now.");
reboot(0);
}
dialog_clear();
msgConfirm("The extraction process seems to have had some problems, but we got most\n"
"of the essentials. We'll treat this as a warning since it may have been\n"
"only non-essential distributions which failed to load.");
}
if (extractingBin) {
msgNotify("OK, now it's time to go pound on your root a little bit to create all the\n"
"/dev entries and such that a 2.1 system expects to see. I'll also perform a\n"
"few \"fixup\" operations to repair the effects of splatting a bin distribution\n"
"on top of an existing system..");
if (installFixup("upgrade") == RET_FAIL) {
dialog_clear();
msgConfirm("Hmmmmm. The fixups don't seem to have been very happy.\n"
"You may wish to examine the system a little more closely when\n"
"it comes time to merge your /etc customizations back.");
}
}
dialog_clear();
msgConfirm("First stage of upgrade completed successfully!\n\n"
"Next comes stage 2, where we attempt to resurrect your /etc\n"
"directory!");
if (chdir(saved_etc)) {
dialog_clear();
msgConfirm("Unable to go to your saved /etc directory in %s?! Argh!\n"
"Something went seriously wrong! It's quite possible that\n"
"your former /etc is toast. I hope you didn't have any\n"
"important customizations you wanted to keep in there.. :(");
}
else {
/* Now try to resurrect the /etc files */
traverseHitlist(etc_files);
}
dialog_clear();
msgConfirm("OK! At this stage, we've resurrected all the /etc files we could\n"
"(and you may have been warned about some that you'll have to merge\n"
"yourself by hand) and we're going to drop you into a shell to do\n"
"the rest yourself (sorry about this!). Once the system looks good\n"
"to you, exit the shell to reboot the system.");
chdir("/");
dialog_clear();
dialog_update();
end_dialog();
DialogActive = FALSE;
signal(SIGTTOU, SIG_IGN);
if (tcgetattr(0, &foo) != -1) {
foo.c_cc[VERASE] = '\010';
if (tcsetattr(0, TCSANOW, &foo) == -1)
msgDebug("Unable to set the erase character.\n");
}
else
msgDebug("Unable to get the terminal attributes!\n");
printf("Well, good luck! When you're done, please type \"reboot\" or exit\n"
"the shell to reboot the new system.\n");
execlp("sh", "-sh", 0);
msgDebug("Was unable to execute sh for post-upgrade shell!\n");
reboot(0);
/* NOTREACHED */
return 0;
}
+217
View File
@@ -0,0 +1,217 @@
/* $XConsortium: lndir.c,v 1.14 95/01/09 20:08:20 kaleb Exp $ */
/* $XFree86: xc/config/util/lndir.c,v 3.3 1995/01/28 15:41:09 dawes Exp $ */
/* Create shadow link tree (after X11R4 script of the same name)
Mark Reinhold ([email protected])/3 January 1990 */
/* Hacked somewhat by Jordan Hubbard, The FreeBSD Project, to make it */
/* an invokable function from sysinstall rather than a stand-alone binary */
/*
Copyright (c) 1990, X Consortium
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the X Consortium.
*/
/* From the original /bin/sh script:
Used to create a copy of the a directory tree that has links for all
non-directories (except those named RCS, SCCS or CVS.adm). If you are
building the distribution on more than one machine, you should use
this technique.
If your master sources are located in /usr/local/src/X and you would like
your link tree to be in /usr/local/src/new-X, do the following:
% mkdir /usr/local/src/new-X
% cd /usr/local/src/new-X
% lndir ../X
*/
#include <stdio.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <errno.h>
#include <dirent.h>
#include <stdarg.h>
#include "sysinstall.h"
#ifndef MAXPATHLEN
#define MAXPATHLEN 2048
#endif
static char *rcurdir;
static char *curdir;
static int
equivalent(char *lname, char *rname)
{
char *s;
if (!strcmp(lname, rname))
return 1;
for (s = lname; *s && (s = strchr(s, '/')); s++) {
while (s[1] == '/')
strcpy(s+1, s+2);
}
return !strcmp(lname, rname);
}
/* Recursively create symbolic links from the current directory to the "from"
directory. Assumes that files described by fs and ts are directories. */
static int
dodir(char *fn, struct stat *fs, struct stat *ts, int rel)
{
DIR *df;
struct dirent *dp;
char buf[MAXPATHLEN + 1], *p;
char symbuf[MAXPATHLEN + 1];
struct stat sb, sc;
int n_dirs;
int symlen;
char *ocurdir;
if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino))
return 1;
if (rel)
strcpy (buf, "../");
else
buf[0] = '\0';
strcat (buf, fn);
if (!(df = opendir (buf))) {
msgDebug("%s: Cannot opendir\n", buf);
return 1;
}
p = buf + strlen (buf);
*p++ = '/';
n_dirs = fs->st_nlink;
while ((dp = readdir (df)) != NULL) {
if (dp->d_name[strlen(dp->d_name) - 1] == '~')
continue;
strcpy (p, dp->d_name);
if (n_dirs > 0) {
if (stat (buf, &sb) < 0) {
msgDebug("Can't stat: %s\n", buf);
continue;
}
if (S_ISDIR(sb.st_mode)) {
/* directory */
n_dirs--;
if (dp->d_name[0] == '.' &&
(dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
continue;
if (!strcmp (dp->d_name, "RCS"))
continue;
if (!strcmp (dp->d_name, "SCCS"))
continue;
if (!strcmp (dp->d_name, "CVS"))
continue;
if (!strcmp (dp->d_name, "CVS.adm"))
continue;
ocurdir = rcurdir;
rcurdir = buf;
curdir = isDebug() ? buf : (char *)0;
if (isDebug())
msgDebug("%s:\n", buf);
if ((stat(dp->d_name, &sc) < 0) && (errno == ENOENT)) {
if (mkdir(dp->d_name, 0777) < 0 ||
stat (dp->d_name, &sc) < 0) {
msgDebug("Unable to make or stat: %s\n", dp->d_name);
curdir = rcurdir = ocurdir;
continue;
}
}
if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
msgDebug("%s: is a link instead of a directory\n", dp->d_name);
curdir = rcurdir = ocurdir;
continue;
}
if (chdir (dp->d_name) < 0) {
msgDebug("Unable to chdir to: %s\n", dp->d_name);
curdir = rcurdir = ocurdir;
continue;
}
(void)dodir(buf, &sb, &sc, (buf[0] != '/'));
if (chdir ("..") < 0) {
msgDebug("Unable to get back to ..\n");
return RET_FAIL;
}
curdir = rcurdir = ocurdir;
continue;
}
}
/* non-directory */
symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1);
if (symlen >= 0) {
symbuf[symlen] = '\0';
if (!equivalent (symbuf, buf))
msgDebug("%s: %s\n", dp->d_name, symbuf);
} else if (symlink (buf, dp->d_name) < 0)
msgDebug("Unable to create symlink: %s\n", dp->d_name);
}
closedir (df);
return 0;
}
int
lndir(char *from, char *to)
{
struct stat fs, ts;
if (!to)
to = ".";
/* to directory */
if (stat(to, &ts) < 0) {
msgDebug("Destination directory doesn't exist: %s\n", to);
return RET_FAIL;
}
if (!(S_ISDIR(ts.st_mode))) {
msgDebug ("%s: Not a directory\n", to);
return RET_FAIL;
}
if (chdir(to) < 0) {
msgDebug("Unable to chdir to %s\n", to);
return RET_FAIL;
}
/* from directory */
if (stat(from, &fs) < 0) {
msgDebug("From directory doesn't exist: %s\n", from);
return RET_FAIL;
}
if (!(S_ISDIR(fs.st_mode))) {
msgDebug ("%s: Not a directory\n", from);
return RET_FAIL;
}
return dodir(from, &fs, &ts, 0);
}
+289
View File
@@ -0,0 +1,289 @@
/*
* The new sysinstall program.
*
* This is probably the last attempt in the `sysinstall' line, the next
* generation being slated for what's essentially a complete rewrite.
*
* $Id: options.c,v 1.26 1995/11/03 12:02:44 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 Jordan Hubbard
* for the FreeBSD Project.
* 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``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 HIS PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "sysinstall.h"
#include <ctype.h>
static char *
varCheck(Option opt)
{
char *cp = NULL;
if (opt.aux)
cp = variable_get((char *)opt.aux);
if (!cp)
return "<not set>";
return cp;
}
/* Show our little logo */
static char *
resetLogo(char *str)
{
return "[WHAP!]";
}
static char *
mediaCheck(Option opt)
{
if (mediaDevice) {
switch(mediaDevice->type) {
case DEVICE_TYPE_UFS:
case DEVICE_TYPE_DISK:
return "File system";
case DEVICE_TYPE_FLOPPY:
return "Floppy";
case DEVICE_TYPE_FTP:
return "FTP";
case DEVICE_TYPE_CDROM:
return "CDROM";
case DEVICE_TYPE_TAPE:
return "Tape";
case DEVICE_TYPE_DOS:
return "DOS";
case DEVICE_TYPE_NFS:
return "NFS";
case DEVICE_TYPE_NONE:
case DEVICE_TYPE_NETWORK:
case DEVICE_TYPE_ANY:
default:
return "<unknown>";
}
}
return "<unset>";
}
#define TAPE_PROMPT "Please enter the tape block size in 512 byte blocks:"
#define RELNAME_PROMPT "Please specify the release you wish to load:"
#define BPKG_PROMPT "Please specify the name of the HTML browser package:"
#define BBIN_PROMPT "Please specify a full pathname to the HTML browser binary:"
#define RETRY_PROMPT "Please specify the number of times to retry an FTP request:"
#define PKG_PROMPT "Please specify a temporary directory with lots of free space:"
static Option Options[] = {
{ "NFS Secure", "NFS server talks only on a secure port",
OPT_IS_VAR, NULL, VAR_NFS_SECURE, varCheck },
{ "NFS Slow", "User is using a slow PC or ethernet card",
OPT_IS_VAR, NULL, VAR_SLOW_ETHER, varCheck },
{ "Debugging", "Emit extra debugging output on VTY2 (ALT-F2)",
OPT_IS_VAR, NULL, VAR_DEBUG, varCheck },
{ "Yes to All", "Assume \"Yes\" answers to all non-critical dialogs",
OPT_IS_VAR, NULL, VAR_NO_CONFIRM, varCheck },
{ "FTP OnError", "What to do when FTP requests fail: abort, retry, reselect.",
OPT_IS_FUNC, mediaSetFtpOnError, VAR_FTP_ONERROR, varCheck },
{ "FTP Retries", "If FTP OnError == retry, this is the number of times to try.",
OPT_IS_VAR, RETRY_PROMPT, VAR_FTP_RETRIES, varCheck },
{ "FTP username", "Username and password to use instead of anonymous",
OPT_IS_FUNC, mediaSetFtpUserPass, VAR_FTP_USER, varCheck },
{ "Tape Blocksize", "Tape media block size in 512 byte blocks",
OPT_IS_VAR, TAPE_PROMPT, VAR_TAPE_BLOCKSIZE, varCheck },
{ "Extract Detail", "How verbosely to display file name information during extractions",
OPT_IS_FUNC, mediaSetCPIOVerbosity, VAR_CPIO_VERBOSITY, varCheck },
{ "Release Name", "Which release to attempt to load from installation media",
OPT_IS_VAR, RELNAME_PROMPT, VAR_RELNAME, varCheck },
{ "Browser Pkg", "This is the browser package that will be used for viewing HTML docs",
OPT_IS_VAR, BPKG_PROMPT, VAR_BROWSER_PACKAGE, varCheck },
{ "Browser Exec", "This is the path to the main binary of the browser package",
OPT_IS_VAR, BBIN_PROMPT, VAR_BROWSER_BINARY, varCheck },
{ "Media Type", "The current installation media type.",
OPT_IS_FUNC, mediaGetType, VAR_MEDIA_TYPE, mediaCheck },
{ "Package Temp", "The directory where package temporary files should go",
OPT_IS_VAR, PKG_PROMPT, "PKG_TMPDIR", varCheck },
{ "Use Defaults", "Reset all values to startup defaults",
OPT_IS_FUNC, installVarDefaults, 0, resetLogo },
{ NULL },
};
#define OPT_START_ROW 4
#define OPT_END_ROW 20
#define OPT_NAME_COL 0
#define OPT_VALUE_COL 16
#define GROUP_OFFSET 40
static char *
value_of(Option opt)
{
static char ival[40];
switch (opt.type) {
case OPT_IS_STRING:
return (char *)opt.data;
case OPT_IS_INT:
sprintf(ival, "%d", (int)opt.data);
return ival;
case OPT_IS_FUNC:
case OPT_IS_VAR:
if (opt.check)
return opt.check(opt);
else
return "<*>";
}
return "<unknown>";
}
static void
fire(Option opt)
{
if (opt.type == OPT_IS_FUNC) {
int (*cp)(char *) = opt.data;
cp(NULL);
}
else if (opt.type == OPT_IS_VAR) {
if (opt.data) {
(void)variable_get_value(opt.aux, opt.data);
dialog_clear();
}
else if (variable_get(opt.aux))
variable_unset(opt.aux);
else
variable_set2(opt.aux, "YES");
}
if (opt.check)
opt.check(opt);
clear();
refresh();
}
int
optionsEditor(char *str)
{
int i, optcol, optrow, key;
static int currOpt = 0;
dialog_clear();
clear();
while (1) {
/* Whap up the header */
attrset(A_REVERSE); mvaddstr(0, 0, "Options Editor"); attrset(A_NORMAL);
for (i = 0; i < 2; i++) {
mvaddstr(OPT_START_ROW - 2, OPT_NAME_COL + (i * GROUP_OFFSET), "Name");
mvaddstr(OPT_START_ROW - 1, OPT_NAME_COL + (i * GROUP_OFFSET), "----");
mvaddstr(OPT_START_ROW - 2, OPT_VALUE_COL + (i * GROUP_OFFSET), "Value");
mvaddstr(OPT_START_ROW - 1, OPT_VALUE_COL + (i * GROUP_OFFSET), "-----");
}
/* And the footer */
mvprintw(OPT_END_ROW + 0, 0, "Use SPACE to select/toggle an option, arrow keys to move,");
mvprintw(OPT_END_ROW + 1, 0, "? or F1 for more help. When you're done, type Q to Quit.");
optrow = OPT_START_ROW;
optcol = OPT_NAME_COL;
for (i = 0; Options[i].name; i++) {
/* Names are painted somewhat gratuitously each time, but it's easier this way */
mvprintw(optrow, OPT_NAME_COL + optcol, Options[i].name);
if (currOpt == i) standout();
mvprintw(optrow++, OPT_VALUE_COL + optcol, value_of(Options[i]));
if (currOpt == i) standend();
if (optrow == OPT_END_ROW) {
optrow = OPT_START_ROW;
optcol += GROUP_OFFSET;
}
clrtoeol();
}
standout();
mvaddstr(OPT_END_ROW + 3, 0, Options[currOpt].desc);
standend();
clrtoeol();
move(0, 14);
/* Start the edit loop */
key = toupper(getch());
switch (key) {
case KEY_F(1):
case '?':
systemDisplayHelp("options");
break;
case KEY_UP:
if (currOpt)
--currOpt;
else
beep();
continue;
case KEY_DOWN:
if (Options[currOpt + 1].name)
++currOpt;
else
beep();
continue;
case KEY_HOME:
currOpt = 0;
continue;
case KEY_END:
while (Options[currOpt + 1].name)
++currOpt;
continue;
case ' ':
dialog_clear();
fire(Options[currOpt]);
dialog_clear();
clear();
continue;
case 'Q':
clear();
dialog_clear();
return RET_SUCCESS;
default:
beep();
}
}
/* NOTREACHED */
return RET_SUCCESS;
}
+280
View File
@@ -0,0 +1,280 @@
/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $Id: package.c,v 1.26 1995/11/12 11:02:43 jkh Exp $
*
* Copyright (c) 1995
* Jordan Hubbard. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 Jordan Hubbard
* for the FreeBSD Project.
* 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``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 HIS PETS 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include "sysinstall.h"
static char *make_playpen(char *pen, size_t sz);
/* Like package_extract, but assumes current media device */
int
package_add(char *name)
{
if (!mediaVerify())
return RET_FAIL;
return package_extract(mediaDevice, name);
}
/* Extract a package based on a namespec and a media device */
int
package_extract(Device *dev, char *name)
{
char path[511];
char pen[FILENAME_MAX];
char *where;
int fd, ret;
/* If necessary, initialize the ldconfig hints */
if (!file_readable("/var/run/ld.so.hints"))
vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib");
/* Check to make sure it's not already there */
if (!vsystem("pkg_info -e %s", name)) {
msgDebug("package %s marked as already installed - return SUCCESS.\n", name);
return RET_SUCCESS;
}
if (!dev->init(dev)) {
dialog_clear();
msgConfirm("Unable to initialize media type for package extract.");
return RET_FAIL;
}
ret = RET_FAIL;
/* Make a couple of paranoid locations for temp files to live if user specified none */
if (!variable_get("PKG_TMPDIR")) {
Mkdir("/usr/tmp", NULL);
Mkdir("/var/tmp", NULL);
}
sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz");
msgNotify("Adding %s\nfrom %s", path, dev->name);
fd = dev->get(dev, path, TRUE);
if (fd >= 0) {
pen[0] = '\0';
if ((where = make_playpen(pen, 0)) != NULL) {
if (mediaExtractDist(pen, fd)) {
if (file_readable("+CONTENTS")) {
/* Set some hints for pkg_add so that it knows how we got here in case of any depends */
switch (mediaDevice->type) {
case DEVICE_TYPE_FTP:
if (variable_get(VAR_FTP_PATH)) {
char ftppath[512];
/* Special case to leave hint for pkg_add that this is an FTP install */
sprintf(ftppath, "%spackages/All/", variable_get(VAR_FTP_PATH));
variable_set2("PKG_ADD_BASE", ftppath);
}
break;
case DEVICE_TYPE_DOS:
variable_set2("PKG_PATH", "/dos/freebsd/packages/All:/dos/packages/All");
break;
case DEVICE_TYPE_CDROM:
variable_set2("PKG_PATH", "/cdrom/packages/All:/cdrom/usr/ports/packages/All");
break;
default:
variable_set2("PKG_PATH", "/dist/packages/All:/dist/freebsd/packages/All");
break;
}
if (vsystem("(pwd; cat +CONTENTS) | pkg_add %s-S",
!strcmp(variable_get(VAR_CPIO_VERBOSITY), "high") ? "-v " : "")) {
dialog_clear();
if (!variable_get(VAR_NO_CONFIRM))
msgConfirm("An error occurred while trying to pkg_add %s.\n"
"Please check debugging screen for possible further details.", name);
else
msgNotify("An error occurred while trying to pkg_add %s.", name);
}
else {
msgNotify("Package %s added successfully!", name);
ret = RET_SUCCESS;
}
}
else {
dialog_clear();
if (!variable_get(VAR_NO_CONFIRM))
msgConfirm("The package specified (%s) has no CONTENTS file. This means\n"
"that there was either a media error of some sort or the package\n"
"file itself is corrupted. It is also possible that you simply\n"
"ran out of temporary space and need to go to the options editor\n"
"to select a package temp directory with more space. Either way,\n"
"you may wish to look into the problem and try again.", name);
else
msgNotify("The package specified (%s) has no CONTENTS file. Skipping.", name);
}
}
else {
ret = RET_FAIL;
if (!variable_get(VAR_NO_CONFIRM))
msgConfirm("Unable to extract the contents of package %s. This means\n"
"that there was either a media error of some sort or the package\n"
"file itself is corrupted.\n"
"You may wish to look into this and try again.", name);
else
msgNotify("Unable to extract the contents of package %s. Skipping.", name);
}
if (chdir(where) == -1)
msgFatal("Unable to get back to where I was before, Jojo! (That was: %s)", where);
vsystem("rm -rf %s", pen);
if (isDebug())
msgDebug("Nuked pen: %s\n", pen);
}
else {
dialog_clear();
msgConfirm("Unable to find a temporary location to unpack this stuff in.\n"
"You must simply not have enough space or you've configured your\n"
"system oddly. Sorry!");
ret = RET_FAIL;
}
dev->close(dev, fd);
if (dev->type == DEVICE_TYPE_TAPE)
unlink(path);
}
else {
msgDebug("pkg_extract: get operation returned %d\n", fd);
if (variable_get(VAR_NO_CONFIRM))
msgNotify("Unable to fetch package %s from selected media.\n"
"No package add will be done.", name);
else {
dialog_clear();
msgConfirm("Unable to fetch package %s from selected media.\n"
"No package add will be done.", name);
}
}
return ret;
}
static size_t
min_free(char *tmpdir)
{
struct statfs buf;
if (statfs(tmpdir, &buf) != 0) {
msgDebug("Error in statfs, errno = %d\n", errno);
return -1;
}
return buf.f_bavail * buf.f_bsize;
}
/* Find a good place to play. */
static char *
find_play_pen(char *pen, size_t sz)
{
struct stat sb;
if (pen[0] && stat(pen, &sb) != RET_FAIL && (min_free(pen) >= sz))
return pen;
else if (stat("/var/tmp", &sb) != RET_FAIL && min_free("/var/tmp") >= sz)
strcpy(pen, "/var/tmp/instmp.XXXXXX");
else if (stat("/tmp", &sb) != RET_FAIL && min_free("/tmp") >= sz)
strcpy(pen, "/tmp/instmp.XXXXXX");
else if ((stat("/usr/tmp", &sb) == RET_SUCCESS || mkdir("/usr/tmp", 01777) == RET_SUCCESS) &&
min_free("/usr/tmp") >= sz)
strcpy(pen, "/usr/tmp/instmp.XXXXXX");
else {
dialog_clear();
msgConfirm("Can't find enough temporary space to extract the files, please try\n"
"This again after your system is up (you can run /stand/sysinstall\n"
"directly) and you've had a chance to point /var/tmp somewhere with\n"
"sufficient temporary space available.");
return NULL;
}
return pen;
}
/*
* Make a temporary directory to play in and chdir() to it, returning
* pathname of previous working directory.
*/
static char *
make_playpen(char *pen, size_t sz)
{
static char Previous[FILENAME_MAX];
if (!find_play_pen(pen, sz))
return NULL;
if (!mktemp(pen)) {
dialog_clear();
msgConfirm("Can't mktemp '%s'.", pen);
return NULL;
}
if (mkdir(pen, 0755) == RET_FAIL) {
dialog_clear();
msgConfirm("Can't mkdir '%s'.", pen);
return NULL;
}
if (isDebug()) {
if (sz)
msgDebug("Requested space: %d bytes, free space: %d bytes in %s\n", (int)sz, min_free(pen), pen);
}
if (min_free(pen) < sz) {
rmdir(pen);
dialog_clear();
msgConfirm("Not enough free space to create: `%s'\n"
"Please try this again after your system is up (you can run\n"
"/stand/sysinstall directly) and you've had a chance to point\n"
"/var/tmp somewhere with sufficient temporary space available.");
return NULL;
}
if (!getcwd(Previous, FILENAME_MAX)) {
dialog_clear();
msgConfirm("getcwd");
return NULL;
}
if (chdir(pen) == RET_FAIL) {
dialog_clear();
msgConfirm("Can't chdir to '%s'.", pen);
}
return Previous;
}
+121
View File
@@ -0,0 +1,121 @@
begin 664 power.gif
M1TE&.#EAJP!``/<```````0#$@L`(0P,#Q,("!0:*A<0'ALE-!X:)2,`4"0D
M,"4`4B4@*28:*2<`52@P02H`62HB-"L#4RL&3BLG.2P`6RT`7C`P$S`P,#$I
M/3((5#(/0#(V13,O0#0>&C4D,S8I/S@H-SA&7#DP0#DP2#HS2CHV1#P22#PK
M"CP]3STP(SXU2#X^)C\X2D`624,V24,Y340]5D0^1$0^3D4<2$5%6D8S.D<0
M.D@714A(3TH_5TI(84ICA$LK.DPB/TPH/TU$74U-8DU38$]:;U`=0%$_35%)
M7%%ND%(W1U,C/54G0%<O1%<S,U=*5%=-8%=265A\H5HK/5I")5]?7V&'IV<Q
M/6A=3FAI9VLU06P]3'%%5'%.5G-R6G0H,G4:)G<Y17A(+7F<J7I6#GQ\77TP
M.X&!@H=&0(@[1HE=38F%>8I00HI@$(UG18Z.B)!M1)2)$Y<\1I=E"IA\"YE8
M,YF8C)IP`YM,`)M=`)N;`*!I'J.CHZ0B+:HP.*MC4JMV%*VLJZY_&*Z8,J]&
M3K")%;"C3["VN;(Z0K*QL;R\O+Z^OK^$`,"Z?L7#0,:%%LJ+%\O*MLPI,<P[
M0LR$&LUM2-`S.M"-#]"?$=9,3]=$1]>6#]GB=]NF"^+7(^;(%>JU">K)`.L]
M0>M%1.VF`O&F!?'I@/1-2_=$0_=44??Q#O?\ZOCE#_R_`/SX!OW[`_W]!O[^
M`_]:5_]K9?^P`/^Q`/^R`/^S`/^T`/^U`/^V`/^W`/^X`/^Y`/^Z`/^[`/^\
M`/^]`/^_`/_``/_!`/_"`/_#`/_$`/_%`/_&`/_(`/_)`/_*`/_+`/_,`/_-
M`/_.`/_/`/_0`/_1`/_2`/_3`/_4`/_5`/_6`/_7`/_8`/_9`/_:`/_;`/_<
M`/_=`/_>`/_?`/_@`/_A`/_B`/_C`/_D`/_E`/_F`/_G`/_H`/_I`/_J`/_K
M`/_L`/_M`/_N`/_O`/_P`/_Q`/_R`/_S`/_S(__U`/_V`/_Y`/_]`/_^\/__
M`/__9````````````````"'Y!`$``(D`+`````"K`$``0`C_`!,)'$BPH,&#
M"!,J7,BPH<.'$"-*G$BQHL6+"9]`@O/@@`P,'FY4P6(#00`"5PQ.,51$P"&,
M,&/*G-E03Y1%;5+=&),J%:E\8;Q0@L,D"9,0$2)T`,$`0!E$-`\"P%!0#P`&
MC-8`D")+#`$`BKR"K84"0!Q%*%"(`H!"EJQ*;!7%02$F#@`Q:._6<BL+@-DZ
M!`BLXB7&KZ)5=%>)07&L#HI-R90M:^8,&C1ITJA9NX8-F[9MW+I]`Q=.W#AR
MJGHP&K=N73LWETZ9R3*E2`Q!I4+I#@6*3X\/(YJTH-!$G_'CR),K7WX<#\5]
M?*.[G9/`1W1)2J1KW\YW%BU;MV[E_](E"4*"7[^$%3.3(($Q3PE.0&/&K%DS
M&I:D3:/^0ULVT*IT$T@%"?Q0#CGFJ$((&&!,L@4GJJB"QA9PP"*(`'B@@@<+
MEV#"&RBFF")($"44P=R)*"[GW$30<4>===L1&%T>YHTBW2P:.`#&+KSPX@MZ
MOSABWC#$%'/,,2Y`,(<G-$CS##319&;!`ME@XT:!WG@SFFGD+)'`(/&HLPX[
M[;SS3CSRS#.//?;<XR8^^M"3P0Q-3`$$B1F`T$$&&235Q"LI'N=*`QY$L046
M333QA`%6J/@<=Y!&VATMM8`W'H^]_/A+,,(,4TPQQAR#C&3U.?.D?M-48PTV
MV7P6VFBEG?]6SCGHI*,..^RX\PX\:,Y33YMNWH,/G*ZP`<LIAFPA0@D<'*"`
M#SK$(&T),:Q@;0<RP+"%*ZVP`FARKWP;J#XK1F7NN1%1P<,14*@+1`Q`[+##
M$#&T(=`A+#R2S[YM-*'%%DXX$8,.4$!1!+H()ZRP0G3\EL%+#"%`@!X+5VSQ
MN7_LT847/.GA11>/%,(''R%4\<476601"2B@4-)#`1QD,$+"4PE4!@!3))*#
M7P`,0,<3`-`QA5]T7.&4'@/PG#,`!@R``2([^S7`(4A+C3-!/?/\1"(#,)#(
M(0"8</$A9)BRQP$?=(%``07TE,@(D$#R114?-#"""0%`?'%"+4K_ZO??DU:*
MRZ6*K*&(,,!PZJF1HBJC##/.5`;E--14PUFKH'7C#6GCG&8.)V"@@0<>:'!R
M9CQJHJ(``R.$\$$(/_2`Q`PK4("``8R,J[NC+$)*G00N!%_!`FZ-8D$"-$BB
M1A2RN"`!7VHL0,0LC20P1RVU&+\`(+T(F8`22]"@P?AS,+.,&>8EX$![)VQR
MC35S3/!#YEJ2)LX2#OQ`JYBYNL-KFJA8@H56D((21.``@CA%*5I&AA',(`A.
MJ($.BK.["I+K48`#W"@D(0GO",X6N<B$(S;Q(V!LBDA'0L:HS&>?9WC"$I;H
M1#.B00W/;"-+X%#%:,:!#M>HPU9DTA4\_^21IGK\ZDW#,HXK'A"*4YB"#TN8
MP0YT`(,'/.`,E)!!#"+@@[email protected]$6X]/$*5'"""QXPPA!*P`5ZM")%Y=J;
M'!T"%:@0)!5_V%<JCO`"+&2A"5?H@R!>4((:U(`"B+!C09Z@!31H008"T\$.
M8E`"$A1"D7/,I"8/@DF!Z($*8:`"%:#``QZ(0`0[*$,A"K')5KJ2CFWHY"MG
M24N$_,$#A@A!!R!2!3A\@)6U#&;%]%`A,D1@#WLP!#(A@844C*`'(2B@4Q!!
M!P3L`0XIZ$`#9"G,;LH$$2'PPA]2\0@/+*(GJ2A#,LF0!!]$H0I12`("G)4!
M!1B`FS/I&08PX/\7BE6L#3A39,UHB0@F]$``!\C`!\H@@$?TY`A[@,0>D("%
M)9C@`0@8@`#\N3!]8L`$]AI:&_:Q#Q8`8!]WN8`4+B`&%K``I01PZ04`P`@`
MO'0?;@#`!5QJ4Y.2M*9N("E);4K2G#*"$``(A!1.*M2F.O6I4(WJ4S51!0N=
MP8EP>,$,%G$((?2`$I$0Q!>2$()L90`!FI"J6M<:1SH>@A&5X,MW;&&+N<Y"
M%K.812448:/MB$(1<2V>(C:QG;S^=1.ZT,4NUB*&5:PB&$0R1JB8\8QH-*,^
MSSA59JRQ*AN^RGZ>,X<XIH`&-[""'>]@A`Q&(`+<Y*84D3!$%I"P!"3_I$`'
M1C`!HRRXN[8^I&_7,0,.VN,"&@1/`PG(Q%TS*)VY;L(,2UA`?(J+W!-8`E3'
MB!\-EJ`!%VS/$EN@07LT8%SQ3<`%>?B$:,E!#DYP`AWMZ,038M$'*]`#'JK@
M@A4X<8]/B`$!'OC``U*PA"IDH08<(`1O+>A;AP!7.B_BRRC`X)9,Y`$'LJ#.
M!)8+!AJ<X`1YB(XCHN"""51A$[C8A?=^D;AAG&`!CEC&'!PP@4U@%DJ9H48>
M%M`?^HVF$^L#0SO.8:MUJ.,=\OC?/`@A"#-0(&9L&X$-EO"%,VC!"5JXLA-@
MP(D%ZZ[!#7EP="+LED9DQRTRXLL<)'#>X)W`_P'9F=()@N<""T#`$:OP7J>(
M00Q/Y.@'RU@&?9PAC4^H87V6P$8>\A>:^H7C-#D*!#SXUP[_]>I7]J"'"4H"
M@A2<P10*O$054A"$(00L8%9XHY?AB,'ML.<$?94.@0+KEB](%PR`P`X8:I&)
MXX'8$7EPP2B$T8CU`<(1C@"#!#3@B68,`@(G`$0GIO%L,)##/VJ(SR!@.`@W
M;``"@3B'.FY%IEVASE=L"E826<$$05#@`1)\@0DH4`5*D&'`(\B=[E[QA#Z<
MH@]9R``G7,$<,#-$S,R%E'>^(Q[%\B)3+`:&,/@<*E$E0]"4>5(T**>JRV7N
M&UL:1SG,88Y:W:H=9?\:8A'3C43CC`$,L*#$%P3A(3@X89(PV($,3`"#%\BL
M!3`H`0B,8`0=9(`$)1`X*A@!1G&AR.`+07C"M4,I2^4"4^A)7*>P:_''91S'
MJ5H5YCX;*P31*AUC*C>OYF%&0KB!$$TG%@9R$`(LU&`')4``*ESQK:4_`00Q
ML!T%C+`"=@6^4:LV#M2]*<<V.'244$#E#@(&A!H`H01'&,)3.HF((LB@"5+>
M0A""0,DA',$)C$\]3%9IRE+R@)1MH(,>>A(R4;8+"D-H%Q5$,`35^_[WP`^^
M\(>O>D3H(00"^`-#E$_\YD>$#EXX@P+HX)`_\,$#]G*^]FUY`THP0`!;2P3_
M'6Q@`!.406\%N0(?=""#[;M_((CP@BDX8H(,)*$+9%A"#U8P@A8(G0#,EPB(
M8``L$0%E\'[N]P>&X#)=H`9]$#=>L`>1\`)U5ULS$`*$(A208%$4T``(J'V)
MQ`15L`4]\05>X%#IM`=?@`558#)9``>0X`5)<``,T`$&D'T?V'SQAP;[@@9=
M0'NI$`9=``ED$`51\!L-@``4$`$*T`$!0'T)LT_[!%(70P<8<(`#@0'A-TO&
MYP4U4`!I@`1'8`/H1`5"L0=%85$*M3I3@4\T,5`WDS.)4`93<`5Z@`ATF`AZ
M,`4YLX?VH@=7,`74APA34`9T@(5T>'Z>=`57$(=8_X,!;5"(>C@%]H*'<F@Q
M0D`)57``(<`$!G``&X""&@$)9Y`%2V`#,+`"!4`5%^-1_40'82-^87,S99`#
M35&+`'`(&:4'A\!/8`,`5W"(`)`#<P@`3P`T*6$"5S,01',(!I"+.W,(M'@Q
M/6`*F'`&D8"&R#=[J<`#>T`)AG`&4=``(6`"(Y`W>S-0`V$T90`=*$``LG`!
M9;$8\]@7**`(^*@(:]$6N5`89X&/E5`6HC`+?G`7RV6/LZ`+A7$8!+!24C`8
MJ[!G7!<9@Z9Q.;89K/(9FO,-X?!HIZ$*1'8KYY`$L'`)9R`(EZ`%(I`%R"0(
M"Q@)9]`%P#$#/L<`J``GB?^G'%"GC@*!ASRC%K)0!W[Q5P!``-\Q"F7A%W5@
MCVY!"X#A%VHA"DFY5&(0'6SQ%0!0!XDE!T7I6&QA#&71#%JA"(\#.1HW#92S
M&=G0*MS`#2`7*Z?A#8S0!VS`">P0#ZB`!G!0`W!P"I%P";F!":`0"IA@"&00
M`B/@!$9``@B@;SFIDZTV=9+9E+0@'H/C"X4!`)NP"BU6)*&"#!2)6<^`*ATW
M=AM9=N-P5*CP"9:@!IQ@:>]`"`'``2[)!V3P`P<@94L@;R.0`0U@!03WF+PC
M$5+7",9YG,@9:Y(Y"Y5R"YG0",CF")6`;)L@D<:`#)XP"'DP!XWP"94%0^`9
MGI__(!H<^6CD4`[E$`Z,,`;T53IKAVZL\`$$T((]\`(=``,PD`+VI&#">2*+
MQS>0DFTGP!>98`8G<)!3QYQT=0NU4&SG(0R;,`<$X@/&D`S9E@>"Y@QNH`&#
M$`W/P`;(TPTBV@F6H`7F@02?\)%N$`AK@`=7$`N$P`B!H`8V8`.4``D#@`><
M\`D>$`)90"&&``FA@`9"0`%=UI_#&1%2EV$+`"/%DPF3Z4&U<`NXH`N\X`CK
MPV+!0`S400/'D`<%@G&F`@A1<@U7\@,VM`V@H0ULX``.,`BS4@[HH`KT`"%(
M-@_Q,`8RD`4R\``Y@`<<('^A8`J@<`DT9PA-(`0F0`](_PJ9O>,B3<H7@/`\
MDH`##K``8)``TB4+FZ`!6"`)<S`E(38+9J`!>8`=$G`"/(*EUC,'RN8"EI`,
MS.`(!*(!8)`'EN`)F%$Y;I`__R&B6M*1+I``2'`.XB8FE69N]:`*6``+I?`"
M#Y"?!P`''4(&&2`",9`",W!S^=:HR?&?"+&D7<I!DO`%$\`7P]-7F9`)#D`$
M?"$)ERH+2I``C0`>N#"O<Q`DZ^-8PN`)MI8`@*`,SP`(:H`$=F8>+E`-W'"F
M'\<YYT`#F%HKK9$KNY(FOH(*2"`#16`$)7``!6`(UKA`9Q`$\K(#1O`$(1"<
MWGI!C[H=9"8+HP"E:)8`<C6NY/\*I;0P/'G@")*`;*/0"\"`I0NP=9(578!V
M8Y;Q">9A"=G@!CS6:)Q##D`V`>P`1)4&#T.D)IAV#ZW@"IR0`SF00)>`J,L2
M`T&0GT"0`H%00>$2+GSGMD[7')$)89$:(S1+H`0R!]%A(UFP`!HP"@['"YX0
M#*SJF<=@"1`P`<U@"2[@":>"#8Y@/=>@#6#Z`Z)A/^B0J6K0#D;F&F82#Y<&
M+&_R"JW0`AT!`C,P`S$``TOHL28P`S:`"KO#"$0P"9'`!U9&`6Z@LL@!K@>!
M<)(0!1I@`2>P!"'VKDI@`1J@!!16/&9@`<NF`6:`/;(@"4DR/C3@"+[`)!9@
M`=1EO)?_M0R60`/$ZV$T$`C=L):!(`'=2P,T4`(:\`-ND*+H0&E"=&Y'I&[&
M\0I5<`J@\`4/P`$CT`$FP`$]P`>@8`,S\`&$($8IX@J$``1;L`4_P`BNP+O?
M.K>365C80Z67T@N]@![!P"F&JT*D0AF6(0V683D9V99:PI&R8@YG=W*[DK7H
M)KHXJ0]C\`6F,*BPY01#0'JJ^P`9RP$EH`,K0`(QT`+U%P$?$`%\T@`F,`0D
MT&5QFZ00L:0;C%=5-SB*!<)9!UF&>PR1@7$6F9:7HY&.)@[G*<,F%T1GLG(L
M)RQDQ`E5939&(`)`4`1PH`5#\"Y)QW,S0`$VT`1%4`9'%0AC_\`(C'S!KL`*
M&/QT&KS%E&FOE^(C(JPXV`6:9=D,F;5QU*`9G.$JW%`_7#)RZ%"_8^(.NA*Z
MZ88/=/P*.=`%I7`*6A`$'/``,P!&C*`#%$`!.4=Z"M``+1`#:Z0"G'#%O.6[
M!H$'=O#,T!S-TCS-U#S-=V`'UWP'VKS-W'P'<7`'=1`'X5P'Y%S.YEP'<H#.
M<K#.[-S.>"`'[QS/);`(^_((94``.1`(@?`&&=`'2%``?$(!!A`(HU/0HS,&
M#=`#L_4"V1K$04`!!&W0$CW1%,W,.1@1>I`/Z01*5.`$?3`)?1#263`#(D`%
M1Y`2""$#658$37!S,*#$.T`"Z'?1M7QT"*\72J3$`SL0+S<'!#I``@&8"'_`
M`$6``#TP956@!5<P24!P!!WMAC1-4(AP!*5T!%0]!#M@2B^1!HFP+QJ="&$0
M!J8F+SPP2C40U=I7"'J0>;U7"%33!D<@`JY7,`4S!$,`3&A]T6JM!V40!F6@
.!W^@!WB=UX2M20$!`#N0
`
end
+1
View File
@@ -0,0 +1 @@
#define RELEASE_NAME "__RELEASE"
-143
View File
@@ -1,143 +0,0 @@
#!/bin/sh
#
# Copyright (c) 1995 Peter Dufault
#
# All rights reserved.
#
# This program is free software.
#
# 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$
#
# scsiformat [-wq] [-p page-control] raw-device-name
#
PATH="/sbin:/usr/sbin:/bin:/usr/bin"; export PATH
READONLY=yes
QUIET=no
RAW=
PAGE=0
usage()
{
echo "Usage: scsiformat [-wq] [-p page-control] raw-device-name" 1>&2
exit 2
}
while getopts "qwp:" option
do
case $option in
q)
QUIET=yes
;;
w)
READONLY=no
;;
p)
case $OPTARG in
c)
PAGE=0
;;
d)
PAGE=2
;;
s)
PAGE=3
;;
v)
PAGE=1
echo "*** note: for variable parameters, 1-bit means 'can write here'"
;;
*)
usage
;;
esac
;;
?)
usage
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -ne 1 ] ; then
usage
fi
RAW=$1
if [ "x$RAW" = "x" ] ; then
usage
fi
if expr "$RAW" : 'sd[0-9][0-9]*$' > /dev/null ; then
# generic disk name given, convert to control device name
RAW="/dev/r${RAW}.ctl"
fi
scsi -f $RAW -v -c "12 0 0 0 v 0" 96 -i 96 "s8 z8 z16 z4" || exit $?
if [ "$QUIET" = "no" ] ; then
scsi -f $RAW \
-v -c "1A 0 v:2 4:6 0 64 0" $PAGE \
-i 72 "{Mode data length} i1 \
{Medium type} i1 \
{Device Specific Parameter} i1 \
{Block descriptor length} i1 \
{Density code} i1 \
{Number of blocks} i3 \
{Reserved} i1 \
{Block length} i3 \
{PS} b1 \
{Reserved} b1 \
{Page code} b6 \
{Page length} i1 \
{Number of Cylinders} i3 \
{Number of Heads} i1 \
{Starting Cylinder-Write Precompensation} i3 \
{Starting Cylinder-Reduced Write Current} i3 \
{Drive Step Rate} i2 \
{Landing Zone Cylinder} i3 \
{Reserved} b6 \
{RPL} b2 \
{Rotational Offset} i1 \
{Reserved} i1 \
{Medium Rotation Rate} i2 \
{Reserved} i1 \
{Reserved} i1 " || exit $?
fi # !quiet
if [ "$READONLY" = "no" ]
then
# grace period, last chance to hit INTR
echo -n "Three seconds until format begins."
sleep 1
echo -n "."
sleep 1
echo -n "."
sleep 1
# formatting may take a huge amount of time, set timeout to 2 hours
echo " Formatting... this may take a while."
scsi -s 7200 -f $RAW -c "4 0 0 0 0 0"
fi
-6
View File
@@ -1,6 +0,0 @@
# $Id$
PROG= find_interface
NOMAN=
.include <bsd.prog.mk>
-9
View File
@@ -1,9 +0,0 @@
This is a simple program which demonstrates how to query the kernel
routing mechanism using only a UDP socket. Pass it a hostname on
the command line (sorry, it doesn't parse dotted decimal) and it will
print out an IP address which names the interface over which UDP
packets intended for that destination would be sent.
A more sophisticated program might use the list obtained from SIOCGIFCONF
to match the address with an interface name, but applications programmers
much more often need to know the address of the interface rather than
the name.
-12
View File
@@ -1,12 +0,0 @@
#!/bin/sh -
#
# @(#)slip.login 8.1 (Berkeley) 6/6/93
#
# generic login file for a slip line. sliplogin invokes this with
# the parameters:
# 1 2 3 4 5 6 7-n
# slipunit ttyspeed loginname local-addr remote-addr mask opt-args
#
/sbin/ifconfig sl$1 inet $4 $5 netmask $6
exit
-643
View File
@@ -1,643 +0,0 @@
/*+M*************************************************************************
* Adaptec AIC7770/AIC7870 sequencer code assembler.
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
* 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 Calgary
* Department of Computer Science 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 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.
*
* Comments are started by `#' and continue to the end of the line; lines
* may be of the form:
* <label>*
* <label>* <undef-sym> = <value>
* <label>* <opcode> <operand>*
*
* A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
* are token separators.
*
*-M*************************************************************************/
static char id[] = "$Id: aic7xxx_asm.c,v 1.8 1995/04/15 21:45:56 gibbs Exp $";
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MEMORY 448
#define MAXLINE 1024
#define MAXTOKEN 32
#define ADOTOUT "a.out"
#define NOVALUE -1
/*
* AIC-7770/AIC-7870 register definitions
*/
#define R_SINDEX 0x65
#define R_ALLONES 0x69
#define R_ALLZEROS 0x6a
#define R_NONE 0x6a
int debug;
int lineno, LC;
char *filename;
FILE *ifp, *ofp;
unsigned char M[MEMORY][4];
void
error(char *s)
{
fprintf(stderr, "%s: %s at line %d\n", filename, s, lineno);
exit(EXIT_FAILURE);
}
void *
Malloc(size_t size)
{
void *p = malloc(size);
if (!p)
error("out of memory");
return(p);
}
void *
Realloc(void *ptr, size_t size)
{
void *p = realloc(ptr, size);
if (!p)
error("out of memory");
return(p);
}
char *
Strdup(char *s)
{
char *p = (char *)Malloc(strlen(s) + 1);
strcpy(p, s);
return(p);
}
typedef struct sym_t {
struct sym_t *next; /* MUST BE FIRST */
char *name;
int value;
int npatch;
int *patch;
} sym_t;
sym_t *head;
void
define(char *name, int value)
{
sym_t *p, *q;
for (p = head, q = (sym_t *)&head; p; p = p->next) {
if (!strcmp(p->name, name))
error("redefined symbol");
q = p;
}
p = q->next = (sym_t *)Malloc(sizeof(sym_t));
p->next = NULL;
p->name = Strdup(name);
p->value = value;
p->npatch = 0;
p->patch = NULL;
if (debug) {
fprintf(stderr, "\"%s\" ", p->name);
if (p->value != NOVALUE)
fprintf(stderr, "defined as 0x%x\n", p->value);
else
fprintf(stderr, "undefined\n");
}
}
sym_t *
lookup(char *name)
{
sym_t *p;
for (p = head; p; p = p->next)
if (!strcmp(p->name, name))
return(p);
return(NULL);
}
void
patch(sym_t *p, int location)
{
p->npatch += 1;
p->patch = (int *)Realloc(p->patch, p->npatch * sizeof(int *));
p->patch[p->npatch - 1] = location;
}
void backpatch(void)
{
int i;
sym_t *p;
for (p = head; p; p = p->next) {
if (p->value == NOVALUE) {
fprintf(stderr,
"%s: undefined symbol \"%s\"\n",
filename, p->name);
exit(EXIT_FAILURE);
}
if (p->npatch) {
if (debug)
fprintf(stderr,
"\"%s\" (0x%x) patched at",
p->name, p->value);
for (i = 0; i < p->npatch; i++) {
M[p->patch[i]][0] &= ~1;
M[p->patch[i]][0] |= ((p->value >> 8) & 1);
M[p->patch[i]][1] = p->value & 0xff;
if (debug)
fprintf(stderr, " 0x%x", p->patch[i]);
}
if (debug)
fputc('\n', stderr);
}
}
}
/*
* Output words in byte-reversed order (least significant first)
* since the sequencer RAM is loaded that way.
*/
void
output(FILE *fp)
{
int i;
for (i = 0; i < LC; i++)
fprintf(fp, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
M[i][3],
M[i][2],
M[i][1],
M[i][0]);
printf("%d out of %d instructions used.\n", LC, MEMORY);
}
char **
getl(int *n)
{
int i;
char *p, *quote;
static char buf[MAXLINE];
static char *a[MAXTOKEN];
i = 0;
while (fgets(buf, sizeof(buf), ifp)) {
lineno += 1;
if (buf[strlen(buf)-1] != '\n')
error("line too long");
p = strchr(buf, '#');
if (p)
*p = '\0';
p = buf;
rescan:
quote = strchr(p, '\"');
if (quote)
*quote = '\0';
for (p = strtok(p, ", \t\n"); p; p = strtok(NULL, ", \t\n"))
if (i < MAXTOKEN-1)
a[i++] = p;
else
error("too many tokens");
if (quote) {
quote++;
p = strchr(quote, '\"');
if (!p)
error("unterminated string constant");
else if (i < MAXTOKEN-1) {
a[i++] = quote;
*p = '\0';
p++;
}
else
error("too many tokens");
goto rescan;
}
if (i) {
*n = i;
return(a);
}
}
return(NULL);
}
#define A 0x8000 /* `A'ccumulator ok */
#define I 0x4000 /* use as immediate value */
#define SL 0x2000 /* shift left */
#define SR 0x1000 /* shift right */
#define RL 0x0800 /* rotate left */
#define RR 0x0400 /* rotate right */
#define LO 0x8000 /* lookup: ori-{jmp,jc,jnc,call} */
#define LA 0x4000 /* lookup: and-{jz,jnz} */
#define LX 0x2000 /* lookup: xor-{je,jne} */
#define NA -1 /* not applicable */
struct {
char *name;
int n; /* number of operands, including opcode */
unsigned int op; /* immediate or L?|pos_from_0 */
unsigned int dest; /* NA, pos_from_0, or I|immediate */
unsigned int src; /* NA, pos_from_0, or I|immediate */
unsigned int imm; /* pos_from_0, A|pos_from_0, or I|immediate */
unsigned int addr; /* NA or pos_from_0 */
int fmt; /* instruction format - 1, 2, or 3 */
} instr[] = {
/*
* N OP DEST SRC IMM ADDR FMT
*/
{ "mov", 3, 1, 1, 2, I|0xff, NA, 1 },
{ "mov", 4, LO|2, NA, 1, I|0, 3, 3 },
{ "mvi", 3, 0, 1, I|R_ALLZEROS, A|2, NA, 1 },
{ "mvi", 4, LO|2, NA, I|R_ALLZEROS, 1, 3, 3 },
{ "not", 2, 2, 1, 1, I|0xff, NA, 1 },
{ "and", 3, 1, 1, 1, A|2, NA, 1 },
{ "and", 4, 1, 1, 3, A|2, NA, 1 },
{ "or", 3, 0, 1, 1, A|2, NA, 1 },
{ "or", 4, 0, 1, 3, A|2, NA, 1 },
{ "or", 5, LO|3, NA, 1, 2, 4, 3 },
{ "xor", 3, 2, 1, 1, A|2, NA, 1 },
{ "xor", 4, 2, 1, 3, A|2, NA, 1 },
{ "nop", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
{ "inc", 2, 3, 1, 1, I|1, NA, 1 },
{ "inc", 3, 3, 1, 2, I|1, NA, 1 },
{ "dec", 2, 3, 1, 1, I|0xff, NA, 1 },
{ "dec", 3, 3, 1, 2, I|0xff, NA, 1 },
{ "jmp", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
{ "jc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
{ "jnc", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
{ "call", 2, LO|0, NA, I|R_SINDEX, I|0, 1, 3 },
{ "test", 5, LA|3, NA, 1, A|2, 4, 3 },
{ "cmp", 5, LX|3, NA, 1, A|2, 4, 3 },
{ "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
{ "ret", 1, 1, I|R_NONE, I|R_ALLZEROS, I|0xff, NA, 1 },
{ "clc", 1, 3, I|R_NONE, I|R_ALLZEROS, I|1, NA, 1 },
{ "clc", 4, 3, 2, I|R_ALLZEROS, A|3, NA, 1 },
{ "stc", 2, 3, 1, I|R_ALLONES, I|1, NA, 1 },
{ "add", 3, 3, 1, 1, A|2, NA, 1 },
{ "add", 4, 3, 1, 3, A|2, NA, 1 },
{ "adc", 3, 4, 1, 1, A|2, NA, 1 },
{ "adc", 4, 4, 1, 3, A|2, NA, 1 },
{ "shl", 3, 5, 1, 1, SL|2, NA, 2 },
{ "shl", 4, 5, 1, 2, SL|3, NA, 2 },
{ "shr", 3, 5, 1, 1, SR|2, NA, 2 },
{ "shr", 4, 5, 1, 2, SR|3, NA, 2 },
{ "rol", 3, 5, 1, 1, RL|2, NA, 2 },
{ "rol", 4, 5, 1, 2, RL|3, NA, 2 },
{ "ror", 3, 5, 1, 1, RR|2, NA, 2 },
{ "ror", 4, 5, 1, 2, RR|3, NA, 2 },
/*
* Extensions (note also that mvi allows A)
*/
{ "clr", 2, 1, 1, I|R_ALLZEROS, I|0xff, NA, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
int
eval_operand(char **a, int spec)
{
int i;
unsigned int want = spec & (LO|LA|LX);
static struct {
unsigned int what;
char *name;
int value;
} jmptab[] = {
{ LO, "jmp", 8 },
{ LO, "jc", 9 },
{ LO, "jnc", 10 },
{ LO, "call", 11 },
{ LA, "jz", 15 },
{ LA, "jnz", 13 },
{ LX, "je", 14 },
{ LX, "jne", 12 },
};
spec &= ~(LO|LA|LX);
for (i = 0; i < sizeof(jmptab)/sizeof(jmptab[0]); i++)
if (jmptab[i].what == want &&
!strcmp(jmptab[i].name, a[spec]))
{
return(jmptab[i].value);
}
if (want)
error("invalid jump");
return(spec); /* "case 0" - no flags set */
}
int
eval_sdi(char **a, int spec)
{
sym_t *p;
unsigned val;
if (spec == NA)
return(NA);
switch (spec & (A|I|SL|SR|RL|RR)) {
case SL:
case SR:
case RL:
case RR:
if (isdigit(*a[spec &~ (SL|SR|RL|RR)]))
val = strtol(a[spec &~ (SL|SR|RL|RR)], NULL, 0);
else {
p = lookup(a[spec &~ (SL|SR|RL|RR)]);
if (!p)
error("undefined symbol used");
val = p->value;
}
switch (spec & (SL|SR|RL|RR)) { /* blech */
case SL:
if (val > 7)
return(0xf0);
return(((val % 8) << 4) |
(val % 8));
case SR:
if (val > 7)
return(0xf0);
return(((val % 8) << 4) |
(1 << 3) |
((8 - (val % 8)) % 8));
case RL:
return(val % 8);
case RR:
return((8 - (val % 8)) % 8);
}
case I:
return(spec &~ I);
case A:
/*
* An immediate field of zero selects
* the accumulator. Vigorously object
* if zero is given otherwise - it's
* most likely an error.
*/
spec &= ~A;
if (!strcmp("A", a[spec]))
return(0);
if (isdigit(*a[spec]) &&
strtol(a[spec], NULL, 0) == 0)
{
error("immediate value of zero selects accumulator");
}
/* falls through */
case 0:
if (isdigit(*a[spec]))
return(strtol(a[spec], NULL, 0));
p = lookup(a[spec]);
if (p)
return(p->value);
error("undefined symbol used");
}
return(NA); /* shut the compiler up */
}
int
eval_addr(char **a, int spec)
{
sym_t *p;
if (spec == NA)
return(NA);
if (isdigit(*a[spec]))
return(strtol(a[spec], NULL, 0));
p = lookup(a[spec]);
if (p) {
if (p->value != NOVALUE)
return(p->value);
patch(p, LC);
} else {
define(a[spec], NOVALUE);
p = lookup(a[spec]);
patch(p, LC);
}
return(NA); /* will be patched in later */
}
int
crack(char **a, int n)
{
int i;
int I_imm, I_addr;
int I_op, I_dest, I_src, I_ret;
/*
* Check for "ret" at the end of the line; remove
* it unless it's "ret" alone - we still want to
* look it up in the table.
*/
I_ret = (strcmp(a[n-1], "ret") ? 0 : !0);
if (I_ret && n > 1)
n -= 1;
for (i = 0; instr[i].name; i++) {
/*
* Look for match in table given constraints,
* currently just the name and the number of
* operands.
*/
if (!strcmp(instr[i].name, *a) && instr[i].n == n)
break;
}
if (!instr[i].name)
error("unknown opcode or wrong number of operands");
I_op = eval_operand(a, instr[i].op);
I_src = eval_sdi(a, instr[i].src);
I_imm = eval_sdi(a, instr[i].imm);
I_dest = eval_sdi(a, instr[i].dest);
I_addr = eval_addr(a, instr[i].addr);
if( LC >= MEMORY )
error("Memory exhausted!\n");
switch (instr[i].fmt) {
case 1:
case 2:
M[LC][0] = (I_op << 1) | I_ret;
M[LC][1] = I_dest;
M[LC][2] = I_src;
M[LC][3] = I_imm;
break;
case 3:
if (I_ret)
error("illegal use of \"ret\"");
M[LC][0] = (I_op << 1) | ((I_addr >> 8) & 1);
M[LC][1] = I_addr & 0xff;
M[LC][2] = I_src;
M[LC][3] = I_imm;
break;
}
return (1); /* no two-byte instructions yet */
}
#undef SL
#undef SR
#undef RL
#undef RR
#undef LX
#undef LA
#undef LO
#undef I
#undef A
void
assemble(void)
{
int n;
char **a;
sym_t *p;
while ((a = getl(&n))) {
while (a[0][strlen(*a)-1] == ':') {
a[0][strlen(*a)-1] = '\0';
p = lookup(*a);
if (p)
p->value = LC;
else
define(*a, LC);
a += 1;
n -= 1;
}
if (!n) /* line was all labels */
continue;
if (n == 3 && !strcmp("VERSION", *a))
fprintf(ofp, "#define %s \"%s\"\n", a[1], a[2]);
else {
if (n == 3 && !strcmp("=", a[1]))
define(*a, strtol(a[2], NULL, 0));
else
LC += crack(a, n);
}
}
backpatch();
output(ofp);
if (debug)
output(stderr);
}
int
main(int argc, char **argv)
{
int c;
while ((c = getopt(argc, argv, "dho:vD")) != EOF) {
switch (c) {
case 'd':
debug = !0;
break;
case 'D':
{
char *p;
if ((p = strchr(optarg, '=')) != NULL) {
*p = '\0';
define(optarg, strtol(p + 1, NULL, 0));
}
else
define(optarg, 1);
break;
}
case 'o':
ofp = fopen(optarg, "w");
if (!ofp) {
perror(optarg);
exit(EXIT_FAILURE);
}
break;
case 'h':
printf("usage: %s [-d] [-Dname] [-ooutput] input\n",
*argv);
exit(EXIT_SUCCESS);
break;
case 'v':
printf("%s\n", id);
exit(EXIT_SUCCESS);
break;
default:
exit(EXIT_FAILURE);
break;
}
}
if (argc - optind != 1) {
fprintf(stderr, "%s: must have one input file\n", *argv);
exit(EXIT_FAILURE);
}
filename = argv[optind];
ifp = fopen(filename, "r");
if (!ifp) {
perror(filename);
exit(EXIT_FAILURE);
}
if (!ofp) {
ofp = fopen(ADOTOUT, "w");
if (!ofp) {
perror(ADOTOUT);
exit(EXIT_FAILURE);
}
}
assemble();
exit(EXIT_SUCCESS);
}
+198
View File
@@ -0,0 +1,198 @@
/*matcd.h---------------------------------------------------------------------
Matsushita(Panasonic) / Creative CD-ROM Driver (matcd)
Authored by Frank Durda IV
Copyright 1994, 1995 Frank Durda IV. All rights reserved.
"FDIV" is a trademark of Frank Durda IV.
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 positioned at the very beginning of this file without
modification, all copyright strings, all related programming
codes that display the copyright strings, this list of
conditions and the following disclaimer.
2. Redistributions in binary form must contain all copyright strings
and related programming code that display the copyright strings.
3. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
4. All advertising materials mentioning features or use of this
software must display the following acknowledgement:
"The Matsushita/Panasonic CD-ROM driver was developed
by Frank Durda IV for use with "FreeBSD" and similar
operating systems."
"Similar operating systems" includes mainly non-profit oriented
systems for research and education, including but not restricted
to "NetBSD", "386BSD", and "Mach" (by CMU). The wording of the
acknowledgement (in electronic form or printed text) may not be
changed without permission from the author.
5. Absolutely no warranty of function, fitness or purpose is made
by the author Frank Durda IV.
6. Neither the name of the author nor the name "FreeBSD" may
be used to endorse or promote products derived from this software
without specific prior written permission.
(The author can be reached at [email protected])
7. The product containing this software must meet all of these
conditions even if it is unsupported, not a complete system
and/or does not contain compiled code.
8. These conditions will be in force for the full life of the
copyright.
9. If all the above conditions are met, modifications to other
parts of this file may be freely made, although any person
or persons making changes do not receive the right to add their
name or names to the copyright strings and notices in this
software. Persons making changes are encouraged to insert edit
history in matcd.c and to put your name and details of the
change there.
10. You must have prior written permission from the author to
deviate from these terms.
Vendors who produce product(s) containing this code are encouraged
(but not required) to provide copies of the finished product(s) to
the author and to correspond with the author about development
activity relating to this code. Donations of development hardware
and/or software are also welcome. (This is one of the faster ways
to get a driver developed for a device.)
THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``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 DEVELOPER(S) 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.
-----No changes are allowed above this line------------------------------------
See matcd.c for Edit History information.
Matsushita CR562/CR563 Commands
This is not a complete list - just the ones this version uses
*/
#define NOP 0x05 /*No action - just return status*/
#define DOOROPEN 0x06 /*Open tray*/
#define DOORCLOSE 0x07 /*Close tray*/
#define ABORT 0x08 /*Abort command*/
#define MODESELECT 0x09 /*Set drive parameters*/
#define LOCK 0x0c /*Prevent/Allow medium removal*/
#define PAUSE 0x0d /*Pause/Resume playback*/
#define PLAYBLOCKS 0x0e /*Play audio - block to block*/
#define PLAYTRKS 0x0f /*Play audio - tracks & index*/
#define READ 0x10 /*Read data*/
#define READERROR 0x82 /*Read Error*/
#define READID 0x83 /*Read Drive Type & Firmware Info*/
#define MODESENSE 0x84 /*<12>Report drive settings*/
#define READSUBQ 0x87 /*<14>Read Q channel information*/
#define READDINFO 0x8b /*<13>Read TOC tracks & drive size*/
#define READTOC 0x8c /*<13>Read entry from TOC*/
#define BLOCKPARAM 0x00 /*Used with MODESELECT command*/
#define SPEEDPARM 0x03 /*<12>Adjust audio playback speed*/
#define AUDIOPARM 0x05 /*<12>Set/read audio levels & routing*/
#define RESUME 0x80 /*Used with PAUSE command*/
#define MAXCMDSIZ 12 /*Max command size with NULL*/
/* Possible data transfers for MODESELECT + BLOCKPARAM */
#define MODE_DATA 0x00 /*2048, 2340*/
#define MODE_DA 0x82 /*2352*/
#define MODE_USER 0x01 /*2048, 2052, 2336, 2340, 2352*/
#define MODE_UNKNOWN 0xff /*Uninitialized state*/
/*<12>The following mode is not implemented in the driver at this time*/
#define MODE_XA 0x81 /*2048, 2060, 2324, 2336, 2340, 2352*/
#define DEFVOL 0xff /*<12>Default drive volume level, 100%
volume. Based on drive action.*/
#define OUTLEFT 0x01 /*Output on Left*/
#define OUTRIGHT 0x02 /*Output on Right*/
/* Matsushita CR562/CR563 Status bits*/
#define MATCD_ST_DOOROPEN 0x80 /*Door is open right now*/
#define MATCD_ST_DSKIN 0x40 /*Disc in drive*/
#define MATCD_ST_SPIN 0x20 /*Disc is spinning*/
#define MATCD_ST_ERROR 0x10 /*Error on command*/
#define MATCD_ST_AUDIOBSY 0x08 /*Drive is playing audio*/
#define MATCD_ST_LOCK 0x04 /*<14>Drive is locked*/
#define MATCD_ST_X2 0x02 /*<14>Media is at double-speed*/
#define MATCD_ST_READY 0x01 /*<14>Drive is ready*/
#define MATCDAUDIOBSY MATCD_ST_AUDIOBSY
#define MATCDDSKCHNG MATCD_ST_DSKCHNG
#define MATCDDSKIN MATCD_ST_DSKIN
#define MATCDDOOROPEN MATCD_ST_DOOROPEN
/* Error codes returned from READERROR command.*/
#define NO_ERROR 0x00
#define RECV_RETRY 0x01
#define RECV_ECC 0x02
#define NOT_READY 0x03
#define TOC_ERROR 0x04
#define UNRECV_ERROR 0x05
#define SEEK_ERROR 0x06
#define TRACK_ERROR 0x07
#define RAM_ERROR 0x08
#define DIAG_ERROR 0x09
#define FOCUS_ERROR 0x0a
#define CLV_ERROR 0x0b
#define DATA_ERROR 0x0c
#define ADDRESS_ERROR 0x0d
#define CDB_ERROR 0x0e
#define END_ADDRESS 0x0f
#define MODE_ERROR 0x10
#define MEDIA_CHANGED 0x11
#define HARD_RESET 0x12
#define ROM_ERROR 0x13
#define CMD_ERROR 0x14
#define DISC_OUT 0x15
#define HARD_ERROR 0x16
#define ILLEGAL_REQ 0x17
/* Human-readable error messages - what a concept!*/
static unsigned char * matcderrors[]={"No error", /* 00 */
"Soft read error after retry", /* 01 */
"Soft read error after error-correction", /* 02 */
"Not ready", /* 03 */
"Unable to read TOC", /* 04 */
"Hard read error of data track",/* 05 */
"Seek did not complete", /* 06 */
"Tracking servo failure", /* 07 */
"Drive RAM failure", /* 08 */
"Drive self-test failed", /* 09 */
"Focusing servo failure", /* 0a */
"Spindle servo failure", /* 0b */
"Data path failure", /* 0c */
"Illegal logical block address",/* 0d */
"Illegal field in CDB", /* 0e */
"End of user encountered on this track", /* 0f */
"Illegal data mode for this track", /* 10 */
"Media changed", /* 11 */
"Power-on or drive reset occurred", /* 12 */
"Drive ROM failure", /* 13 */
"Illegal drive command received from host",/* 14 */
"Disc removed during operation",/* 15 */
"Drive Hardware error", /* 16 */
"Illegal request from host"}; /* 17 */
/*End of matcd.h*/
-29
View File
@@ -1,29 +0,0 @@
-----BEGIN PGP SIGNED MESSAGE-----
Sorry for the long wait, but there still were a few things to
be ironed out in at, which I've finally done :-)
The FreeBSD team does have my permission to use at, version 2.9,
under the BSD license.
You'll find it on sunsite.unc.edu's Incoming, hopefully; the
md5 checksum is
3ba2ca3c0e87e1a04feae2c6c1376b0d at-2.9.tgz
Best regards
Thomas
- --
Thomas Koenig, [email protected], [email protected].
The joy of engineering is to find a straight line on a double
logarithmic diagram.
-----BEGIN PGP SIGNATURE-----
Version: 2.6.2i
iQCVAwUBMCjVrPBu+cbJcKCVAQFNiQP/dpWP57s/E8plVGUD3zfgOXDmKUvg8U7a
VwRzJrIMuSgnSJs0wkpvcomc3NLicipfX7hhWLh/xatPM2YbF7O5HZoNdvWvexD2
1Y67zJ+0HFb1mPnSBOrS5RFiQAe3KqmGec6E14Rih/qNoFQZBVRFXZ4xxuwP+0Rs
e2U+TVTUz6A=
=TvyW
-----END PGP SIGNATURE-----
-7
View File
@@ -1,7 +0,0 @@
MAN1= killall.1
beforeinstall:
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${.CURDIR}/killall.pl ${DESTDIR}${BINDIR}/killall
.include <bsd.prog.mk>
-32
View File
@@ -1,32 +0,0 @@
.Dd May, 1995
.Dt SPKRTEST 8
.Os FreeBSD
.Sh NAME
.Nm spkrtest
.Nd test script for the speaker driver
.Sh DESCRIPTION
.Nm
is an easy to use test script for the speaker driver.
.Sh FILES
.Bl -tag -width /dev/speakerxx
.It Pa /dev/speaker
speaker device file
.El
.Sh SEE ALSO
.Xr spkr 4 ,
.Xr dialog 1 ,
.Xr perl 1
.\" only for the record
.\" .Sh AUTHOR
.\" Eric S. Raymond <[email protected]) June 1990;
.\" dialog+perl by Wolfram Schneider <[email protected]>, May 1995
.Sh HISTORY
The
.Nm
script appeared in FreeBSD 1.0
-96
View File
@@ -1,96 +0,0 @@
#!/usr/bin/perl
#
# Test script for the speaker driver
#
# v1.0 by Eric S. Raymond (Feb 1990)
# v1.1 rightstuff contributed by Eric S. Tiedemann ([email protected])
# v2.0 dialog+perl by Wolfram Schneider <[email protected]>, May 1995
#
# NOTE for iso-* (latin1) fonts: use TERM=cons25-iso8859-1
#
$title = "
reveille -- Reveille
contact -- Contact theme from Close Encounters
dance -- Lord of the Dance (aka Simple Gifts)
loony -- Loony Toons theme
sinister -- standard villain's entrance music
rightstuff -- a trope from \"The Right Stuff\" score by Bill Conti
toccata -- opening bars of Bach's Toccata and Fugue in D Minor
startrek -- opening bars of the theme from Star Trek Classic
";
$music = "
reveille -- t255l8c.f.afc~c.f.afc~c.f.afc.f.a..f.~c.f.afc~c.f.afc~c.f.afc~c.f..
contact -- <cd<a#~<a#>f
dance -- t240<cfcfgagaa#b#>dc<a#a.~fg.gaa#.agagegc.~cfcfgagaa#b#>dc<a#a.~fg.gga.agfgfgf.
loony -- t255cf8f8edc<a>~cf8f8edd#e~ce8cdce8cd.<a>c8c8c#def8af8
sinister -- mst200o2ola.l8bc.~a.~>l2d#
rightstuff -- olcega.a8f>cd2bgc.c8dee2
toccata -- msl16oldcd4mll8pcb-agf+4.g4p4<msl16dcd4mll8pa.a+f+4p16g4
startrek -- l2b.f+.p16a.c+.p l4mn<b.>e8a2mspg+e8c+f+8b2
";
$checklist = 'dialog \
--title "Speaker test" \
--checklist "Please select the melodies you wish to play (space for select)" \
-1 -1 10 \
';
sub Exit {
unlink $tmp if $tmp;
}
$SIG{'INT'} = $SIG{'HUP'} = $SIG{'TRAP'} = $SIG{'QUIT'} =
$SIG{'TERM'} = '&Exit';
# make assoc array from variable 'var'
# 'name -- description' -> $var{$name} = $description
sub splitconfig {
local(*var) = @_;
local($t, $name, $description);
foreach $t (split('\n', $var)) {
($name, $description) = split('--', $t);
$name =~ s/^\s+//; $name =~ s/\s+$//;
$description =~ s/\s+//; $description =~ s/\s+$//;
$var{$name} = $description if $name && $description;
}
}
&splitconfig(*title);
&splitconfig(*music);
foreach $e (sort keys %title) {
($t = $title{$e}) =~ s/(\")/\\$1/g; # quote '"'
$checklist .= "\"$e\" \"$t\" OFF ";
}
$tmp = ($ENV{'TMP'} || "/tmp") . "/_spkrtest$$";
system("$checklist 2> $tmp"); # start dialog
if (!$?) { # not cancel
open(SPEAKER, ">/dev/speaker") || die "/dev/speaker: $!\n";
select(SPEAKER); $| = 1;
select(STDOUT); $| = 1;
if (! -z $tmp) { # select melod(y/ies)
foreach $melody (split($", `cat $tmp`)) {
$melody =~ s/^"//; $melody =~ s/"$//;
print STDOUT "$title{$melody}\n";
print SPEAKER "$music{$melody}";
sleep 1;
}
} else { # use default melody
$melody = (sort keys %title)[0];
print STDOUT "Use default melody: $title{$melody}\n";
print SPEAKER "$music{$melody}";
}
close SPEAKER;
}
unlink $tmp;