mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-30 12:25:10 +01:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3ab491d64 |
No files matched your search
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
;
|
||||
}
|
||||
@@ -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)))))
|
||||
@@ -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))))
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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 :-).
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
#define RELEASE_NAME "__RELEASE"
|
||||
@@ -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
|
||||
@@ -1,6 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
PROG= find_interface
|
||||
NOMAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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*/
|
||||
|
||||
|
||||
@@ -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-----
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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;
|
||||
Reference in new issue
Block a user