CAP 6.0 pl198 + asip1

This commit is contained in:
mabam 2015-03-18 22:05:00 +01:00
parent de21798186
commit 743b427168
461 changed files with 139331 additions and 0 deletions

223
CAP.faq Normal file
View File

@ -0,0 +1,223 @@
CAP FAQ
-------
Last update:
Mon Aug 3 02:10:07 EST 1992
> What is CAP ?
The Columbia AppleTalk Package (CAP) implements the AppleTalk protocol
stack on a variety of UNIX machines. The main applications provide an
AppleShare 2.0 compatible server (aufs), a LaserWriter Spooler (lwsrv)
and a program to print to LaserWriters (papif). The latter can be used
to talk to EtherTalk LaserWriters, LocalTalk LaserWriters used on Dayna
EtherPrint cards or on a LocalTalk/EtherTalk gateway. There are also a
number of contributed packages bundled with CAP (see cap60/contrib).
> What extra hardware is required for CAP ?
On a SUN or ULTRIX machine, CAP can speak Phase 1 or Phase 2 EtherTalk
packets using packet filters based on the Stanford ENET model. Where
available, CAP can also use Kernel based AppleTalk or run the UNIX
AppleTalk Bridge (UAB) to act as a gateway. On other UNIX boxes you
need to have a gateway that can translate IPTalk packets. Suitable
candidates are Shiva FastPath, Cayman GatorBox or Webster MultiPort Gateway.
> What machines will CAP run on ?
The CAP Configure script has specific support for the following
Operating Systems:
sunos - SUN SunOS
ultrixnn - DEC Ultrix 1.2, 2.0, 4.N
irix - Silicon Graphics IRIS/IRIX
aix - IBM AIX System V
hpux - HP HP-UX 8.0
uts - Amdahl UTS
aux - Apple A/UX 2.0
encore - Encore MultiMax BSD
pyr - Pyramid (BSD Universe)
next - NeXT/MACH
dynix - Sequent Balance
newsos - Sony NEWS
bsd - BSD 4.2, 4.3
> What is the current CAP version ?
CAP is at version 6.0 with (currently) 125 patches to be applied, most of
which add extra functionality to the original. To determine the current
patch level of your sources, check the cap60/README file for a line of
the form
o CAP Distribution 6.0, Patch Level 125, July 1992
> Where can I get CAP ?
CAP can be obtained by anonymous FTP from
rutgers.EDU src/{cap60.tar.Z,cap60.patches/*}
munnari.OZ.AU mac/{cap60.tar.Z,cap.patches/*}
gatekeeper.DEC.COM pub/net/appletalk/cap/{cap60.tar.Z,cap.patches/*}
ftp.kuis.kyoto-u.AC.JP net/cap/{cap60.tar.Z,cap60.patches/*.Z}
src.doc.ic.AC.UK mac/multigate/{cap60.tar.Z,cap.patches/*}
Please choose an appropriate site and an off-peak time for the transfer.
The patches are available individually or as the files "patches.1-75.tar.Z",
"patches.76-100.tar.Z" and "patches.101-125.tar.Z". Additionally, for new
users, a partially patched source file is available as "cap60.pl100.tar.Z"
(the file cap60.tar.Z is unpatched).
> How do I apply the patches ?
To make the process of patching easier, you should get the 'patch' utility
written by Larry Wall, it is normally archived at sites that archive
comp.sources.unix in volume7/patch2. If you can't find anywhere closer
it is on munnari.OZ.AU. CAP Version 6.1 will be 6.0 with all the patches
applied and updated cap60/contrib packages. It will appear when the number
of patches stabilizes.
For each of the patches, run 'patch -p < cap60.patch0NN' from the top level
cap60 directory, for example, in csh
foreach i (cap60.patches/cap60.patch*)
patch -p < $i >>& /tmp/patches
end
and check the /tmp/patches file for patching errors (should be none).
To remove the *.orig files that patch leaves behind (containing the original
version of the file), run 'make spotless' from the top level directory (note
that spotless also removes all makefiles so gen.makes needs to be run to
regenerate them).
> I picked up CAP 6.0 from rutgers.edu, but our Unix system administrator
> refuses to install it because there are 74 patches (can't say I blame him)!
Sigh. Using the patch program to apply patches requires a minimal amount of
time and energy. Taking time to install the patch program will pay off for
CAP and other program updates.
% date
Sat Mar 7 23:51:05 EST 1992
% touch /tmp/patches
% foreach i (cap60.patches/cap60.patch*)
? patch -p < $i >>& /tmp/patches
? end
% grep rej /tmp/patches
% date
Sat Mar 7 23:54:26 EST 1992
It took just 3:11 to apply 75 patches to the raw CAP tar source. The extra
overhead is the time to FTP 3 files, cap60.tar.Z, patches.1-74.tar.Z and
cap60.patch075 and uncompress them. The total time spent on this ... 8:02.
> Is CAP Public Domain ?
No, CAP is distributed with the following condition on its use:
Copyright (c) 1986, 1987, 1988, The Trustees of Columbia University in
the City of New York. Charlie C. Kim, User Services Group, Academic
Information Services Division, Libraries and Center for Computing
Activities and Bill Schilit, formerly of Computer Research Facilities,
Computer Science Department.
Permission is granted to any individual or institution to use, copy,
or redistribute this software so long as it is not sold for profit,
provided that this notice and the original copyright notices are
retained. Columbia University makes no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
Some portions of CAP have other copyrights and are suitably marked.
> Is there a version of CAP available that supports Ethertalk Phase 2 ?
Phase 2 support was added in CAP 6.0 patches 25, 28 & 35 for SUN NIT, ULTRIX
4.n and SUN enet driver respectively.
> Can a workstation with 2 ethernet cards running Cap s/w act as a phaseII
> to (phaseI or phaseII) "Gateway"? If so, what patch level of Cap do I need
> to do this?
The UNIX AppleTalk Bridge (UAB) is the EtherTalk gateway. It can handle
multiple ethernet interfaces and gateway between them. This is its primary
function but it can also be set up to provide CAP services. But ...
> Does anyone have a patch that will support the phase 2 appletalk protocol
> on UAB (CAP6.0).
UAB is *currently* Phase 1 only.
> Is there any standard way yet of implementing a execute only, copy
> protected CAP AUFS server?
The original method of achieving this was to removing read permission from
the data fork of the Application (make it non-zero length if the file is
empty). The current method involves using the Application Manager added in
patch number 61. Either of these methods can be circumvented by users who
are either knowledgeable or determined.
> Recently I introduced a new color postscript printer, Tektronix Phaser III
> 4698PXi, under one of the LocalTalks. It works fine from Macintosh's so I
> tried to use it from papif but failed.
CAP uses DDP checksums by default, the checksum code in the Phaser III PXi
and the Apple Personal LaserWriter NTR incorrectly calculate the checksum
value and the packet is dropped. The programs aufs, lwsrv, papif, atis,
atlooklws and tlw now support the -k option to disable CAP checksums on a
per-program basis. To disable CAP checksums completely, add the following
lines to the m4.features file, rerun gen.makes and remake CAP.
# + DONT_DOCHKSUM no DDP checksums (Tektronix Phaser III PXi & Apple LW NTR)
define(`specialcflags',concat(specialcflags,` -DDONT_DOCHKSUM'))
#
No other code changes are necessary.
> We've just upgraded our DECstations to version 4.2 of ULTRIX, and our CAP
> distribution very neatly broke.
You need to obtain the net_common.o and pfilt.o patches from DEC. Do not
turn on the ifconfig copyall (stop-gap measure previously suggested on the
net). Do not define ULT42PFBUG in m4.features.
> When we run aarpd with a command like:
> aarpd pf0 our_zone
> the daemon doesn't start & we get the message 'failed to start ZIS listener'.
This means that something has been allocated the UPD port 774 (768+6)
by 'portmap'. You can check this with the command 'rpcinfo -p'.
There are two solutions, break 'start-cap-servers' into two so that aarpd
and atis is started before portmap. Alternatively, and preferably, install
the NIC assigned port numbers into /etc/services. See the doc in the file
cap60/doc/install.ms for more details.
> I have installed the enet driver. But aarpd won't start successfully.
> Instead the following error message is being printed.
> unix!: # aarpd le0 EtherTalk
> open: /dev/enetXX: No such file or directory
The ENET drivers use devices of the form enet0, enet1 etc. Replace the
string "le0" with "enet0".
For more information, see the CAP60.README file in the CAP distribution.
Send CAP FAQ contributions to cap@munnari.OZ.AU

559
CAP60.README Normal file
View File

@ -0,0 +1,559 @@
CAP 6.0
-------
This distribution of CAP is an attempt to collect together all of the patches
available for cap50 and provides an opportunity to perform some very necessary
maintenance. The code contains the original "official" patches plus bug fixes
and extra features contributed by *many* people. Local configuration of the
extra features is controlled by the file 'm4.features'. For more details,
see Features below.
Other changes
-------------
* AUFS support for AFP 2.0 is (practically) complete (see below).
* 'Configure' will automatically recognize the host byte ordering.
* 'Configure' has support for more machines and custom local features.
* UAB is now bundled and configured with this CAP distribution.
* UAB now supports Asynchronous AppleTalk on a UNIX host.
* The format of 'atalk.local' has been extended for async appletalk.
* Zone names in 'atalk.local' MUST now be quoted to include spaces.
* A "free format" 'etalk.local' is used by EtherTalk LAPs (& UAB/UAR).
* atis is now Phase 2 NBP compatible (partial obj/type matches).
* There are more (& updated) manual entries and documentation.
* There are more contributed packages bundled with CAP.
Features
--------
Additional features have been incorporated into CAP. Most of these were
supplied as patch files from a variety of sources. In addition, some changes
were made at The University of Melbourne, these changes concentrated on making
AUFS comply with AFP2.0 specifications and adding extra facilities and host
support to Configure. Currently, AUFS supports ProDOS* (Apple IIgs)
workstations running AppleTalk, the extended directory and volume attributes
and the additional error result codes. AUFS supports user editable encrypted
passwords using the DISTRIB_PASSWDS feature.
* ProDOS requires the NOCASEMATCH feature, or use of upper-case
application filenames only.
Specific host support that was new with CAP 6.0 includes ...
A/UX 2.0 Native AppleTalk William Roberts <liam@cs.qmw.ac.uk>
IBM Risc 6000 AIX System V David Hornsby <djh@munnari.OZ.AU>
Silicon Graphics IRIS-4D/IRIX David Hornsby <djh@munnari.OZ.AU>
SCO Xenix System V Chip Salzenberg <chip@tct.com>
Sequent Balance William Roberts <liam@cs.qmw.ac.uk>
ICL DRS6000 Michael Brown <mgb@geol.utas.edu.au>
DEC OSF/1 Alpha Scooter Morris <scooter@genie.gene.com>
Amdahl UTS Mark Haynie <mnh@cat.amdahl.com>
Sun Solaris 2.N Andy Polyakov <appro@fy.chalmers.se>
Sony NEWS TAYA Shin'ichiro <taya@sm.sony.co.jp>
Control Data CD4000-EP/IX John Huntley <John.Huntley@zeus.cdc.com>
386/BSD, FreeBSD 2.0 Dave Matthews <dcjm@dcs.ed.ac.uk>
NetBSD 1.0 Paul Nash <paul@frcs.alt.za>
BSDI BSD/386 1.1 David Hornsby <djh@munnari.OZ.AU>
HP/Apollo Domain BSD 4.3 Darrell Skinner
<skinner@lpmi.polytechnique.fr>
The features file ("m4.features") can be edited from within Configure by
answering yes to the question "Do you wish to customise the feature list ?".
The contents of the file are not processed by Configure so you can edit the
feature list at any time then (re)generate the makefiles with "./gen.makes".
To include a particular feature, uncomment (remove '#') the definition line.
The available flags, their meanings and original authors are:
SHORT_NAMES
Include AUFS code to support short file names as required by
AppleShare client implementations on PCs.
Bridget Rogers <brogers@ub.d.umn.edu>
NOCASEMATCH
Make AUFS filenames case insensitive as in other AppleShare
servers and Mac applications.
Edward Moy <edmoy@violet.berkeley.edu>
SIZESERVER
Compile 'sizeserver' daemon for AUFS to obtain volume size
information. Useful with operating systems that have no
support for getmnt() or statfs() to determine the amount of
free space on a filesystem.
Edward Moy <edmoy@violet.berkeley.edu>
FIXED_DIRIDS
Implement server and AUFS code to provide support for
fixed directory and file IDs. The 'afpidsrvr' daemon must
be started before any AUFS processes. Refer to the file
"applications/aufs/afpid.notes" for more information.
John Forrest <jf@ap.co.umist.ac.uk>
Scooter Morris <scooter@gene.com>
LWSRV_AUFS_SECURITY
Require LWSRV LaserWriter spooler users to have an AUFS
volume connected (and therefore be password validated).
Phil Budne <phil@shiva.com>
LWSRV_LPR_LOG
Include stdout/stderr messages from lpr in the lwsrv log.
Rakesh Patel <rapatel@khnphwzhn.njin.net>
AUTHENTICATE
AUFS or LWSRV connections must comply with the rules
specified in "/etc/cap.auth". This may specify permit
or deny permission by network number and/or server type.
Refer to the file cap60/doc/cap.auth.doc for details.
Edward Moy <edmoy@violet.berkeley.edu>
STAT_CACHE
Provide a speed enhancement by caching UNIX stat(2) calls
within AUFS.
Dan Oscarsson <dan@dna.lth.se>
TREL_TIMEOUT
ATP transaction release packets (TREL) can sometimes be
lost. AUFS will timeout after 30 seconds and continue with
the next request. This option adds a second request
listener to avoid the timeout delays.
Dan Oscarsson <dan@dna.lth.se>
ATPREQCACHE
Cache ATP TREQ packets to avoid 2 second wait if request
control block (RqCB) not set up in time by AUFS.
Rudy Nedved <Rudy_Nedved@RUDY.FAC.CS.CMU.EDU>
RUTGERS
Include Rutgers specific code. You probably don't want
either this or MELBOURNE unless you check the sources.
MELBOURNE
Include Melbourne specific code.
USE_HOST_ICON
If available, the AUFS volume ICON will represent the
underlying machine hardware (instead of the BSD daemon).
PERMISSIVE_USER_NAME
Allow the AUFS login name (from the Chooser User Name) to be
partially matched to the gecos field in the password entry.
IE: you can login with full user name, first name or surname.
Jean-Luc Mounier <mounier@masi.ibp.fr>
ULTRIX_SECURITY
Activate AUFS login security based on an authorisation
file. Check this file if normal password field is "*".
Rusty Wright <rusty@groan.berkeley.edu>
DIGITAL_UNIX_SECURITY
Use Digital UNIX enhanced security for AUFS logins.
Andrew Greer <andrew@totara.its.vuw.ac.nz>
Richard Rogers <r.m.rogers@staffs.ac.uk>
USE_MAC_DATES
Keep the modification date of the Mac file intact when
copied to an AUFS volume (otherwise it is the latter of
the UNIX creation and modify times).
David Hornsby <djh@munnari.OZ.AU>
DEV_NIT
Allow an alternate name for the NIT interface. The default
name is "/dev/nit".
Austin Shelton <austin@chalmers.se>
APPLICATION_MANAGER
Control the maximum number of times an Application may be
run and optionally prevent Finder copying for AUFS mounted
volumes. More details in contrib/AppManager/README
David Hornsby <djh@munnari.OZ.AU>
DENYREADWRITE
Implement AFP Access/Deny modes on AUFS file accesses.
David Hornsby <djh@munnari.OZ.AU>
AUFS_README
Add '-r <arg>' option to AUFS. The <arg> is expected to
be a full path name to an explanatory README file and is
linked into the top level volume of a new AUFS user.
Edward Moy <edmoy@violet.berkeley.EDU>
AUFS_IDLE_TIMEOUT
Add -i and -I options to AUFS to disconnect users who
exceed the specified idle time. -I includes all users,
-i is for guest sessions only.
David Hornsby <djh@munnari.OZ.AU>
REREAD_AFPVOLS
A SIGUSR1 signal sent to AUFS causes the global AFP volumes
file to be re-read.
Eugene Bogaart <bogaart@serc.nl>
CLOSE_LOG_SIG
A SIGUSR2 signal sent to AUFS causes the log file to be
closed and then re-opened (allows the file to be truncated,
for example, by a script which regularly does something like
'cat > logfile; kill -USR2 <pid>'). See also PID_FILE.
Scooter Morris <scooter@gene.com>
PID_FILE
Cause AUFS to write a (named) process-ID file.
Scooter Morris <scooter@gene.com>
XDEV_RENAME
Allows AUFS to copy/move files across file systems.
Mark Abbott <m.abbott@ucl.ac.uk>
NOCHGRPEXEC
Make AUFS use the third argument to chown(2) instead of
exec'ing chgrp(1) to change group membership of file.
NB: Unavailable under System V, recommended for others.
Edward Moy <edmoy@violet.berkeley.EDU>
USEDIRSETGID
Set the group ID bit on directories whose group is not the
primary group of the AUFS user. Under SunOS and System V,
new files and directories are by default created with the
primary group unless the group ID bit of the parent is set.
David Hornsby <djh@munnari.OZ.AU>
USR_FILE_TYPES
Map UNIX filename suffix to Mac Type/Creator. The map file
may be global (specified with -F option to AUFS) or per
user (~/.afpfile or ~/afpfile). The mapping also controls
the file translation method used (ascii, text or raw). See
the sample file in cap60/extras/afpfile.
David Hornsby <djh@munnari.OZ.AU> et. al.
CREATE_AFPVOL
Create the .afpvols file, .finderinfo and .resource
directories in a subdirectory (default 'mac') of the home
directory of a new AUFS user (if they don't already exist).
An alternate subdirectory/volume name is specified with
the string -DCREATE_AFPVOL=\"other\" in m4.features
Heather Ebey <hebey@ucsd.edu>
CREATE_AFPVOL_NAME (now CREAT_AFPVOL_NAM)
Modifies the CREATE_AFPVOL option to use the user/account
name for the volume label instead of the value of the
CREATE_AFPVOL variable. Assumes CREATE_AFPVOL.
Craig Zook <zook@pat.mdc.com>
NETWORKTRASH
Under System 7.0, the "Network Trash Folder" mode is set
to 0x707 (world writeable). Defining NETWORKTRASH sets the
mode to that of the parent (top level) directory.
Edward Moy <edmoy@violet.berkeley.EDU>
ISO_TRANSLATE
Translate ISO 8859 characters in command line arguments
and configuration files into their Macintosh equivalents.
Likewise translate Macintosh characters to ISO 8859 for
etalk.local zone name, log file entries.
Austin Shelton <austins@cdg.chalmers.se>
ISO_FILENAMES
Extend ISO/Mac character translation to AUFS file names
(assumes ISO_TRANSLATE is in use)
Dan Oscarsson <Dan.Oscarsson@malmo.trab.se>
ISO_FILE_TRANS
Translate ISO 8859 characters in Creator "unix", Type
"TEXT" AUFS files into Mac characters on read and vice
versa on write (assumes ISO_TRANSLATE is in use).
Dan Oscarsson <Dan.Oscarsson@malmo.trab.se>
NCS_ALL_TEXT
Apply ASCII or ISO 8859 file translation to all files of
type "TEXT", regardless of Creator.
Dan Oscarsson <Dan.Oscarsson@malmo.trab.se>
LOGIN_AUTH_PROG
Allows AUFS -L command line argument to specify an external
authorization program for AUFS logins. See man/AUFS.8
Irwin S. Tillman <irwin@phoenix.Princeton.EDU>
PSJOBHEADER
If defined, PAPIF will check for an environmental variable of
the same name. The variable specifies a file which contains
a postcript header (for example to change paper trays or
print double sided) to be sent before the print job.
Jay Plett <jay@silence.princeton.nj.us>
DUPLEXMODE
If defined, PAPIF accepts a -2 option (also if the printer
name contains -dup*) to set double sided printing. Duplex
printing must be supported by the printer hardware.
Dan Mosedale <mosedale@genome.stanford.edu>
TRANS3
Setup PAPIF for 'psdman' from the TranScript 3.0 package.
Dan Mosedale <mosedale@genome.stanford.edu>
PASS_THRU
If defined for LWSRV, print jobs will be passed through
with no Adobe pre-processing. This is useful for spoolers
providing service for PCs.
Gavin Longmuir <gavin@coombs.anu.edu.au>
DONT_PARSE
If defined for LWSRV, print jobs will be passed through
with no Adobe pre-processing at all. This is useful for
spoolers which require an unaltered file, as the PASS_THRU
option does not disable some Adobe handling. The crtolf
option will continue to work if it is enabled with this
option.
Rakesh Patel <rapatel@rutgers.edu>
LPRARGS
Allows LWSRV -L command line arguments to be passed directly
to lpr. For example, printing via TransScript without
-T quote8bit set causes option-key characters to be printed
incorrectly. Setting -T quote8bit causes binary PostScipt
(usually gray scale images) to fail. In this situation use
LWSRV argument "-L-l" to pass "-l" to lpr.
Edward Moy <edmoy@violet.berkeley.EDU>
RUN_AS_USER & USER_REQUIRED
Attempt to map Mac Chooser/Owner name to a real UNIX user
name (based on map file, eg: cap60/extras/lib.cap.macusers)
then setuid() the lwsrv session as this user. IE: lpr can be
lprm'd as normal. USER_REQUIRED must find a match otherwise
it prints a failure message eg: cap60/extras/lib.cap.refused.
NB: no password authentication is provided.
Maarten Carels <maarten@fwi.uva.nl>
PROCSET_PATCH
If defined for LWSRV, procset "patches" are not passed
through to the printer. These patches are code changes
for Apple LaserWriters and can have strange effects if
used on non-Apple printers.
Alexander Dupuy <dupuy@tiemann.cs.columbia.edu>
ULT42PFBUG
Workaround for ULTRIX 4.2 packet filter problem (see Gotchas)
David Hornsby <djh@munnari.OZ.AU>
STEAL_PORTS
Extend DDP Dynamic Socket range down into the experimental
AppleTalk socket range 64 - 128. Adds another 64 possible
sockets for server use.
Rakesh Patel <rapatel@rutgers.edu>
David Hornsby <djh@munnari.OZ.AU>
USING_FDDI_NET
Includes code to determine if interface is running on
FDDI network and adjust packets accordingly. Digital UNIX
and Ultrix only at this stage.
Conrad Huang <conrad@cgl.ucsf.edu>
NOCAPDOTPRINTERS
If defined, PAPIF will not use /etc/cap.printers, instead
the first line of the file /etc/lp/printers/lw/comment (for
printer "lw") is expected to contain a fully qualified
AppleTalk NBP name for the printer, ie: lw:LaserWriter@Zone
This option is intended for use on Solaris 2.N hosts only.
Andy Polyakov <appro@fy.chalmers.se>
USESYSLOG
If defined, PAPIF will send Information, Warning and Debug
messages to syslog().
Andy Polyakov <appro@fy.chalmers.se>
DISTRIB_PASSWDS
If defined, CAP will use AUFS authentication methods that
involve exchanging encrypted random numbers instead of
sending passwords in clear text over the network. Refer to
manual entries aufsmkkey.8 and aufsmkusr.8 in cap60/man.
David Hornsby <djh@munnari.OZ.AU>
AFP_DISTPW_PATH
Specifies that the distributed password files used in
DISTRIB_PASSWDS be kept in a directory other than the
user's home directory. For example, you could use the
following -DAFP_DISTPW_PATH=\"/usr/local/lib/cap/upw\"
David Hornsby <djh@munnari.OZ.AU>
AFP_DISTPW_MODE
Modifies the file mode being enforced with DISTRIB_PASSWDS.
For use when user home directories are mounted via NFS. Uses
mode 0600 by default, use 0644 with NFS.
David Hornsby <djh@munnari.OZ.AU>
DEBUG_AFP_CMD
If defined, AUFS will dump detailed logs of AFP command I/O
parameters in the file specified with the AUFS -Z option.
Use in conjunction with Inside AppleTalk 2nd edition for
debugging the AUFS AFP implementation.
David Hornsby <djh@munnari.OZ.AU>
LOG_WTMP
If defined, AUFS will write an entry into the wtmp log file
on each successful AUFS connection. Allows usage tracking.
Gavin Longmuir <Gavin.Longmuir@anu.edu.au>
Heather Ebey <heather@sdcc6.ucsd.edu>
LOG_WTMP_FILE
Specifies alternate name for the wtmp file used in LOG_WTMP.
Heather Ebey <heather@sdcc6.ucsd.edu>
ADMIN_GRP
If defined, AUFS will check if the user is a member of a
special admin group and connect them with superuser privs.
Tim Leamy <ccctim@rocky.ucdavis.edu>
TEMPFILE
Allow the LWSRV temporary file path to be specified.
Serge <serge@zooks.ME.berkeley.edu>
USELPRSYM
Option to allow optional lpr '-s' (broken under OSF/1).
Serge <serge@zooks.ME.berkeley.edu>
The following were originally to be defined in m4.setup, they have
been moved to m4.features for convenience.
NONLXLATE - don't translate newlines on "line-at-a-time" reads
FULL_NCS_SUPPORT - National Character Support
GGTYPE="gid_t" - Host type definition for groups
DOCNAME - include document name in lpr job name
PAGECOUNT - include page count in lpr job name
ADOBE_DSC2_CONFORMANT - Conform to Adobe DSC2 specs
CAP Patches
-----------
The primary source of CAP information is, as always, the network newsgroup
comp.protocols.appletalk. This forum will continue to be used to disseminate
information about CAP 6.0 updates, but we would very much like to encourage a
slightly more formal approach to the process of propogating CAP patches.
Therefore, please send patches for CAP bug-fixes and new features to
cap@munnari.OZ.AU
Context diffs (from 'diff -c') are preferred, but not essential. Patches
received will be assigned a patch number, a priority and will be included in
regular (but not too frequent) CAP releases. In addition to then being sent
to comp.protocols.appletalk, the patches will be available via FTP from
munnari.OZ.AU (in mac/cap.patches)
ftp-ns.rutgers.edu (in pub/cap/cap.patches)
gatekeeper.DEC.COM (in pub/net/appletalk/cap/cap.patches)
ftp.kuis.kyoto-u.AC.JP (in net/cap/cap60.patches)
src.doc.ic.AC.UK (in mac/multigate/cap.patches)
The intent is to minimise the nightmare of trying to apply useful patches
that have come from divergent versions of the source code. Another goal is
to reduce the maintenance needed for CAP code, if the incremental patches are
applied in order, the result will be identical to any new release.
To apply the patches with an absolute minimum of effort, it is recommended
that you use the 'patch' program written by Larry Wall. This can be obtained
from sites that archive postings from the newsgroup comp.sources.unix in the
directory volume7/patch2. It is important to ensure that any patches for the
patch sources are applied, some CAP patches can fail if the unmodified patch
code is used.
The current patch level is recorded in the cap60/README file. New patches
are applied from the top level directory with the command
% patch -p < cap60.patches/cap60.patch0NN
where NN is the patch number. The -p option tells patch to obtain
information about which file to alter from the patch header (use -p0 on
a DEC Alpha under OSF/1). If you attempt to apply a patch more than once,
patch will enquire about "a reversed or previously applied patch", answering
yes to this will remove the patch, leaving the original file (and bug), this
is not good ...
CAP and AppleTalk Phase 2
-------------------------
CAP 6.0 supports EtherTalk Phase 2 using the SunOS NIT interface, the enet
packet filter (requiring kernel mods, see cap60/support/enet) and the ULTRIX
packet filter (ULTRIX 4.0 or later). It also is possible to use CAP in a
Phase 2 environment with IPTalk as indicated below.
Traditionally, the CAP transport mechanism uses UDP/IP packets. This is
called IPTalk (also known as KIP) and is a "non-extended" (1 net number
and 1 zone name) network. CAP with IPTalk can run on a LARGE variety of
UNIX platforms.
On some machines, CAP can also produce EtherTalk Phase 1 packets directly
(using Native EtherTalk, Kernel AppleTalk or UAB - the UNIX AppleTalk
Bridge). EtherTalk Phase 1 is also a "non-extended" network.
Macintoshes on EtherNet can speak EtherTalk Phase 1 or Phase 2. EtherTalk
Phase 2 networks are always "extended", allowing multiple network numbers
and zone names on a single cable. An "extended" network can be "restricted"
to have one net number and one zone name. This permits the Phase 2 routing
information to be translated into Phase 1 routing packet format. This is
not otherwise possible.
For completeness, LocalTalk networks can use either Phase 1 or Phase 2
AppleTalk packets, but such networks are always "non-extended".
In a brief summary of AppleTalk Phase 1 and Phase 2 differences on LocalTalk,
routing information (RTMP) packet formats are different. NBP packets allow a
new character (approxEquals or 0xc5) for partial NBP name and type matching.
Nodes are no longer required to send to the last RTMP sender that they heard
from, rather, they can choose to send to the "best" router. There are other
differences for Phase 1 and Phase 2 EtherTalk packets on EtherNet. These
differences relate mainly to delivery mechanisms.
If you use CAP with IPTalk and *NO* AppleTalk routing over IP (ie: via an
IP link between IP gateways) then you can use CAP with Phase 2, "extended"
networks with no restrictions (except of course, that you must have an
AppleTalk Gateway capable of talking IPTalk and EtherTalk Phase 2).
On the other hand, if you are using CAP and IPTalk with AppleTalk routing
over IP, or CAP with EtherTalk Phase 1, then your Phase 2 networks must all
be "restricted" and you need to have a gateway capable of operating in
"transition" mode (the problem with the first case is due to the way IPTalk
works rather than CAP. IPTalk 2 is under development and will solve this).
The gateway translates the packets from one format to another. Suitable
IPTalk/Phase 2 gateways are the Webster MultiPort Gateway (running Megan
2.1 or later) and the Shiva FastPath 4 (running KSTAR 8.0 or later). Most
earlier versions of the gateway code will happily translate from IPTalk to
either Phase 1 or LocalTalk.
See Also
--------
Manual entries cap60/man/*
Various documentation cap60/doc/*
Native EtherTalk cap60/support/ethertalk/README
Kernel AppleTalk lib/cap/abkas.c, netatalk-1.2 distribution
http://www.cs.mu.OZ.AU/appletalk/atalk.html
Gotchas
-------
There are various problems known to exist with CAP and particular UNIX
systems or programs.
ULTRIX:
You may see the error message
open: ln0: No such file or directory
when running aarpd. The problem is due to missing packet
filter devices in /dev/pf. For details on how to make the
devices, refer to the manual entry for 'packetfilter'.
ULTRIX 4.1:
There is a problem with packet filter code in ULTRIX 4.1
that prevents CAP writing packets to the network. Before
running CAP with 4.1 (on any hardware platform), request
the patched version of the file "net_common.o" from your
DEC Customer Support Center. You may also need to obtain
the updated "if_ln.o" to prevent problems with LAT.
ULTRIX 4.2/4.2A:
There are three known "problems" with packet filter code
and unicast/802.3 packet handling under ULTRIX 4.2. The
problems have been identified and fixed. Contact your
local DEC Customer Support Center and query the status
of patches for "net_common.o" and "pfilt.o". The problems
and WORKAROUNDS for UNPATCHED systems are as follows:
"unicast packets are not delivered properly to PF clients"
define COPYALL mode using 'ifconfig ... +copyall'
"802.3 (phase 2) AARP packets converted to EtherNet equiv."
apply CAP patch 75, define ULT42PFBUG in Configure
"3rd-party Mac EtherNet cards that round up odd 802.3 packets"
no workaround, requires new net_common.o, pfilt.o
with less stringent 802.3 length sanity checking.
ULTRIX 4.3
under ULTRIX V4.3 you may need to obtain a patched version of
/etc/lockd to use DENYREADWRITE code. A possible workaround is
to 'nfssetlock off' ... this will impact NFS mounted volumes.
HP/Apollo Domain BSD 4.3
Avoid using the //node/path syntax in afpvols, either
explicitly or from expansion of ~. If such a definition
appears in afpvols, the volume corresponding to it may
be visible in the Chooser but be unmountable or may not
appear in the Chooser. Other volumes defined after such
a line also may not show up in the Chooser. You may use
directories mounted on other nodes using soft links or
a path such as /../node/path. It is not clear how much of
the file locking carries over directories on other nodes.
See NOTES for avoiding the //node/path construction.
NFS
In some circumstances, CAP AUFS using NFS mounted
filesystems may complain about files being locked when
they are not obviously so. Ensure that you have the latest
NFS bugfixes for your UNIX platform.
Bug Fixes
---------
The following CAP 5.0 bug fixes were incorporated into CAP 6.0.
abpap.c.tickletimer Jim Guyton <guyton@rand.org>
abpaps.c.flowquantum William Roberts <liam@cs.qmw.ac.uk>
procset.c.looping William Roberts <liam@cs.qmw.ac.uk>
mips.ultrix.byteswap <rob@cs.aukuni.ac.nz>
snitch.c.stringlength Phil Farrell <farrell@pangea.stanford.edu>
papif.c.atpresponse Phil Farrell <farrell@pangea.stanford.edu>
papif.c.variousbugs Jeff Stearns <jeff@tc.fluke.COM>
papif.c.reverse Robert McLay <mclay@emx.utexas.edu>
afpos.c.strcmp JQ Johnson <jqj@duff.uoregon.edu>
simple.c.comment Mark Rawling <rcomr@koel.co.rmit.oz.au>
rtmp.c.nocase John Sellens <jmsellen@watmath.waterloo.edu>

1975
Configure Executable file

File diff suppressed because it is too large Load Diff

1
LICENSE Normal file
View File

@ -0,0 +1 @@
For license information see 'NOTICE' and 'README'

535
MANIFEST Normal file
View File

@ -0,0 +1,535 @@
-rw-r--r-- 1 djh 9033 Mar 14 23:57 CAP60.README
-rwxr-xr-x 1 djh 31416 Mar 13 19:32 Configure
-rw-r--r-- 1 djh 25821 Mar 15 15:14 MANIFEST
-rw-r--r-- 1 djh 2759 Feb 28 23:42 MODIFICATIONS
-rw-r--r-- 1 djh 1461 Mar 14 16:15 Makefile
-rw-r--r-- 1 djh 7310 Mar 14 16:14 NOTES
-rw-r--r-- 1 djh 1460 Feb 28 23:42 NOTICE
-rw-r--r-- 1 djh 6312 Feb 28 23:42 PORTING
-rw-r--r-- 1 djh 9256 Mar 13 20:04 README
-rw-r--r-- 1 djh 1747 Mar 13 19:56 conf.func.lst
-rwxr-xr-x 1 djh 8221 Feb 28 23:42 conf.func.sh
-rw-r--r-- 1 djh 1842 Feb 28 23:45 conf.sysv.lst
-rwxr-xr-x 1 djh 4760 Feb 28 23:45 conf.sysv.sh
-rwxr-xr-x 1 djh 825 Feb 28 23:45 gen.makes
-rw-r--r-- 1 djh 12974 Feb 28 23:46 m4.setup
applications:
-rw-r--r-- 1 djh 467 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 321 Feb 28 23:44 Makefile.m4
-rw-r--r-- 1 djh 429 Feb 28 23:44 README
-rw-r--r-- 1 djh 460 Feb 28 23:44 makefile
applications/aufs:
-rw-r--r-- 1 djh 10802 Feb 28 23:44 INSTALLATION
-rw-r--r-- 1 djh 4954 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 5016 Feb 28 23:44 Makefile.m4
-rw-r--r-- 1 djh 7223 Feb 28 23:44 NOTES
-rw-r--r-- 1 djh 1882 Feb 28 23:44 README
-rw-r--r-- 1 djh 1832 Feb 28 23:44 abmisc2.c
-rw-r--r-- 1 djh 8405 Feb 28 23:44 afpavl.c
-rw-r--r-- 1 djh 843 Feb 28 23:44 afpavl.h
-rw-r--r-- 1 djh 26109 Mar 13 20:18 afpdid.c
-rw-r--r-- 1 djh 400 Feb 28 23:44 afpdid.h
-rw-r--r-- 1 djh 9761 Feb 28 23:44 afpdir.c
-rw-r--r-- 1 djh 45300 Mar 13 20:21 afpdt.c
-rw-r--r-- 1 djh 4533 Feb 28 23:44 afpdt.h
-rw-r--r-- 1 djh 7731 Feb 28 23:44 afpfile.c
-rw-r--r-- 1 djh 11102 Mar 14 14:37 afpfork.c
-rw-r--r-- 1 djh 6638 Feb 28 23:44 afpgc.c
-rw-r--r-- 1 djh 1379 Feb 28 23:44 afpgc.h
-rw-r--r-- 1 djh 2252 Feb 28 23:44 afpmisc.c
-rw-r--r-- 1 djh 4341 Feb 28 23:44 afpntoh.h
-rw-r--r-- 1 djh 84426 Mar 13 19:40 afpos.c
-rw-r--r-- 1 djh 23870 Mar 14 16:21 afposenum.c
-rw-r--r-- 1 djh 20664 Feb 28 23:44 afposfi.c
-rw-r--r-- 1 djh 21166 Mar 13 20:29 afposncs.c
-rw-r--r-- 1 djh 936 Feb 28 23:44 afposncs.h
-rw-r--r-- 1 djh 3279 Mar 13 20:29 afppasswd.c
-rw-r--r-- 1 djh 535 Feb 28 23:44 afppasswd.h
-rw-r--r-- 1 djh 7479 Feb 28 23:44 afps.h
-rw-r--r-- 1 djh 20917 Mar 13 20:29 afpserver.c
-rw-r--r-- 1 djh 5111 Feb 28 23:44 afpspd.c
-rw-r--r-- 1 djh 7484 Feb 28 23:44 afpudb.c
-rw-r--r-- 1 djh 577 Feb 28 23:44 afpudb.h
-rw-r--r-- 1 djh 212 Feb 28 23:44 afpvols
-rw-r--r-- 1 djh 13145 Mar 13 20:29 afpvols.c
-rw-r--r-- 1 djh 1206 Feb 28 23:44 afpvols.h
-rw-r--r-- 1 djh 35073 Mar 14 20:00 aufs.c
-rwxr-xr-x 1 djh 16 Mar 13 19:51 aufs_vers
-rw-r--r-- 1 djh 356 Feb 28 23:44 aufs_vers.sh
-rw-r--r-- 1 djh 13042 Mar 14 16:03 aufsicon.c
-rw-r--r-- 1 djh 92 Mar 13 19:54 aufsv.c
-rw-r--r-- 1 djh 21413 Feb 28 23:44 design.notes
-rw-r--r-- 1 djh 5001 Feb 28 23:44 makefile
-rw-r--r-- 1 djh 1672 Mar 14 14:30 sizeserver.c
-rw-r--r-- 1 djh 45 Feb 28 23:44 sizeserver.h
-rw-r--r-- 1 djh 3377 Feb 28 23:44 todo
-rw-r--r-- 1 djh 7564 Feb 28 23:44 user.doc
-rw-r--r-- 1 djh 1171 Feb 28 23:44 whatiswhat
applications/lwsrv:
-rw-r--r-- 1 djh 280 Feb 28 23:44 LWFonts
-rw-r--r-- 1 djh 664 Feb 28 23:44 LWPlusFonts
-rw-r--r-- 1 djh 1995 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 1971 Feb 28 23:44 Makefile.m4
-rw-r--r-- 1 djh 5471 Feb 28 23:44 README
-rw-r--r-- 1 djh 1747 Feb 28 23:44 fontlist.c
-rw-r--r-- 1 djh 717 Feb 28 23:44 fontlist.h
-rw-r--r-- 1 djh 20867 Mar 14 13:42 lwsrv.c
-rw-r--r-- 1 djh 2014 Feb 28 23:44 makefile
-rw-r--r-- 1 djh 3680 Feb 28 23:44 papstream.c
-rw-r--r-- 1 djh 1366 Feb 28 23:44 papstream.h
-rw-r--r-- 1 djh 5500 Feb 28 23:44 procset.c
-rw-r--r-- 1 djh 832 Feb 28 23:44 procset.h
-rw-r--r-- 1 djh 18717 Feb 28 23:44 simple.c
-rw-r--r-- 1 djh 2068 Feb 28 23:44 spmisc.c
-rw-r--r-- 1 djh 711 Feb 28 23:44 spmisc.h
-rw-r--r-- 1 djh 355 Feb 28 23:44 whatiswhat
applications/papif:
-rw-r--r-- 1 djh 1337 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 2108 Feb 28 23:44 Makefile.m4
-rw-r--r-- 1 djh 7842 Feb 28 23:44 README
-rw-r--r-- 1 djh 426 Feb 28 23:44 cap.printers
-rw-r--r-- 1 djh 1355 Feb 28 23:44 makefile
-rw-r--r-- 1 djh 36711 Mar 14 13:52 papif.c
-rw-r--r-- 1 djh 4919 Feb 28 23:44 papof.c
-rw-r--r-- 1 djh 917 Feb 28 23:44 printcap.samp1
-rw-r--r-- 1 djh 469 Feb 28 23:44 printcap.samp2
contrib:
-rw-r--r-- 1 djh 1338 Mar 14 17:59 Makefile
-rw-r--r-- 1 djh 1296 Mar 13 20:42 Makefile.m4
-rw-r--r-- 1 djh 1208 Mar 13 20:44 README
-rwxr-xr-x 1 djh 749 Mar 14 15:59 atprint
-rw-r--r-- 1 djh 7714 Feb 28 23:44 cvt2apple.c
-rw-r--r-- 1 djh 6218 Feb 28 23:45 cvt2cap.c
-rw-r--r-- 1 djh 5200 Feb 28 23:45 lwrename.c
-rw-r--r-- 1 djh 1357 Mar 14 17:59 makefile
-rw-r--r-- 1 djh 38620 Feb 28 23:45 printQDA.hqx
-rw-r--r-- 1 djh 14370 Feb 28 23:45 printqueue.c
-rw-r--r-- 1 djh 12296 Feb 28 23:45 snitch.c
contrib/AsyncATalk:
-rw-r--r-- 1 djh 2087 Feb 28 23:45 INSTALLATION
-rw-r--r-- 1 djh 1181 Feb 28 23:45 Makefile
-rw-r--r-- 1 djh 5238 Feb 28 23:45 README.rfc
-rw-r--r-- 1 djh 30688 Feb 28 23:45 async.1.4.hqx
-rw-r--r-- 1 djh 31083 Feb 28 23:45 async.c
-rw-r--r-- 1 djh 4124 Feb 28 23:45 async.h
-rw-r--r-- 1 djh 3872 Mar 14 14:27 asyncad.c
-rw-r--r-- 1 djh 5323 Feb 28 23:45 atalkdbm.c
-rw-r--r-- 1 djh 1235 Feb 28 23:45 macros.h
contrib/AufsTools:
-rw-r--r-- 1 djh 1912 Feb 28 23:44 MANIFEST
-rw-r--r-- 1 djh 488 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 739 Feb 28 23:44 README
contrib/AufsTools/binhex:
-rw-r--r-- 1 djh 1248 Feb 28 23:44 8to6.c
-rw-r--r-- 1 djh 482 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 4134 Feb 28 23:44 aufs.h
-rw-r--r-- 1 djh 4441 Feb 28 23:44 binhex.c
-rw-r--r-- 1 djh 1488 Feb 28 23:44 crc.c
-rw-r--r-- 1 djh 4043 Feb 28 23:44 gethead.c
-rw-r--r-- 1 djh 1175 Feb 28 23:44 run.c
contrib/AufsTools/capit:
-rw-r--r-- 1 djh 141 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 8924 Feb 28 23:44 capit.c
contrib/AufsTools/man:
-rw-r--r-- 1 djh 526 Feb 28 23:44 binhex.1
-rw-r--r-- 1 djh 499 Feb 28 23:44 capit.1
-rw-r--r-- 1 djh 335 Feb 28 23:44 cleanup.1
-rw-r--r-- 1 djh 400 Feb 28 23:44 drag.1
-rw-r--r-- 1 djh 401 Feb 28 23:44 dup.1
-rw-r--r-- 1 djh 341 Feb 28 23:44 m2u.1
-rw-r--r-- 1 djh 362 Feb 28 23:44 macp.1
-rwxr-xr-x 1 djh 85 Feb 28 23:44 makeman
-rw-r--r-- 1 djh 5991 Feb 28 23:44 mcvert.1
-rw-r--r-- 1 djh 299 Feb 28 23:44 newfolder.1
-rw-r--r-- 1 djh 1006 Feb 28 23:44 sit.1
-rw-r--r-- 1 djh 657 Feb 28 23:44 toaufs.1
-rw-r--r-- 1 djh 348 Feb 28 23:44 trash.1
-rw-r--r-- 1 djh 4233 Feb 28 23:44 unsit.1
-rw-r--r-- 1 djh 2942 Feb 28 23:44 unstuffit.1
contrib/AufsTools/mcvert:
-rw-r--r-- 1 djh 443 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 19992 Feb 28 23:44 hqxify.c
-rw-r--r-- 1 djh 7478 Feb 28 23:44 mactypes.h
-rw-r--r-- 1 djh 13666 Feb 28 23:44 mcvert.c
-rw-r--r-- 1 djh 6606 Feb 28 23:44 unpack.c
contrib/AufsTools/shell:
-rw-r--r-- 1 djh 108 Feb 28 23:44 Makefile
-rwxr-xr-x 1 djh 120 Feb 28 23:44 cleanup
-rwxr-xr-x 1 djh 513 Feb 28 23:44 drag
-rwxr-xr-x 1 djh 513 Feb 28 23:44 dup
-rwxr-xr-x 1 djh 83 Feb 28 23:44 m2u
-rwxr-xr-x 1 djh 55 Feb 28 23:44 macp
-rwxr-xr-x 1 djh 99 Feb 28 23:44 newfolder
-rwxr-xr-x 1 djh 71 Feb 28 23:44 toaufs
-rwxr-xr-x 1 djh 64 Feb 28 23:44 trash
-rwxr-xr-x 1 djh 83 Feb 28 23:44 u2m
contrib/AufsTools/stuffit:
-rw-r--r-- 1 djh 229 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 12353 Feb 28 23:44 sit.c
-rw-r--r-- 1 djh 1834 Feb 28 23:44 sit.h
-rw-r--r-- 1 djh 5848 Feb 28 23:44 updcrc.c
contrib/AufsTools/unstuffit:
-rw-r--r-- 1 djh 364 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 1074 Feb 28 23:44 getopt.c
-rw-r--r-- 1 djh 1871 Feb 28 23:44 stuffit.h
-rw-r--r-- 1 djh 31757 Feb 28 23:44 unsit.c
-rw-r--r-- 1 djh 5848 Feb 28 23:44 updcrc.c
contrib/MacPS:
-rw-r--r-- 1 djh 3485 Feb 28 23:45 Installation
-rw-r--r-- 1 djh 1119 Feb 28 23:45 Makefile
-rw-r--r-- 1 djh 4682 Feb 28 23:45 ReadMe
-rw-r--r-- 1 djh 3585 Feb 28 23:45 macaux.c
-rw-r--r-- 1 djh 1949 Feb 28 23:45 macps-22.hdr
-rw-r--r-- 1 djh 36921 Feb 28 23:45 macps-22.shar
-rw-r--r-- 1 djh 2592 Feb 28 23:45 macps.1
-rw-r--r-- 1 djh 5053 Feb 28 23:45 macps.c
-rw-r--r-- 1 djh 536 Feb 28 23:45 macps.config
-rw-r--r-- 1 djh 2100 Feb 28 23:45 prepfix.1
-rw-r--r-- 1 djh 5999 Feb 28 23:45 prepfix.c
-rw-r--r-- 1 djh 1160 Feb 28 23:45 str.h
-rw-r--r-- 1 djh 3273 Feb 28 23:45 ucbwhich.c
-rw-r--r-- 1 djh 778 Feb 28 23:45 ucbwhich.h
contrib/Messages:
-rw-r--r-- 1 djh 918 Mar 14 17:27 Makefile
-rw-r--r-- 1 djh 3067 Mar 14 17:27 README
-rw-r--r-- 1 djh 41 Feb 28 23:45 dot.forward
-rw-r--r-- 1 djh 2056 Feb 28 23:45 macto.1l
-rw-r--r-- 1 djh 1872 Feb 28 23:45 macuser.1l
-rw-r--r-- 1 djh 8122 Mar 14 14:21 macuser.c
-rw-r--r-- 1 djh 1068 Feb 28 23:45 macwho.1l
-rw-r--r-- 1 djh 1835 Mar 14 14:23 macwho.c
-rw-r--r-- 1 djh 4676 Mar 14 14:22 messages.c
-rw-r--r-- 1 djh 35239 Mar 14 19:27 messages.hqx
-rw-r--r-- 1 djh 6556 Mar 14 14:24 notify.c
-rw-r--r-- 1 djh 1671 Mar 14 14:25 notify.h
contrib/Timelord:
-rw-r--r-- 1 djh 214 Mar 14 17:30 Makefile
-rw-r--r-- 1 djh 18399 Feb 28 23:45 tardis.hqx
-rw-r--r-- 1 djh 951 Feb 28 23:45 timelord.1l
-rw-r--r-- 1 djh 7478 Mar 14 14:26 timelord.c
-rw-r--r-- 1 djh 471 Feb 28 23:45 timelord.h
doc:
-rw-r--r-- 1 djh 107 Mar 14 16:10 Makefile
-rw-r--r-- 1 djh 516 Mar 14 16:09 README
-rw-r--r-- 1 djh 3633 Feb 28 23:42 abmisc.doc
-rw-r--r-- 1 djh 4824 Feb 28 23:42 asp.notes
-rw-r--r-- 1 djh 2163 Feb 28 23:42 atp.notes
-r--r--r-- 1 djh 1097 Mar 14 14:39 cap.auth.doc
-rw-r--r-- 1 djh 3742 Feb 28 23:42 cap.notes
-rw-r--r-- 1 djh 11245 Mar 14 16:13 install.ms
-rw-r--r-- 1 djh 10507 Feb 28 23:42 nbp.ext
-rw-r--r-- 1 djh 2741 Feb 28 23:42 pap.notes
-rw-r--r-- 1 djh 8214 Feb 28 23:42 sched.notes
-rw-r--r-- 1 djh 8069 Feb 28 23:42 uab.desc.ms
etc:
-rw-r--r-- 1 djh 921 Feb 28 23:43 Makefile
-rw-r--r-- 1 djh 941 Feb 28 23:43 Makefile.m4
-rw-r--r-- 1 djh 400 Feb 28 23:43 README
-rw-r--r-- 1 djh 902 Feb 28 23:43 atalk.local
-rw-r--r-- 1 djh 27084 Mar 13 19:48 atis.c
-rw-r--r-- 1 djh 517 Feb 28 23:43 etalk.local
-rw-r--r-- 1 djh 939 Feb 28 23:43 makefile
-rw-r--r-- 1 djh 9281 Mar 13 19:50 nisaux.c
-rw-r--r-- 1 djh 673 Feb 28 23:43 start-cap-servers
extras:
-rw-r--r-- 1 djh 506 Feb 28 23:43 Makefile
-rw-r--r-- 1 djh 440 Feb 28 23:43 Makefile.m4
-rw-r--r-- 1 djh 324 Mar 14 17:36 README
-rw-r--r-- 1 djh 3666 Feb 28 23:43 att_getopt.c
-rw-r--r-- 1 djh 13301 Feb 28 23:43 des.c
-rw-r--r-- 1 djh 1258 Feb 28 23:43 dummy.des.c
-rw-r--r-- 1 djh 2241 Feb 28 23:43 iwif.c
-rw-r--r-- 1 djh 926 Feb 28 23:44 lnof.c
-rw-r--r-- 1 djh 525 Feb 28 23:44 makefile
-rw-r--r-- 1 djh 249 Feb 28 23:44 printcap.iw
lib:
-rw-r--r-- 1 djh 506 Feb 28 23:42 Makefile
-rw-r--r-- 1 djh 480 Feb 28 23:43 Makefile.m4
-rw-r--r-- 1 djh 499 Feb 28 23:43 makefile
lib/afp:
-rw-r--r-- 1 djh 1374 Feb 28 23:43 Makefile
-rw-r--r-- 1 djh 1420 Feb 28 23:43 Makefile.m4
-rw-r--r-- 1 djh 188 Feb 28 23:43 README
-rw-r--r-- 1 djh 13894 Feb 28 23:43 afpcmd.c
-rw-r--r-- 1 djh 2356 Feb 28 23:43 afperr.c
-rw-r--r-- 1 djh 9202 Mar 13 19:44 afposlock.c
-rw-r--r-- 1 djh 23206 Feb 28 23:43 afppacks.c
-rw-r--r-- 1 djh 1384 Feb 28 23:43 makefile
lib/afpc:
-rw-r--r-- 1 djh 748 Feb 28 23:43 Makefile
-rw-r--r-- 1 djh 798 Feb 28 23:43 Makefile.m4
-rw-r--r-- 1 djh 968 Feb 28 23:43 README
-rw-r--r-- 1 djh 19432 Mar 14 14:36 afpc.c
-rw-r--r-- 1 djh 24803 Feb 28 23:43 afpc.mss
-rw-r--r-- 1 djh 17132 Feb 28 23:43 afpcc.c
-rw-r--r-- 1 djh 767 Feb 28 23:43 makefile
-rw-r--r-- 1 djh 1405 Feb 28 23:43 probs
lib/cap:
-rw-r--r-- 1 djh 2731 Mar 14 18:32 Makefile
-rw-r--r-- 1 djh 2810 Mar 14 14:01 Makefile.m4
-rw-r--r-- 1 djh 60621 Mar 14 13:47 abasp.c
-rw-r--r-- 1 djh 3941 Feb 28 23:42 abasp.h
-rw-r--r-- 1 djh 33717 Feb 28 23:42 abatp.c
-rw-r--r-- 1 djh 2721 Feb 28 23:42 abatp.h
-rw-r--r-- 1 djh 13024 Feb 28 23:42 abauxddp.c
-rw-r--r-- 1 djh 14591 Feb 28 23:42 abauxnbp.c
-rw-r--r-- 1 djh 11505 Mar 14 14:35 abddp.c
-rw-r--r-- 1 djh 16059 Feb 28 23:42 abkip.c
-rw-r--r-- 1 djh 3846 Feb 28 23:42 ablap.c
-rw-r--r-- 1 djh 3712 Mar 13 20:16 ablog.c
-rw-r--r-- 1 djh 7955 Mar 14 14:29 abmisc.c
-rw-r--r-- 1 djh 20150 Mar 13 20:00 abnbp.c
-rw-r--r-- 1 djh 10688 Feb 28 23:42 abnet.c
-rw-r--r-- 1 djh 23370 Feb 28 23:42 abpap.c
-rw-r--r-- 1 djh 4393 Feb 28 23:42 abpap.h
-rw-r--r-- 1 djh 6863 Feb 28 23:42 abpapc.c
-rw-r--r-- 1 djh 15404 Feb 28 23:42 abpaps.c
-rw-r--r-- 1 djh 2294 Feb 28 23:42 abpp.c
-rw-r--r-- 1 djh 5975 Feb 28 23:42 abqueue.c
-rw-r--r-- 1 djh 22880 Feb 28 23:42 absched.c
-rw-r--r-- 1 djh 1067 Feb 28 23:43 abversion.c
-rw-r--r-- 1 djh 4029 Feb 28 23:43 abzip.c
-rw-r--r-- 1 djh 13844 Mar 15 14:56 atalkdbm.c
-rw-r--r-- 1 djh 478 Feb 28 23:43 atalkdbm.h
-rw-r--r-- 1 djh 8881 Feb 28 23:43 authenticate.c
-rw-r--r-- 1 djh 1201 Feb 28 23:43 cap_conf.h
-rw-r--r-- 1 djh 2736 Mar 14 18:32 makefile
-rw-r--r-- 1 djh 392 Feb 28 23:43 todist
-rw-r--r-- 1 djh 929 Feb 28 23:43 whatiswhat
lib/xenix:
-rw-r--r-- 1 djh 773 Feb 28 23:43 Makefile
-rw-r--r-- 1 djh 302 Feb 28 23:43 fsync.c
-rw-r--r-- 1 djh 1347 Feb 28 23:43 ftruncate.c
-rw-r--r-- 1 djh 585 Feb 28 23:43 groups.c
-rw-r--r-- 1 djh 1791 Feb 28 23:43 rename.c
-rw-r--r-- 1 djh 3196 Feb 28 23:43 scandir.c
man:
-rw-r--r-- 1 djh 16823 Feb 28 23:42 AUFS.1
-rw-r--r-- 1 djh 8483 Feb 28 23:42 AUFS.8
-rw-r--r-- 1 djh 2228 Feb 28 23:42 CAP.3
-rw-r--r-- 1 djh 5237 Mar 13 20:45 CAP.8
-rw-r--r-- 1 djh 6129 Feb 28 23:42 UAB.8
-rw-r--r-- 1 djh 3301 Feb 28 23:42 ash.1
-rw-r--r-- 1 djh 5971 Mar 13 20:47 atalk.local.5
-rw-r--r-- 1 djh 3869 Feb 28 23:42 atis.8
-rw-r--r-- 1 djh 3059 Feb 28 23:42 atlook.1
-rw-r--r-- 1 djh 3329 Feb 28 23:42 atprint.1
-rw-r--r-- 1 djh 2080 Feb 28 23:42 cvt2apple.1
-rw-r--r-- 1 djh 1516 Mar 15 00:50 etalk.local.5
-rw-r--r-- 1 djh 557 Feb 28 23:42 getzones.1
-rw-r--r-- 1 djh 2541 Feb 28 23:42 instappl.1
-rw-r--r-- 1 djh 8346 Feb 28 23:42 lwsrv.8
-rw-r--r-- 1 djh 1020 Feb 28 23:42 makefile
-rw-r--r-- 1 djh 13770 Feb 28 23:42 papif.8
-rw-r--r-- 1 djh 3455 Feb 28 23:42 snitch.1
netat:
-rw-r--r-- 1 djh 216 Feb 28 23:43 Makefile
-rw-r--r-- 1 djh 2571 Feb 28 23:43 aberrors.h
-rw-r--r-- 1 djh 3024 Feb 28 23:43 abnbp.h
-rw-r--r-- 1 djh 640 Feb 28 23:43 abqueue.h
-rw-r--r-- 1 djh 10274 Feb 28 23:43 afp.h
-rw-r--r-- 1 djh 482 Feb 28 23:43 afpc.h
-rw-r--r-- 1 djh 20501 Feb 28 23:43 afpcmd.h
-rw-r--r-- 1 djh 13515 Feb 28 23:43 appletalk.h
-rw-r--r-- 1 djh 1779 Feb 28 23:43 compat.h
-rw-r--r-- 1 djh 3533 Feb 28 23:43 macfile.h
-rw-r--r-- 1 djh 3550 Feb 28 23:43 sysvcompat.h
patches:
-rw-r--r-- 1 djh 512 Mar 14 17:50 README
-rw-r--r-- 1 djh 2345 Feb 28 23:45 abpap.c.tickletimer
-rw-r--r-- 1 djh 2010 Feb 28 23:45 abpaps.c.flowquantum
-rw-r--r-- 1 djh 1594 Feb 28 23:45 afpos.c.strcmp
-rw-r--r-- 1 djh 1787 Feb 28 23:45 mips.ultrix.byteswap
-rw-r--r-- 1 djh 2352 Feb 28 23:45 papif.c.atpresponse
-rw-r--r-- 1 djh 2565 Feb 28 23:45 papif.c.reverse
-rw-r--r-- 1 djh 4528 Feb 28 23:45 papif.c.variousbugs
-rw-r--r-- 1 djh 3045 Feb 28 23:45 procset.c.looping
-rw-r--r-- 1 djh 2699 Mar 14 23:27 rtmp.c.nocase
-rw-r--r-- 1 djh 2414 Feb 28 23:45 simple.c.comments
-rw-r--r-- 1 djh 2117 Feb 28 23:45 snitch.c.stringlength
patches/AUX.NATIVE:
-rw-r--r-- 1 djh 14519 Feb 28 23:45 cap.for.aux.2
-rw-r--r-- 1 djh 29478 Feb 28 23:45 cap.for.aux.2-2
patches/BUGS.orig:
-rw-r--r-- 1 djh 3701 Feb 28 23:45 cap5.0-patch00001
-rw-r--r-- 1 djh 4401 Feb 28 23:45 cap5.0-patch00002
-rw-r--r-- 1 djh 2806 Feb 28 23:45 cap5.0-patch00003
-rw-r--r-- 1 djh 1369 Feb 28 23:45 cap5.0-patch00004
-rw-r--r-- 1 djh 622 Feb 28 23:45 cap5.0-patch00005
-rw-r--r-- 1 djh 803 Feb 28 23:45 cap5.0-patch00006
-rw-r--r-- 1 djh 2959 Feb 28 23:45 cap5.0-report0001
-rw-r--r-- 1 djh 3773 Feb 28 23:45 cap5.0-report0002
-rw-r--r-- 1 djh 3604 Feb 28 23:45 cap5.0-report0003
-rw-r--r-- 1 djh 1509 Feb 28 23:45 cap5.0-report0004
-rw-r--r-- 1 djh 865 Feb 28 23:45 cap5.0-report0005
-rw-r--r-- 1 djh 919 Feb 28 23:45 cap5.0-report0006
patches/Dan@lth.se:
-rw-r--r-- 1 djh 1588 Feb 28 23:45 README
-rw-r--r-- 1 djh 479 Feb 28 23:45 README.FIRST
-rw-r--r-- 1 djh 5074 Feb 28 23:45 afpspd.c
-rw-r--r-- 1 djh 14907 Feb 28 23:45 stat.cache.patches
-rw-r--r-- 1 djh 1686 Feb 28 23:45 trel.README
-rw-r--r-- 1 djh 5421 Feb 28 23:45 trel.patches
patches/Moy@Berkeley:
-rw-r--r-- 1 djh 2258 Feb 28 23:45 Configure.diff
-rw-r--r-- 1 djh 1327 Feb 28 23:45 README
-rw-r--r-- 1 djh 2206 Feb 28 23:45 abasp.c.diff
-rw-r--r-- 1 djh 448 Feb 28 23:45 abatp.c.diff
-rw-r--r-- 1 djh 710 Feb 28 23:45 abkip.c.diff
-rw-r--r-- 1 djh 1428 Feb 28 23:45 afpc.c.diff
-rw-r--r-- 1 djh 3235 Feb 28 23:45 afpcmd.h.diff
-rw-r--r-- 1 djh 1305 Feb 28 23:45 afpdid.c.diff
-rw-r--r-- 1 djh 459 Feb 28 23:45 afpdir.c.diff
-rw-r--r-- 1 djh 391 Feb 28 23:45 afpdt.c.diff
-rw-r--r-- 1 djh 41043 Feb 28 23:45 afpos.c.diff
-rw-r--r-- 1 djh 7261 Feb 28 23:45 afposenum.c.diff
-rw-r--r-- 1 djh 6644 Feb 28 23:45 afposfi.c.diff
-rw-r--r-- 1 djh 895 Feb 28 23:45 afps.h.diff
-rw-r--r-- 1 djh 460 Feb 28 23:45 afpserver.c.diff
-rw-r--r-- 1 djh 557 Feb 28 23:45 atalkdbm.c.diff
-rw-r--r-- 1 djh 2688 Feb 28 23:45 atis.c.diff
-rw-r--r-- 1 djh 470 Feb 28 23:45 papof.c.diff
-rw-r--r-- 1 djh 7955 Feb 28 23:45 sizeserver.shar
patches/PC.aufs:
-rw-r--r-- 1 djh 2075 Feb 28 23:45 README
-rw-r--r-- 1 djh 2174 Feb 28 23:45 README.orig
-rw-r--r-- 1 djh 1644 Feb 28 23:45 afp.h.diffs
-rw-r--r-- 1 djh 7480 Feb 28 23:45 afpdid.c.diffs
-rw-r--r-- 1 djh 1161 Feb 28 23:45 afpdir.c.diffs
-rw-r--r-- 1 djh 1675 Feb 28 23:45 afpfile.c.diffs
-rw-r--r-- 1 djh 613 Feb 28 23:45 afpfork.c.diffs
-rw-r--r-- 1 djh 2409 Feb 28 23:45 afpos.c.diffs
-rw-r--r-- 1 djh 8229 Feb 28 23:45 afposenum.c.diffs
-rw-r--r-- 1 djh 1252 Feb 28 23:45 afposfi.c.diffs
-rw-r--r-- 1 djh 2681 Feb 28 23:45 afposncs.c.diffs
-rw-r--r-- 1 djh 1389 Feb 28 23:45 afpserver.c.diffs
-rw-r--r-- 1 djh 1420 Feb 28 23:45 afpvols.c.diffs
patches/Rutgers:
-rw-r--r-- 1 djh 1826 Feb 28 23:45 README
-rw-r--r-- 1 djh 14645 Feb 28 23:45 afpos.c.diffs
-rw-r--r-- 1 djh 14589 Feb 28 23:45 aufs-lwsrv-mods
-rw-r--r-- 1 djh 6787 Feb 28 23:45 lwsrv.c.diffs
patches/XENIX:
-rw-r--r-- 1 djh 11503 Feb 28 23:45 file.1
-rw-r--r-- 1 djh 12009 Feb 28 23:45 file.2
-rw-r--r-- 1 djh 35225 Feb 28 23:45 file.3
samples:
-rw-r--r-- 1 djh 2465 Feb 28 23:44 Makefile
-rw-r--r-- 1 djh 2508 Feb 28 23:44 Makefile.m4
-rw-r--r-- 1 djh 1421 Feb 28 23:44 README
-rw-r--r-- 1 djh 22919 Feb 28 23:44 ash.c
-rw-r--r-- 1 djh 2593 Feb 28 23:44 atistest.c
-rw-r--r-- 1 djh 14500 Mar 14 13:59 atlook.c
-rw-r--r-- 1 djh 1654 Feb 28 23:44 getzones.c
-rw-r--r-- 1 djh 4043 Feb 28 23:44 instappl.c
-rw-r--r-- 1 djh 5081 Mar 14 14:38 isrv.c
-rw-r--r-- 1 djh 10624 Feb 28 23:44 look.c
-rw-r--r-- 1 djh 7246 Feb 28 23:44 lwpr.c
-rw-r--r-- 1 djh 2484 Feb 28 23:44 makefile
-rw-r--r-- 1 djh 7386 Mar 15 00:53 ruiwpr.c
-rw-r--r-- 1 djh 5801 Feb 28 23:44 tlw.c
support/enet:
-rw-r--r-- 1 djh 6454 Feb 28 23:46 README
-rw-r--r-- 1 djh 21000 Feb 28 23:46 enet.4
-rw-r--r-- 1 djh 45628 Feb 28 23:46 enet.c
-rw-r--r-- 1 djh 6108 Feb 28 23:46 enet.h
-rw-r--r-- 1 djh 7613 Feb 28 23:46 enetdefs.h
-rw-r--r-- 1 djh 23 Feb 28 23:46 enetfilter.h
-rw-r--r-- 1 djh 1185 Feb 28 23:46 etherstat.8
-rw-r--r-- 1 djh 9976 Feb 28 23:46 etherstat.c
support/ethertalk:
-rw-r--r-- 1 djh 829 Feb 28 23:46 Makefile
-rw-r--r-- 1 djh 1527 Mar 13 20:06 Makefile.m4
-rw-r--r-- 1 djh 2599 Mar 15 15:12 README
-rw-r--r-- 1 djh 422 Feb 28 23:46 STILL_TO_DO
-rw-r--r-- 1 djh 7033 Mar 13 19:34 aarpd.c
-rw-r--r-- 1 djh 267 Feb 28 23:46 aarpd.h
-rw-r--r-- 1 djh 201 Feb 28 23:46 aarpd.x
-rw-r--r-- 1 djh 1351 Mar 14 14:32 aarpd_clnt.c
-rw-r--r-- 1 djh 1565 Mar 14 14:32 aarpd_svc.c
-rw-r--r-- 1 djh 474 Mar 14 14:33 aarpd_xdr.c
-rw-r--r-- 1 djh 1474 Mar 13 20:12 aarptest.c
-rw-r--r-- 1 djh 20676 Mar 13 20:10 abelap.c
-rw-r--r-- 1 djh 6867 Feb 28 23:46 dlip.c
-rw-r--r-- 1 djh 10526 Mar 14 20:06 ethertalk.c
-rw-r--r-- 1 djh 1470 Feb 28 23:46 makefile
-rw-r--r-- 1 djh 1749 Mar 13 20:13 rtmptest.c
-rw-r--r-- 1 djh 10810 Mar 13 20:15 senetp.c
-rw-r--r-- 1 djh 10134 Feb 28 23:46 snitp.c
support/uab:
-rw-r--r-- 1 djh 1374 Feb 28 23:45 Makefile.m4
-rw-r--r-- 1 djh 1420 Feb 28 23:45 README
-rw-r--r-- 1 djh 241 Feb 28 23:45 STILL_TO_DO
-rw-r--r-- 1 djh 26462 Mar 13 20:08 aarp.c
-rw-r--r-- 1 djh 1880 Feb 28 23:45 aarp.h
-rw-r--r-- 1 djh 3727 Feb 28 23:45 aarp_defs.h
-rw-r--r-- 1 djh 13436 Mar 13 20:38 asyncatalk.c
-rw-r--r-- 1 djh 4171 Feb 28 23:45 bridge_desc
-rw-r--r-- 1 djh 6448 Mar 13 20:38 ddpport.c
-rw-r--r-- 1 djh 4223 Feb 28 23:45 ddpport.h
-rw-r--r-- 1 djh 14131 Feb 28 23:45 ddprouter.c
-rw-r--r-- 1 djh 6971 Mar 13 20:39 ddpsvcs.c
-rw-r--r-- 1 djh 6212 Feb 28 23:45 dlip.c
-rw-r--r-- 1 djh 12707 Mar 13 20:39 ethertalk.c
-rw-r--r-- 1 djh 1012 Feb 28 23:45 ethertalk.h
-rw-r--r-- 1 djh 2563 Feb 28 23:45 gw.h
-rw-r--r-- 1 djh 17620 Feb 28 23:45 hash.3
-rw-r--r-- 1 djh 21202 Feb 28 23:45 hash.c
-rw-r--r-- 1 djh 4509 Feb 28 23:45 hash.h
-rw-r--r-- 1 djh 1927 Feb 28 23:45 if_desc.h
-rw-r--r-- 1 djh 12116 Mar 13 20:39 kip_mpx.c
-rw-r--r-- 1 djh 3579 Mar 13 20:38 log.c
-rw-r--r-- 1 djh 945 Feb 28 23:45 log.h
-rw-r--r-- 1 djh 1440 Feb 28 23:45 makefile
-rw-r--r-- 1 djh 2210 Feb 28 23:45 mpxddp.h
-rw-r--r-- 1 djh 1324 Feb 28 23:45 node.h
-rw-r--r-- 1 djh 2206 Feb 28 23:45 proto_intf.h
-rw-r--r-- 1 djh 35153 Mar 14 20:26 rtmp.c
-rw-r--r-- 1 djh 8127 Feb 28 23:45 senetp.c
-rw-r--r-- 1 djh 8529 Feb 28 23:45 snitp.c
-rw-r--r-- 1 djh 21040 Mar 13 20:37 uab.c
-rw-r--r-- 1 djh 969 Feb 28 23:46 whatiswhat
support/uab/patches:
-rw-r--r-- 1 djh 4930 Feb 28 23:45 bug.1
-rw-r--r-- 1 djh 1494 Feb 28 23:45 bug.2
-rw-r--r-- 1 djh 718 Feb 28 23:45 bug.3

73
MODIFICATIONS Normal file
View File

@ -0,0 +1,73 @@
The following is an (incomplete) list of the modifications from CAP
Distribution 5 to CAP Distribution 6.
* Many patches for extra functionality have been incorporated.
* Subdirectory 'support' has been added for alternate LAPs.
* UAB is now bundled with this CAP distribution (support/uab).
* 'Configure' will recognize the host byte ordering.
* 'Configure' handles a wider range of machine types.
* AUFS support for AFP 2.0 is (practically) complete.
* UAB now supports Asynchronous AppleTalk on a UNIX host.
* The format of 'atalk.local' has been extended for async appletalk.
* Zone names in 'atalk.local' MUST now be quoted to include spaces.
* A "free format" 'etalk.local' is used by EtherTalk LAPs.
* atis is now Phase 2 NBP compatible (obj/type partial matching).
The following is an (incomplete) list of the modifications from CAP
Distribution 4 to CAP Distribution 5.
The general change are:
o various directories have been reorganized. The major ones are:
doc - documentation, man - manual pages, samples - sample
programs, applications - heavily used programs (at Columbia),
lib - libraries, and etc - support programs.
o While a generic Makefile is included, an "os specific" makefile
generation facility is included and should now be used.
We do not list bug fixes below, only major changes in functionality.
In samples, the various programs now use a define to find cap.printers
allowing it to be relocated from etc. In addition, look has been
revised to make its operation easier and renamed to atlook to prevent
naming conflicts (looks => atlooklws, and pinger => atpinger)
applications/lwsrv
lwsrv rewritten. The major change is that it now stores prep
files in a directory and automatically captures unknown ones.
applications/papif
essentially rewritten
supports psrev, pstext now
pscomm compatible now
applications/aufs
user data base of icon types added
normalizing character set for different types of ascii
clean up of kbox too slow code
new desktop format
new finderinfo format
aux support
sun quota fixed
.afpvols used if no afpvols
shutdown code from Scooter Morris added.
lib/cap
allow modifcation of response cache timeout in atp
pap fix for cleaning up outstanding papwrites
fix problem with timeouts in abmisc
print nis node
fix up asp to match up specifiable values better
rework abnet.c,abddp.c,abmisc.c so that they "layer" better
abnet moved into abkip.c and absched.c
parts of abmisc.c moved to absched.c
abddp had KIP (udp) encapsulation dependencies removed
or hidden
absched now "schedules" protocol events
abkip now holds all code for KIP (udp) encapsulation
lib/afp
fix afposlock up for nfs systems w/o lock daemon
lib/afpc
clean up

94
Makefile Normal file
View File

@ -0,0 +1,94 @@
all:
@echo "You didn't read NOTES and doc/install.ms did you?"
@echo
@echo "First two steps are: Configure and gen.makes"
include: .
(cd netat; make install)
libsmade:
(cd lib/cap; make)
(cd lib/afp; make)
(cd lib/afpc; make)
touch libsmade
libinstall: libsmade
(cd lib/cap; make install)
(cd lib/afp; make install)
(cd lib/afpc; make install)
touch libinstall
programs: libinstall
-(cd etc; make)
-(cd samples; make)
-(cd contrib; make)
-(cd applications; make)
-(cd support/uab; make)
-(cd support/capd; make)
-(cd support/ethertalk; make)
touch programs
install: libinstall programs
-(cd etc; make install)
-(cd samples; make install)
-(cd contrib; make install)
-(cd applications; make install)
-(cd support/uab; make install)
-(cd support/capd; make install)
-(cd support/ethertalk; make install)
cap.shar: listtodist
cap.dist shar
cap.tar: listtodist
cap.dist tar
dist:
@cat todist
@(cd netat; make dist)
@(cd lib; make dist)
@(cd etc; make dist)
@(cd samples; make dist)
@(cd contrib; make dist)
@(cd extras; make dist)
@(cd doc; make dist)
@(cd man; make dist)
@(cd applications; make dist)
clean:
-rm -f m4.tmp
-rm -f libsmade
-rm -f programs
-rm -f libinstall
-(cd netat; make clean)
-(cd man; make clean)
-(cd doc; make clean)
-(cd lib; make clean)
-(cd etc; make clean)
-(cd samples; make clean)
-(cd contrib; make clean)
-(cd extras; make clean)
-(cd applications; make clean)
-(cd support/uab; make clean)
-(cd support/capd; make clean)
-(cd support/ethertalk; make clean)
spotless:
-rm -f *.orig
-rm -f m4.tmp
-rm -f libsmade
-rm -f programs
-rm -f libinstall
-(cd netat; make spotless)
-(cd man; make spotless)
-(cd doc; make spotless)
-(cd lib; make spotless)
-(cd etc; make spotless)
-(cd samples; make spotless)
-(cd contrib; make spotless)
-(cd extras; make spotless)
-(cd applications; make spotless)
-(cd support/uab; make spotless)
-(cd support/capd; make spotless)
-(cd support/ethertalk; make spotless)

231
NOTES Normal file
View File

@ -0,0 +1,231 @@
CAP Installation notes
The Columbia University Appletalk Package is actually a rather broad
collection of libraries and programs. Following are some guidelines
in building the various programs and libraries.
Following are notes about the various components of CAP that require
special attention during installation or porting. Hopefully, we've
caught most of the major points, but there may be things missing.
Index:
CONFIGURATION
INSTALLATION
MACHINE SPECIFIC
LIBRARIES
SAMPLE PROGRAMS
CONTRIB
APPLICATIONS
*************
CONFIGURATION
*************
Configuration is somewhat automated. The configuration parameters are
divided into features and major and minor parameters. The major parameters
must be set to compile properly. The minor parameters are for
configuration of programs, etc.
To start off, you can run the "Configure" shell script to configure
the main parameters. One of the options in Configure allows you to edit
a file called 'm4.features'. This file is used to specify which of a set
of alternate features are included. For more details about the features,
see the README files in the patches subdirectories. Configure creates a
file called m4.setup. If necessary, you should then modify the secondary
(minor) parameters in this file.
Makefiles are generated from templates. m4.setup and m4.features define
variables used in the template. The command gen.makes builds the Makefiles.
Makefiles are included in all directories (Makefile) configured for
a standard BSD system. (Major configuration: bsd, no fastether,
needgetopt, no quotas). gen.makes creates "makefile" which should
be used in preference to "Makefile" on most machines.
Make sure you read "MACHINE SPECIFIC"! It points out os/machine
dependencies that are not handled by Configure.
************
DESTINATIONS
************
Or where do the files go? Generally, the defaults are:
/usr/local/cap - general programs
/usr/local/lib/cap - programs not for general use, data files
/usr/local/lib - libraries
/etc - some configuration files
Certainly machines do not search /usr/local/lib by default.
In these cases, the libraries are place in /usr/lib.
You should be modifying these in m4.setup.
************
INSTALLATION
************
A detailed procedure with testing mechanisms is defined in
doc/install.ms (a formatted copy is doc/install.doc).
However, you should peruse this document first.
****************
MACHINE SPECIFIC
****************
The current CAP distribution should work on:
BSD 4.2
BSD 4.3
Ultrix 1.0, 1.1, 1.2, 2.0 and hopefully 2.2
Sun OS 3.2 or higher
Pyramid's Unix under the BSD universe
ACIS 4.2 or 4.3 for the IBM RT PC
A/UX (using native AppleTalk with 2.0)
HP-UX for the series 9000 (release 6.0)
Encore (Multimax) (version unknown)
IRIS/IRIX for Silicon Graphics
AIX for the IBM 6000
and the majority should work under:
Convex Unix V6.1
and most should work with some manual work under:
HP-UX - release before 6.0
However, it should be noted that the baseline development system is
Ultrix 2.0 and things are tuned for that environment.
If your machine isn't listed, take a close look at the document
"PORTING" for things to watch out for.
On the pyramid, everything is compiled with the "-q" option to be
safe. "-q" tells it to pack the structures, possibly at the expense
of speed. SEE LOCKF below.
On the Encore Multimax, there are reports that the optimizer may be
overzealous. It may be wise to compile without optimization (or try
recompiling without optimization if there are problems).
On HP-UX, if you have an old release, you will have to define
"NEEDMSGHDR" in caposdefs in m4.setup as output by Configure. (You
can do it lib/cap/makefile, but that is not recommended).
On MORE/BSD, getgroups may return an array of gid_t instead of type
int. If this happens to be the case, you should edit aufsosdefs in
m4.setup and add:
-DGGTYPE="gid_t"
ALSO SEE LOCKF BELOW.
LOCKF - You should be careful here. Lockf is known to work properly
under Ultrix and A/UX. It should work okay under SunOS. There have
been reports of problems with lockf under Pyramid OSx and MORE/BSD.
If it is truly broken then you should comment out the "lockf in
system" in m4.setup. In other words, find the line:
define([X_LOCKF],1)
and put a "#" in front of it. If you do this and have already
compiled, then you should regenerate your makefiles with gen.makes,
regenerate libafp (lib/afp) making sure you recompile afposlock and
relink any programs that use libafp (currently samples/ash and
applications/aufs). Note that some systems may require a special
daemon for lockf to function (e.g. locking down outside the kernel).
Another problem may simply be the number of allowable locks in the
system.
Paul Campbell reports that AUX 1.0 goes to the disk for every call to
gettimeofday to validate the TZ information. In absched, a larger
number of gettimeofday calls are done that do not require TZ
information (even if they did require this information there are
better ways of doing things than going to disk on every call). To get
around this, the cap library LOCALTIME_GTOD says to call the function
_gettimeofday to grab the time only. This is noted here because
future versions of aux will probably require slightly different
handling.
On HP/Apollo Domain OS, CAP builds under the BSD 4.3 environment,
for Domain OS version 10.4. The main applications (aufs and
papif tested, lwsrv not tested) work on both 68K and 88K/PRISM
machines. The Domain OS syntax //node/path must be avoided in the
afpvol file. Note that this may result from the expansion of ~ if
home directories are defined using the full network syntax. The
problem is purely one of syntax, directories on other nodes may be
mounted using soft links or alternative syntax such as /../node/path.
You may want to modify the aufs man page to communicate this.
[Note: it is better for aufs (and other Unix software) if home
directories are defined without reference to //node and soft links
used between different nodes, so that ~ will never expand to the
unusual Apollo syntax.] Both flock, lockf and (if either the
APPLICATION_MANAGER or DENYREADWRITE options are chosen, see
netat/fcntldomv.h) undocumented fcntl range locking is used. Since
the underlying Domain file system handles locking, one hopes this
may all work -- but, from restrictions in the Domain file sytem,
perhaps not as well on files on remote nodes. If you primarily use
the System V environment but installed the BSD 4.3 environment, you
could probably build aufs, at least, under the BSD environment and
use it under System V.
*********
LIBRARIES
*********
There are three sets of libraries. The first is the core Appletalk
libraries. The second is the generic AFP libraries. The third is the
AFP client libraries. In the following we discuss some of the points
you should be aware of when building these.
CAP LIBRARIES
-------------
The core of CAP is the Appletalk libraries.
The major configuration parameter is for atalkdbm.c and tells it where
to find the atalk.local file. By default, it assumes
/etc/atalk.local, but can be reconfigured in m4.setup.
cap_conf.h contains a set of configuration parameters that defined
standard timeouts, etc, for protocols. At present, it only contains
parameters for PAP. You shouldn't need to touch this file.
AFP Libraries
-------------
o locking
The two defines for locking are "NOLOCKF" and "NOFLOCK" that should be
set appropriately for your machine. Most BSD systems should have
flock available. The only program that uses these calls is Aufs. For
the implications of what happens when you do or don't have these, see
the documentation on the various client and server (Aufs) programs.
In particular, see applications/aufs/INSTALLATION.
AFP Client Libraries
--------------------
You should be able to build afpc without any configuration changes.
***************
SAMPLE PROGRAMS
***************
You should be able to get away without modifying the default
compilation parameters. See samples/README for futher information.
***********
CONTRIBUTED
***********
See contrib/README for further information.
************
APPLICATIONS
************
See the README files in the various directories for further
information about configuration of these programs.
It is highly recommended that you look at the default configuration
for Aufs. This holds in particular if you are not running a virgin
BSD4.3 or BSD 4.2 system (have NFS added, etc): there is a good chance
you can configure parameters in that will result in better performance
and/or more functionality.

38
NOTICE Normal file
View File

@ -0,0 +1,38 @@
NOTICE
The Columbia AppleTalk Package for UNIX, referred to as CAP
and which consists of files in the enclosed MANIFEST, is Copyright
1986, 1987, and 1988 by the Trustees of Columbia University in the
City of New York. CAP is provided with certain restrictions as
outlined below.
COPYRIGHT NOTICE
Copyright (c) 1986, 1987, 1988, The Trustees of Columbia University in the
City of New York. Charlie C. Kim, User Services Group, Academic
Information Services Division, Libraries and Center for Computing
Activities & Bill Schilit, Computer Research Facilities, Computer
Science Department.
Permission is granted to any individual or institution to use, copy,
or redistribute this software so long as it is not sold for profit,
provided that this notice and the original copyright notices are
retained. Columbia University makes no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
The following notices apply to certain of the files in the CAP
distribution and such files are clearly marked.
Portions Copyright (c) 1985, Stanford Univ. SUMEX project.
May be used but not sold without permission.
Portions Copyright (c) 1984, Apple Computer Inc.
Gene Tyacke, Alan Oppenheimer, G. Sidhu, Rich Andrews.
Portions Copyright (c) 1988, Carnegie Mellon University. Rob Chandhok,
Computer Science Department.
Portions Copyright (c) 1990, 1991, The University of Melbourne.

154
PORTING Normal file
View File

@ -0,0 +1,154 @@
The following notes point out some of the items to watch out for when
porting CAP to different variants of BSD and other machines. Most of
these are items that have been "hit" in the past.
Index: GENERAL COMPATIBILITY
SYSTEM V
LIBRARIES
APPLICATIONS
CONFIGURATION
*********************
GENERAL COMPATIBILITY
*********************
sysvcompat.h in netat/sysvcompat.h attempts to allow the various
modules to mask incompatibilities between System V machines and bsd
machines. Except for some very basic translations (e.g. strchr vs.
index), all the mappings are done under a machine dependency (e.g.
ifdef hpux). Many different parts of CAP make use of this file,
though the largest client by far is Aufs. Most of the samples and
applications have not been tested or modified for System V
compatibility. NOTE: Aufs does not attempt to deal with the file name
length restrictions in System V: file names are simply truncated.
The machines in sysvcompat.h at present are: hpux and aux. Note: some
of the defintions for hpux are for older versions of hpux. This
points to a need to redo this file at a future point.
compat.h in netat/compat.h attempts to masks differences between
various bsd machine. To be more specific, it defines an additional
set of "macros", etc. that aren't found on all bsd based machines such
as sigmask, etc.
********
SYSTEM V
********
You can use conf.sysv.sh to generate a set of "ifdefs" suitable for
inclusion in sysvcompat.h for a particular machine. conf.sysv.sh
takes as an argument, the output file. The default is sysv.cpp.
Allowable ifdefs in sysvcompat.h are:
B2S_STRING_MAPON - Set if no strings.h or rindex or index. Must have
string.h and strrchr, strchr in this case.
B2S_BSTRING_MAPON - Set if no bcopy, bcmp, bzero. Then you must have
memcpy, memcmp, and memset.
USECHOWN - set you may chown a file to another
NEEDFCNTLDOTH - set if you need to include fcntl to get O_READONLY, etc.
USETIMES - use times to get process usage times instead of the
preferred bsd getrusage. Also assume that wait3 does not return usage
information.
NOWAIT3 - set if no wait3 in system - use wait instead which isn't as
flexible.
NODUP2 - No DUP2 call. Emulate with "close/dup"
NOLSTAT - no lstat for symbolic links. Use stat or don't use at all.
USERAND - don't use the bsd random call, use srand, rand instead
USEGETCWD - use the system 5 getcwd call to get the current working
directory instead of the bsd getwd call.
NOUTIMES - use utime to set file times instead of bsd utimes
NOPGRP - set if either setpgrp or killpg is missing. If one is, both
probably are, but it might be like hpux where one is in libc and one
in libBSD (in which case you need not define this, but modify
libspecial to have libBSD (SLIB in makefiles))
NOVFORK - system doesn't have vfork - what a shame. Use fork instead.
*********
LIBRARIES
*********
CAP LIBRARIES
-------------
Most of the machine dependencies are encoded into the modules and deal
with issues of structure byte alignment, incompatibilities with BSD
Unix, etc. Most of these are dealt with by doing "ifdef machine" and
triggering internal defines. Following is a module by module
description of some of the more important of these.
abkip.c has four major "defines". NORECVMSG and NOSENDMSG are set by
Configure and say whether sendmsg and recvmsg exist in the system
(they do scatter/gather io). NEEDMSGHDR should also be set if
<sys/socket.h> doesn't define it (as in old versions of aux).
NOFFS means that the target machine does not have the "ffs" subroutine
defined (find first set bit) and that we must use our own copy. hpux
and aux use NOFFS.
abddp.c has one major "define": INLINECHKSUM. INLINECHKSUM attempts
to speed up the ddp checksumming by defining the code in-line. This
been optimized for a vax and only tested on a vax. It is only set for
a vax :-). Note: it is possible to turn off ddp checksumming by
compiling abddp.c with "DONT_DOCHKSUM". This is NOT recommended. If
you have an application that requires turning off ddp checksumming,
you can call "checksum_error" with FALSE to ignore checksum errors.
abnbp.h in netat has an ifdef important for byteswapped machines.
Specifically, there is a bitfield definition and the order of the
items may depend upon the byte ordering of the target. You may need
to add an ifdef for your machine.
AFP Libraries
-------------
The AFP libraries contain three main components at the present time:
(1) a set of packing and unpacking routines that attempts to hide byte
swapping and struct packing differences between machines, (2) the des
subroutines, and (3) the locking routines. There are all routines
that might be used by either the client or server AFP software.
o Packing and unpacking
afpcmd.c is a driver for the packing and unpacking routines that
attempts to mask byte ordering and structure alignments. Currently
there are two defines in this module: BYTESWAPPED and
LOOSE_BYTESWAPPED. Like the defines in the libraries, these are also
hidden. The first simply says the machine is byte swapped like a vax.
The second allows cheating in dealing with byte swapping and should
only be defined if you are byte swapping and you can be sure that a
pointer to a "byte" will be usuable as pointer to a word or double
word. Currently, both defines are set for a vax. Sequents (nsxxxxx
and 386 based machines) and ns16000/ns32000 machines have BYTESWAPPED
on. pyramids, ibm032 (ibm rt pc), and 680xx based machines (sun,
aux/mac-ii, hpux/hp-9000 series) do not need either define. Note: you
should be able to turn on LOOSE_BYTESWAPPED for the nsxxxx processors,
but it is not done by default.
o locking
The two defines for locking are "NOLOCKF" and "NOFLOCK" that should be
set appropriately for you machine. Most BSD systems should have flock
available. For the implications of what happens when you do or don't
have these, see the documentation on the various client and server
(Aufs) programs.
************
APPLICATIONS
************
Aufs has a seperate document on porting/installation in
applications/aufs/INSTALLATION. However, it is worth mentioning that
most of the Aufs porting requirements are covered through the use of
sysvcompat.h and compat.h as mentioned in "GENERAL COMPATIBILITY".

338
README Normal file
View File

@ -0,0 +1,338 @@
The purpose of setting up CAP on GitHub is to build an AppleTalk
protocol stack for OS X 10.6 and newer that is compatible with
Classic Mac OS. That is, AFP-version up to 2.x and transport via DDP
(despite Apple removing DDP from OS X since 10.6).
This will enable AppleTalk networking with emulated machines running
Classic Mac OS as well as printing on non-IP, AppleTalk-only printers.
It should be possible to make this work using Homebrew.
- 'mabam', March 2015
----------------------------------------------------------------------
CAP Distribution 6.0, Patch Level 198 + 'asip1', March 1999
In 'CAP.faq' it is stated that the following interim patches are
available for download from munnari.OZ.AU and can be reversed once
patch 199 is completed:
asip.patch - AppleShareIP support
cicon.patch - Color Desktop Icon support
extnd.patch - Extended volume size support
desktop.patch - Desktop tool color icon support
It appears that patch 199 has never been released and the interim
patches are not available anymore at munnari.OZ.AU.
They are, however, available for download at
ftp://iubio.bio.indiana.edu/util/cap/ (log in as guest)
with the first patch substituted for a fixed version called
'asip1.patch'.
In this therefore unofficial, though fully patched version of CAP 6.0
these patches have been applied in the required, above stated order on
top of the patches 001 to 198.
See also 'cap60.pl198+asip.README' for the original information by
Don Gilbert from the Department of Biology, Indiana University
Bloomington.
- 'mabam', March 2015
----------------------------------------------------------------------
CAP - Columbia AppleTalk Package for UNIX
o RELEASE NOTES
o CAP Distribution 6.0, Patch Level 198, June 1996
Notice
------
Copyright (c) 1986, 1987, 1988, The Trustees of Columbia University in
the City of New York. Charlie C. Kim, User Services Group, Academic
Information Services Division, Libraries and Center for Computing
Activities and Bill Schilit, formerly of Computer Research Facilities,
Computer Science Department.
Permission is granted to any individual or institution to use, copy,
or redistribute this software so long as it is not sold for profit,
provided that this notice and the original copyright notices are
retained. Columbia University makes no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
--
Portions Copyright (c) 1985, Stanford Univ. SUMEX project.
May be used but not sold without permission.
Portions Copyright (c) 1984, Apple Computer Inc.
Gene Tyacke, Alan Oppenheimer, G. Sidhu, Rich Andrews.
Portions Copyright (c) 1990 - 1996 The University of Melbourne
Modules copyright in part or whole by any other entity than Columbia
University are clearly marked as such.
--
Portions are of the CAP distribution are public domain software. The
specific items are:
extras/att_getopt.c
extras/des.c
Portions of the CAP distribution are contributed by other sites including:
Rob Chandhok, Computer Science Department, Carnegie Mellon University
Ed Moy, University of California at Berkeley
David Hornsby, The University of Melbourne
Rakesh Patel, Rutgers University
Paul Campbell
ABSTRACT
--------
CAP was written for BSD 4.2 Unix and derivatives. CAP implements a
library containing a portion of Apple Computer's AppleTalk protocols.
In order to use this package you may need an AppleTalk/Ethernet bridge
(e.g. Shiva FastPath, Webster MultiPort Gateway). CAP includes a number
of applications that can be used to print to a LaserWriter, spool for a
LaserWriter, and act as Unix based AppleShare compatible file server.
CAP also includes a number of sample programs and contributed software.
CAP library routines are structured, for the most part, the same as
the Apple routines described in "Inside AppleTalk" and "Inside
LaserWriter." Refer to the Apple documents and the procedure comments
for a complete description of the routines and how to call them.
Bill Croft's original work in this area provided the inspiration for CAP.
Prerequisties
------------
o CAP as originally shipped needs a gateway capable of supporting
IPTalk (the transmission of AppleTalk DDP packets inside IP UDP packets)
to translate (gateway) IPTalk packets to/from EtherTalk or LocalTalk.
Suitable candidates include ...
* Webster MultiPort Gateway
* Cayman Gatorbox
* Shiva FastPath
* Cisco Router
o This CAP version supports Native EtherTalk, UAR (Phase 1 or Phase 2) and
Kernel AppleTalk, UAB (Phase 1) on certain hosts. A gateway as listed
above is only required to access LocalTalk services.
o baseline host system: Ultrix 2.0-1. Most will work under BSD 4.2,
BSD 4.3, Ultrix 1.0-1.2, Sun OS 3.2 or higher, ACIS 4.2, A/UX, IBM
RISC 6000, IRIS/IRIX, HP/Apollo Domain (BSD environment), OSF/Alpha,
386/BSD, FreeBSD and other systems with BSD like networking
facilities with varying levels of functionality. Under certain
systems, only portions will work.
Where
-----
CAP can be obtained by anonymous FTP from
munnari.OZ.AU mac/{cap60.pl100.tar.Z,cap.patches/*}
ftp-ns.rutgers.EDU pub/cap/{cap60.pl100.tar.Z,cap.patches/*}
gatekeeper.DEC.COM pub/net/appletalk/cap/{cap60.pl100.tar.Z,cap.patches/*}
ftp.kuis.kyoto-u.AC.JP net/cap/{cap60.pl100.tar.Z,cap60.patches/*.Z}
src.doc.ic.AC.UK packages/multigate/{cap60.pl100.tar.Z,cap.patches/*}
Please choose an appropriate site and an off-peak time for the transfer.
The patches are available individually or as the files "patches.1-100.tar.Z",
"patches.101-126.tar.Z", "patches.127-143.tar.Z", "patches.144-154.tar.Z",
"patches.155-162.tar.Z", "patches.163-182.tar.Z" & "patches.183-192.tar.Z".
Additionally, for new users, a partially patched source file is available
as "cap60.pl100.tar.Z" (beware: the file cap60.tar.Z is totally unpatched).
Patches
-------
To make the process of patching easier, you should get the 'patch' utility
written by Larry Wall, it is normally available from sites that archive
comp.sources.unix in volume7/patch2 and at GNU archive sites as
patch-2.1.tar.gz (which requires gzip-1.2.2.tar for unpacking).
For each of the patches, run 'patch -p < cap60.patchNNN' from the top level
cap60 directory, for example, in csh
foreach i (cap60.patches/cap60.patch*)
patch -p < $i >>& /tmp/patches
end
and check the /tmp/patches file for patching errors (look for the strings
"rej", "failed", "offset", "fuzz" - should be none). To remove the *.orig
files that patch leaves behind (containing the original version of the file),
run 'make spotless' from the top level directory (note that spotless also
removes all makefiles so gen.makes needs to be run to regenerate them).
Information
-----------
There is no CAP mailing list. Instead, notices and information about
CAP are posted to the mailing list info-appletalk which is gatewayed
with the USENET news group comp.protocols.appletalk. If you don't
have access to comp.protocols.appletalk and have access to the
ARPANET, you can get on the mailing list by sending mail to
info-appletalk-request@andrew.cmu.edu.
Information about CAP and related UNIX AppleTalk packages is available
via the World Wide Web using
http://www.cs.mu.OZ.AU/appletalk/atalk.html
The CAP FAQ (Frequently Asked Questions) file is available via FTP
from munnari.OZ.AU as the file
mac/CAP.faq
Documentation
-------------
Important documentation resides in:
doc/install.ms - stepwise installation document: assumes
you have read NOTES and this document
doc/print.cookbook - simple steps to implement CAP printing
man/* - UNIX manual entries for the various CAP programs
NOTES - installation notes: READ THIS BEFORE STARTING INSTALLATION
PORTING - notes on porting CAP to machines it doesn't know about
What's in CAP
-------------
The Columbia AppleTalk Package consists of a number of libraries, a
number of programs, and associated documentation. Following is a list
of the main parts along with a brief description.
o NOTES for a general overview of installation and some overview material.
o PORTING for information about making CAP work on systems not listed
in NOTES
netat - general header files used by various parts of CAP
man - man pages for some of the programs
doc - documentation
lib/cap - main appletalk libraries: ASP, PAP, ATP, NBP, DDP
lib/afp - generic AppleTalk Filing Protocol (AFP) routines
lib/afpc - AFP client libraries
lib/xenix - compatibility routines for XENIX use
etc - support programs: only atis - support program for NBP
extras - code and materials not necessarily related to AppleTalk
samples - sample programs: allow simple interaction with lw, appleshare
server, etc. See README there.
contrib - contributed programs
support - alterative LAP delivery support, Native EtherTalk,
Kernel AppleTalk and UAB.
applications - main applications.
The following programs in applications are in regular use at Columbia
and are a main part of the reason we work on CAP:
papif - UNIX lpd "input" filter for spooling to appletalk
- also includes sample "output" filter and printcap entry
- Note: this is a very bare bones filter
lwsrv - Simple LaserWriter spooler suitable for extension
aufs - AppleTalk Filing Protocol Unix File Server
NOTE: You must have the AppleShare 1.1 or 2.0 client code installed in
your Macintosh to use this. You must obtain this from Apple -
we do not and do not plan to supply this. The client code is
a lot of work and Apple's already done an excellent job here.
Bug Reports
-----------
Send bug report, comments, etc. to cap@munnari.OZ.AU or uunet!munnari!cap
Notes
-----
Hasn't been througly checked out on any system except Ultrix 2.0 & SunOS.
It it known to have run or should be able to run under: BSD 4.2, BSD
4.3, Ultrix 1.0, 1.1, 1.2, 2.2, Sun OS 3.2 or higher, Pyramid's Unix
under the BSD universe, ACIS 4.2 or 4.3 for the IBM RT PC, A/UX, HP-UX
for the series 9000 (release 6.0), Convex Unix V6.1, Sequents, IBM AIX
on the RISC 6000, Silicon Graphics IRIS/IRIX, HP/Apollo Domain (BSD),
OSF/1 Alpha, 386/BSD, FreeBSD and the Encore Multimax.
LAP - will probably never be implemented
DDP - don't try to use it directly
Documentation - in shorter supply than it should really be
TODO list
---------
a) Complete NBP - completed.
b) Complete PAP - completed.
c) Complete ATP - completed.
d) Complete DDP - essentially completed, but some minor parts missing.
e) Complete ASP - completed.
f) Start AFP - client side needs to be redone, server side okay.
g) Start ZIP work. KIP modified to allow under rev 1/88.
h) Start RTMP work. Not need under KIP.
i) miscellanous other fixes and cleanup
Credits
-------
Thanks to the User Services staff at Columbia University Center for
Computing Activies for patiently testing all the broken software that
was foisted on them as "working" with special thanks going to:
Rob Cartolano for testing Aufs beyond the call of duty
Alan Crosswell for making papif die more than anyone else and
letting me use his RT.
Lisa Covi and Jeff Eldredge for living with the software in
our Mac MicroLab
Mark Kennedy, Tom Chow, and Richard Sacks for giving Charlie
the support and time to work on CAP
and Father Larry "Mac" McCormick from the Columbia University
Macintosh Users Group for his inspiration and support.
And to the following list of people for their
support, help, commentary, and bug fixes:
Bill Croft, SUMEX, Stanford University
Janet Tornow, Apple Computer
Dan Tappan, Bolt Beranek and Newman
Rakesh Patel, Rutgers University
Charles Hedrick, Rutgers University
Robert Elz, University of Melbourne, Australia
Dan Sahlin, Swedish Institute of Computer Science, Sweden
Scooter Morris, Genentech
Mike Byron, Adobe Systems Incorporated
Tom Mallory, Adobe Systems Incorporated
Phil Farrell, School of Earth Sciences, Stanford University
Mark Davies, VUW, New Zealand
Roy Smith, Public Health Research Institute, NYC
Ritch Ruff, Oregeon State
Dan Lanciani, Harvard University
Ravinder (Rob) Chandhok, Carnegie Mellon University
Dwight Mckay, Purdue University
Steve Fram, CITI, University of Michigan
Paul Campbell, Unisoft
Edward Moy, WSSG, University of California at Berkelely
Tharen Debold, Georgia Tech
Jim Guyton, The Rand Corporation
and any we might accidently left out of this list
our thanks!
Further CAP 6.0 thanks to
William Roberts, Queen Mary & Westfield College, UK
Edward Moy, University of California at Berkeley
Steve P. Andrewartha, University of Tasmania
Tom Evans, Webster Computer Corp.
Phil Budne, Shiva
Rakesh Patel, Rutgers University
Chip Salzenberg, Teltronics/TCT
Dan Oscarsson, Lund Institute of Technology, Sweden
Bridget Rogers, University of MN, Duluth
Matthew Lewis, University of Amsterdam
Max Tardiveau, University of St. Thomas
and lots of nice people at the University of Melbourne, Australia.

29
applications/Makefile.m4 Normal file
View File

@ -0,0 +1,29 @@
all:
(cd lwsrv; make)
(cd papif; make)
(cd aufs; make)
install:
(cd lwsrv; make install)
(cd papif; make install)
(cd aufs; make install)
clean:
-(cd lwsrv; make clean)
-(cd papif; make clean)
-(cd aufs; make clean)
spotless:
-rm -f *.orig Makefile makefile
-(cd lwsrv; make spotless)
-(cd papif; make spotless)
-(cd aufs; make spotless)
dist:
@cat todist
@(cd papif; make dist)
@(cd lwsrv; make dist)
@(cd aufs; make dist)

12
applications/README Normal file
View File

@ -0,0 +1,12 @@
Installation notes
lwsrv - lwsrv is a spooling agent - it pretends to be a LaserWriter.
See lwsrv/README for installation notes.
aufs - aufs is a Appletalk Filing Protocol Unix based File Server
(AppleShare compatible)
papif - contains a set of programs that can be "plugged" into the
Berkeley lpd to allow printing to a laserwriter from unix
via appletalk. See papif/README for installation notes.

View File

@ -0,0 +1,234 @@
Aufs Installation notes
Note: Installation of Aufs assumes you have the CAP libraries already
installed.
Aufs installation on BSD 4.2, BSD 4.3, Ultrix and Sun machines
shouldn't be that hard, but you do have to go through the various
possible defines and decide if you need them or not. Also included
here is information on the password look aside file. Finally, if you
aren't running on a machine as listed above see the section on
porting.
Previously, the Makefile built two versions of Aufs. The second
version was used to slow down sends from the host system. Under this
version of Aufs, you can use the "S" switch to limit the number of
packets sent. See the section Fastpath below.
FASTPATH
********
The Kinetics FastPath box MAY have problems keeping up with packets
from a 8600 or faster machine with a high speed ethernet interface.
We can't quantify which machines will have this problem (other than to
say we saw it on a 8650 with a DELUA running Ultrix 1.2 and an 8700
with a DEBNT running Ultrix 2.0, but didn't on a MicroVax II's running
BSD 4.3 and Ultrix 2.0 with DEQNA's or a VAX750 running Ultrix 2.0
with a DEUNA), but if you see extensive delays, then you may have this
problem. You can check things out by running aufs with the debugging
command "-a server" - if you see a long delay between "Sending reply
..." and "done", then you probably need to reduce the packet burst
number via the "-S" switch. [You can also turn on atp debugging and
watch for "incoming bitmap" messages -- if they tend to be most of the
bits, then the same holds]. The standard (and maxiumum) is 8. You'll
probably have to reduce it to one. (Note: other causes might be
problems on your ethernet, etc.). If this doesn't fix things, then
something else in your environment has problems.
LOCKING
********
For a full explanation of how locking is managed, see "design.notes",
but here's the basic information. The modules that handles locking is
actually in libafp(afposlock) to allow its use by client programs that
go into Aufs volumes.
If you have both lockf and flock available on your system, then you
are set. You can have shared writeable volumes with the following
caveat - the open fork command does not implement "deny" permissions,
thus you should probably not have shared "writable" applications
unless they are AppleShare compatible (e.g. don't write to
themselves). In addition, programs that depend on "deny" permissions
being set on data files will also cause problems (MacWrite 4.6
actually sets a byte range lock on the files it uses (but locks for
0x7fffffff instead of using -1 for the entire file)).
If you only have lockf on your system, then some coordination of
shared volumes is possible and Byte Range Lock will be available.
Allowing general write access to a volume is feasible, but not
recommended since setting a lock blocks. Also, files that are
read-only by one class of users and writable by others may result in
the read-only users getting corrupted data since they have to way to
tell the writers not to write because they are reading. This applies
mainly to the Desktop and finderinfo files.
If you have flock, then you don't have byte range locks. flock is
better than lockf in dealing with shared files like the desktop and
finderinfo files - you should be able to share writable volumes as if
you had both flock and lockf except you cannot do Byte Range Locks, so
be careful (e.g. probably a bad idea to share data files).
NFS: lockf and/or flock must be coordinated across machines with a
special daemon outside of the standard NFS protocol. If this is not
done, errors that designate problems because of "remote files system"
are ignored and the code proceeds on the assumption the lock has been
made (just like the case when one or both are not available)--but you
should know that they haven't! In particular, don't have multiple
writers.
DEFINES
*******
The m4.features file in the top level CAP directory can be used to
select additional server features. Configure offers the opportunity to
customise this file at configuration time. See CAP60.README.
Defines can also be set by changing m4.setup and reconfiguring your
makefiles. See [smartunixfinderinfo] and [aufsosdefs] in m4.setup.
All the configurable options listed below go in "OSDEFS" in the MakeFile.
International Character Sets
----------------------------
Provision has now been made to handle international character sets or
rather "ascii"s that are different from what most people in the U.S.
see. The idea (and tables) come from Dan Sahlin of the Swedish
Institute of Computer Science.
There are three major character set translation tables defined:
Swedish D47 file ends in .swe and has a type of TEXT
Swedish-Finnish E47 file ends in .fin and has a type of TEXT
ISO 8859-1 Latin 1 file ends in .latin1 and has a type of TEXT
These are only active if "FULL_NCS_SUPPORT" is defined in OSDEFS.
In addtion, there is our standard unix to macintosh definition that
maps between carriage returns and line feeds which happens when the
file has a type of "TEXT" and a creator of "unix". This cannot be
turned off without editing the source.
The action should really be specifiable on a per volume basis instead
of a server wide basis.
End of line translation
-----------------------
The automatic cr/lf translate feature for read a line a time mode can
be turned off by defining NONXLATE.
Unix file types
---------------
You can make Aufs "guess" the file type by turning on
"SMART_UNIX_FINDERINFO". This is not turned on by default because of
the heavy penalty involved - you must open and read every file when
getting the finderinfo (at least the first time). All this is handled
in afpudb.c which knows about a couple of different file types. You
can add icons here if you wish and we will include them in the
distribution if we like them if you send them to us. Note: this is
highly unix version dependent.
VOLUME INFO
-----------
If you have the statfs or getmnt systems calls available on your
system, then you will be able to get information on space used and
free on a volume. The information returned is for space free on the
file system that the root directory of the volume is on. Note that
volumes may span file systems - in this case, the information will be
misleading and incorrect. To use statfs or getmnt simply define
USESTATFS or USEGETMNT respectively.
You can define USEQUOTA if you want Aufs to return the person's quota
if it exists.
NOTE ON SUNS (and other other system that uses the Sun quota code
instead of the Melbourne quota code) : On current versions of SunOS
(possibly all, I don't know), the quota code used differs from the
Berkeley code (which is derived from and/or is the Melbourne code) -
it is their own private version. The major external difference as far
as Aufs is concerned is that system call and some of the arguments are
different. (SunOS's system call is quotactl vs. quota in BSD). Code
under the USESUNQUOTA define masks the differences by implementing a
quota subroutine that calls quotactl with the proper arguments. On
Suns, USESUNQUOTA is the default and need not be turned on. (Systems
other than Suns that run SunOS quota code must turn on the code by
defining USESUNQUOTA). If this behavior is unwanted, then you
shouldn't define "USEQUOTA"!
WARNING: the USESUNQUOTA code builds a table of mounted file systems -
the table length is taken from param.h as NMOUNT. If you are
compiling for another system or multiple systems with differing values
of NMOUNT, you should define MAXUFSMOUNTED to the larger of these
values.
You can define USTAT if you have the ustat system call on your system.
However, ustat returns the free space left including the safe margin
(usually 10%) that is only writable by root. It also doesn't say how
much is used. The problem is that the first time around the query is
for the free space and total space and subsequent queries are for free
space only. This means that if space frees up, then the free space
(to the mac) goes negative. We must be able to return the real total
space to make this work right and we can't without mucho work (that
requires munging through the kernel). THIS OPTION IS NOT RECOMMENDED.
Edward Moy has supplied us with a "server" based method of getting
volume information (that uses one server per Aufs process). It is
workable, but isn't all that efficient (or inefficient). Some method
of using this in conjuction with the ustat call should probably be
figured out. To include, use -DSIZESERVER. See sizeserver.shar in the
patches/Moy@Berkeley directory.
PASSWORD
********
Aufs normally uses the unix password file. This means we are limited
to 8 characters for the login name and we don't know the "real"
password. Thus, we have encrypted passwords.
Aufs now allows a password lookaside file that will be used under the
following conditions:
o specified at startup with the -P option
o des encryption supplied (cf. afp/README)
o it is owned by root and not readable by world
The format of this file is very rigid (and stupid). Each entry must
be formatted as (scanf format):
"USER: %s\tUNIXUSER: %s\tPASSWORD: %s"
where user is the username that must be supplied by the AFP client,
unixuser is the user name that user runs under and password is the
password to use. No comments, etc. are allowed.
PORTING
*******
It is entirely possible to run Aufs under other versions of Unix than
listed before. One we have tried is hpux - a System V machine with
BSD networking extensions. There are number of problems with it
(especially in older versions (pre-6.0) where you have to supply a
rename function, etc), but it does work. Most of the configuration
options that will allow us to run on a System V machine with BSD
networking extensions are in cap/netat/sysvcompat.h (there because
some of the defines also apply to other code).
It is worth nothing that we by-pass the problem of how to map the 32
character files names from the Mac to the 14 character file names of
System V R2 and the 32 character file names of System V R3 by simply
not allowing names longer than the operating system limit. This limit
is encoded in afpdid.c by using the MAXNAMLEN (assumed to be in
<sys/dir.h>)
Some assumptions:
off_t is defined in <sys/types.h> and encodes the "whence"
and return values of lseek and tell. Furthermore, it must
be at least a signed double word (32 bits) in size.
groups (gid_t) is short or unsigned short
Late breaking news:
Some systems may have getgroups defined to return an array of type
gid_t instead of type int. This will cause problems if typeof(gid_t)
!= typeof(int) (which is generally true). To get around this problem,
define use "-DGGTYPE=gid_t" in afposdefs.

View File

@ -0,0 +1,193 @@
CFLAGS=cflags() bigcflags() specialcflags()
I=includedir()
#
# SEE INSTALLATION for documentation
#
# valid are NONXLATE,FULL_NCS_SUPPORT,USECHOWN
# USESTATFS or USEGETMNT
# USEQUOTA or USESUNQUOTA
# and GGTYPE="gid_t"
OSDEFS=aufsosdefs()
AFPLIB=libafp()
CAPLIB=libcap()
# for other libraries (like BSD on hpux)
SLIB=libspecial()
# for Rutgers
RULIB=libru()
# used mainly for debugging
CAPFILES=
# aufs.c definitions: USEVPRINTF - use vprintf in logging
AUFSDEFS=ifdef([usevprintf],[-DUSEVPRINTF ])
# to get "more" information about files with a speed penalty
# Also, is specific to 4.2 BSD. May not work on some machines
ifdef([smartunixfinderinfo],[],[#])AFPUDB=-DSMART_UNIX_FINDERINFO
#For hpux (you have you may need to supply a routine that does rename)
# (Other limitations apply!!!!)
# RENAME=rename.o
# make sure that you define point getopt to att_getopt.o if your system
# doesn't have it builtin
GETOPT=ifdef([needgetopt],[needgetopt])
# This encodes the assumed location of certain directories
EXTRAS=../../extras
# Set the following approriately
DESTDIR=capsrvrdestdir()
#
# End of configurable options
#
SRCS=afpos.c afpvols.c afpfile.c afpdir.c afpfork.c \
afpmisc.c afpserver.c aufsicon.c abmisc2.c \
afpdt.c afpdid.c afposenum.c afpavl.c \
afposfi.c afpgc.c afppasswd.c afposlock.c aufsv.c \
afpudb.c afposncs.c afpspd.c afpfid.c afpdsi.c aufscicon.c
OBJS=afpos.o afpvols.o afpfile.o \
afpmisc.o afpserver.o aufsicon.o abmisc2.o \
afpdt.o afpdir.o afpfork.o afpdid.o afposenum.o afpavl.o \
afposfi.o afpgc.o afppasswd.o aufsv.o \
afpudb.o afposncs.o afpspd.o afpfid.o afpdsi.o aufscicon.o
SYMLINKS=att_getopt.c
all: aufs sizeserver afpidsrvr afpidlist afpidtool
aufs: aufs.o $(OBJS) $(CAPFILES) ${RENAME} $(GETOPT)
${CC} $(LFLAGS) -o aufs aufs.o $(OBJS) $(CAPFILES) ${RENAME} \
$(GETOPT) ${AFPLIB} ${CAPLIB} ${SLIB} ${RULIB}
sizeserver: sizeserver.o
${CC} ${LFLAGS} -o sizeserver sizeserver.o ${SLIB} ${RULIB}
sizeserver.o: sizeserver.c sizeserver.h
${CC} ${OSDEFS} ${CFLAGS} -c sizeserver.c
afpidsrvr: afpidsrvr.c ../../lib/afp/afpidaufs.h
${CC} ${OSDEFS} ${CFLAGS} -o afpidsrvr afpidsrvr.c \
${GETOPT} ${AFPLIB} ${SLIB}
afpidlist: afpidlist.c ../../lib/afp/afpidaufs.h
${CC} ${OSDEFS} ${CFLAGS} -o afpidlist afpidlist.c \
${GETOPT} ${AFPLIB} ${SLIB}
afpidtool: afpidtool.c ../../lib/afp/afpidaufs.h
${CC} ${OSDEFS} ${CFLAGS} -o afpidtool afpidtool.c \
${GETOPT} ${AFPLIB} ${SLIB}
newver:
/bin/sh aufs_vers.sh `cat aufs_vers` aufs_vers aufsv.c
make all
aufsv.c: aufs_vers
/bin/sh aufs_vers.sh `cat aufs_vers` useold aufsv.c
clean:
-rm -f *.o aufs sizeserver afpidsrvr afpidlist afpidtool ${SYMLINKS}
spotless:
-rm -f *.o *.orig aufs sizeserver afpidsrvr afpidlist afpidtool \
${SYMLINKS} Makefile makefile
lint: aufs.c $(SRCS)
lint aufs.c $(SRCS)
install: aufs sizeserver
-strip aufs
ifdef([sysvinstall],[install -f $(DESTDIR) aufs],
[${INSTALLER} aufs $(DESTDIR)])
-strip sizeserver
ifdef([sysvinstall],[install -f $(DESTDIR) sizeserver],
[${INSTALLER} sizeserver $(DESTDIR)])
-strip afpidsrvr afpidlist afpidtool
ifdef([sysvinstall],[install -f $(DESTDIR) afpidsrvr afpidlist afpidtool],
[${INSTALLER} afpidsrvr afpidlist afpidtool $(DESTDIR)])
dist:
@cat todist
att_getopt.o: att_getopt.c
att_getopt.c:
ln -s ${EXTRAS}/att_getopt.c
afpos.o: afpos.c
${CC} ${OSDEFS} ${CFLAGS} -c afpos.c
afposncs.o: afposncs.c
${CC} ${OSDEFS} ${CFLAGS} -c afposncs.c
afpudb.o: afpudb.c
${CC} ${CFLAGS} ${AFPUDB} -c afpudb.c
aufs.o: aufs.c
${CC} ${OSDEFS} ${CFLAGS} ${AUFSDEFS} -c aufs.c
afpserver.o: afpserver.c
${CC} ${OSDEFS} ${CFLAGS} ${AUFSDEFS} -c afpserver.c
# Dependencies
afpos.o: afpos.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h \
afpvols.h $I/netat/afpcmd.h
afpudb.o: afpudb.c $I/netat/appletalk.h afpudb.h
afpfork.o: afpfork.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
afpdir.o: afpdir.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
afposfi.o: afposfi.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h afpgc.h afpudb.h
afpvols.o: afpvols.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpvols.h \
afpntoh.h
afpfile.o: afpfile.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
afpmisc.o: afpmisc.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h
afpserver.o: afpserver.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
aufsicon.o: aufsicon.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h
afpcmd.o: afpcmd.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h $I/netat/afpcmd.h
abmisc2.o: abmisc2.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h \
$I/netat/afpcmd.h
afpdt.o: afpdt.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h \
$I/netat/afp.h $I/netat/afpcmd.h \
afpvols.h afpdt.h afpavl.h \
afpntoh.h afpudb.h
afpdid.o: afpdid.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h
afposenum.o: afposenum.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
afpdt.h afpavl.h
afppacks.o: afppacks.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h $I/netat/afpcmd.h
afpavl.o: afpavl.c afpavl.h
afperr.o: afperr.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h
afpgc.o: afpgc.c afpgc.h
afppasswd.o: afppasswd.c $I/netat/sysvcompat.h afppasswd.h
afposncs.o: afposncs.c $I/netat/appletalk.h $I/netat/afp.h \
afposncs.h afps.h
afpdsi.o: afpdsi.c $I/netat/appletalk.h ../../lib/cap/abasp.h \
afpdsi.h

172
applications/aufs/NOTES Normal file
View File

@ -0,0 +1,172 @@
What does AUFS do?
Through the use of the AFP protocol Aufs maps the macintosh file
system into the Unix file system.
Things to note about Aufs:
User info:
o Resource Fork, and finder information are stored in subdirectories
(.resource, .finderinfo). The data fork is stored as is. For
example the file "dir:Hey" on the mac is stored as three files
dir/Hey, dir/.resource/Hey, and dir/.finderinfo/Hey.
o Login requires a username and password. The password is verified
and no more than 8 chars (AFP spec). This is your unix user name
and passowrd and is transmitted in clear text. You will not be
able to login if your unix password is longer than 8 chars.
Also, no randnum password encryption is used due to the lack of a
key on the unix side :-(. (Note: there is a mechanism to allow a
"lookaside password file so you can have long user ids, encrypted
passwords, etc".)
o Volumes are defined by an "afpvols" file. The vols file contains
lines with the volume's name, the path, and an optional password.
The root directory of the volume is specified by the path. (New:
Aufs version 3 will search for the file afpvols first and then
.afpvols).
o When a user logs into the server the user's home directory is
searched for an afpvols file. The names in this file can then
be mounted by the Mac client. See the sample afpvols file "afpvols".
o If the user does not have a afpvols file then their home
directory will be added as a volume.
o A server wide vols file can be specified on the aufs command
line. The volumes in this file are always seen by clients
and could contain general (maybe read-only) mac utilities
and files.
o Case does not matter on Mac filenames, to make Aufs implement this
feature, define NOCASEMATCH. Beware of the performance degradation.
o Since unix file names may not contain 8 bit chars and slash,
Aufs translates special characters in file names into colon
followed by two hex digits.
o Unix files are given the type "TEXT" and creator "unix" and the
standard unix end of line "linefeed" is translated to a "carriage
return" when sending to the mac and vice versa.
o National character sets may be defined using afposncs.c -- see
INSTALLATION and design.notes and afposncs.c
o Since mac file names may not be longer than 31 chars, Aufs
simply skips long file names on the unix side.
o Two files are maintained by Aufs for the desktop database,
these are .IDeskTop and .ADeskTop. .IDeskTop stores icon
information, .ADeskTop stores APPL information. Both of
these files are created in the volumes root directory.
o Bytes used, and bytes free on a volume are set to arbitrary
values (unless you are running a machine with "statfs" or "getmnt").
o Depending on your system, there may be no file or desktop locking.
Share writable volumes at your own risk in these situations. (cf.
INSTALLATION for information).
o Aufs will follow symbolic links for directories and files.
However, for directories, Aufs will not permit more than about 4
symbolic links to be followed in any path. When the limit is
reached, the symbolic links to directories will not appear to be
there. However, be careful - you can do really strange things with
symbolic links.
Admin info:
o Aufs disassociates itself when run without debugging turned on.
o Aufs forks a new child process for each session.
o For other bugs, problems, etc. see todo and design.notes
o See the design.notes for info on protections.
o You cannot run many programs on a write locked directory/disk.
o Be careful when moving volumes around: tar has a very small limit
on path names. rdist and dump work well though.
What Aufs does not do?
----------------------
It does not handle the problem of 14 character file names under System
V - file names are simply truncated.
Known problems
--------------
Here's the big one: we finally realized that the .ADeskTop, .IDeskTop
and .finderinfo files are NOT written in network order. This means
you can't transport directly between machines with different byte
orders! (Not tar, dump, or NFS). Aufs version 3 will destroy the old
desktop files. Aufs version 3 will also rewrite the old .finderinfo
files when it sees them. To ensure things are okay, rebuild your
desktop.
Both DeskTop files grow without bounds. The only way to prune them is
to delete then and rebuild the desktop from the Mac.
The Applications mapping database can quickly get out of sync with
reality - not enough information is stored to keep in line (and even
we did store enough it would be costly to recover). Problem comes
when you start moving directories holding Applications around - it may
or may not work out - remember though, you can alway rebuild the
desktop (painful as it might be..).
The file creator "unix" and file type "TEXT" are not registered with
Apple.
read/writes and many other operation are blocking - this may cause
problems! However, making them run async is a lot of work. The
"solution" is to stay away from things that might block for a long
long time - e.g. ttys. For the most part though, it wouldn't cause
problems.
Aufs uses a complete path name specification to deal with files in
general. When it exceeds the maximum path name on a system, this will
cause serious problems - Aufs should really enforce this restriction
or remove it, but it doesn't.
Unix systems keep three dates on files: ctime - last status change
time, mtime - last modification time, and atime - last access time.
Mac wants modification and creation. Modification is really later of
mtime and ctime. Creation time is unknown and we give the earliest of
ctime, mtime and atime to give an approximation.
How to Run
----------
Aufs can be run with no arguments in which case it registers the
name "Hostname Aufs:AFPServer@*."
A logfile is created as "object".log in your currently connected
directory.
If you are not running aufs from root, then other users will not
be able to login since it tries to do a setuid, etc.
Other useful options are:
-a for AFP debugging by level (or setenv AUFSDEBUG):
All DeskTop Directory File Fork OS Server Volume debug
The option "debug" disables forking among other things.
-t for packet traces (or setenv AUFSTRACE):
[I|O|B]CmdName
-n for setting the server's name
-V volfile - set the server wide volumes file
-U # - set the maximum number of asp/afp sessions allowed
(default is 10)
-G to specify an id to use as "<guest>" (disallowed o.w.)
-P specify an auxillary password file to override the standard one
(this is a mess)
-c specify directory to put coredumps into (note: if you specify
this, be sure to give absolute path names for -P)
-s for statistics after run
Example: aufs -t 'bdelete irename' -a 'file fork dir' -s -n Billy
Above example would trace delete packets on both input and output,
rename packets on input only. File, fork and directory routines will
print their own information. Statistics will be printed at the end of
the run. The server will register as "Billy:AFPServer@*".
See the man page in cap/man for more information.

59
applications/aufs/README Normal file
View File

@ -0,0 +1,59 @@
AUFS - AppleTalk to Unix File Server
o RELEASE NOTES
o Aufs, version 3.00, Feb. 1988
Introduction
------------
Aufs provides file service for a Mac client running AppleShare software.
Aufs implements most of the AppleTalk Filing Protocol, as specified by
protocol version 1.1, February 17, 1987. AFP 2.0 is also supported, except
for the (optional) password change feature. It is possible to add code for
this, but is dangerous to use with clear text passwords across networks.
Though this version has been extensively tested, but definitely
contain bugs - it is far to big not to.
Installation
============
See INSTALLATION in this directory for notes on installation.
What Aufs Does
=============
See the Aufs man page and see NOTES in this directory
The actual design parameters are mapped in design.notes.
MAJOR CHANGES since Version 2.0:
Here's the big one: we finally realized that the .ADeskTop, .IDeskTop
and .finderinfo files are NOT written in network order. This means
you can't transport directly between machines with different byte
orders! (Not tar, dump, or NFS). Aufs version 3 will destroy the old
desktop files. Aufs version 3 will also rewrite the old .finderinfo
files when it sees them. To ensure things are okay, rebuild your
desktop.
Accepts .afpvols if no afpvols.
Provision has now been made to handle international character sets or
rather "ascii"s that are different from what most people in the U.S.
see. The idea (and tables) come from Dan Sahlin of the Swedish
Institute of Computer Science.
Turning on SMART_FINDERINFO in afpudb.c will yield more information;
however, it is unix variant (BSD) dependent and slows things down
considerably.
Simple minded shutdown mechanism added.
Disallow "." and ".." as file names.
Kinetics Box too slow code dropped in favor of settable values.
Update to use sun quota system properly

View File

@ -0,0 +1,83 @@
/*
* $Author: djh $ $Date: 91/02/15 21:05:37 $
* $Header: abmisc2.c,v 2.1 91/02/15 21:05:37 djh Rel $
* $Revision: 2.1 $
*/
/*
* abmisc2.c - miscellaneous, but nevertheless useful routines
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
*
* Edit History:
*
* March 1987 Schilit Created.
*
*/
#include <stdio.h>
#include <netat/appletalk.h>
#include <ctype.h>
#include <sys/types.h>
#include <netat/afp.h>
#include <netat/afpcmd.h>
/* Should be put in abnbp.c */
/* cck - is server dependent - don't want in libraries */
/*
* OSErr SrvrRegister(int skt, char *name, char *type, char *zone)
*
* Register the name and socket using NBP.
*
* If type is NULL then 'name' is a compound name in the form "name:type@zone"
* otherwise 'name', 'type' and 'zone' point to the respective parts of the
* name.
*
*/
#define SRV_RTI (sectotick(1)) /* retransmit interval is 4 seconds */
#define SRV_RTC 5 /* retransmit count */
OSErr
SrvrRegister(skt,name,type,zone, en)
int skt;
char *name,*type,*zone;
EntityName *en;
{
nbpProto nbpr;
NBPTEntry nbpt[1];
int err;
if (type == NULL) /* if no type then compound name */
create_entity(name,en); /* create entity */
else { /* otherwise already split */
strcpy(en->objStr.s,name);
strcpy(en->typeStr.s,type);
strcpy(en->zoneStr.s,zone);
}
nbpr.nbpAddress.skt = skt;
nbpr.nbpRetransmitInfo.retransInterval = SRV_RTI;
nbpr.nbpRetransmitInfo.retransCount = SRV_RTC;
nbpr.nbpBufPtr = nbpt;
nbpr.nbpBufSize = sizeof(nbpt);
nbpr.nbpDataField = 1;
nbpr.nbpEntityPtr = en; /* entity */
return(NBPRegister(&nbpr,FALSE)); /* register the name */
}
OSErr
SrvrShutdown(en)
EntityName *en;
{
return(NBPRemove(en));
}

316
applications/aufs/afpavl.c Normal file
View File

@ -0,0 +1,316 @@
/*
* $Author: djh $ $Date: 91/02/15 21:05:43 $
* $Header: afpavl.c,v 2.1 91/02/15 21:05:43 djh Rel $
* $Revision: 2.1 $
*/
/*
* afpavl.c - Appletalk Filing Protocol AVL Tree Management
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University in the
* City of New York.
*
*
* Edit History:
*
* Mar 30, 1987 Schilit Created, based on older versions
*
*
*/
#include <stdio.h>
#include "afpavl.h"
/*
* The compare routines for the following MUST be used as:
* compare(userdata, node->userdata)
* This is because some of the callers may want to "cheat" on copying
* data and only send the key as the userdata. Since AVLInsert returns
* the AVLNode, the user data there can be modified after the fact
* if the userdata passed is not quite what we wanted (was only a search
* key)
*/
#define TRUE 1
#define FALSE 0
AVLNode *
AVLLookup(r,udata,compar)
AVLNodePtr r; /* root, start of search */
AVLUData *udata; /* check for this user data */
int (*compar)(); /* comparison routine */
{
int cmp;
while (r != NILAVL) { /* until we runnout... */
cmp = (*compar)(udata,r->b_udata); /* compare the keys */
if (cmp < 0) /* key < r */
r = r->b_l; /* move left */
else if (cmp > 0) /* key > r */
r = r->b_r; /* move right */
else /* key = r */
return(r); /* return the node */
}
return(NULL); /* not found, return null */
}
AVLNode *
AVLNew(udata)
AVLUData *udata;
{
AVLNode *new;
new = (AVLNode *) malloc(sizeof(AVLNode));
new->b_bf = 0; /* init balance factor */
new->b_l = /* and left, right pointer */
new->b_r = NILAVL; /* fields in new node */
new->b_udata = udata; /* install user data */
return(new); /* and return new ptr */
}
/*
* int AVLInsert(AVLNode **root, AVLUData *udata, int (*compar)())
*
* Create a new node with the user's data attached to it (AVLUData).
* Use the compar routine to decide where this entry goes in the
* tree. Always returns user data of node inserted or found.
*
* Rewrote to match closer to Knuth version: cf. Searching and Sorting,
* The Art of Computer Programming, Volume 3, pp. 455-457.
*
*/
AVLNode *
AVLInsert(root,udata,compar)
AVLNode **root; /* handle on root node */
AVLUData *udata; /* user data for new node */
int (*compar)(); /* comparison routine */
{
AVLNodePtr t,s,p,q,r;
int bf,cmp; /* balance factor */
if ((p = *root) == NILAVL) { /* check for empty tree */
*root = AVLNew(udata); /* if so then insert and */
return(*root); /* return... */
}
/*
* p move down the tree to locate the insertion
* point for new.
*
* s is the node to rebalance around: the closest node to new which
* has a balance factor different from zero. t is the father of s.
* If t stays null then we want to rebalance around "root"
*/
/* A1 */
t = NILAVL;
s = p;
do {
/* A2 */
if ((cmp = (*compar)(udata,p->b_udata)) == 0)
return(p);
if (cmp < 0) { /* comparison base */
/* A3 */
if ((q = p->b_l) == NILAVL) { /* go left unless NIL */
p->b_l = q = AVLNew(udata); /* if nil, then insert */
break; /* and goto rest of code */
}
} else { /* cmp > 0 */
/* A4 */
if ((q = p->b_r) == NILAVL) { /* go right unless NIL */
p->b_r = q = AVLNew(udata);
break;
}
}
if (q->b_bf != 0) {
t = p; /* new rebalance point */
s = q;
}
p = q;
} while (1);
/* A6 */
/* adjust the balance factors of nodes on path from next of s to q */
/* remember bf at balance point */
bf = ((*compar)(udata,s->b_udata) < 0) ? -1 : 1;
if (bf < 0) /* take the first step... */
r = p = s->b_l; /* to get past the balance point */
else
r = p = s->b_r;
/* follow p down to q and set each balance factor to 1 or -1.
* no addition is required since balance factors of all nodes after
* s are zero (s is the closest non zero node).
*/
while (p != q) { /* follow the path from p to new */
/* set balance factors for nodes */
cmp = (*compar)(udata,p->b_udata);
#ifdef DEBUG
if (cmp == 0) { /* p == q !! */
fprintf(stderr, "Can't happen p == q in AVLInsert A6\n");
exit(9999);
}
#endif
p->b_bf = cmp < 0 ? -1 : 1; /* adjust */
p = cmp < 0 ? p->b_l : p->b_r; /* and follow correct path */
}
/* A7 */
/* check if the tree is unbalanced */
if (s->b_bf == 0) { /* at balance point check bf */
s->b_bf = bf; /* was balanced now only 1 off */
return(q); /* tree is ok (return(q)) */
}
if (s->b_bf == -bf) { /* at balance point did we improve? */
s->b_bf = 0; /* yes, set balance factor to 0 */
return(q); /* and return (q - new node ) */
}
/* balance factor went to -2 or +2, rebalance the tree */
if (r->b_bf == bf) { /* single rotation */
p = r;
if (bf < 0) {
s->b_l = r->b_r;
r->b_r = s;
} else {
s->b_r = r->b_l;
r->b_l = s;
}
s->b_bf = r->b_bf = 0; /* subtree is now balanced */
} else {
/* double rotation */
if (bf < 0) {
p = r->b_r;
r->b_r = p->b_l;
p->b_l = r;
s->b_l = p->b_r;
p->b_r = s;
} else {
p = r->b_l;
r->b_l = p->b_r;
p->b_r = r;
s->b_r = p->b_l;
p->b_l = s;
}
if (p->b_bf == 0)
s->b_bf = r->b_bf = 0;
else {
if (p->b_bf == bf) { /* b(p) = a */
s->b_bf = -bf;
r->b_bf = 0;
} else { /* b(p) = -a */
s->b_bf = 0;
r->b_bf = bf;
}
}
p->b_bf = 0;
}
/* A10 */
/* Finishing touch: s points to the new root and t points to the
* father of the old root of the rebalanced subtree. Make t point
* to the head of the balanced subtree.
*/
if (t == NILAVL) /* rebalance around the root node? */
*root = p; /* yes, set a new root */
else {
if (s == t->b_r) /* did we rebalance on right? */
t->b_r = p; /* yes, then set new subtree there */
else
t->b_l = p; /* else rebalanced on left */
}
return(q); /* return new node */
}
#ifdef notdef
AVLNode *
AVLLookN(r,udata,n,comp)
AVLNode *r;
AVLUData *udata;
int *n;
int (*comp)();
{
AVLNode *s;
int cmp;
while (r != NILAVL) { /* until we runnout... */
cmp = (*comp)(udata,r->b_udata); /* compare the keys */
if (cmp < 0) /* key < r */
r = r->b_l; /* move left */
else if (cmp > 0) /* key > r */
r = r->b_r; /* move right */
else /* key = r */
break; /* found a match */
}
if (r == NILAVL) /* check if runnout */
return(NILAVL); /* yes... then not found */
if (--(*n) <= 0) /* no... found something, decr n */
return(r); /* it was the one we wanted */
s = AVLLookN(r->b_l,udata,n,comp); /* else check left subtree */
if (s != NILAVL) /* found it there? */
return(s); /* return the node */
return(AVLLookN(r->b_r,udata,n,comp)); /* else check right subtree */
}
/*
* AVLLookupNth(AVLNode *root, AVLUData *udata, int n, int (*compare)())
*
* Call the specified comparison routine to locate the n'th node
* that matches user data. The primary key used by compare must
* match the primary key used by AVLInsert.
*
*/
AVLUData *
AVLLookupNth(r,udata,n,comp)
AVLNodePtr r;
AVLUData *udata;
int n;
int (*comp)();
{
AVLNode *s,*f; /* subtree */
int cmp;
f = NILAVL;
while (r != NILAVL && f == NILAVL) { /* locate first matching */
cmp = (*comp)(udata,r->b_udata); /* compare the keys */
if (cmp < 0) /* key < r */
r = r->b_l; /* move left */
else if (cmp > 0) /* key > r */
r = r->b_r; /* move right */
else /* key = r */
f = r; /* found it set f exits loop */
}
if (f == NILAVL)
return((AVLUData *) 0); /* nothing found */
s = AVLLookN(f,udata,&n,comp); /* call locator routine */
if (s != NILAVL) /* did we find it? */
return(s->b_udata); /* yes, return user data */
return((AVLUData *) 0); /* return failure */
}
#endif
void
AVLMapTree(root,pnode,uhdl)
AVLNodePtr root;
void (*pnode)();
char *uhdl;
{
if (root == NILAVL)
return;
(*pnode)(root->b_udata,uhdl); /* call with udata */
if (root->b_l != NILAVL)
AVLMapTree(root->b_l,pnode,uhdl); /* do left nodes */
if (root->b_r != NILAVL)
AVLMapTree(root->b_r,pnode,uhdl); /* do right nodes */
}

View File

@ -0,0 +1,38 @@
/*
* $Author: djh $ $Date: 91/02/15 21:05:50 $
* $Header: afpavl.h,v 2.1 91/02/15 21:05:50 djh Rel $
* $Revision: 2.1 $
*/
/*
* afpavl.h - Appletalk Filing Protocol AVL Tree Management definitions
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University in the
* City of New York.
*
*
* Edit History:
*
* Mar 30, 1987 Schilit Created, based on older versions
*
*
*/
typedef char AVLUData; /* baggage for user */
typedef struct avl_node {
short b_bf; /* balance factor 0, 1, or -1 */
struct avl_node *b_l; /* left child */
struct avl_node *b_r; /* right child */
AVLUData *b_udata; /* user data (baggage) */
} AVLNode, *AVLNodePtr;
#define NILAVL ((AVLNodePtr) 0)
AVLNode *AVLInsert();
AVLNode *AVLLookup();
void AVLPrintTree();
void AVLMapTree();

1190
applications/aufs/afpdid.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
/*
* $Author: djh $ $Date: 91/02/15 21:06:05 $
* $Header: afpdid.h,v 2.1 91/02/15 21:06:05 djh Rel $
* $Revision: 2.1 $
*/
/*
* afpdid.h - header file for AFP directory id mechanism.
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986,1987 by The Trustees of Columbia University in
* the City of New York.
*
* Edit History:
*
* Mon Mar 23, 1987 Schilit Created
*
*/

1070
applications/aufs/afpdir.c Normal file

File diff suppressed because it is too large Load Diff

2029
applications/aufs/afpdsi.c Normal file

File diff suppressed because it is too large Load Diff

108
applications/aufs/afpdsi.h Normal file
View File

@ -0,0 +1,108 @@
/*
* $Author: djh $ $Date: 91/03/14 13:45:20 $
* $Header: afpdsi.h,v 2.2 91/03/14 13:45:20 djh Exp $
* $Revision: 2.2 $
*
*/
/*
* afpdsi.h - Data Stream Interface Includes
*
* AFP via a Transport Protocol (eg: TCP/IP)
*
* AppleTalk package for UNIX
*
* The following routines implement a lightweight extra
* layer between AFP (as embodied in the AUFS code), the
* original ASP via ATP layer, and delivery via other
* Transport Protocol layers, currently only TCP/IP.
*
* Refer: "AppleTalk Filing Protocol 2.2 &
* AFP over TCP/IP Specification"
*
* SSS == Server Session Socket
* SLS == Session Listening Socket
* WSS == Workstation Session Socket
*
* Copyright (c) 1997 The University of Melbourne
* David Hornsby <djh@munnari.OZ.AU>
*
*/
/*
* options
*
*/
#define DSI_OPT_REQQ 0x00
#define DSI_OPT_ATTQ 0x01
#define DSI_OPT_REQLEN 4
#define DSI_OPT_ATTLEN 4
/*
* quantum sizes
*
*/
#define DSI_ATTN_SIZ 2
#define DSI_SRVR_CMD 1500
#define DSI_SRVR_MAX 64*1024
/*
* the DSI header will be inserted in front of
* every AFP request or reply packet
*
*/
struct dsi_hdr {
byte dsi_flags; /* used to determine packet type */
#define DSI_REQ_FLAG 0x00
#define DSI_REP_FLAG 0x01
byte dsi_command; /* similar to ASP commands, except WrtCont */
#define DSICloseSession 1
#define DSICommand 2
#define DSIGetStatus 3
#define DSIOpenSession 4
#define DSITickle 5
#define DSIWrite 6
#define DSIAttention 8
word dsi_requestID; /* req ID on per-session basis, wraps */
dword dsi_err_offset; /* error for reply, offset for write, else 0 */
dword dsi_data_len; /* total data length following dsi_hdr */
dword dsi_reserved; /* reserved for future, should be zero */
};
/*
* per-session demux info
*
*/
struct dsi_sess {
int sesstype;
#define DSI_SESSION_ATALK 0x01
#define DSI_SESSION_TCPIP 0x02
int state; /* type of DSI data expected */
#define DSI_STATE_HDR 0x01
#define DSI_STATE_AFP 0x02
#define DSI_STATE_DAT 0x03
#define DSI_STATE_REP 0x04
char *ptr; /* where we have to put incoming data */
int lenleft; /* amount of data expected to arrive */
int timeout; /* per-session tickle timer */
#define DSI_TIMEOUT 5*4
word sess_id_out; /* outgoing session ID (0-65535) */
word sess_id_in; /* incoming session ID (0-65535) */
struct dsi_hdr hdr; /* current incoming header (for reply) */
ASPQE *aspqe; /* callback data for GetRequest etc. */
};
/*
* IP filter list
*
*/
#define MAXIPFILTERS 100
#define MAXIPFILTSIZ sizeof(struct ipFilter)
struct ipFilter {
sword perm;
dword mask;
dword addr;
};

2159
applications/aufs/afpdt.c Normal file

File diff suppressed because it is too large Load Diff

148
applications/aufs/afpdt.h Normal file
View File

@ -0,0 +1,148 @@
/*
* $Author: djh $ $Date: 1994/10/10 09:02:04 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpdt.h,v 2.2 1994/10/10 09:02:04 djh Rel djh $
* $Revision: 2.2 $
*
*/
/*
* afpdt.h - Appletalk Filing Protocol Desktop definitions
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* Mar 30, 1987 Schilit Created.
*
*
*/
#include "afpavl.h" /* relies strickly on avl structs */
#define FF_ICON 00
#define FF_APPL 01
#define FF_COMM 02
#define FCreatorSize 4
#define FTypeSize 4
#define ITagSize 4
typedef struct { /* Icon Information */
sdword i_bmsize; /* 4: size of the icon bitmap */
byte i_FCreator[FCreatorSize]; /* 4[8]: file's creator type */
byte i_FType[FTypeSize]; /* 4[12] file's type */
byte i_IType; /* 1[13] icon type */
byte i_pad1; /* 1[14] */
byte i_ITag[ITagSize]; /* 4[18] user bytes */
byte i_pad2[2]; /* 2[20] pad out to double word boundry */
} IconInfo;
typedef struct { /* APPL information */
byte a_FCreator[4]; /* creator of application */
byte a_ATag[4]; /* user bytes */
} APPLInfo;
/* never use zero or 0x1741 as the major version */
#define AFR_MAGIC 0x00010002 /* version 1.2 (don't use 1.1, 2.2, etc) */
/* version 1.0 (version 0x1741.0000/0x1741) */
typedef struct { /* File Format APPL record */
dword afr_magic; /* magic number for check */
APPLInfo afr_info; /* the appl info */
sdword afr_pdirlen; /* length of (relative) parent directory */
sdword afr_fnamlen; /* length of application name */
/* name follows */
} APPLFileRecord;
/* never use zero or 0x2136 as the major version */
#define IFR_MAGIC 0x00010002 /* Version 1.2, skip 1.1, 2.2, etc. */
/* version 1.0: 0x2136.0000/0x2136 */
typedef struct { /* File Format ICON record */
dword ifr_magic; /* the magic check */
IconInfo ifr_info; /* the icon info */
/* bitmap follows this */
} IconFileRecord;
struct IconNodeStruct { /* Internal format Icon record */
IconInfo in_info; /* the icon info */
off_t in_iloc; /* file location */
int in_mloc; /* cache index */
byte *in_uloc; /* if set, then pointer to unix icon */
struct IconNodeStruct *in_next; /* pointer to next in chain */
};
typedef struct IconNodeStruct IconNode;
struct APPLNodeStruct { /* Internal format APPL record */
struct APPLNodeStruct *an_next;
APPLInfo an_info; /* Appl info */
IDirP an_ipdir; /* parent directory */
IDirP an_ippdir; /* parent of parent */
off_t an_iloc; /* location in .ADeskTop */
int an_flags; /* flags */
#define AN_DEL 0x1 /* entry is deleted - really need AVLDelete */
#define AN_MOD 0x2 /* entry is "new" - modified or added */
/* after readadesktop */
char *an_fnam; /* file name pointer */
};
typedef struct APPLNodeStruct APPLNode;
typedef struct {
int dt_ifd; /* handle on desktop file */
int dt_afd; /* handle on desktop file */
int dt_ivol; /* desktop belongs to this volume */
word dt_evol; /* external value of above */
AVLNode *dt_avlroot; /* root of avl tree mapping file creators */
byte dt_oFCreator[FCreatorSize]; /* key for last cache entry of above */
AVLNode *dt_avllast; /* node pointed to by key */
IDirP dt_rootd; /* volumes root dir */
int dt_opened; /* true if desktop is open */
} DeskTop, *DeskTopP;
#define IFRLEN (sizeof(IconFileRecord))
#define AFRLEN (sizeof(APPLFileRecord))
#define NILDT ((DeskTop *) 0)
private DeskTop *VolGetDesk();
private void VolSetDesk();
private void VolClrDesk();
typedef struct {
IconNode *ib_node; /* pointer to owner node */
byte *ib_data; /* pointer to the icon data */
int ib_size; /* size of icon data */
} IconCacheEntry, *ICEP;
/*
* ICSize is the size of the icon cache which is used to store icon
* bitmaps in memory. The size of the cache is dependant on the
* following:
*
* Memory:
* size of each entry is about 256 bytes (icon data size for b&w icons) +
* Sizeof(IconCacheEntry).
*
* Work:
* Reference to an icon bitmap in memory is constant time since the
* cache index is stored in the IconNode.
*
* Reference to an icon bitmap in a file causes a scan of the entire
* cache in order to find the minimum entry for replacement.
*
* Performance:
* A good cache size would try to contain all the icons on the desktop
* (considering the above constaints) since the finder will try to read
* the icon bitmaps when returning to the desktop.
*
*/
#define ICSize 100 /* number of icon cache entries */

View File

@ -0,0 +1,99 @@
/*
* $Author: djh $ $Date: 1996/04/27 12:03:04 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpfid.c,v 2.2 1996/04/27 12:03:04 djh Rel djh $
* $Revision: 2.2 $
*
*/
/*
* afpfid.c - File ID routines
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* September 1995 scooter Created
*
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h>
#endif _TYPES
#include <sys/stat.h>
#include <netat/appletalk.h>
#include <netat/afp.h>
#include "afps.h"
#ifdef FIXED_DIRIDS
#include "../../lib/afp/afpidaufs.h"
#endif /* FIXED_DIRIDS */
/*
* FIdmove(IDirP fpdir, char *from, IDirP tpdir, char *to)
*
* Maintains consistency in database structures when a file
* is renamed or moved.
*
* The file "from" in parent fpdir is being renamed to be
* "to" in the parent tpdir. Because file ids may not
* change we must modify the tree instead of recreating nodes.
*
*/
#ifndef FIXED_DIRIDS
void
FIdmove(fpdir,from,tpdir,to)
IDirP fpdir,tpdir;
char *from,*to;
{
return;
}
#else /* FIXED_DIRIDS */
void
FIdmove(fpdir,from,tpdir,to)
IDirP fpdir,tpdir;
char *from,*to;
{
IDirP fdir;
sdword toEid, fileID;
char path[MAXUFLEN];
#ifdef SHORT_NAMES
if (DBFIL && fpdir != NULL)
printf("FIdmove fpdir->name %s, tpdir->name %s, from %s, to %s\n",fpdir->name, tpdir->name, from, to);
#endif SHORT_NAMES
if (DBFIL) {
printf("FIdmove: changing path=%s, file=%s",pathstr(fpdir),from);
if (tpdir == fpdir)
printf(" to new name %s\n",to);
else
printf(" to path=%s, file=%s\n",pathstr(tpdir),to);
}
sprintf(path, "%s/%s", pathstr(fpdir), from);
/* Look up from to see if we have a FileID */
if ((fileID = aufsExtFindId(path)) < 0) {
if (DBFIL)
printf("FIdmove: no ID for %s/%s",pathstr(fpdir),from);
return; /* Nope, we're done */
}
/* We've got one, now rename it! */
if (fpdir != tpdir) { /* if different parents then... */
toEid = Edirid(tpdir);
aufsExtMoveIds(fileID, toEid, to);
} else { /* effectively a rename */
aufsExtRenameId(fileID, to);
}
}
#endif FIXED_DIRIDS

726
applications/aufs/afpfile.c Normal file
View File

@ -0,0 +1,726 @@
/*
* $Author: djh $ $Date: 1996/06/19 04:20:09 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpfile.c,v 2.11 1996/06/19 04:20:09 djh Rel djh $
* $Revision: 2.11 $
*
*/
/*
* afpfile.c - Appletalk Filing Protocol File Level Routines
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* March 1987 Schilit Created.
*
*/
/*
* Non OS dependant support routines for:
*
* FPExchangeFiles()
* FPSetFileParms()
* FPCreateFile()
* FPCopyFile()
* FPRename()
* FPDelete()
* FPMove()
*
*/
#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h>
#endif
#include <netat/appletalk.h>
#include <netat/afp.h>
#include <netat/afpcmd.h>
#include "afpntoh.h"
#include "afps.h"
#ifdef DEBUG_AFP_CMD
extern FILE *dbg;
#endif /* DEBUG_AFP_CMD */
/*
* OSErr FPSetFileParms(...)
*
*/
/*ARGSUSED*/
OSErr
FPSetFileParms(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
SetFileParmsPkt sfp;
FileDirParm fdp;
IDirP idir,ipdir;
char file[MAXUFLEN];
int ivol,len,err;
len = ntohPackX(PsSetFileParms,p,l,(byte *) &sfp);
ntohPackXbitmap(ProtoFileAttr,p+len,l-len,(byte *) &fdp,sfp.sfp_bitmap);
err = EtoIfile(file,&idir,&ipdir,&ivol,sfp.sfp_dirid,
sfp.sfp_volid,sfp.sfp_ptype,sfp.sfp_path);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_bmap();
void dbg_print_parm();
void dbg_print_path();
fprintf(dbg, "\tVolID: %04x\n", sfp.sfp_volid);
fprintf(dbg, "\tDirID: %08x\n", sfp.sfp_dirid);
fprintf(dbg, "\tBtMap: %08x\t", sfp.sfp_bitmap);
dbg_print_bmap(sfp.sfp_bitmap);
fprintf(dbg, "\tPType: %d\t(%s Names)\n", sfp.sfp_ptype,
(sfp.sfp_ptype == 1) ? "Short" : "Long");
dbg_print_path(sfp.sfp_path);
if (err == noErr)
fprintf(dbg, "\tUPath: \"%s/%s\"\n", pathstr(ipdir), file);
else
fprintf(dbg, "\tUPath: <EtoIfile returned %d>\n", err);
dbg_print_parm(sfp.sfp_bitmap, p+len, l-len, 0);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (err != noErr)
return(err);
fdp.fdp_fbitmap = sfp.sfp_bitmap; /* set file bitmap */
if (DBFIL)
printf("FPSetFileParms: setting bm=%d for %s %s\n",
fdp.fdp_fbitmap,pathstr(ipdir),file);
return(OSSetFileParms(ipdir,file,&fdp));
}
/*
* OSErr FPCreateFile(byte *p,byte *r,int *rl)
*
* This call is used to create a file.
*
*/
/*ARGSUSED*/
OSErr
FPCreateFile(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
CreateFilePkt crf;
int ivol,delf,err;
IDirP idir,ipdir;
char file[MAXUFLEN];
ntohPackX(PsCreateFile,p,l,(byte *) &crf);
err = EtoIfile(file,&idir,&ipdir,&ivol,crf.crf_dirid,
crf.crf_volid,crf.crf_ptype,crf.crf_path);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_path();
fprintf(dbg, "\tVolID: %04x\n", crf.crf_volid);
fprintf(dbg, "\tDirID: %08x\n", crf.crf_dirid);
fprintf(dbg, "\tPType: %d\t(%s Names)\n", crf.crf_ptype,
(crf.crf_ptype == 1) ? "Short" : "Long");
dbg_print_path(crf.crf_path);
if (err == noErr)
fprintf(dbg, "\tUPath: \"%s/%s\"\n", pathstr(ipdir), file);
else
fprintf(dbg, "\tUPath: <EtoIfile returned %d>\n", err);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (err != noErr)
return(err);
delf = (crf.crf_flg & CRF_HARD) != 0;
if (DBFIL)
printf("FPCreateFile flg=%02x, delf=%d, path=%s, fn=%s\n",
crf.crf_flg,delf,pathstr(ipdir),file);
err = OSCreateFile(ipdir,file,delf);
if (err == noErr) /* if success */
VolModified(ivol); /* then volume modified */
return(err);
}
#ifdef FIXED_DIRIDS
/*
* OSErr FPCreateID(byte *p,byte *r,int *rl)
*
* This call is used to create a file ID.
*
*/
/*ARGSUSED*/
OSErr
FPCreateID(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
CreateIDPkt crid;
int ivol,delf,err;
IDirP idir,ipdir;
char file[MAXUFLEN];
sdword fileID;
ntohPackX(PsCreateID,p,l,(byte *) &crid);
err = EtoIfile(file,&idir,&ipdir,&ivol,crid.crid_dirid,
crid.crid_volid,crid.crid_ptype,crid.crid_path);
if (err == noErr)
fileID = aufsExtEFileId(ipdir->edirid, file);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_path();
fprintf(dbg, "\tVolID: %04x\n", crid.crid_volid);
fprintf(dbg, "\tDirID: %08x\n", crid.crid_dirid);
fprintf(dbg, "\tPType: %d\t(%s Names)\n", crid.crid_ptype,
(crid.crid_ptype == 1) ? "Short" : "Long");
dbg_print_path(crid.crid_path);
if (err == noErr)
fprintf(dbg, "\tUPath: \"%s/%s\"\n", pathstr(ipdir), file);
else
fprintf(dbg, "\tUPath: <EtoIfile returned %d>\n", err);
fprintf(dbg, "\tFileID: %08x\n", fileID);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if ((err != noErr) && (DBFIL))
printf("error returned from EtoIfile\n");
PackDWord(fileID,r);
*rl = 4;
return(noErr);
}
/*
* OSErr FPResolveID(byte *p,byte *r,int *rl)
*
* This call is used to resolve a file ID.
*
*/
/*ARGSUSED*/
OSErr
FPResolveID(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
ResolveIDPkt rid;
int ivol,delf,err;
IDirP idir,ipdir;
FileDirParm fdp;
char file[MAXUFLEN];
sdword fileID;
char *path, *filep;
extern char *strrchr();
extern char *aufsExtPath();
idir = NULL;
ntohPackX(PsRslvID,p,l,(byte *) &rid);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_bmap();
fprintf(dbg, "\tVolID: %04x\n", rid.rid_volid);
fprintf(dbg, "\tFilID: %04x\n", rid.rid_fileid);
fprintf(dbg, "\tFBMap: %04x\t", rid.rid_fbitmap);
dbg_print_bmap(rid.rid_fbitmap, 0);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
/*
* get the path from the database
*/
if ((path = aufsExtPath(rid.rid_fileid)) == NULL)
return(aeIDNotFound);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
fprintf(dbg, "\tFName: %s\n", path);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
/*
* devide into file and dir
*/
filep = strrchr(path, '/');
if (filep)
*filep++ = '\0';
/*
* get the Volume ID
*/
ivol = EtoIVolid(rid.rid_volid); /* set internal volid */
/*
* get the directory ID
*/
ipdir = Idirid(path);
/*
* call OSFileDirInfo
*/
fdp.fdp_pdirid = ItoEdirid(ipdir,ivol);
fdp.fdp_dbitmap = 0;
fdp.fdp_fbitmap = rid.rid_fbitmap;
fdp.fdp_zero = 0;
err = OSFileDirInfo(ipdir,idir,filep,&fdp,ivol); /* fill in information */
if (err != noErr) {
if (DBFIL)
printf("FPResolveID: OSFileDirInfo returns %d on %s/%s\n",
err,pathstr(ipdir),file);
return(err);
}
PackWord(rid.rid_fbitmap,r);
*rl = 2;
*rl += htonPackX(FilePackR,(byte *) &fdp,r+(*rl));
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_parm();
void dbg_print_bmap();
fprintf(dbg, " Return Parameters:\n");
fprintf(dbg, "\tFBMap: %04x\t", fdp.fdp_fbitmap);
dbg_print_bmap(fdp.fdp_fbitmap, 0);
fprintf(dbg, "\tFDFlg: %02x\t(%s)\n", fdp.fdp_flg,
FDP_ISDIR(fdp.fdp_flg) ? "Directory" : "File");
if (*rl == 2)
fprintf(dbg, "\t<No Parameter List>\n");
else
dbg_print_parm(fdp.fdp_fbitmap, r+2, (*rl)-2, 0);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
return(noErr);
}
/*
* OSErr FPDeleteID(byte *p,byte *r,int *rl)
*
* This call is used to delete a file ID.
*
*/
/*ARGSUSED*/
OSErr
FPDeleteID(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
return(aeParamErr);
}
#endif /* FIXED_DIRIDS */
/*
* FPCopyFile(byte *p,byte *r,int *rl) [NOP]
*
* Optional, may not be supported on all servers.
*
*
*/
/*ARGSUSED*/
OSErr
FPCopyFile(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
CopyFilePkt cpf;
char sfile[MAXUFLEN],dfile[MAXUFLEN],newname[MAXUFLEN];
char *dfilep;
IDirP sidir,sipdir,didir,dipdir;
int sivol,divol;
int err;
ntohPackX(PsCopyFile,p,l,(byte *) &cpf);
err = EtoIfile(sfile,&sidir,&sipdir,&sivol,cpf.cpf_sdirid,
cpf.cpf_svolid,cpf.cpf_sptype,cpf.cpf_spath);
if (err != noErr)
return(err);
err = EtoIfile(dfile,&didir,&dipdir,&divol,cpf.cpf_ddirid,
cpf.cpf_dvolid,cpf.cpf_dptype,cpf.cpf_dpath);
if (err != noErr)
return(err);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_path();
fprintf(dbg, "\tSVolID: %04x\n", cpf.cpf_svolid);
fprintf(dbg, "\tSDirID: %08x\n", cpf.cpf_sdirid);
fprintf(dbg, "\tDVolID: %04x\n", cpf.cpf_dvolid);
fprintf(dbg, "\tDDirID: %08x\n", cpf.cpf_ddirid);
fprintf(dbg, "\tSPType: %d\t(%s Names)\n", cpf.cpf_sptype,
(cpf.cpf_sptype == 1) ? "Short" : "Long");
dbg_print_path(cpf.cpf_spath);
fprintf(dbg, "\tSUPath: \"%s/%s\"\n", pathstr(sipdir), sfile);
fprintf(dbg, "\tDPType: %d\t(%s Names)\n", cpf.cpf_dptype,
(cpf.cpf_dptype == 1) ? "Short" : "Long");
dbg_print_path(cpf.cpf_dpath);
fprintf(dbg, "\tDUPath: \"%s/%s\"\n", pathstr(dipdir), dfile);
fprintf(dbg, "\tNPType: %d\t(%s Names)\n", cpf.cpf_newtype,
(cpf.cpf_newtype == 1) ? "Short" : "Long");
fprintf(dbg, "\tNMFile: \"%s\"\n", cpf.cpf_newname);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (didir == NILDIR) /* destination directory */
return(aeParamErr); /* must be around */
#ifdef SHORT_NAMES
/* i don't have to worry about this if we are doing short names */
if ((err = EtoIName(cpf.cpf_newname,newname)) != noErr)
return(err);
#else SHORT_NAMES
if ((err = EtoIName(cpf.cpf_newname,newname)) != noErr)
return(err);
#endif SHORT_NAMES
if (*newname != '\0') /* if new name was specified */
dfilep = newname; /* then use that */
else /* otherwise if no new name */
dfilep = sfile; /* then use the source file name */
if (DBFIL) {
printf("FPCopyFile: srcvol=%d, srcdir=%s srcfil=%s\n",
sivol,pathstr(sipdir),sfile);
printf("FPCopyFile: dstvol=%d, dstdir=%s, dstname=%s\n",
divol,pathstr(didir),dfilep);
}
err = OSCopyFile(sipdir,sfile,didir,dfilep);
if (err == noErr) /* if success */
VolModified(divol); /* then dest volume modified */
return(err);
}
/*
* FPRename(byte *p,byte *r,int *rl)
*
* This call is used to rename either a file or directory.
*
*/
/*ARGSUSED*/
OSErr
FPRename(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
RenamePkt ren;
IDirP idir,ipdir,nidir,nipdir;
int ivol,err;
char file[MAXUFLEN],nfile[MAXUFLEN];
ntohPackX(PsRename,p,l,(byte *) &ren);
err = EtoIfile(file,&idir,&ipdir,&ivol,ren.ren_dirid,
ren.ren_volid,ren.ren_ptype,ren.ren_path);
if (err != noErr)
return(err);
err = EtoIfile(nfile,&nidir,&nipdir,&ivol,ren.ren_dirid,
ren.ren_volid,ren.ren_ntype,ren.ren_npath);
if (err != noErr)
return(err);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_path();
fprintf(dbg, "\tVolID: %04x\n", ren.ren_volid);
fprintf(dbg, "\tDirID: %08x\n", ren.ren_dirid);
fprintf(dbg, "\tPType: %d\t(%s Names)\n", ren.ren_ptype,
(ren.ren_ptype == 1) ? "Short" : "Long");
dbg_print_path(ren.ren_path);
fprintf(dbg, "\tPPath: \"%s/%s\"\n", pathstr(ipdir), file);
fprintf(dbg, "\tNType: %d\t(%s Names)\n", ren.ren_ntype,
(ren.ren_ntype == 1) ? "Short" : "Long");
dbg_print_path(ren.ren_npath);
fprintf(dbg, "\tNPath: \"%s/%s\"\n", pathstr(nipdir), nfile);
fprintf(dbg, "\tNwTyp: %d\t(%s Names)\n", ren.ren_ntype,
(ren.ren_ntype == 1) ? "Short" : "Long");
dbg_print_path(ren.ren_npath);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (DBFIL) {
printf("FPRename path=%s, name=%s,",pathstr(ipdir),file);
printf("to path=%s, name=%s\n",pathstr(nipdir),nfile);
}
if (ipdir != nipdir) {
printf("FPRename: different parent directory\n");
return(aeParamErr);
}
err = OSRename(ipdir,file,nfile);
if (err == noErr) {
OFNFIXUP(ipdir, file, ipdir, nfile);
}
return(err);
}
/*
* FPDelete(byte *p,byte *r,int *rl)
*
* This call is used to delete either a file or directory.
*
*/
/*ARGSUSED*/
OSErr
FPDelete(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
DeletePkt del;
IDirP idir,ipdir;
int ivol,err;
char file[MAXUFLEN];
ntohPackX(PsDelete,p,l,(byte *) &del);
err = EtoIfile(file,&idir,&ipdir,&ivol,del.del_dirid,
del.del_volid,del.del_ptype,del.del_path);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_path();
fprintf(dbg, "\tVolID: %04x\n", del.del_volid);
fprintf(dbg, "\tDirID: %08x\n", del.del_dirid);
fprintf(dbg, "\tPType: %d\t(%s Names)\n", del.del_ptype,
(del.del_ptype == 1) ? "Short" : "Long");
dbg_print_path(del.del_path);
if (err == noErr)
fprintf(dbg, "\tUPath: \"%s/%s\"\n", pathstr(ipdir), file);
else
fprintf(dbg, "\tUPath: <EtoIfile returned %d>\n", err);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (err != noErr)
return(err);
if (DBFIL)
printf("FPDelete: path=%s file=%s\n",pathstr(ipdir),file);
if (is_open_file(ipdir, file))
return(aeFileBusy);
#ifdef STAT_CACHE
OScd(pathstr(ipdir)); /* so we don't try and delete current directory */
#endif STAT_CACHE
err = OSDelete(ipdir,idir,file);
if (err == noErr) /* if success */
VolModified(ivol); /* then volume modified */
return(err);
}
/*
* FPMove(...)
*
* This call is used to move (not just copy) a directory or file
* to another location on a single volume (source and destination
* must be on the same volume). An object cannot be moved from one
* volume to another with this call, even though both volumes may be
* managed by the server. The destination of the move is specified
* by providing a DirID and Pathname that indicates the object's new
* Parent Directory.
*
*/
/*ARGSUSED*/
OSErr
FPMove(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
MovePkt mov;
IDirP idir,ipdir,nidir,nipdir;
int ivol,err;
char file[MAXUFLEN],nfile[MAXUFLEN];
char *nf;
#ifdef SHORT_NAMES
char tempfile[MAXUFLEN];
int i;
#endif SHORT_NAMES
ntohPackX(PsMove,p,l,(byte *) &mov);
err = EtoIfile(file,&idir,&ipdir,&ivol,mov.mov_sdirid,
mov.mov_volid,mov.mov_sptype,mov.mov_spath);
if (err != noErr)
return(err);
err = EtoIfile(nfile,&nidir,&nipdir,&ivol,mov.mov_ddirid,
mov.mov_volid,mov.mov_dptype,mov.mov_dpath);
if (err != noErr)
return(err);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_path();
fprintf(dbg, "\tSVolID: %04x\n", mov.mov_volid);
fprintf(dbg, "\tSDirID: %08x\n", mov.mov_sdirid);
fprintf(dbg, "\tDVolID: %04x\n", mov.mov_volid);
fprintf(dbg, "\tDDirID: %08x\n", mov.mov_ddirid);
fprintf(dbg, "\tSPType: %d\t(%s Names)\n", mov.mov_sptype,
(mov.mov_sptype == 1) ? "Short" : "Long");
dbg_print_path(mov.mov_spath);
fprintf(dbg, "\tSUPath: \"%s/%s\"\n", pathstr(ipdir), file);
fprintf(dbg, "\tDPType: %d\t(%s Names)\n", mov.mov_dptype,
(mov.mov_dptype == 1) ? "Short" : "Long");
dbg_print_path(mov.mov_dpath);
fprintf(dbg, "\tDUPath: \"%s/%s\"\n", pathstr(nipdir), nfile);
fprintf(dbg, "\tNPType: %d\t(%s Names)\n", mov.mov_newtype,
(mov.mov_newtype == 1) ? "Short" : "Long");
dbg_print_path(mov.mov_newname);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
/* nidir, nfile must be a directory! */
if (nidir == NILDIR)
return(aeParamErr);
/* where should this be done if not here? */
#ifdef SHORT_NAMES
if ((mov.mov_newtype != 0x2) && (mov.mov_newname[0]!= '\0')) {
for (i = 1; i <= (int)mov.mov_newname[0]; i++)
tempfile[i-1] = mov.mov_newname[i];
tempfile[mov.mov_newname[0]] = '\0';
if (DBFIL)
printf("tempfile %s\n",tempfile);
EtoIName_Short(nidir,tempfile, nfile);
nf = nfile;
}else if (mov.mov_newname[0] != '\0'){
EtoIName(mov.mov_newname, nfile);
nf = nfile;
#else SHORT_NAMES
if (mov.mov_newtype != 0x2)
return(aeParamErr);
if (mov.mov_newname[0] != '\0') {
EtoIName(mov.mov_newname, nfile);
nf = nfile;
#endif SHORT_NAMES
} else nf = file;
if (DBFIL) {
printf("FPMove path=%s, name=%s,",pathstr(ipdir),file);
printf("to path=%s, name=%s\n",pathstr(nidir),nf);
}
err = OSMove(ipdir,file,nidir,nf);
if (err == noErr) { /* if success */
OFNFIXUP(ipdir, file, nidir, nfile);
VolModified(ivol); /* then volume modified */
}
return(err);
}
/*
* FPExchangeFiles(...)
*
* Atomic exchange of two files. Swaps the data and resource forks
* but not the finder info.
*
*/
/*ARGSUSED*/
OSErr
FPExchangeFiles(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
ExchPkt xch;
IDirP aidir,aipdir,bidir,bipdir;
int ivol,err;
char afile[MAXUFLEN],bfile[MAXUFLEN];
char *nf;
ntohPackX(PsExchange,p,l,(byte *)&xch);
err = EtoIfile(afile,&aidir,&aipdir,&ivol,xch.exc_adirid,
xch.exc_volid,xch.exc_aptype,xch.exc_apath);
if (err != noErr)
return(err);
err = EtoIfile(bfile,&bidir,&bipdir,&ivol,xch.exc_bdirid,
xch.exc_volid,xch.exc_bptype,xch.exc_bpath);
if (err != noErr)
return(err);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_path();
fprintf(dbg, "\tEVolID: %04x\n", xch.exc_volid);
fprintf(dbg, "\tSDirID: %08x\n", xch.exc_adirid);
fprintf(dbg, "\tDDirID: %08x\n", xch.exc_bdirid);
fprintf(dbg, "\tSType: %d\t(%s Names)\n", xch.exc_aptype,
(xch.exc_aptype == 1) ? "Short" : "Long");
dbg_print_path(xch.exc_apath);
fprintf(dbg, "\tDType: %d\t(%s Names)\n", xch.exc_bptype,
(xch.exc_bptype == 1) ? "Short" : "Long");
dbg_print_path(xch.exc_bpath);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
/*
* Neither a nor b should be directories.
*
*/
if (aidir != NILDIR || bidir != NILDIR)
return(aeObjectTypeErr);
if (DBFIL) {
printf("FPExchangeFiles path=%s, name=%s,\n",pathstr(aipdir),afile);
printf(" with path=%s, name=%s\n",pathstr(bipdir),bfile);
}
err = OSExchangeFiles(aipdir,afile,bipdir,bfile);
if (err == noErr) { /* if success */
VolModified(ivol); /* then volume modified */
#ifdef FIXED_DIRIDS
{
char a_path[MAXPATHLEN], b_path[MAXPATHLEN];
sprintf(a_path, "%s/%s", pathstr(aipdir),afile);
sprintf(b_path, "%s/%s", pathstr(bipdir),bfile);
aufsExtExchange(a_path, b_path);
}
#endif /* FIXED_DIRIDS */
}
return(err);
}

705
applications/aufs/afpfork.c Normal file
View File

@ -0,0 +1,705 @@
/*
* $Author: djh $ $Date: 1995/06/26 05:49:55 $
* $Header: /local/mulga/mac/src/cap60/applications/aufs/RCS/afpfork.c,v 2.8 1995/06/26 05:49:55 djh Rel djh $
* $Revision: 2.8 $
*/
/*
* afpfork.c - Appletalk Filing Protocol Fork Level Routines
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* March 1987 Schilit Created.
*
*/
/*
* Non OS dependant support routines for:
*
* FPGetForkParms()
* FPSetForkParms()
* FPOpenFork()
* FPCloseFork()
* FPRead()
* FPWrite()
* FPFlushFork()
* FPByteRangeLock()
*
*/
#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h>
#endif
#include <netat/appletalk.h>
#include <netat/afp.h>
#include <netat/afpcmd.h>
#include "afps.h"
#include "afpntoh.h"
#include "afposncs.h"
#ifdef DEBUG_AFP_CMD
extern FILE *dbg;
#endif /* DEBUG_AFP_CMD */
typedef struct {
int ofn_fd; /* file descriptor */
sdword ofn_pos; /* file position */
IDirP ofn_ipdir;
int ofn_ivol;
int ofn_efn; /* external file number */
char ofn_fnam[MAXUFLEN]; /* file name */
int ofn_mode;
int ofn_type; /* data or rsrc */
int ofn_flgs; /* file flags */
#define OF_EOF 0x020 /* eof on file */
#define OF_NOTOPEN 0x02 /* to support non-existent files */
#define OF_INUSE 0x04 /* OFN is in use */
int ofn_trans_table; /* Translation table if any */
} OFN;
#define MaxOFN 30
private OFN OFNTBL[MaxOFN];
private int oinit = FALSE;
private
iniofn()
{
int i;
for (i=0; i < MaxOFN; i++) {
OFNTBL[i].ofn_flgs = 0;
OFNTBL[i].ofn_pos = -1;
OFNTBL[i].ofn_trans_table = -1; /* no index */
OFNTBL[i].ofn_efn = i+1;
}
oinit = TRUE;
}
private word
ItoEOFN(o)
OFN *o;
{
return(o->ofn_efn);
}
private OFN *
EtoIOFN(i)
int i;
{
i = i-1;
if (i > MaxOFN || i < 0) {
printf("EtoIOFN: bad file number\n");
return(NULL);
}
if (!oinit || (OFNTBL[i].ofn_flgs & OF_INUSE) == 0) /* ofn assigned? */
return(NULL); /* no, mark as bad */
return(&OFNTBL[i]);
}
private void
relofn(ofn)
OFN *ofn;
{
ofn->ofn_flgs = 0;
ofn->ofn_pos = -1;
ofn->ofn_trans_table = -1; /* delete */
}
private OFN *
asnofn()
{
int i;
if (!oinit)
iniofn();
for (i=0; i < MaxOFN; i++)
if ((OFNTBL[i].ofn_flgs & OF_INUSE) == 0) {
OFNTBL[i].ofn_trans_table = -1; /* paranoia: no index */
OFNTBL[i].ofn_flgs = OF_INUSE;
return(&OFNTBL[i]);
}
return(0);
}
/*
* This is a horrible hack that is necessary to ensure that renames
* get reflected back. Really, really, points to the need for internal
* directory of names.... Can't use fstat because file name is required
* to return some of the information (from finderinfo). Sigh...
*
*/
OFNFIXUP(oipdir, ofile, nipdir, nfile)
IDirP oipdir;
char *ofile;
IDirP nipdir;
char *nfile;
{
OFN *ofn;
if (!oinit)
return(-1);
for (ofn = OFNTBL; ofn < OFNTBL+MaxOFN; ofn++)
if (ofn->ofn_flgs & OF_INUSE) {
if (ofn->ofn_ipdir == oipdir && strcmp(ofn->ofn_fnam, ofile) == 0) {
ofn->ofn_ipdir = nipdir; /* remember new directory */
strcpy(ofn->ofn_fnam, nfile); /* remember new file */
}
}
return(0);
}
/*
* determine if file is already open
*
*/
int
is_open_file(ipdir, file)
IDirP ipdir;
char *file;
{
OFN *ofn;
if (!oinit)
return(0);
for (ofn = OFNTBL; ofn < OFNTBL+MaxOFN; ofn++)
if (ofn->ofn_flgs & OF_INUSE)
if (ofn->ofn_ipdir == ipdir
&& strcmp(ofn->ofn_fnam, file) == 0)
return(1);
return(0);
}
/*
* OSErr FPGetForkParms(...)
*
* This call is used to retrieve parameters for a file associated with
* a particular open fork.
*
* Inputs:
* refnum Open fork refnum
* bitmap Bitmap describing which parameters are to be retrieved.
* This field is the same as the FPGetFileDirParms call.
*
* Outputs:
* Same as FPGetFileDirParms.
*
* Errors:
* ParamErr, BitMapErr, AccessDenied.
*
* The fork must be open for read.
*
*/
OSErr
FPGetForkParms(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
GetForkParmsPkt gfp;
FileDirParm fdp;
int err;
OFN *ofn;
ntohPackX(PsGetForkParms,p,l,(byte *) &gfp);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_bmap();
fprintf(dbg, "\tRefNum: %d\n", gfp.gfp_refnum);
fprintf(dbg, "\tBitMap: %04x\t", gfp.gfp_bitmap);
dbg_print_bmap(gfp.gfp_bitmap, 0);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if ((ofn = EtoIOFN(gfp.gfp_refnum)) == NULL)
return(aeParamErr);
fdp.fdp_pdirid = ItoEdirid(ofn->ofn_ipdir,ofn->ofn_ivol);
fdp.fdp_dbitmap = 0;
fdp.fdp_fbitmap = gfp.gfp_bitmap;
fdp.fdp_zero = 0;
err = OSFileDirInfo(ofn->ofn_ipdir,NILDIR,ofn->ofn_fnam,&fdp,ofn->ofn_ivol);
if (err != noErr)
return(err);
PackWord(gfp.gfp_bitmap,r);
*rl = 2;
*rl += htonPackX(FilePackR,(byte *) &fdp,r+(*rl));
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_parm();
fprintf(dbg, " Return Parameters:\n");
dbg_print_parm(fdp.fdp_fbitmap, r+2, (*rl)-2, 0);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
return(noErr);
}
/*
* OSErr FPSetForkParms(...)
*
* Inputs:
*
* refnum Open fork refnum.
* bitmap Bitmap describing which params are to be set.
*
* Output:
* Function Result.
*
* Errors:
* ParamErr, BitMapErr, DiskFull, LockErr, AccessDenied.
*
* The bitmap is the same as FPSetFileDirParms, however in AFP 1.1
* only the fork length may be set.
*
* The fork must be opened for write.
*
*/
/*ARGSUSED*/
OSErr
FPSetForkParms(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
SetForkParmsPkt sfkp;
OFN *ofn;
sdword len;
ntohPackX(PsSetForkParms,p,l,(byte *) &sfkp);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_bmap();
fprintf(dbg, "\tRefNum: %d\n", sfkp.sfkp_refnum);
fprintf(dbg, "\tBitMap: %04x\t", sfkp.sfkp_bitmap);
dbg_print_bmap(sfkp.sfkp_bitmap, 0);
fprintf(dbg, "\tForkLn: %d\n",
(sfkp.sfkp_bitmap & FP_DFLEN) ? sfkp.sfkp_dflen : sfkp.sfkp_rflen);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if ((ofn = EtoIOFN(sfkp.sfkp_refnum)) == NULL)
return(aeParamErr);
if (DBFRK)
printf("FPSetForkParms: ofn=%d\n",sfkp.sfkp_refnum);
if ((sfkp.sfkp_bitmap & ~(FP_DFLEN|FP_RFLEN)) != 0 || sfkp.sfkp_bitmap==0) {
printf("FPSetForkParms: bad bitmap %x\n",sfkp.sfkp_bitmap);
return(aeBitMapErr);
}
len = (sfkp.sfkp_bitmap & FP_DFLEN) ? sfkp.sfkp_dflen : sfkp.sfkp_rflen;
/* can only set fork length for now */
return((ofn->ofn_flgs&OF_NOTOPEN) ? noErr : OSSetForklen(ofn->ofn_fd, len));
}
OSErr
FPOpenFork(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
OpenForkPkt ofk;
OpenForkReplyPkt ofr;
FileDirParm fdp;
int ivol,err,err1,flg,fhdl,len, ttidx;
IDirP idir,ipdir;
char file[MAXUFLEN];
byte finderinfo[FINFOLEN];
OFN *ofn;
extern PackEntry ProtoOFkRP[];
ntohPackX(PsOpenFork,p,l,(byte *) &ofk);
err = EtoIfile(file,&idir,&ipdir,&ivol,ofk.ofk_dirid,
ofk.ofk_volid,ofk.ofk_ptype,ofk.ofk_path);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_mode();
void dbg_print_bmap();
void dbg_print_path();
fprintf(dbg, "\tOFork: %s\n", (ofk.ofk_rdflg) ? "Resource" : "Data");
fprintf(dbg, "\tVolID: %04x\n", ofk.ofk_volid);
fprintf(dbg, "\tDirID: %08x\n", ofk.ofk_dirid);
fprintf(dbg, "\tBtMap: %04x\t", ofk.ofk_bitmap);
dbg_print_bmap(ofk.ofk_bitmap, 0);
fprintf(dbg, "\tAMode: %04x\t", ofk.ofk_mode);
dbg_print_mode(ofk.ofk_mode);
fprintf(dbg, "\tPType: %d\t(%s Names)\n", ofk.ofk_ptype,
(ofk.ofk_ptype == 1) ? "Short" : "Long");
dbg_print_path(ofk.ofk_path);
if (err == noErr)
fprintf(dbg, "\tUPath: \"%s/%s\"\n", pathstr(ipdir), file);
else
fprintf(dbg, "\tUPath: <EtoIfile returned %d>\n", err);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (err != noErr)
return(err);
if (DBFRK)
printf("OpenFork: rdflg=%d, mode=%d, path=%s file=%s\n",
ofk.ofk_rdflg,ofk.ofk_mode,pathstr(ipdir),file);
flg = (ofk.ofk_rdflg == 0) ? F_DATA : F_RSRC;
err = OSOpenFork(ipdir,file,ofk.ofk_mode,flg,&fhdl);
if (err != noErr
&& err != aeDenyConflict
&& !(flg == F_RSRC && err == aeObjectNotFound))
return(err);
/*
* now, if data fork exists and resource
* open failed, allow go ahead
*
*/
if (err == aeObjectNotFound) {
#ifdef notdef
/* why did I do this? */
if (ofk.ofk_mode & OFK_MWR) /* don't allow write access */
return(aeAccessDenied);
#endif
if (OSFileExists(ipdir, file, F_DATA) != noErr)
return(aeObjectNotFound);
else {
if (DBFRK)
printf("Allowing fake access to resource fork\n");
}
}
if ((ofn = asnofn()) == 0) {
if (err == noErr)
OSClose(fhdl);
return(aeTooManyFilesOpen);
}
ofn->ofn_fd = fhdl;
ofn->ofn_mode = ofk.ofk_mode;
ofn->ofn_type = flg;
ofn->ofn_ipdir = ipdir;
ofn->ofn_ivol = ivol;
if (err == aeObjectNotFound
|| err == aeDenyConflict)
ofn->ofn_flgs |= OF_NOTOPEN;
if (flg == F_DATA) {
/* Never translate resource fork */
OSGetFNDR(ipdir, file, finderinfo); /* check file type */
#ifdef SHORT_NAMES
if (DBFRK)
printf("afpfork, ofk.ofk_path %d\n",ofk.ofk_ptype);
if ((ttidx = ncs_istrans(finderinfo, file, ofk.ofk_ptype)) >= 0) {
#else SHORT_NAMES
if ((ttidx = ncs_istrans(finderinfo, file)) >= 0) {
#endif SHORT_NAMES
ofn->ofn_trans_table = ttidx;
if (DBFRK)
printf("Open fork: translation table: %s\n", ncs_tt_name(ttidx));
}
}
strcpy(ofn->ofn_fnam,file); /* remember file name (UGH!!!!) */
fdp.fdp_fbitmap = ofk.ofk_bitmap;
fdp.fdp_dbitmap = 0;
if ((err1 = OSFileDirInfo(ipdir,NILDIR,file,&fdp,ivol)) != noErr) {
if (err != noErr)
OSClose(fhdl);
relofn(ofn);
return(err1);
}
ofr.ofkr_bitmap = ofk.ofk_bitmap;
ofr.ofkr_refnum = (err == aeDenyConflict) ? 0x0000 : ItoEOFN(ofn);
len = htonPackX(ProtoOFkRP, &ofr, r); /* pack away */
*rl = len + htonPackX(FilePackR,(byte *) &fdp,r+len);
if (err == aeDenyConflict) {
relofn(ofn);
return(err);
}
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
void dbg_print_parm();
void dbg_print_bmap();
fprintf(dbg, " Return Parameters:\n");
fprintf(dbg, "\tFDescr: %d\n", ofn->ofn_fd);
fprintf(dbg, "\tBitMap: %04x\t", ofr.ofkr_bitmap);
dbg_print_bmap(ofk.ofk_bitmap, 0);
fprintf(dbg, "\tRefNum: %d\n", ofr.ofkr_refnum);
dbg_print_parm(ofr.ofkr_bitmap, r+len, *rl, 0);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
return(noErr);
}
/*ARGSUSED*/
OSErr
FPCloseFork(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
CloseForkPkt cfk;
word attr;
OFN *ofn;
int err;
ntohPackX(PsCloseFork,p,l,(byte *) &cfk);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
fprintf(dbg, "\tRefNum: %d\n", cfk.cfk_refnum);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (DBFRK)
printf("CloseFork: refnum=%d\n",cfk.cfk_refnum);
if ((ofn = EtoIOFN(cfk.cfk_refnum)) == NULL)
return(aeParamErr);
if ((ofn->ofn_mode & OFK_MWR) != 0) /* if opened for write */
VolModified(ofn->ofn_ivol); /* then set volume modification dt */
err = (ofn->ofn_flgs & OF_NOTOPEN) ? noErr : OSClose(ofn->ofn_fd);
if (err == noErr) {
OSGetAttr(ofn->ofn_ipdir, ofn->ofn_fnam, &attr);
attr &= ~((ofn->ofn_type == F_DATA) ? FPA_DAO : FPA_RAO);
OSSetAttr(ofn->ofn_ipdir, ofn->ofn_fnam, attr);
}
relofn(ofn);
return(err);
}
/*
*
* FPRead(...)
*
* The fork is read starting offset bytes from the beginning of the fork
* and terminating at the first newline-char encountered.
*
*/
OSErr
FPRead(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
ReadPkt rp;
OFN *ofn;
extern int sqs; /* get max send quantum size */
ntohPackX(PsRead,p,l,(byte *) &rp);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
fprintf(dbg, "\tRefNum: %d\n", rp.rdf_refnum);
fprintf(dbg, "\tOffSet: %d\n", rp.rdf_offset);
fprintf(dbg, "\tReqCnt: %d\n", rp.rdf_reqcnt);
fprintf(dbg, "\tNLMask: %d\n", rp.rdf_flag);
fprintf(dbg, "\tNLChar: 0x%02x\n", rp.rdf_nlchar);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if (DBFRK)
printf("Read: ofn=%d, offset=%d, reqcnt=%d, flg=%d, nlc=%02x\n",
rp.rdf_refnum,rp.rdf_offset,rp.rdf_reqcnt,
rp.rdf_flag,rp.rdf_nlchar);
if ((ofn = EtoIOFN(rp.rdf_refnum)) == NULL)
return(aeParamErr);
if (ofn->ofn_flgs & OF_NOTOPEN) {
*rl = 0;
return(aeEOFErr);
}
return(OSRead(ofn->ofn_fd,rp.rdf_offset,
min(rp.rdf_reqcnt,sqs),
rp.rdf_flag,rp.rdf_nlchar,r,rl,&ofn->ofn_pos,
ofn->ofn_trans_table));
}
OSErr
FPWrite(p,l,r,rl,cno,reqref)
byte *p,*r;
int l,*rl;
int cno;
ReqRefNumType reqref;
{
WritePkt wrt;
int rcvlen;
int comp,err;
OFN *ofn;
extern int n_rrpkts;
ntohPackX(PsWrite,p,l,(byte *) &wrt);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
fprintf(dbg, "\tS/EFlg: %02x\n", wrt.wrt_flag);
fprintf(dbg, "\tRefNum: %d\n", wrt.wrt_refnum);
fprintf(dbg, "\tOffset: %d\n", wrt.wrt_offset);
fprintf(dbg, "\tReqCnt: %d\n", wrt.wrt_reqcnt);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if ((ofn = EtoIOFN(wrt.wrt_refnum)) == NULL)
return(aeParamErr);
if (DBFRK)
printf("FPWrite: ofn=%d, flg=%d, offs=%d, req=%d\n",
wrt.wrt_refnum,wrt.wrt_flag,wrt.wrt_offset,wrt.wrt_reqcnt);
if (ofn->ofn_flgs & OF_NOTOPEN) {
if (wrt.wrt_reqcnt != 0) /* allow zero length requests */
return(aeAccessDenied);
}
err = dsiWrtContinue(cno,reqref,r,n_rrpkts*atpMaxData,&rcvlen,-1,&comp);
if (err != noErr)
return(err);
do { abSleep(4,TRUE); } while (comp > 0);
if (comp < 0)
return(comp);
err = OSWrite(ofn->ofn_fd,r,(sdword) rcvlen,
wrt.wrt_offset,wrt.wrt_flag,&ofn->ofn_pos,
ofn->ofn_trans_table);
if (err != noErr)
return(err);
PackDWord(ofn->ofn_pos,r);
*rl = sizeof(ofn->ofn_pos);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
fprintf(dbg, " Return Parameters:\n");
fprintf(dbg, "\tWrittn: %d\n", ofn->ofn_pos);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
return(noErr);
}
/*ARGSUSED*/
OSErr
FPFlushFork(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
OFN *ofn;
FlushForkPkt flf;
ntohPackX(PsFlush, p, l, (byte *)&flf);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL ) {
fprintf(dbg, "\tRefNum: %d\n", flf.flf_refnum);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if ((ofn = EtoIOFN(flf.flf_refnum)) == NULL)
return(aeParamErr);
if (DBFRK)
printf("FLFlush: ofn=%d\n", flf.flf_refnum);
return((ofn->ofn_flgs & OF_NOTOPEN) ? noErr : OSFlushFork(ofn->ofn_fd));
}
/*ARGSUSED*/
OSErr
FPByteRangeLock(p,l,r,rl)
byte *p,*r;
int l,*rl;
{
OFN *ofn;
ByteRangeLockPkt brl;
OSErr err;
ntohPackX(PsByteRangeLock, p, l, (byte *)&brl);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
fprintf(dbg, "\tULFlag: %s\n", (brl.brl_flg & 0x01) ? "UNLOCK" : "LOCK");
fprintf(dbg, "\tSEFlag: %s\n", (brl.brl_flg & 0x80) ? "END" : "START");
fprintf(dbg, "\tRefNum: %d\n", brl.brl_refnum);
fprintf(dbg, "\tOffset: %d\n", brl.brl_offset);
fprintf(dbg, "\tLength: %d\n", brl.brl_length);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
if ((ofn = EtoIOFN(brl.brl_refnum)) == NULL)
return(aeParamErr);
if (DBFRK)
printf("Byte Range Lock: ofn=%d (file %s)\n",ofn->ofn_fd,ofn->ofn_fnam);
if (ofn->ofn_flgs & OF_NOTOPEN)
ofn->ofn_pos = brl.brl_offset;
else {
err = OSByteRangeLock(ofn->ofn_fd, brl.brl_offset, brl.brl_length,
brl.brl_flg, &ofn->ofn_pos);
if (err != noErr)
return(err);
}
PackDWord(ofn->ofn_pos,r);
*rl = sizeof(ofn->ofn_pos);
#ifdef DEBUG_AFP_CMD
if (dbg != NULL) {
fprintf(dbg, " Return Parameters:\n");
fprintf(dbg, "\tRStart: %d\n", ofn->ofn_pos);
fflush(dbg);
}
#endif /* DEBUG_AFP_CMD */
return(noErr);
}
#ifdef DEBUG_AFP_CMD
void
dbg_print_mode(mode)
u_short mode;
{
if (dbg != NULL) {
fprintf(dbg, "(");
if (mode & 0x0001)
fprintf(dbg, "Read ");
if (mode & 0x0002)
fprintf(dbg, "Write ");
if (mode & 0x0004)
fprintf(dbg, "DenyRead ");
if (mode & 0x0008)
fprintf(dbg, "DenyWrite ");
fprintf(dbg, ")\n");
}
}
#endif /* DEBUG_AFP_CMD */

251
applications/aufs/afpgc.c Normal file
View File

@ -0,0 +1,251 @@
/*
* $Author: djh $ $Date: 91/02/15 21:07:18 $
* $Header: afpgc.c,v 2.1 91/02/15 21:07:18 djh Rel $
* $Revision: 2.1 $
*/
/*
* afpgc.c - Appletalk Filing Protocol General Cache Manager
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
*
* Apr 3, 1987 Schilit Created.
*
*/
/*
* General Cache Routines.
*
* These routines may be used for building a cache based on LRU
* replacement.
*
* The caller controls the cache by supplying routines for loading,
* purging, comparing, and validating entries.
*
* The cache is initialized and the size is defined by a call to
* GCNew, all the other work is performed by the lookup routine,
* GCLocate. See the comments on those routines for calling
* conventions.
*
*/
/*
* GCNew - create a new cache
* GCScan - locate cache entry
* GCLocate - locate cache entry, loading if necessary
* GCFlush - flush cache
* GCGet - get cache entry
* GCAdd - add cache entry
*/
#include "afpgc.h" /* include defs for cache */
#define TRUE 1
#define FALSE 0
/*
* GCHandle *GCNew(size,int (*valid)(), int (*comp)(),
* char *(*load)(), void (*purge)());
*
* Create a new cache of size 'size' and define the interface routines
* for validating, comparing, loading, and purging entries.
*
* int valid(ce) - returns TRUE if entry is valid.
* int comp(ce,key) - compare and return 0 if equal.
* char *load(key) - load an entry (allocate stg and/or read from disk).
* void purge(ce) - purge an entry (release stg & write to disk).
* void flush(ce) - flush entry (write to disk)
*
*
* The datatype of a cache entry is defined by the *result* of load().
* This datatype is stored in the cache and passed to purge(), valid()
* and as the first argument to comp().
*
* A second datatype may be defined for the lookup key. This is the
* argument to GCLocate and is sent to comp() to compare against an
* existing cache entry. Load() accepts a key and returns the cache
* entry for that key.
*
*/
GCHandle *
GCNew(size,cvalid,ccomp,cload,cpurge,cflush)
int size;
int (*cvalid)();
int (*ccomp)();
char *(*cload)();
void (*cpurge)();
void (*cflush)();
{
GCHandle *gch;
int i;
gch = (GCHandle *) malloc(sizeof(GCHandle));
gch->gch_clock = 0;
gch->gch_size = size;
gch->gch_valid = cvalid; /* validation routine */
gch->gch_comp = ccomp; /* compare routine */
gch->gch_load = cload; /* loading routine */
gch->gch_purge = cpurge; /* release routine */
gch->gch_flush = cflush; /* write or update */
gch->gch_lru = (int *) malloc(sizeof(int)*size);
gch->gch_ents = (GCUData **) malloc(sizeof(GCUData *) * (size));
for (i=0; i < size; i++)
gch->gch_lru[i] = -1;
return(gch);
}
/*
* boolean GCScan(GCHandle *gch, GCUData *key, int *idx)
*
* Scan the cache (gch) looking for key.
*
* Returns TRUE if the entry was found in the cache, idx is the index
* of the entry.
*
* Returns FALSE if no entry was found in the cache, idx is a free
* entry (may have called user's purge).
*
*/
/* private */ int
GCScan(gch, key, idx)
GCHandle *gch;
GCUData *key;
int *idx;
{
register GCUData **ent = gch->gch_ents;
register int *lru = gch->gch_lru;
register int i;
register int mi = 0;
register int mf = -1;
for (i=0; i < gch->gch_size; i++) { /* scan cache for entry and min */
if (lru[i] < 0) /* entry in cache? */
mf = i; /* no, remember free entry */
else {
if ((*gch->gch_comp)(ent[i],key)) /* compare */
if ((*gch->gch_valid)(ent[i])) { /* match, see if entry is valid */
lru[i] = gch->gch_clock++; /* found matching valid entry */
*idx = i; /* here is the cache index */
return(TRUE); /* aready in cache return TRUE */
} else {
mf = i; /* invalid and matching, so reuse it */
break; /* break out of for loop */
}
if (lru[i] < lru[mi]) /* no match, check for min entry */
mi = i; /* if so remember */
}
}
/* Miss. cache scan is over without locating the desired entry. */
/* if we did not find a free entry then free the min lru found */
/* and load the cache with the desired entry. */
if (mf < 0) { /* did we find a free entry */
(*gch->gch_purge)(ent[mi]); /* no, free the min entry */
mf = mi; /* now here is a slot */
}
*idx = mf; /* set index */
return(FALSE);
}
/*
* char *GCLocate(GCHandle *gch, char *key)
*
* Locate the entry matching 'key' in the cache 'gch' by calling
* the comparision routine comp() for each cache entry.
*
* If no entry is found, or the matching entry fails the user
* specified valid() check, then add a new cache entry by calling
* the load() procedure.
*
* If the cache is full, then replacement is required and the
* user specified purge() is called to release the LRU entry.
*
*/
char *
GCLocate(gch,key)
GCHandle *gch;
char *key;
{
int idx;
if (GCScan(gch,key,&idx)) /* scan for entry */
return(gch->gch_ents[idx]); /* found it, so return */
gch->gch_lru[idx] = gch->gch_clock++; /* else free entry, set clock */
gch->gch_ents[idx] = (*gch->gch_load)(key); /* load it in */
return(gch->gch_ents[idx]); /* and return it */
}
/*
* flush is called when OSFlush gets called -- could and should be
* done without releasing cache entries by using user defined flush
* routine: in other words, it is a prime opportunity to scan for "bad"
* items
*
* allows passing of userdata (single long)
*
*/
void
GCFlush(gch, udata)
GCHandle *gch;
unsigned long udata;
{
int i;
char **ent = gch->gch_ents;
int *lru = gch->gch_lru;
for (i=0; i < gch->gch_size; i++) /* scan cache for entry and min */
if (lru[i] >= 0) /* entry in cache? */
if ((*gch->gch_valid)(ent[i])) /* yes... entry valid? */
(*gch->gch_flush)(ent[i], udata); /* yes.. then flush */
}
/*
* GCUData *GCGet(GCHandle *gch, int idx)
*
* Return the cache entry at index idx.
*
*/
GCUData *
GCGet(gch,idx)
GCHandle *gch;
int idx;
{
return(gch->gch_ents[idx]);
}
/*
* int GCAdd(GCHandle *gch, GCUData *udata)
*
* Add the entry udata to the cache. Returns cache index.
*
* Adding an entry may cause user's flush routine to be called
* if the cache is full.
*
*/
int
GCAdd(gch, udata)
GCHandle *gch;
GCUData *udata;
{
int idx;
if (GCScan(gch,udata,&idx)) /* scan for entry in cache */
return(idx); /* found it, oh well.. */
gch->gch_lru[idx] = gch->gch_clock++; /* else free entry, set clock */
gch->gch_ents[idx] = udata; /* store entry */
return(idx); /* and return index */
}

48
applications/aufs/afpgc.h Normal file
View File

@ -0,0 +1,48 @@
/*
* $Author: djh $ $Date: 91/02/15 21:07:27 $
* $Header: afpgc.h,v 2.1 91/02/15 21:07:27 djh Rel $
* $Revision: 2.1 $
*/
/*
* afpgc.c - Appletalk Filing Protocol General Cache Manager Definitions
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
*
* Apr 3, 1987 Schilit Created.
*
*/
/* GCHandle is the general cache manager's handle on a cache */
typedef char GCUData;
typedef struct {
int gch_clock; /* the current cache clock */
int gch_size; /* the size of the cache */
int (*gch_valid)(); /* valid function */
int (*gch_comp)(); /* compare function */
char *(*gch_load)(); /* load function */
void (*gch_purge)(); /* free function */
void (*gch_flush)(); /* write to disk function */
int *gch_lru; /* clocks for each entry */
GCUData **gch_ents; /* data for each entry */
} GCHandle;
/* given a pointer cache pointer and an index, returns an entry */
#define GCidx2ent(gch,idx) ((gch)->gch_ents[(idx)])
GCHandle *GCNew(); /* create a new cache */
GCUData *GCLocate(); /* locate an entry in the cache */
void GCFlush(); /* flush the cache */
GCUData *GCGet(); /* direct access get by index */
int GCAdd(); /* direct access add to cache */
#define NOGCIDX -1 /* NULL cache index */

View File

@ -0,0 +1,160 @@
afpidsrvr
---------
This provides aufs with permanent external directory and file id's.
Rather than remembering pathnames, Mac's often store a number for
the directory and the name of the file. These id's must be mapped
by aufs onto the Unix file system - thus the term "external id's".
External id's are used extensively by the alias manager, and also
affect QuickTime. aufs's problem is that it forgets the id's after
each session. This causes many problems, the greatest being that
aliases do not work properly.
The previous, and still default, version created external id's as
required in a linear manner. These are mapped onto pointers -
internally aufs holds the directory picture as a tree. An array of
these pointers, indexed by the external id, was used to perform the
external to internal mapping. The reverse mapping was achieved
primarily by a field in the internal directory records.
This new version uses a central database to hold the external id's.
Various schemes were examined, including the use of inode numbers.
Most were rejected on the realisation that a single scheme had to
cover the whole file system: you cannot assign numbers by volumes.
The database is single-writer/multi-reader. aufs processes read
id/path pairs from the database, but if they want to add entries they
send a request to the 'afpidsrvr'. The use of a server at least
ensures consistency is maintained, gets around the basic problem of
the lack of locks, and preserves some security. So far, at least, the
system has worked without locks - aufs does re-open databases after
it detects change, to avoid some problems. Security is not
particularly strict - the server will not create entries if
directories don't exist, and will not remove entries for existing
directories. The system is not foolproof, and can have problems if
the database gets corrupted, but there we are.
The current version (1.1) of the database is the second go. The first
version contained two sets of entries: fullpath->id and id->fullpath.
This worked fine until the system tried to delete or move directory
trees - it just moved the top one, and left the children in their
original places. The second version mirrors the directory structure
in providing a tree. Moving and deleting now alters the tree
structure. This means that many more accesses are required, but the
records themselves are on average smaller. Each record, looked up by
key N<id>, consists of:
<parent id><num children><child ids....><name>
There is also an initial record consisting of the databased version
and the root id.
As well as a the afpidsrvr server there is an afpidtool, which can
send messages directly to the server, and afpidlist, which will
list the database.
The system is by no means foolproof. Expect problems if different
people are working on the same area - aufs still cannot detect
automatically that other processes have changed the Unix
filestructure. Since the server routines pass a fullpath back to
aufs itself, and let it then decode that into the internal aufs
directory tree, if the name is changed by another process, then aufs
may see a whole new path. If this proves a problem, a mechanism will
be required to pass back the information to aufs - it is essentially
a problem with the aufs/afpidsrvr interface, rather than with afpidsrvr
itself. One possibility would be to passback a list of extId/name
pairs, rather than a path. If the names changed than aufs would
realise that, and could change its internal record. I've no idea how
it would tell the Mac though!
Another area of concern is in the integrity of the database. The
current database should not get corrupted, but if it does the
programs are not very resiliant to it - the contents of a record are
believed. It is not particularly clear how this will workout in
practice - my experience with corruptions is limited to problems
during testing, when bugs caused process crashes. If corruptions turn
out to be a problem, then some extra checks will be required. To be
worth while, adding CRC checks to the database records is probably
required. For the moment the simple scheme seems preferable. Do note
that, in the extreme case, you may have to delete the database in
/usr/local/lib/cap and start again. If you do this, ensure you stop both
afpidsrvr and aufs first - neither like this event! This will obviously
cause problems to users. The previous version of afpidsrvr had a clean
function, which was intended to remove unused and faulty entries.
This is currently non-operative, but may be re-instated in the
future.
In will be noted that afpidsrvr is optional. Why might you not wish to
use this:
* There is a performance penalty, and you might not wish to pay it.
In practice, there is a slight penalty on startup, and in opening
folders for the first time - especially new ones. The only "bad case"
scenario that actually occurs is the reverse lookup of an id to a
pathname, which is then converted to an internal pointer by a second
tree semi-traversal. My experience with a Sun II server suggests that
this delay is negligable.
* Reliability. The system has, currently, only been tested on a Sun
II server. There may be minor problems elsewhere, but there is
nothing to suggest that there should be huge problems. I'm still not
sure about the big-endian/little-endian situation, but I believe that
providing the database is not moved from one machine to another there
should be no problem.
* NFS. We do not use NFS much, and I have little experience of it. I
would only expect problems if the aufs server for the same area ran
on serveral machines, but there are several suspect areas.
* Portability. The system runs under SunOS4.1. I have not tested it
on other systems - not even Solaris. The chief problem areas may be
in named sockets, which are used to send the information between
client processes and the server. On other systems you my have to use
equivalents.
On a final point, the modified server does contain emergency code for
use if the server ceases to function. This should never happen in
normal running, but may if errors are hit. This backup mechanism
actually reflects v1.0 if the database, and just records name/id
pairs. It is anything but efficient, and is merely intended to avoid
having to crash the server. Really there ought to be a few bells
ringing if this happens, but there are not! [Perhaps in a future
version, if something thinks of a good interface.] It is suggested
that this should not be used routinely - not least it has problems
still with moving and deleting sub-trees of directories - and is very
inefficient. In case you wonder why not just fall back on the default
scheme, the assumption is that the existing database is fine, but
cannot be modified.
Installation and Use
--------------------
To use the file/directory ID server, select the FIXED_DIRIDS option in
the m4.features file. Re-run gen.makes, 'make clean' and rebuild CAP.
When compiled and installed, you will get the additional tools afpidsrvr,
afpidlist and afpidtool in your cap bin directory - along with the
modified aufs.
To bring them into operation, you must:
* Modify /etc/rc.local or your start-cap-servers file to place the
following lines, or similar, before you start aufs:
rm /usr/local/lib/cap/afpIDsock
afpidsrvr -l /usr/adm/afpidsrvr.log
Then restart as appropriate. The first call to afpidsrvr will create
the database, and aufs processes will then use it. Note the first
line is to delete the socket used for communication. This normally
happens when afpidsrvr exits, but may not if the machine crashes. In
normal running, you should be careful about running this - ensure
there is no afpidsrvr server running. This will only happen in normal
running if the afpidsrvr falls over. If this does happen, run
afpidlist first to ensure you can printout the database. If you
have real problems, you may have to close down aufs and delete the
database before continuing. You may prefer to try to restore the
database off backup.
John Forrest,
jf@ap.co.umist.ac.uk

View File

@ -0,0 +1,102 @@
/*
* $Author: djh $ $Date: 1996/06/18 10:49:40 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpidlist.c,v 2.3 1996/06/18 10:49:40 djh Rel djh $
* $Revision: 2.3 $
*
*/
/*
* tool that prints out the contents of the AUFS fixed directory ID database
*
* John Forrest <jf@ap.co.umist.ac.uk>
*
*/
#ifdef FIXED_DIRIDS
#include <stdio.h>
#include <errno.h>
#include <sys/param.h>
#include "../../lib/afp/afpidaufs.h"
void
print_tree(id, prefix)
sdword id;
char *prefix;
{
char me [MAXPATHLEN];
sdword parent;
char *name;
int num_children;
sdword *children;
datum key, data;
int i;
if (id != rootEid) { /* root a bit different, because name is "/" */
strcpy(me, prefix);
strcat(me, "/");
} else
strcpy(me, "");
key = num_datum(id);
#ifdef USE_GDBM
data = gdbm_fetch(db, key);
#else /* USE_GDBM */
data = dbm_fetch(db, key);
#endif /* USE_GDBM */
if (data.dptr == NULL) {
printf("**Error** id %d not found (prefix '%s')\n", id, prefix);
return;
}
if (extract_entry(data,&name,&parent,&num_children,&children) < 0) {
printf("**Error** had probs with data for id %d(prefix '%s')\n",
id, prefix);
return;
}
if (id == rootEid)
printf("RootEid = %d (+%d)\n", id, num_children);
else {
strcat(me, name);
printf("%d = (%d) '%s' (+%d)\n", id, parent, me, num_children);
}
children = copy_children(children, num_children);
#ifdef USE_GDBM
free(data.dptr);
#endif /* USE_GDBM */
for (i = 0; i < num_children; i++)
print_tree(children[i], me);
free(children);
}
main(argc, argv)
int argc;
char *argv[];
{
int ret;
if ((ret = open_dbase(1)) < 0) {
fprintf(stderr, "Can't open database %s (%d,%d)\n",
aufsDbName, ret, errno);
exit(-1);
}
print_tree(rootEid, NULL);
close_dbase();
exit(0);
}
#else FIXED_DIRIDS
#include <stdio.h>
main()
{
printf("afpidlist: not compiled with -DFIXED_DIRIDS\n");
}
#endif FIXED_DIRIDS

View File

@ -0,0 +1,830 @@
/*
* $Author: djh $ $Date: 1996/06/19 10:32:13 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpidsrvr.c,v 2.5 1996/06/19 10:32:13 djh Rel djh $
* $Revision: 2.5 $
*
*/
/*
* Server to provide AUFS fixed directory ID database write facilities
*
* John Forrest <jf@ap.co.umist.ac.uk>
*
*/
#ifdef FIXED_DIRIDS
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#ifdef USE_GDBM
#include <gdbm.h>
#else /* USE_GDBM */
#include <ndbm.h>
#endif /* USE_GDBM */
#include <assert.h>
#ifdef USESTRINGDOTH
# include <string.h>
#else USESTRINGDOTH
# include <strings.h>
#endif USESTRINGDOTH
#include "../../lib/afp/afpidaufs.h"
int verbose = 0;
int disconnect = 1;
char *log = NULL;
int continue_clean;
extern char *optarg;
extern int optind, opterr;
int queries; /* request socket */
int bound_queries = 0; /* whether to delete socket or not */
void create_queries();
void session();
void set_signal();
void do_disconnect();
void clean_entries();
void open_database();
void
fatal(message)
char *message;
{
if (message != NULL)
fprintf(stderr, "%s:", message);
if (errno > 0) {
fprintf(stderr, " %d: ", errno);
perror("");
} else
putc('\n', stderr);
#ifdef USE_GDBM
if (db != NULL)
gdbm_close(db);
#else /* USE_GDBM */
if (db != NULL)
dbm_close(db);
#endif /* USE_GDBM */
if (bound_queries)
unlink(aufsSockname);
exit(-1);
}
void
fatal2(message, a1)
char *message, *a1;
{
fprintf(stderr, "afpidsrvr: fatal error: %s%s :", message, a1);
fatal(NULL);
}
void
clean_exit(n)
int n;
{
#ifdef USE_GDBM
if (db != NULL)
gdbm_close(db);
#else /* USE_GDBM */
if (db != NULL)
dbm_close(db);
#endif /* USE_GDBM */
if (bound_queries)
unlink(aufsSockname);
exit(n);
}
main(argc, argv)
char *argv[];
{
int c;
extern char *optarg;
int doClean = 0;
while ((c = getopt(argc, argv, "vtcl:")) != -1) {
switch (c) {
case 'v':
verbose = 1;
break;
case 't':
disconnect = 0;
break;
case 'l':
log = optarg;
break;
case 'c':
doClean = 1;
break;
case '?':
fprintf(stderr,
"usage: afpidsrvr [-c] [-v] [-t] [-l logfile]\n");
exit(-1);
}
}
set_signal();
if (disconnect)
do_disconnect();
if (log) {
int fd;
if ((fd = open(log, O_WRONLY|O_APPEND|O_CREAT)) < 0)
fd = open("/dev/null", O_WRONLY);
if (fd >= 0) {
#ifndef NODUP2
dup2(fd, 2);
#else NODUP2
close(2);
dup(fd);
#endif NODUP2
close(fd);
}
}
init_aufsExt();
open_database();
create_queries();
if (doClean)
do
clean_entries();
while (continue_clean);
#ifdef USE_GDBM
gdbm_close(db);
db = NULL;
#endif /* USE_GDBM */
{
time_t now;
time(&now);
fprintf(stderr, "Starting afpidsrvr with %s at %s",
aufsDbName, ctime(&now));
}
session();
/* NOTREACHED */
}
/*
* create queries "pipe" entry
*
*/
void
create_queries()
{
struct sockaddr *addr;
int addrlen;
if ((queries = query_socket()) < 0)
fatal("Problem creating socket");
query_addr(&addr, &addrlen);
if (bind(queries, addr, addrlen) < 0)
fatal2("Problem binding socket ", aufsSockname);
bound_queries = 1;
#ifdef linux
chmod(aufsSockname, 0666);
#endif /* linux */
if (listen(queries, 5) < 0)
fatal("Listen");
return;
}
void
do_exit()
{
clean_exit(-1);
}
/*
* force clean exit
*
*/
void
set_signal()
{
if (signal(SIGHUP, SIG_IGN)!=SIG_IGN)
signal(SIGHUP, do_exit);
if (signal(SIGINT, SIG_IGN)!=SIG_IGN)
signal(SIGINT, do_exit);
if (signal(SIGTERM, SIG_IGN)!=SIG_IGN)
signal(SIGTERM, do_exit);
}
void
create_database()
{
datum initial_key, initial;
datum root, root_datum;
#ifdef USE_GDBM
if ((db = gdbm_open(aufsDbName, 2048, GDBM_WRCREAT, 0644, 0L)) == NULL)
fatal("Creating db");
#else /* USE_GDBM */
if ((db = dbm_open(aufsDbName, O_RDWR|O_CREAT, 0644)) == NULL)
fatal("Creating db");
#endif /* USE_GDBM */
rootEid = valid_id(); /* any will do */
root_datum = new_entry(aufsRootName, (sdword)0);
root = num_datum(rootEid);
#ifdef USE_GDBM
if (gdbm_store(db, root, root_datum, GDBM_REPLACE) < 0)
fatal("Writing root record");
#else /* USE_GDBM */
if (dbm_store(db, root, root_datum, DBM_REPLACE) < 0)
fatal("Writing root record");
#endif /* USE_GDBM */
initial_key.dptr = "I";
initial_key.dsize = strlen(initial_key.dptr);
initial = create_init(aufsDbVersion, rootEid);
#ifdef USE_GDBM
if (gdbm_store(db, initial_key, initial, GDBM_REPLACE) < 0)
fatal("Writing root record");
#else /* USE_GDBM */
if (dbm_store(db, initial_key, initial, DBM_REPLACE) < 0)
fatal("Writing root record");
#endif /* USE_GDBM */
flush_database();
}
void
open_database()
{
datum initial_key, initial;
char *version;
initial_key.dptr = "I";
initial_key.dsize = strlen(initial_key.dptr);
#ifdef USE_GDBM
db = gdbm_open(aufsDbName, 2048, GDBM_READER, 0644, 0L);
#else /* USE_GDBM */
db = dbm_open(aufsDbName, O_RDWR, 0644);
#endif /* USE_GDBM */
if (db == NULL && errno == ENOENT)
create_database();
if (db == NULL)
fatal("Opening db");
#ifdef USE_GDBM
initial = gdbm_fetch(db, initial_key);
#else /* USE_GDBM */
initial = dbm_fetch(db, initial_key);
#endif /* USE_GDBM */
if (initial.dptr == NULL)
fatal("Suspect Database");
if (extract_init(initial, &version, &rootEid) < 0)
fatal("Problem with initial record");
if (strcmp(version, aufsDbVersion) != 0)
fatal2("Incompatible d/b, can't deal with version ", version);
#ifdef USE_GDBM
free(initial.dptr);
#endif /* USE_GDBM */
return;
}
void
add_entry(entry)
char *entry;
{
int ret;
if (!is_directory(entry))
return;
if ((ret = lookup_path(entry, NULL, NULL, 1)) <= 0)
fprintf(stderr, "Failed to create '%s' (%d, %d)\n",
entry, ret, errno);
return;
}
void
delete_entry_id();
void
add_entry_id(parent, rest)
sdword parent;
char *rest;
{
int ret;
sdword id;
char *entry;
if ((ret = lookup_path_id(parent, rest, &id, NULL, 1)) <= 0) {
fprintf(stderr, "Failed to create %d/'%s' (%d, %d)\n",
parent, rest, ret, errno);
return;
}
if (verbose)
fprintf(stderr, "Created entry %d/'%s' (%d, %d) id = %d\n",
parent, rest, ret, errno, id);
entry = equiv_path(id);
if (!is_directory(entry)) /* check existance in restrospect! */
delete_entry_id(id);
flush_database();
return;
}
void
add_entry_fid(parent, rest)
sdword parent;
char *rest;
{
int ret;
sdword id;
char *entry;
if ((ret = lookup_path_id(parent, rest, &id, NULL, 1)) <= 0) {
fprintf(stderr, "Failed to create %d/'%s' (%d, %d)\n",
parent, rest, ret, errno);
return;
}
entry = equiv_path(id);
if (!is_file(entry)) /* check existance in restrospect! */
delete_entry_id(id);
flush_database();
return;
}
void
delete_entry(entry)
char *entry;
{
sdword id, parent;
datum data;
if (is_directory(entry) || is_file(entry))
return;
if (lookup_path(entry, &id, &data, 0) > 0){
(void) extract_entry(data, NULL, &parent, NULL, NULL);
do_delete_entry(id);
delete_child(parent, id);
flush_database();
}
return;
}
void
delete_entry_id(id)
sdword id;
{
sdword parent;
datum data;
char *entry = equiv_path(id);
if (is_directory(entry) || is_file(entry))
return;
data = get_datum(id);
if (data.dptr == NULL)
return;
if (extract_entry(data, NULL, &parent, NULL, NULL) < 0)
return;
do_delete_entry(id);
delete_child(parent, id);
flush_database();
return;
}
void
delete_entry_fid(id)
sdword id;
{
sdword parent;
datum data;
char *entry = equiv_path(id);
if (is_file(entry))
return;
data = get_datum(id);
if (data.dptr == NULL)
return;
if (extract_entry(data, NULL, &parent, NULL, NULL) < 0)
return;
do_delete_entry(id);
delete_child(parent, id);
flush_database();
return;
}
void
move_entry(from, to)
char *from, *to;
{
datum data;
sdword id, from_parent, to_parent;
char to_directory[MAXPATHLEN];
char *new_name;
char *name;
char *ptr;
assert(to[0] == '/');
if (is_directory(from) || !is_directory(to))
if (is_file(from) || !is_file(to))
return;
if (lookup_path(from, &id, &data, 0) <= 0) {
/* did not know previously! */
add_entry(to);
return;
}
if (lookup_path(to, NULL, NULL, 0) > 0) /* exists already! */
return;
extract_entry(data, &name, &from_parent, NULL, NULL);
name = string_copy(name); /* just in case it gets clobbered */
ptr = rindex(to, '/');
strcpy(to_directory, "");
strncat(to_directory, to, ptr-to);
new_name = ptr+1;
assert(new_name[0] != '\0');
/* will happen for trailing /, so be careful */
lookup_path(to_directory, &to_parent, NULL, 1);
fprintf(stderr, "Moving %d/%s to %d/%s\n",
from_parent, name, to_parent, new_name);
if (from_parent != to_parent) {
/* NB it may be quicker to try compare the two strings */
delete_child(from_parent, id);
add_child(to_parent, id);
}
data = get_datum(id); /* get again - in case overwritten */
data = modify_parent(data, to_parent);
if (strcmp(name, new_name) != 0) /* name change too */
data = modify_name(data, new_name);
store_datum(id, data, DBM_REPLACE);
flush_database();
return;
}
void
move_entry_id(from_parent, name, to_parent, new_name)
sdword from_parent, to_parent;
char *name, *new_name;
{
datum data;
sdword id;
char *ptr;
if (lookup_path_id(from_parent, name, &id, NULL, 0) <= 0) {
/* did not know previously! */
add_entry_id(from_parent, name);
return;
}
if (lookup_path_id(to_parent, new_name, NULL, NULL, 0) > 0)
/* exists already! */
return;
if (is_directory(equiv_path(id))||is_file(equiv_path(id)))
return;
if (from_parent == to_parent) {
data = get_datum(id); /* get here in case corrupted earlier */
data = modify_name(data, new_name);
store_datum(id, data, DBM_REPLACE);
} else {
delete_child(from_parent, id);
add_child(to_parent, id);
data = get_datum(id); /* get here in case corrupted earlier */
data = modify_parent(data, to_parent);
if (strcmp(name, new_name) != 0) /* name change too */
data = modify_name(data, new_name);
store_datum(id, data, DBM_REPLACE);
}
if (! is_directory(equiv_path(id)) && ! is_file(equiv_path(id)))
delete_entry_id(id); /* does not actually exist */
else
flush_database();
return;
}
void
rename_entry_id(id, new_name)
sdword id;
char *new_name;
{
datum data;
int ret;
if (verbose)
fprintf(stderr, "rename_entry_id: %d -> %s\n",
id, new_name);
data = get_datum(id);
if (data.dptr == NULL) {
if (verbose)
fprintf(stderr, "Unknown id: %d\n", id);
/* did not know previously! */
return;
}
data = modify_name(data, new_name);
if (ret = store_datum(id, data, DBM_REPLACE) < 0)
if (verbose)
fprintf(stderr, "rename_entry_id: store returned %d\n",
ret);
if (! is_directory(equiv_path(id)) && ! is_file(equiv_path(id))) {
if (verbose)
fprintf(stderr, "rename_entry_id: Ooops! %s doesn't exist!\n",
equiv_path(id));
delete_entry_id(id); /* does not actually exist */
} else
flush_database();
return;
}
void
rename_entry(path, new_name)
char *path, *new_name;
{
datum data;
sdword id;
char *ptr;
if (lookup_path(path, &id, &data, 0) <= 0) {
/* did not know previously! */
return;
}
data = modify_name(data, new_name);
store_datum(id, data, DBM_REPLACE);
if (! is_directory(equiv_path(id)) && ! is_file(equiv_path(id)))
delete_entry_id(id); /* does not actually exist */
else
flush_database();
return;
}
void
clean_entries()
{
/* currently no-op */
continue_clean = 0;
return;
}
void
session()
{
struct sockaddr addr;
int addrlen;
int sock;
char buff[2*MAXPATHLEN+3];
char command, arg1[MAXPATHLEN], arg2[MAXPATHLEN];
sdword id1, id2;
int count;
int prob, args, fileID;
for (;;) {
fileID = 0;
addrlen = sizeof(struct sockaddr);
if ((sock = accept(queries, &addr, &addrlen)) < 0)
fatal("Accept");
if ((count = recv(sock, buff, 2*MAXPATHLEN+3, 0)) < 0)
fatal("Recv");
buff[count] = '\0';
if (verbose && count > 0)
fprintf(stderr, "Received: '%s'\n", buff);
prob = 0;
if (buff[0] != '\0') {
command = buff[0];
switch (command) { /* first decode arguments */
case 'A': case 'D':
args = sscanf(buff+1, "%[^\277]\277", arg1);
break;
case 'M':
args = sscanf(buff+1, "%[^\277]\277%[^\277]\277", arg1, arg2);
break;
case 'R':
args = sscanf(buff+1, "%[^\277]\277%[^\277]\277", arg1, arg2);
break;
case 'a':
args = sscanf(buff+1, "%d\277%[^\277]\277", &id1, arg1);
break;
case 'f':
args = sscanf(buff+1, "%d\277%[^\277]\277", &id1, arg1);
break;
case 'd':
args = sscanf(buff+1, "%d\277", &id1);
break;
case 'm':
args = sscanf(buff+1, "%d\277%[^\277]\277%d\277%[^\277]\277",
&id1, arg1, &id2, arg2);
break;
case 'r':
args = sscanf(buff+1, "%d\277%[^\277]\277", &id1, arg1);
break;
}
switch (command) {
case 'A':
if (args < 1 || arg1[0] != '/')
prob = 1;
else
add_entry(arg1);
break;
case 'a':
if (args < 2)
prob = 1;
else
add_entry_id(id1, arg1);
break;
case 'f':
if (args < 2)
prob = 1;
else
add_entry_fid(id1, arg1);
break;
case 'D':
if (args < 1 || arg1[0] != '/')
prob = 1;
else
delete_entry(arg1);
break;
case 'd':
if (args < 1)
prob = 1;
else
delete_entry_id(id1);
break;
case 'M':
if (args < 2 || arg1[0] != '/' || arg2[0] != '/')
prob = 1;
else
move_entry(arg1, arg2);
break;
case 'm':
if (args < 4)
prob = 1;
else
move_entry_id(id1, arg1, id2, arg2);
break;
case 'R':
if (args < 2 || arg1[0] != '/')
prob = 1;
else
rename_entry(arg1, arg2);
break;
case 'r':
if (args < 2)
prob = 1;
else
rename_entry_id(id1, arg1);
break;
case 'C':
clean_entries();
break;
default:
prob = 1;
break;
}
}
if (prob)
fprintf(stderr, "Bad command '%s'\n", buff);
close(sock);
}
return;
}
/*
* disassociate
*
*/
void
do_disconnect()
{
if (fork())
_exit(0);
{
int f;
for (f = 0; f < 10; f++)
(void) close(f);
}
(void) open("/", 0);
#ifndef NODUP2
(void) dup2(0, 1);
(void) dup2(0, 2);
#else NODUP2
(void)dup(0); /* for slot 1 */
(void)dup(0); /* for slot 2 */
#endif NODUP2
#ifndef POSIX
#ifdef TIOCNOTTY
{
int t;
if ((t = open("/dev/tty", 2)) >= 0) {
ioctl(t, TIOCNOTTY, (char *)0);
(void) close(t);
}
}
#endif TIOCNOTTY
#ifdef xenix5
/*
* USG process groups:
* The fork guarantees that the child is not a process group leader.
* Then setpgrp() can work, whick loses the controllong tty.
* Note that we must be careful not to be the first to open any tty,
* or it will become our controlling tty. C'est la vie.
*
*/
setpgrp();
#endif xenix5
#else POSIX
(void) setsid();
#endif POSIX
}
/*
* These are here to ensure we pick up these
* versions for the server, and not those in lib_client.c
*
*/
int
amAufsExt()
{
return(1);
}
/*
* flush_database: force any outstanding writes
*
*/
void
flush_database()
{
#ifndef USE_GDBM
extern void open_database( /* void */ );
dbm_close(db);
open_database();
#endif /* USE_GDBM */
return;
}
#else FIXED_DIRIDS
#include <stdio.h>
main()
{
printf("afpidsrvr: not compiled with -DFIXED_DIRIDS\n");
}
#endif FIXED_DIRIDS

View File

@ -0,0 +1,216 @@
/*
* $Author: djh $ $Date: 1996/06/19 10:51:19 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpidtool.c,v 2.3 1996/06/19 10:51:19 djh Rel djh $
* $Revision: 2.3 $
*
*/
/*
* Tell the AUFS fixed directory ID sever to do some basic things
*
* John Forrest <jf@ap.co.umist.ac.uk>
*
*/
#ifdef FIXED_DIRIDS
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <errno.h>
#ifdef USESTRINGDOTH
# include <string.h>
#else USESTRINGDOTH
# include <strings.h>
#endif USESTRINGDOTH
#include "../../lib/afp/afpidaufs.h"
int verbose = 0;
void
fatal(message)
char *message;
{
if (message != NULL)
fprintf(stderr, "%s:", message);
if (errno > 0)
perror("");
else
putc('\n', stderr);
exit(-1);
}
void
fatal2(message, a1)
char *message, *a1;
{
fprintf(stderr, "afpidtool: fatal error: %s%s :", message, a1);
fatal(NULL);
}
void
getcdwd(path, result)
char *path, *result;
{
char command [256];
FILE *pwd;
sprintf(command, "cd '%s'; pwd\n", path);
if ((pwd = popen(command, "r")) == NULL)
strcpy(result, "");
else {
fgets(result, MAXPATHLEN, pwd);
pclose(pwd);
if (result[0] != '/')
strcpy(result, "");
result[strlen(result)-1] = '\0'; /* remove trailing lf */
}
}
void
doFullPath(path, fullPath)
char *path, *fullPath;
{
char *ptr;
if (path[0] == '\0')
#ifdef SOLARIS
getcwd(fullPath, MAXPATHLEN);
#else /* SOLARIS */
getwd(fullPath);
#endif /* SOLARIS */
else
if (is_directory(path))
getcdwd(path, fullPath);
else
if ((ptr = (char *)rindex(path, '/')) != NULL) {
*ptr = '\0';
doFullPath(path, fullPath);
strcat(fullPath, "/");
strcat(fullPath, ptr+1);
} else { /* directory name only */
doFullPath("", fullPath);
strcat(fullPath, "/");
strcat(fullPath, path);
}
}
char *fullpath(path)
char *path;
{
char temp[MAXPATHLEN];
char fullPath[MAXPATHLEN];
if (is_directory(path))
getcdwd(path, fullPath);
else {
strcpy(temp, path);
doFullPath(path, fullPath);
}
return string_copy(fullPath);
}
main(argc, argv)
int argc;
char *argv[];
{
int c;
extern char *optarg;
extern optind;
char *arg1, *arg2;
sdword id1, id2;
int res;
while ((c = getopt(argc, argv, "vn:a:m:d:r:cN:A:D:M:R:")) != -1) {
switch (c) {
case 'v':
verbose = 1;
break;
case 'n': case 'a':
arg1 = fullpath(optarg);
if (verbose)
fprintf(stderr, "New %s\n", arg1);
if (send_new(arg1) < 0)
fatal("Sending new");
break;
case 'N': case 'A':
id1 = atoi(optarg);
arg1 = argv[optind++];
if (verbose)
fprintf(stderr, "New %d/%s\n", id1, arg1);
if (send_new_id(id1,arg1) < 0)
fatal("Sending new");
break;
case 'd':
arg1 = fullpath(optarg);
if (verbose)
fprintf(stderr, "Delete %s\n", arg1);
if (send_delete(arg1) < 0)
fatal("Sending delete");
break;
case 'D':
id1 = atoi(optarg);
if (verbose)
fprintf(stderr, "Delete %d\n", id1);
if (send_delete_id(id1) < 0)
fatal("Sending delete");
break;
case 'm':
arg1 = fullpath(optarg);
arg2 = fullpath(argv[optind++]);
if (verbose)
fprintf(stderr, "Move %s -> %s\n", arg1, arg2);
if (send_move(arg1, arg2) < 0)
fatal("Sending move");
break;
case 'M':
id1 = atoi(optarg);
arg1 = argv[optind++];
id2 = atoi(argv[optind++]);
arg2 = argv[optind++];
if (verbose)
fprintf(stderr, "Move %d/%s -> %s\n",
id1, arg1, id2, arg2);
if (send_move_id(id1, arg1, id2, arg2) < 0)
fatal("Sending move");
break;
case 'r':
arg1 = fullpath(optarg);
arg2 = argv[optind++];
if (verbose)
fprintf(stderr, "Rename %s -> %s\n", arg1, arg2);
if (send_rename(arg1, arg2) < 0)
fatal("Sending rename");
break;
case 'R':
id1 = atoi(optarg);
arg1 = argv[optind++];
if (verbose)
fprintf(stderr, "Rename %d -> %s\n", id1, arg1);
if (send_rename_id(id1, arg1) < 0)
fatal("Sending rename");
break;
case 'c':
if (verbose)
fprintf(stderr, "Clean\n");
if (send_clean() < 0)
fatal("Sending clean");
break;
case '?':
fprintf(stderr,
"usage: afpidtool [-v] [-n path] [-d path] [-m from to]\n");
exit(-1);
}
}
exit(0);
}
#else FIXED_DIRIDS
#include <stdio.h>
main()
{
printf("afpidtool: not compiled with -DFIXED_DIRIDS\n");
}
#endif FIXED_DIRIDS

106
applications/aufs/afpmisc.c Normal file
View File

@ -0,0 +1,106 @@
/*
* $Author: djh $ $Date: 91/02/15 21:07:34 $
* $Header: afpmisc.c,v 2.1 91/02/15 21:07:34 djh Rel $
* $Revision: 2.1 $
*/
/*
* afpmisc.c - miscellaneous, but nevertheless useful routines
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
*
* Edit History:
*
* March 1987 Schilit Created.
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <netat/appletalk.h>
#include <netat/afp.h>
#include "afps.h"
int afp_dbug;
/*
* int SetDBLevel(char *argv)
*
* Process arguments for tracing of AFP levels: fork, file, directory,
* etc. The options are:
*
*/
struct {
int db_flg;
char *db_nam;
} dbtab[] = {
{DBG_ALL,"All"},
{DBG_DEBG|DBG_DESK,"DeskTop"},
{DBG_DEBG|DBG_DIRS,"Directory"},
{DBG_DEBG|DBG_ENUM,"Enumerate"},
{DBG_DEBG|DBG_FILE,"File"},
{DBG_DEBG|DBG_FORK,"Fork"},
{DBG_DEBG|DBG_OSIN,"OS"},
{DBG_DEBG|DBG_SRVR,"Server"},
{DBG_DEBG|DBG_UNIX,"Unix"},
{DBG_DEBG|DBG_VOLS,"Volume"},
{DBG_DEBG,"debug"}
};
#define DBTABN 11 /* size of debug table */
char *DBLevelOpts()
{
int i;
static char dbopts[100];
*dbopts = '\0';
for (i=0; i < DBTABN; i++) {
strcat(dbopts,dbtab[i].db_nam);
strcat(dbopts," ");
}
return(dbopts);
}
int SetDBLevel(s)
char *s;
{
char dbuf[30],*cp;
int i,idx,len;
while (*s != '\0') { /* until runnout */
while(*s == ' ' || *s == '\t') /* skip spaces */
s++;
if (*s == '\0')
break;
for (len=0, cp = dbuf; *s != ' ' && *s != '\t' && *s != '\0' && len < 29;
cp++, s++, len++)
*cp = *s;
*cp++ = '\0';
/* length should be correct */
/* len = strlen(dbuf); */ /* find length of command */
idx = -1;
for (i=0; i < DBTABN; i++) {
if (strncmpci(dbuf,dbtab[i].db_nam,len) == 0)
if (idx > 0) {
printf("SetDBLevel: ambiguous debug '%s' (%s and %s)\n",
dbuf,dbtab[idx].db_nam,dbtab[i].db_nam);
return(FALSE);
} else
idx = i;
}
if (idx < 0) {
printf("SetDBLevel: unknown debug level %s\n",dbuf);
return(FALSE);
}
printf("SetDBLevel: Debugging %s\n",dbtab[idx].db_nam);
afp_dbug |= dbtab[idx].db_flg; /* add the flag */
}
return(TRUE);
}

140
applications/aufs/afpntoh.h Normal file
View File

@ -0,0 +1,140 @@
/*
* $Author: djh $ $Date: 1996/04/25 03:15:24 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpntoh.h,v 2.5 1996/04/25 03:15:24 djh Rel djh $
* $Revision: 2.5 $
*
*/
/*
* afpntoh.h - Server Net to Host Unpacking.
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University
* in the City of New York.
*
* Edit History:
*
* Sun Apr 5 Schilit Created, based on afpcmd.c
*
*/
extern PackEntry ProtoBRL[]; /* 1 ByteRangeLock */
#define PsByteRangeLock ProtoBRL
extern PackEntry ProtoCVP[]; /* 2 CloseVol */
#define PsCloseVol ProtoCVP
extern PackEntry ProtoCDP[]; /* 3 CloseDir */
#define PsCloseDir ProtoCDP
extern PackEntry ProtoCFkP[]; /* 4 CloseFork */
#define PsCloseFork ProtoCFkP
extern PackEntry ProtoCpFP[]; /* 5 CopyFile */
#define PsCopyFile ProtoCpFP
extern PackEntry ProtoCRDP[]; /* 6 CreateDir */
#define PsCreateDir ProtoCRDP
extern PackEntry ProtoCFP[]; /* 7 CreateFile */
#define PsCreateFile ProtoCFP
extern PackEntry ProtoDFP[]; /* 8 Delete */
#define PsDelete ProtoDFP
extern PackEntry ProtoEP[]; /* 9 Enumerate */
#define PsEnumerate ProtoEP
extern PackEntry ProtoFVP[]; /* 10 Flush */
#define PsFlush ProtoFVP
/* 11 Flush a fork */
extern PackEntry ProtoGFkPP[]; /* 14 GetForkParms */
#define PsGetForkParms ProtoGFkPP
/* 15 GetSrvrInfo */
/* 16 GetSrvrParms */
extern PackEntry ProtoGVPP[]; /* 17 GetVolParms */
#define PsGetVolParms ProtoGVPP
extern PackEntry ProtoLP[]; /* 18 Login */
#define PsLogin ProtoLP
extern PackEntry ProtoLRP[]; /* login reply */
#define PsLoginReply ProtoLRP
extern PackEntry ProtoLCP[]; /* 19 LoginCont */
#define PsLoginCont ProtoLCP
extern PackEntry ProtoLCR[]; /* loginCont reply */
#define PsLoginContR ProtoLCR
/* 20 Logout */
extern PackEntry ProtoMIP[]; /* 21 MapID */
#define PsMapID ProtoMIP
extern PackEntry ProtoMNP[]; /* 22 MapName */
#define PsMapName ProtoMNP
extern PackEntry ProtoMFP[]; /* 23 Move */
#define PsMove ProtoMFP
extern PackEntry ProtoOVP[]; /* 24 OpenVol */
#define PsOpenVol ProtoOVP
extern PackEntry ProtoODP[]; /* 25 OpenDir */
#define PsOpenDir ProtoODP
extern PackEntry ProtoOFkP[]; /* 26 OpenFork */
#define PsOpenFork ProtoOFkP
extern PackEntry ProtoRP[]; /* 27 Read */
#define PsRead ProtoRP
extern PackEntry ProtoRFP[]; /* 28 Rename */
#define PsRename ProtoRFP
extern PackEntry ProtoSDPP[]; /* 29 SetDirParms */
#define PsSetDirParms ProtoSDPP
extern PackEntry ProtoSFPP[]; /* 30 SetFileParms */
#define PsSetFileParms ProtoSFPP
extern PackEntry ProtoSFkPP[]; /* 31 SetForkParms */
#define PsSetForkParms ProtoSFkPP
extern PackEntry ProtoSVPP[]; /* 32 SetVolParms */
#define PsSetVolParms ProtoSVPP
extern PackEntry ProtoWP[]; /* 33 Write */
#define PsWrite ProtoWP
extern PackEntry ProtoGFDPP[]; /* 34 GetFileDirParms */
#define PsGetFileDirParms ProtoGFDPP
extern PackEntry ProtoSFDPP[]; /* 35 SetFileDirParms */
#define PsSetFileDirParms ProtoSFDPP
extern PackEntry ProtoMsgP[]; /* 38 GetSrvrMsg */
#define PsGetSrvrMsg ProtoMsgP
extern PackEntry ProtoCreateID[]; /* 39 CreateID */
#define PsCreateID ProtoCreateID
extern PackEntry ProtoDelID[]; /* 40 DeleteID */
#define PsDelID ProtoDelID
extern PackEntry ProtoRslvID[]; /* 41 ResolveID */
#define PsRslvID ProtoRslvID
extern PackEntry ProtoExP[]; /* 42 ExchangeFiles */
#define PsExchange ProtoExP
extern PackEntry ProtoODT[]; /* 48 OpenDT */
#define PsOpenDT ProtoODT
extern PackEntry ProtoCDT[]; /* 49 CloseDT */
#define PsCloseDT ProtoCDT
extern PackEntry ProtoGI[]; /* 51 GetIcon */
#define PsGetIcon ProtoGI
extern PackEntry ProtoGII[]; /* 52 GetIconInfo */
#define PsGetIconInfo ProtoGII
extern PackEntry ProtoAAP[]; /* 53 AddAPPL */
#define PsAddAPPL ProtoAAP
extern PackEntry ProtoRMA[]; /* 54 RmvAPPL */
#define PsRmvAPPL ProtoRMA
extern PackEntry ProtoGAP[]; /* 55 GetAPPL */
#define PsGetAPPL ProtoGAP
extern PackEntry ProtoACP[]; /* 56 AddComment */
#define PsAddComment ProtoACP
extern PackEntry ProtoRMC[]; /* 57 RmvComment */
#define PsRmvComment ProtoRMC
extern PackEntry ProtoGCP[]; /* 58 GetComment */
#define PsGetComment ProtoGCP
extern PackEntry ProtoAIP[]; /* 192 AddIcon */
#define PsAddIcon ProtoAIP
#define PsChangePassword ProtoCPP
extern PackEntry ProtoCPP[];
#define PsGetUserInfo ProtoGUIP
extern PackEntry ProtoGUIP[];
#define PsGetUserInfoReply ProtoGUIRP
extern PackEntry ProtoGUIRP[];
#define PsGetIconInfoReply ProtoGIIR
extern PackEntry ProtoGIIR[];
#define PsGetSrvrMsgReply ProtoMsgRP
extern PackEntry ProtoMsgRP[];
extern PackEntry ProtoAuthInfo[];
extern PackEntry DirParmPackR[];
extern PackEntry FilePackR[];
extern PackEntry ProtoFileAttr[];
extern PackEntry DirPackR[];
extern PackEntry EnumPackR[];
extern PackEntry ProtoDirAttr[];
extern PackEntry ProtoFileDirAttr[];
extern PackEntry ProtoSRP[];

5258
applications/aufs/afpos.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,990 @@
/*
* $Author: djh $ $Date: 1996/06/18 10:49:40 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afposenum.c,v 2.15 1996/06/18 10:49:40 djh Rel djh $
* $Revision: 2.15 $
*
*/
/*
* afposenum.c - Appletalk Filing Protocol OS enumeration.
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* March 1987 Schilit Created.
*
*/
#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h>
#endif /* _TYPES */
#include <sys/stat.h>
#include <sys/time.h>
#include <netat/appletalk.h>
#include <netat/afp.h>
#ifdef USESTRINGDOTH
#include <string.h>
#else USESTRINGDOTH
#include <strings.h>
#endif USESTRINGDOTH
#ifdef SHORT_NAMES
#include <ctype.h>
#endif SHORT_NAMES
#ifdef NOCASEMATCH
#include <sys/file.h>
#include <ctype.h>
#endif NOCASEMATCH
#ifdef USEDIRENT
# include <dirent.h>
#else /* USEDIRENT */
# ifdef xenix5
# include <sys/ndir.h>
# else xenix5
# include <sys/dir.h>
# endif xenix5
#endif /* USEDIRENT */
#ifdef SOLARIS
# include <unistd.h>
#endif /* SOLARIS */
#ifdef linux
# include <unistd.h>
#endif /* linux */
#ifdef DISTRIB_PASSWDS
#include <netat/afppass.h>
#endif /* DISTRIB_PASSWDS */
#include "afps.h"
#include "afpdt.h"
#include "afpgc.h"
#ifdef SHORT_NAMES
typedef struct {
char s_name[MAXSFLEN+1];
}s_entry;
typedef struct { /* Enumeration cache entry */
IDirP ece_dirid; /* enumerated directory id */
int ece_lru;
int ece_lock; /* do not purge lock */
int ece_cnt; /* count of entries */
#ifdef USEDIRENT
struct dirent **ece_nlst; /* direct info */
#else USEDIRENT
struct direct **ece_nlst; /* direct info */
#endif USEDIRENT
s_entry * s_namearray;
time_t ece_ctime; /* last directory write dt */
int ece_mmode; /* last directory mode */
int ece_mcnt; /* last internal modify count */
int ece_idx; /* our index in the cache */
} EnumCE;
#else SHORT_NAMES
typedef struct { /* Enumeration cache entry */
IDirP ece_dirid; /* enumerated directory id */
int ece_lru;
int ece_lock; /* do not purge lock */
int ece_cnt; /* count of entries */
#ifdef USEDIRENT
struct dirent **ece_nlst; /* direct info */
#else USEDIRENT
struct direct **ece_nlst; /* direct info */
#endif USEDIRENT
time_t ece_ctime; /* last directory write dt */
int ece_mmode; /* last directory mode */
int ece_mcnt; /* last internal modify count */
int ece_idx; /* our index in the cache */
} EnumCE;
#endif SHORT_NAMES
#define NILECE ((EnumCE *) 0)
private EnumCE *EnumCache[NECSIZE];
private int EC_Clock; /* lru clock */
#ifdef USEDIRENT
#define NILNLST ((struct dirent **) 0)
#else USEDIRENT
#define NILNLST ((struct direct **) 0)
#endif USEDIRENT
private EnumCE *EC_Min(),*EC_Find(),*EC_Fetch(),*EC_Load();
private boolean EC_Valid();
private void EC_Free();
private iselect();
#ifdef SHORT_NAMES
private name_toupper(), convert(),add_ast();
private int mysort();
#endif SHORT_NAMES
#ifdef NOCASEMATCH
private noCaseDir();
private searchDirectory();
#endif NOCASEMATCH
/*
* int iselect(struct direct *d)
*
* See if this directory entry should be included in our enumeration.
* Special files are skipped ("." , ".." ".finderinfo", etc) and
* a length check is made to see if the name is too long for AFP.
*
*/
private
iselect(d)
#ifdef USEDIRENT
struct dirent *d;
#else USEDIRENT
struct direct *d;
#endif USEDIRENT
{
if (d == NULL)
return(FALSE);
if (d->d_name == NULL)
return(FALSE);
if (ENameLen(d->d_name) > MAXLFLEN) /* external name too long? */
return(FALSE); /* sorry this name is too long */
if (d->d_name[0] != '.') /* all special dirs begin with dot */
return(TRUE);
if (d->d_name[1] == '\0') /* check for dot */
return(FALSE);
if (d->d_name[1] == '.' && /* check for dot dot */
d->d_name[2] == '\0')
return(FALSE);
if (strcmp(d->d_name,RFDIRFN) == 0) /* resource fork directory? */
return(FALSE); /* yes... don't include */
if (strcmp(d->d_name,FIDIRFN) == 0) /* finder info directory? */
return(FALSE); /* yes... don't include */
if (strcmp(d->d_name,DESKTOP_ICON) == 0) /* check for desktop files */
return(FALSE);
if (strcmp(d->d_name,DESKTOP_APPL) == 0)
return(FALSE);
#ifdef DISTRIB_PASSWDS
if (strcmp(d->d_name,AFP_DISTPW_USER) == 0) /* local password file */
return(FALSE);
#endif /* DISTRIB_PASSWDS */
return(TRUE);
}
/*
* void ECacheInit()
*
* Initialize the cache table.
*
*/
void
ECacheInit()
{
int i;
if (DBENU)
printf("ECacheInit: Cache size is %d\n",NECSIZE);
EC_Clock = 1; /* init clock */
for (i=0; i < NECSIZE; i++) {
EnumCache[i] = (EnumCE *) malloc(sizeof(EnumCE));
EnumCache[i]->ece_dirid = NILDIR;
EnumCache[i]->ece_idx = i;
}
}
private EnumCE *
EC_Min()
{
int i,mi = -1;
int mlru = EC_Clock+1;
for (i=0; i < NECSIZE; i++) {
if (EnumCache[i]->ece_dirid == NILDIR)
return(EnumCache[i]); /* found unused slot */
if (!EnumCache[i]->ece_lock && /* if not locked and... */
EnumCache[i]->ece_lru < mlru) { /* is older than current */
mlru = EnumCache[i]->ece_lru; /* remember new clock */
mi = i; /* and new index */
}
}
if (mi == -1) /* all locked? big problem */
logit(0,"EC_Min: no entry found\n");/* at least we will know */
return(EnumCache[mi]);
}
/*
* void EC_Free(EnumCE *ec)
*
* Free storage associate with a cache entry and set the entry to be
* unused by making ece_dirid = NILDIR.
*
*/
private void
EC_Free(ec)
EnumCE *ec;
{
int i;
if (ec->ece_dirid == NILDIR) /* unused entry? */
return; /* yes, just return */
if (DBENU)
printf("EC_Free: releasing %s\n",pathstr(ec->ece_dirid));
for (i=0; i < ec->ece_cnt; i++)
free((char *) ec->ece_nlst[i]);
free((char *) ec->ece_nlst);
(ec->ece_dirid)->eceidx = NOECIDX; /* not in cache */
ec->ece_dirid = NILDIR; /* indicate free entry */
}
/*
* boolean EC_Valid(EnumCE *ec, struct stat *stb)
*
* Check if the cache entry is valid by comparing information in
* the cache entry with information provided from the stat.
*
* If the cache entry is empty, the internal modification counters
* are different, or the directory modification time_t differs from
* the time_t the entry was created, then return FALSE.
*
*/
private boolean
EC_Valid(ec,stb)
EnumCE *ec;
struct stat *stb;
{
IDirP dirid = ec->ece_dirid;
if (ec->ece_dirid == NILDIR) /* no entry? */
return(FALSE); /* should not happen */
/* See if the directory has been modified and needs to be reread */
/* Check both the internal modified counter and the os modify times. */
/* The internal mod counts are to prevent a race condition with the */
/* file's mod times not getting set/read correctly */
if (ec->ece_dirid->modified != ec->ece_mcnt) { /* modified by us? */
if (DBENU)
printf("EC_Valid: internal modify invalidates %s\n",pathstr(dirid));
return(FALSE); /* yes... */
}
if ((stb->st_ctime != ec->ece_ctime) || (stb->st_mode != ec->ece_mmode)) {
if (DBENU)
printf("EC_Valid: external modify invalidates %s\n",pathstr(dirid));
return(FALSE);
}
return(TRUE); /* not modified */
}
/*
* EnumCE * EC_Find(IDirP dirid)
*
* Given a dirid return the cached Enum entry or NILECE.
*
*/
private EnumCE *
EC_Find(dirid)
IDirP dirid;
{
int cidx = dirid->eceidx; /* cache index */
if (cidx == NOECIDX) /* check dir for cache entry */
return(NILECE); /* no cache entry */
EnumCache[cidx]->ece_lru = EC_Clock++; /* this is a reference */
return(EnumCache[cidx]); /* return the cache */
}
/*
* EnumCE * EC_Fetch(IDirP dirid)
*
* Get the EnumCE entry for this dirid. If the entry is in the
* cache then validate it by calling EC_Valid. If not valid
* (changed) then reload the information. If the directory info
* is not in the cache then recycle the min cache entry and load
* a new entry.
*
* Returns NILECE on failure, ece on success.
*
*/
private EnumCE *
EC_Fetch(dirid)
IDirP dirid;
{
EnumCE *ec;
struct stat stb;
if (DBENU)
printf("EC_Fetch: request for %s\n",pathstr(dirid));
ec = EC_Find(dirid); /* see if entry is cached */
if (ec != NILECE && ec->ece_lock) /* found and locked? */
return(ec); /* then being enumerated, return */
#ifndef STAT_CACHE
if (stat(pathstr(dirid),&stb) != 0) { /* else do a stat for checks */
#else STAT_CACHE
if(OSstat(pathstr(dirid),&stb)!= 0) { /* else do a stat for checks */
#endif STAT_CACHE
Idrdirid(Ipdirid(dirid),dirid); /* unlink from directory tree */
return(NILECE); /* nothing there... */
}
if (ec != NILECE) { /* find anything? */
if (EC_Valid(ec,&stb)) /* yes... do validity check */
return(ec); /* seems ok, return it */
} else
ec = EC_Min(); /* else get a current min */
EC_Free(ec); /* free entry or min */
return(EC_Load(dirid,ec,&stb)); /* load dir and return */
}
#ifdef SHORT_NAMES
/*
* table to map Mac character set represented with :aa into something
* "approximately similar" for MSDOS, any bad characters map to '#'
* (valid character list from "MSDOS User's Guide").
*
* this is horrible!, but the results look a little nicer on the PC
*
* Modified 91/12/14 by Paul Buddington to improve translation based
* on MSDOS 5.0 User's Guide
*
*/
char mapMacChar[] = {
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'-', '!', '#', '#', '$', '%', '&', '\'','(', ')', '#', '#', '#', '-', '#', '#',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '#', '#', '#', '#', '#',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#', '#', '#', '^', '_',
'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '#', '}', '~', '#',
'A', 'A', 'C', 'E', 'N', 'O', 'U', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E',
'E', 'E', 'I', 'I', 'I', 'I', 'N', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U',
'#', '#', 'C', '#', '#', '#', '#', 'B', 'R', 'C', 'T', '#', '#', '#', 'A', 'O',
'#', '#', '#', '#', '#', 'U', '#', '#', '#', '#', '#', 'A', '#', '#', 'A', 'O',
'#', '#', '#', '#', 'F', '#', '#', '#', '#', '#', '#', 'A', 'A', 'O', 'O', 'O',
'#', '#', '#', '#', '#', '#', '#', '#', 'Y', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'
};
/*
* Map a long name into a short, uppercase DOS compatible name.
* Nothing specifies exactly how to do this, so try and make it
* resemble the behaviour of a Mac AppleShare server.
*/
private
name_toupper(nlen,name,s_name)
int nlen;
char *name, *s_name;
{
int c;
int period = 0;
int altered = 0;
int i=0,j=0,k=0;
private byte hex2nibble();
char sname[MAXSFLEN+4]; /* slop */
if (DBENU)
printf("nlen %d, MAXSFLEN %d name %s \n",nlen,MAXSFLEN,name);
while (name[i] != '\0' && i < nlen && j < MAXSFLEN && period < 5) {
/* if the name starts with a . ignore for now, mark altered */
if ((i == 0) && (name[i] == '.')) {
altered++;
i++;
/* when you hit the first period, save it and count it */
} else if ((period == 0) && (name[i] == '.')) {
sname[j++] = '.';
period++;
i++;
/* any weird characters, just say no !!!! */
/* if we hit another period, skip over it */
} else if ((name[i] == '*') || (name[i] == '+') ||
(name[i] == '|') || (name[i] == '?') ||
(name[i] == '<') || (name[i] == '>') ||
(name[i] == '[') || (name[i] == ']') ||
(name[i] == '"') || (name[i] == '=') ||
(name[i] == '`') || (name[i] == '.') ||
(name[i] == '/') || (name[i] == '\\')||
(name[i] == ';') || (name[i] == ',')) {
altered++;
i++;
/* if we see a space, ignore it, but don't mark as altered */
} else if (name[i] == ' ') {
i++;
/* check for aufs :aa special chars, map down into sim. ascii char */
} else if (name[i] == ':' && i < (nlen-2)) {
c = hex2nibble(name[++i]);
c = c << 4;
c |= hex2nibble(name[++i]);
if ((sname[j] = mapMacChar[c & 0xff]) != '#')
j++;
altered++;
i++;
/* otherwise, just convert to upper */
} else {
if (isalpha(name[i]) && !(isupper(name[i])))
sname[j++] = toupper(name[i]);
else
sname[j++] = name[i];
i++;
}
if (period)
period++; /* keep counting to get 3 more chars for DOS suffix */
}
sname[j] = '\0';
/* more characters to go ? */
if (name[i] != '\0')
altered++;
j = k = 0;
/* copy to s_name, mark start of name with ! if altered */
while(sname[j] != '\0' && j < MAXSFLEN && k < MAXSFLEN) {
if (altered && k == 0)
s_name[k++] = '!';
if (!period && k == 8)
s_name[k++] = '.';
s_name[k++] = sname[j++];
}
s_name[k] = '\0';
}
private byte
hex2nibble(a)
char a;
{
if (a >= '0' && a <= '9')
return(a - '0');
if (a >= 'a' && a <= 'f')
return(a - 'a' + 10);
if (a >= 'A' && a <= 'F')
return(a - 'A' + 10);
return(0);
}
private add_ast (ec,pos)
EnumCE *ec;
int pos;
{
int i = 1;
char c,c1;
c = ec->s_namearray[pos].s_name[0];
ec->s_namearray[pos].s_name[0] = '*';
while ((c != '\0') && (i<MAXSFLEN)) {
if (i == 8) {
ec->s_namearray[pos].s_name[i] = '.';
c1 = ec->s_namearray[pos].s_name[i+1];
ec->s_namearray[pos].s_name[i+1] = c;
i+=2;
} else {
c1 = ec->s_namearray[pos].s_name[i];
ec->s_namearray[pos].s_name[i] = c;
i++;
}
c = c1;
}
ec->s_namearray[pos].s_name[i] = '\0';
}
private
convert(ec)
EnumCE *ec;
{
int ast,i;
ec->s_namearray = (s_entry*)malloc (ec->ece_cnt*sizeof(s_entry));
ast = FALSE;
for (i = 0; i<ec->ece_cnt; i++) {
#ifdef USEDIRENT
name_toupper(strlen(ec->ece_nlst[i]->d_name),ec->ece_nlst[i]->d_name,
#else /* USEDIRENT */
name_toupper(ec->ece_nlst[i]->d_namlen, ec->ece_nlst[i]->d_name,
#endif /* USEDIRENT */
ec->s_namearray[i].s_name);
if (i>0) {
if ((strcmp(ec->s_namearray[i].s_name,
ec->s_namearray[i-1].s_name)) == 0){
add_ast(ec,i-1);
ast = TRUE;
} else if (ast) {
add_ast(ec,i-1);
ast = FALSE;
}
}
}
if (ast)
add_ast(ec,(ec->ece_cnt)-1);
}
private int
mysort(x,y)
#ifdef USEDIRENT
struct dirent **x,**y;
#else USEDIRENT
struct direct **x,**y;
#endif USEDIRENT
{
char tempx[MAXNAMLEN],tempy[MAXNAMLEN];
int i = 0;
#ifdef USEDIRENT
while (i < strlen((*x)->d_name)) {
#else /* USEDIRENT */
while (i < (*x)->d_namlen) {
#endif /* USEDIRENT */
tempx[i] = toupper((*x)->d_name[i]);
i++;
}
tempx[i] = '\0';
i = 0;
#ifdef USEDIRENT
while (i < strlen((*y)->d_name)) {
#else /* USEDIRENT */
while (i < (*y)->d_namlen) {
#endif /* USEDIRENT */
tempy[i] = toupper((*y)->d_name[i]);
i++;
}
tempy[i] = '\0';
return(strcmp(tempx,tempy));
}
#endif SHORT_NAMES
/*
* EnumCE *EC_Load(IDirP dirid, EnumCE *ec, struct stat *stb)
*
* Read the directory dirid into ec, filling in information from
* the stat structure stb.
*
* Return ec on success, or NILECE if failure.
*
*/
private EnumCE *
EC_Load(dirid,ec,stb)
IDirP dirid;
EnumCE *ec;
struct stat *stb;
{
char *path = pathstr(dirid);
#ifdef STAT_CACHE
extern char *cwd_path();
#endif STAT_CACHE
int i;
if (DBENU)
printf("EC_Load: adding %s\n",path);
#ifdef STAT_CACHE
path = cwd_path(path);
#endif STAT_CACHE
#ifdef SHORT_NAMES
ec->ece_cnt = scandir(path,&ec->ece_nlst,iselect,mysort);
#else SHORT_NAMES
ec->ece_cnt = scandir(path,&ec->ece_nlst,iselect,0);
#endif SHORT_NAMES
if (ec->ece_cnt < 0) {
if (DBENU)
printf("EC_Load: scandir failed for %s\n",path);
return(NILECE);
}
#ifdef SHORT_NAMES
convert(ec);
#endif SHORT_NAMES
ec->ece_ctime = stb->st_ctime; /* copy last modify time */
ec->ece_mmode = stb->st_mode; /* copy the last mode */
ec->ece_dirid = dirid; /* copy directory id */
ec->ece_mcnt = dirid->modified; /* copy modify count */
ec->ece_lru = EC_Clock++; /* set LRU from clock */
dirid->eceidx = ec->ece_idx; /* add new entry */
return(ec); /* and return table */
}
/*
* char * OSEnumGet(dirid,idx)
*
* Fetch the idx'th file/dir name from an enumerated directory.
* Index starts at 1.
*
* You must have first called OSEnumIni() to initialize and
* discover the maximun count of entries in the directory.
*
*/
char *
OSEnumGet(dirid,idx)
IDirP dirid;
int idx; /* ranges from 1..count */
{
EnumCE *ec;
ec = EC_Find(dirid); /* find enum entry given dirid */
if (ec == NILECE) { /* was locked could not be purged */
logit(0,"OSEnumGet: bad enum!\n");
return("");
}
if (idx > ec->ece_cnt) { /* check for bad idx */
logit(0,"OSEnumGet: Bad idx!\n");
return("");
}
if (!ec->ece_lock) /* check for bad lock */
logit(0,"OSEnumGet: Handle not locked!\n");
if (DBENU)
printf("OSEnumGet: %d:%s\n",idx,ec->ece_nlst[idx-1]->d_name);
return(ec->ece_nlst[idx-1]->d_name);
}
/*
* int OSEnumInit(IDirP idir)
*
* Call OSEnumInit to initialize enumeration information. This
* procedure must be called before OSEnumGet which returns the
* nth entry for a directory.
*
* OSEnumDone must be called when finished to release enumeration
* information for a directory.
*
* Returns the count of entries in the directory or a negative error
* code.
*
*/
int
OSEnumInit(idir)
IDirP idir;
{
EnumCE *ec;
if (DBENU)
printf("OSEnumInit: %s\n",pathstr(idir));
#ifdef STAT_CACHE
OScd(pathstr(idir));
#endif STAT_CACHE
OSValFICacheForEnum(idir); /* make sure fi cache for directory is valid */
ec = EC_Fetch(idir); /* get directory info */
if (ec == NILECE) /* access problem? */
return(aeAccessDenied); /* yes... */
if (ec->ece_lock == TRUE)
logit(0,"OSEnumInit: directory already locked!\n");
ec->ece_lock = TRUE; /* entry is locked, no purge */
return(ec->ece_cnt); /* return count */
}
/*
* void OSEnumDone(dirid)
*
* Call this routine to say that enumeration is no longer active for
* a directory.
*
* OSEnumDone unlocks the directory entry and allows it to be removed
* from the cache.
*
*/
void
OSEnumDone(dirid)
IDirP dirid;
{
EnumCE *ec;
ec = EC_Find(dirid); /* get cached entry */
if (ec == NILECE) /* should not happen */
logit(0,"OSEnumDone: no cache for dirid\n");
else
ec->ece_lock = FALSE; /* unlock */
}
/*
* int OSEnumCount(dirid)
*
* Return the count of entries in a directory.
*
*/
int OSEnumCount(dirid)
IDirP dirid;
{
EnumCE *ec;
ec = EC_Fetch(dirid); /* get directory info */
if (ec == NILECE) /* access problem? */
return(aeAccessDenied); /* yes... */
if (DBENU)
printf("OSEnumCount: %s = %d\n",pathstr(ec->ece_dirid),ec->ece_cnt);
return(ec->ece_cnt); /* return the count */
}
OSfname(r,idir,fn,typ)
IDirP idir;
register char *fn,*r;
register int typ;
{
register char *p;
for (p = pathstr(idir); *p != '\0';) /* copy the directory */
*r++ = *p++;
if (typ == F_RSRC || typ == F_FNDR) /* append directory names */
for (p = ((typ == F_RSRC) ? RFDIR : FIDIR); *p != '\0'; )
*r++ = *p++;
if (*fn != '\0') { /* add slash */
*r++ = '/'; /* if not null file */
while (*fn != '\0')
*r++ = *fn++;
}
*r = '\0';
}
toResFork(str, fn)
register char *str;
char *fn;
{
register char *fp, *tp;
if(*fn) { /* a real file */
if(fp = rindex(str, '/')) /* skip over last slash */
fp++;
else
fp = str;
str = fp;
fp = str + strlen(str);
tp = fp + DIRRFLEN;
*tp = 0;
while(fp > str) /* move filename, leaving space for .resource */
*--tp = *--fp;
fp = DIRRF;
while(*fp)
*str++ = *fp++;
} else /* a directory */
strcat(str,RFDIR); /* just append .resource */
}
toFinderInfo(str, fn)
register char *str;
char *fn;
{
register char *fp, *tp;
if(*fn) { /* a real file */
if(fp = rindex(str,'/')) /* skip over last slash */
fp++;
else
fp = str;
str = fp;
fp = str + strlen(str);
tp = fp + DIRFILEN;
*tp = 0;
while(fp > str) /* move filename, leaving space for .finderinfo */
*--tp = *--fp;
fp = DIRFI;
while(*fp)
*str++ = *fp++;
} else /* a directory */
strcat(str,FIDIR); /* just append .finderinfo */
}
#ifdef NOCASEMATCH
/*
* searchDirectory(dir, name)
* Do a case insensitive search for name in dir, and write the true name
* of the file in name.
*/
private
searchDirectory(dir, name)
char *dir, *name;
{
register char *fp, *tp;
register DIR *dp;
#ifdef USEDIRENT
register struct dirent *d;
#else USEDIRENT
register struct direct *d;
#endif USEDIRENT
register int len;
char lname[BUFSIZ], dname[BUFSIZ];
if((dp = opendir(dir)) == NULL)
return(0);
len = 0;
for(fp = name, tp = lname ; *fp ; fp++) {
*tp++ = isupper(*fp) ? tolower(*fp) : *fp;
len++;
}
*tp = 0;
while(d = readdir(dp)) {
#ifdef USEDIRENT
if (strlen(d->d_name) != len)
#else /* USEDIRENT */
if (d->d_namlen != len)
#endif /* USEDIRENT */
continue;
for(fp = d->d_name, tp = dname ; *fp ; fp++)
*tp++ = isupper(*fp) ? tolower(*fp) : *fp;
*tp = 0;
if(strcmp(dname, lname) == 0) {
strcpy(name, d->d_name);
closedir(dp);
return(1);
}
}
closedir(dp);
return(0);
}
/*
* noCaseDir(path)
* Recursively verify the components of path.
*/
private
noCaseDir(path)
register char *path;
{
register char *last;
register int status;
if(access(path, F_OK) >= 0)
return(1);
if(last = rindex(path, '/')) {
if(last == path)
return(searchDirectory("/", last + 1));
else {
*last++ = 0;
status = 0;
if(noCaseDir(path))
status = searchDirectory(path, last);
*--last = '/';
return(status);
}
}
return(searchDirectory(".", path));
}
/*
* noCaseFind(path)
* noCaseFind() calls noCaseDir() and searchDirectory() recursively to
* take path (case insensitive) and converts it to (case sensitive) newpath
* corresponding to the true Unix filename. This is mainly to fix
* HyperCard doing funny things to stack names.
*/
void
noCaseFind(path)
register char *path;
{
register char *last;
if(last = rindex(path, '/')) {
if(last == path)
searchDirectory("/", last + 1);
else {
*last++ = 0;
if(noCaseDir(path))
searchDirectory(path, last);
*--last = '/';
}
} else
searchDirectory(".", path);
}
/*
* noCaseMatch(path)
* noCaseMatch() tests path first and will call noCaseFind() is path
* doesn't exist.
*/
void
noCaseMatch(path)
register char *path;
{
if(access(path, F_OK) >= 0)
return;
noCaseFind(path);
}
#endif NOCASEMATCH
#ifdef SHORT_NAMES
private int
searchn (name,ec,type)
char *name;
EnumCE *ec;
{
int i = 0;
if (ec == NILECE) /* hmmmm ... */
return(-1);
if (type != 1)
while ((i<ec->ece_cnt)
&& (strcmp (name, ec->ece_nlst[i]->d_name) != 0)) {
i++;
}
else
while ((i<ec->ece_cnt)
&& (strcmp (name, ec->s_namearray[i].s_name) != 0)) {
i++;
}
if (i == ec->ece_cnt)
return(-1);
else
return(i);
}
char*
Get_name(dirid,name,type,outname)
IDirP dirid;
char *name,*outname;
int type;
{
EnumCE *ec;
int i, idx;
ec = EC_Fetch(dirid);
if (ec == NILECE)
idx = -1;
else
idx = searchn(name,ec,type);
if (idx == -1) {
if (strcmp (name, dirid->name) == 0) /*then it is a directory*/
printf("wasn't found and it is a directory\n");
if (DBENU)
printf("name wasn't found!!!!!Index == -1\n");
sprintf(outname,"%s",name);
}
else if (type != 1) /*return longname*/
sprintf(outname,"%s",ec->s_namearray[idx].s_name);
else /* return short name */
sprintf(outname,"%s",ec->ece_nlst[idx]->d_name);
}
#endif SHORT_NAMES

907
applications/aufs/afposfi.c Normal file
View File

@ -0,0 +1,907 @@
/*
* $Author: djh $ $Date: 1995/06/12 06:58:18 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afposfi.c,v 2.7 1995/06/12 06:58:18 djh Rel djh $
* $Revision: 2.7 $
*/
/*
* afposfi.c - Appletalk Filing Protocol OS FNDR File Interface.
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* March 1987 Schilit Created.
* Jan 1988 CCKim New finderinfo format
* December 1990 djh tidy up for AFP 2.0
*
*/
/* PATCH: PC.aufs/afposfi.c.diffs, djh@munnari.OZ.AU, 15/11/90 */
/* PATCH: Dan@lth.se/stat.cache.patches, djh@munnari.OZ.AU, 16/11/90 */
/* PATCH: Moy@Berkeley/afposfi.c.diff, djh@munnari.OZ.AU, 17/11/90 */
#include <stdio.h>
#include <errno.h>
extern int errno;
#include <sys/param.h>
#ifndef _TYPES
# include <sys/types.h>
#endif
#include <sys/file.h>
#include <sys/stat.h>
#include <netinet/in.h> /* for htons, htonl */
#include <netat/appletalk.h>
#include <netat/compat.h>
#include <netat/afp.h>
#include "afps.h"
#include "afpgc.h"
#ifdef NEEDFCNTLDOTH
# include <fcntl.h>
#endif
#include "afpudb.h"
typedef struct FCacheEnt {
struct FCacheEnt *next; /* link for free queue */
IDirP fe_pdir; /* directory */
int fe_okay; /* last internal modify count */
char *fe_fnam; /* file */
long fe_hash; /* hash value of fe_fnam */
/* should we use ctime instead perhaps? */
time_t fe_mtime; /* last modify time: file system */
time_t fe_vtime; /* last time validated */
FileInfo fe_fi; /* file info */
} FCacheEnt;
export GCHandle *fich; /* handle on cache */
private FCacheEnt *fce, *lfce; /* recycle purge-load */
private FCacheEnt *getfe; /* last os_getfi */
private int fc_valid();
private int fc_compare();
private char *fc_load();
private void WriteFA();
private void fc_purge();
private void fc_flush();
private void fc_flush_start();
private void fc_flush_end();
private FileInfo *os_getfi();
private fc_readent();
#define FICacheSize 128
/* Each cache entry has a lifetime that it goes through before it must */
/* be revalidated before reuse: this prevents cache entries from getting */
/* "stale". */
/* The revalidation consists of seeing if the disk copy has changed */
#define FI_VALID_TIME (60*5) /* 5 minutes */
InitOSFI()
{
fich = GCNew(FICacheSize,fc_valid,fc_compare,fc_load,fc_purge,fc_flush);
lfce = fce = (FCacheEnt *) 0;
getfe = (FCacheEnt *) 0;
}
/*
* Our flush doesn't flush modified entries since our cache is
* write through, but attempts instead to check validity of items in
* our cache
*
* can bracket with fc_flush_start and fc_flush_end to reduce # of
* stats. This depends on the .finderinfo directory modify time
* getting changed when a finderinfo entry is modified. WriteFA
* guarantees this as best it can (can you say hack?)
*
*
*/
private time_t fcf_val_time = 0; /* validate time */
private IDirP fcf_val_dir = NILDIR; /* directory val time is for */
private void
fc_flush_start(pdir)
IDirP pdir;
{
char path[MAXPATHLEN];
struct stat stb;
OSfname(path, pdir, "", F_FNDR); /* get directory */
if (stat(path, &stb) < 0) {
#ifdef NOCASEMATCH
noCaseFind(path);
if (stat(path, &stb) < 0) {
fcf_val_dir = NILDIR;
fcf_val_time = 0;
return; /* nothing else we can do */
}
#else NOCASEMATCH
fcf_val_dir = NILDIR;
fcf_val_time = 0;
return; /* nothing else we can do */
#endif NOCASEMATCH
}
fcf_val_dir = pdir;
fcf_val_time = stb.st_mtime; /* remember */
}
private void
fc_flush_end()
{
fcf_val_time = 0; /* mark none */
fcf_val_dir = NILDIR;
}
private void
fc_flush(fe, pdir)
FCacheEnt *fe;
IDirP pdir;
{
char path[MAXPATHLEN];
struct stat stb;
/* if passed directory isn't nildir (flush all), then the file */
/* will only be check if the particular item has the same directory */
if (pdir != NILDIR && (fe->fe_pdir != pdir))
return;
if ((fe->fe_pdir->flags & DID_FINDERINFO)) { /* always okay */
OSfname(path, fe->fe_pdir, fe->fe_fnam, F_FNDR);
/* if we have a .finderinfo directory update time */
/* and it is more recent than cache entry, then check the */
/* cache entry */
/* also add a check against vtime. Makes it much more useful */
/* since it is more than likely that fcf_val_time is later */
/* than the mtime for the majority of the files */
if (fcf_val_dir == fe->fe_pdir &&
(fcf_val_time > fe->fe_mtime) &&
(fcf_val_time > fe->fe_vtime)) {
#ifdef NOCASEMATCH
if (stat(path, &stb) < 0) {
noCaseFind(path);
if (stat(path, &stb) < 0)
return; /* nothing else we can do */
}
#else NOCASEMATCH
if (stat(path, &stb) < 0)
return; /* nothing else we can do */
#endif NOCASEMATCH
if (stb.st_mtime != fe->fe_mtime) /* reload entry */
fe->fe_okay = FALSE; /* make entry as bad */
}
}
time(&fe->fe_vtime); /* mark last validate time */
}
private
fc_valid(fe)
FCacheEnt *fe;
{
char path[MAXPATHLEN];
struct stat stb;
time_t mtime;
if (!fe->fe_okay) /* if not okay, don't */
return(fe->fe_okay); /* bother with checks */
time(&mtime);
if (fe->fe_vtime + FI_VALID_TIME < mtime) {
fe->fe_vtime = mtime; /* mark as new validate time */
if ((fe->fe_pdir->flags & DID_FINDERINFO) == 0) /* always okay */
return(fe->fe_okay);
OSfname(path, fe->fe_pdir, fe->fe_fnam, F_FNDR);
#ifdef NOCASEMATCH
if (stat(path, &stb) < 0) {
noCaseFind(path);
if (stat(path, &stb) < 0)
return(fe->fe_okay); /* nothing else we can do */
}
#else NOCASEMATCH
if (stat(path, &stb) < 0)
return(fe->fe_okay); /* nothing else we can do */
#endif NOCASEMATCH
if (stb.st_mtime != fe->fe_mtime) /* reload entry */
return(FALSE); /* bad entry */
}
return(fe->fe_okay);
}
private void
fc_purge(fe)
FCacheEnt *fe;
{
if (DBOSI)
printf("fc_purge: %s\n",fe->fe_fnam);
if (fe == getfe) /* purging last get? */
getfe = (FCacheEnt *) 0; /* yes... then zero */
free(fe->fe_fnam); /* always free the name */
fe->fe_fnam = (char *) 0; /* and zero... */
fe->fe_hash = 0; /* clear hash */
fe->next = NULL; /* trash it here since want in both */
if (fce == (FCacheEnt *) 0) /* check for recycled entry */
lfce = fce = fe; /* if none then save */
else {
lfce->next = fe; /* put at end of free list */
lfce = fe; /* remember the end */
#ifdef notdef
free(fe); /* and the struct itself */
#endif
}
}
private
fc_compare(fe,key)
FCacheEnt *fe,*key;
{
if (fe->fe_pdir != key->fe_pdir)
return(FALSE);
if (fe->fe_hash != key->fe_hash)
return(FALSE);
return(strcmp(fe->fe_fnam,key->fe_fnam) == 0);
}
private char *
fc_load(key)
FCacheEnt *key;
{
FCacheEnt *fe;
if (DBOSI)
printf("fc_load: %s\n",key->fe_fnam);
if (fce != (FCacheEnt *) 0) { /* recycled fc avail? */
fe = fce; /* yes... use that */
fce = fce->next;
} else /* else allocate */
fe = (FCacheEnt *) malloc(sizeof(FCacheEnt));
fe->fe_pdir = key->fe_pdir;
fe->fe_fnam = (char *) malloc(strlen(key->fe_fnam)+1);
fe->fe_okay = TRUE;
fe->fe_mtime = 0;
time(&fe->fe_vtime); /* validate time stamp */
strcpy(fe->fe_fnam,key->fe_fnam);
fe->fe_hash = key->fe_hash;
fc_readent(fe);
return((char *) fe);
}
private
fc_readent(fe)
FCacheEnt *fe;
{
struct stat stb;
char path[MAXPATHLEN];
int fd, ft, len, err;
FileInfo *fi = &fe->fe_fi;
FinderInfo *fndr;
extern struct ufinderdb uf[];
extern int sessvers;
word newattr;
#ifdef USR_FILE_TYPES
extern struct uft uft[];
#endif USR_FILE_TYPES
bzero((char *) fi,sizeof(FileInfo)); /* make sure clear before */
if (fe->fe_pdir->flags & DID_FINDERINFO) {
OSfname(path,fe->fe_pdir,fe->fe_fnam,F_FNDR);
if (DBOSI)
printf("fc_readent: reading %s\n",path);
#ifndef STAT_CACHE
fd = open(path,O_RDONLY);
#else STAT_CACHE
fd = cwd_open(path,O_RDONLY);
#endif STAT_CACHE
#ifdef NOCASEMATCH
if (fd < 0) {
noCaseFind(path);
#ifndef STAT_CACHE
fd = open(path,O_RDONLY);
#else STAT_CACHE
fd = cwd_open(path,O_RDONLY);
#endif STAT_CACHE
}
#endif NOCASEMATCH
if (fd >= 0) {
OSLockFileforRead(fd);
err = fstat(fd, &stb);
len = read(fd,(char *) fi,sizeof(FileInfo));
OSUnlockFile(fd);
if (len < FI_BASELENGTH) {
close(fd);
if (len == 0) /* length zero means creat'd */
goto dummy;
if (DBOSI)
printf("fc_readent: finderinfo too short\n");
goto nofileinfo;
}
if (fi->fi_magic1 != FI_MAGIC1) {
OldFileInfo *ofi = (OldFileInfo *)fi;
bcopy(ofi->fi_comnt, fi->fi_comnt, fi->fi_magic1);
fi->fi_comln = fi->fi_magic1;
newattr = (sessvers >= AFPVersion2DOT0) ? (FPA_RNI|FPA_DEI) : 0;
if (ofi->fi_attr & FI_ATTR_SETCLEAR)
fi->fi_attr = ofi->fi_attr &
(FI_ATTR_READONLY|FI_ATTR_MUSER|FI_ATTR_INVISIBLE|newattr);
else
fi->fi_attr = 0;
fi->fi_magic1 = FI_MAGIC1;
fi->fi_magic = FI_MAGIC;
fi->fi_version = FI_VERSION;
fi->fi_bitmap = FI_BM_MACINTOSHFILENAME;
#ifdef SHORT_NAMES
ItoEName(fe->fe_fnam, fi->fi_macfilename);
ItoEName_Short(fe->fe_pdir,fe->fe_fnam,fi->fi_shortfilename);
#else SHORT_NAMES
ItoEName(fe->fe_fnam, fi->fi_macfilename);
#endif SHORT_NAMES
/* make sure we update it */
WriteFA(fe->fe_pdir, fe->fe_fnam, fi);
} else {
if (fi->fi_magic != FI_MAGIC || fi->fi_version != FI_VERSION) {
if (DBOSI)
printf("fc_readent: fileinfo check fail\n");
close(fd);
goto nofileinfo;
}
fi->fi_attr = ntohs(fi->fi_attr);
if (err == 0) /* stat okay */
fe->fe_mtime = stb.st_mtime; /* remember mtime */
}
if (close(fd) != 0)
printf("fc_readent: close error");
return(noErr);
}
/* Open failed for .finderinfo file. Use defaults finfo or zero if dir */
if (DBOSI)
printf("fc_readent: Open failed for %s\n",path);
}
nofileinfo:
/* convert name to internal name */
OSfname(path,fe->fe_pdir,fe->fe_fnam,F_DATA); /* create plain name */
#ifdef NOCASEMATCH
#ifndef STAT_CACHE
if (stat(path,&stb) != 0) { /* check if it exists */
#else STAT_CACHE
if (OSstat(path,&stb) != 0) { /* check if it exists */
#endif STAT_CACHE
noCaseFind(path);
#endif NOCASEMATCH
#ifndef STAT_CACHE
if (stat(path,&stb) != 0) /* check if it exists */
#else STAT_CACHE
if (OSstat(path,&stb) != 0) /* check if it exists */
#endif STAT_CACHE
return(aeObjectNotFound); /* no... */
#ifdef NOCASEMATCH
}
#endif NOCASEMATCH
if (S_ISDIR(stb.st_mode)) {
fi->fi_comln = 0;
} else {
ft = os_getunixtype(path, &stb);
fndr = (FinderInfo *)fi->fi_fndr; /* get pointer to finder info */
#ifdef USR_FILE_TYPES
if (ft >= FNDR_UFT) {
ft -= FNDR_UFT; /* ft is now the index into the UFT table */
bcopy(uft[ft].uft_ftype, fndr->file.fdType, sizeof(uft[ft].uft_ftype));
bcopy(uft[ft].uft_creat, fndr->file.fdCreator, sizeof(uft[ft].uft_creat));
bcopy(uft[ft].uft_comment, fi->fi_comnt, uft[ft].uft_commentlen);
fi->fi_comln = uft[ft].uft_commentlen;
} else {
#endif USR_FILE_TYPES
bcopy(uf[ft].ufd_ftype, fndr->file.fdType, sizeof(fndr->file.fdType));
bcopy(uf[ft].ufd_creat,fndr->file.fdCreator,sizeof(fndr->file.fdCreator));
bcopy(uf[ft].ufd_comment, fi->fi_comnt, uf[ft].ufd_commentlen);
fi->fi_comln = uf[ft].ufd_commentlen;
#ifdef USR_FILE_TYPES
}
#endif USR_FILE_TYPES
}
fi->fi_attr = DEFATTR; /* set default attributes */
dummy:
fi->fi_magic1 = FI_MAGIC1;
fi->fi_version = FI_VERSION;
fi->fi_magic = 0; /* mark as "default" entry */
fi->fi_bitmap = FI_BM_MACINTOSHFILENAME;
#ifdef SHORT_NAMES
ItoEName(fe->fe_fnam, fi->fi_macfilename);
ItoEName_Short(fe->fe_pdir,fe->fe_fnam, fi->fi_shortfilename);
#else SHORT_NAMES
ItoEName(fe->fe_fnam, fi->fi_macfilename);
#endif SHORT_NAMES
return(noErr);
}
private void
WriteFA(ipdir,fn,fi)
IDirP ipdir;
char *fn;
FileInfo *fi;
{
char path[MAXPATHLEN];
int fd;
int needu = 0;
if ((ipdir->flags & DID_FINDERINFO) == 0) {
if (DBOSI)
printf("WriteFA skipped, no finderinfo directory\n");
return;
}
OSfname(path,ipdir,fn,F_FNDR); /* convert to internal name */
if (DBOSI)
printf("WriteFA: writing %s\n",path);
needu++;
fd = open(path,O_WRONLY);
#ifdef NOCASEMATCH
if(fd < 0) {
noCaseFind(path);
fd = open(path,O_WRONLY);
}
#endif NOCASEMATCH
if (fd < 0) { /* open for write */
if (errno != ENOENT) {
printf("WriteFA: error opening %s errno=%d\n",path,errno);
return;
}
if ((fd = open(path,O_WRONLY|O_CREAT,0666)) < 0) {
if (DBOSI)
printf("fc_flush: create failed for %s %d\n",path,errno);
return;
}
if (DBOSI)
printf("fc_flush: created %s\n",path);
} else needu++;
fi->fi_attr = htons(fi->fi_attr); /* swab!!!@ */
fi->fi_magic = FI_MAGIC;
OSLockFileforWrite(fd);
(void)write(fd,(char *) fi,sizeof(FileInfo)); /* write stuff */
OSUnlockFile(fd);
if (close(fd) != 0)
printf("WriteFA: close error");
fi->fi_attr = htons(fi->fi_attr); /* then swab back!!!@ */
/* horrible hack, but can't use utimes, because we must be owner then */
if (needu) { /* update directory modified time */
OSfname(path,ipdir,FIDIRFN,F_FNDR); /* pick bad name */
if ((fd = open(path, O_WRONLY|O_CREAT,0666)) < 0)
return;
close(fd);
unlink(path);
}
/* EModified(fe->fe_pdir); /* and mark directory as modified */
}
private FileInfo *
os_getfi(pdir,fn)
IDirP pdir;
char *fn;
{
FCacheEnt key;
register long hash;
register char *p;
key.fe_pdir = pdir;
p = key.fe_fnam = fn;
hash = 0;
while (*p) {
hash <<= 2;
hash += *p++;
}
key.fe_hash = hash;
/* do the "quick" check first */
if (getfe == 0 || !fc_compare(getfe,&key)) {
/* nope, either find in cache or load from disk */
getfe = (FCacheEnt *)GCLocate(fich,(char *)&key);
}
return(&getfe->fe_fi); /* and return the FileInfo */
}
FModified(pdir, fn)
IDirP pdir;
char *fn;
{
FCacheEnt key;
register long hash;
register char *p;
int idx;
key.fe_pdir = pdir;
p = key.fe_fnam = fn;
hash = 0;
while (*p) {
hash <<= 2;
hash += *p++;
}
key.fe_hash = hash;
EModified(pdir); /* make parent directory as modified */
if (getfe == 0 || !fc_compare(getfe,&key)) {
/* no kept entry */
if (!GCScan(fich, &key, &idx)) /* not in cache, already flushed */
return;
getfe = (FCacheEnt *)GCidx2ent(fich, idx);
}
if (DBOSI)
printf("Invalidating file cache entry %s/%s\n",pathstr(pdir),fn);
getfe->fe_okay = FALSE; /* invalidate entry */
}
/*
* OSValidateFICacheforEnum(directory)
*
* validate a file cache for enumerate
*
* make fc_flush only stat if .finderinfo directory modification time
* has changed -- writefa guarantees us that
*
*/
OSValFICacheForEnum(pdir)
IDirP pdir;
{
fc_flush_start(pdir);
GCFlush(fich, pdir); /* make sure valid */
fc_flush_end();
}
/*
* OSSetFA(IDirP pdir, char *fn, word bm, FileDirParm *fdp)
*
* Set finder and attr for a file specified by ancestor directory
* (pdir) and file name (fn). The bitmap in bm specifies which
* FP_FINFO (DP_FINFO) or FP_ATTR (DP_ATTR) are to be set.
*
* Update to handle AFP 2.0 as defined by "Inside AppleTalk", 2nd Ed, p13-21
* djh@munnari.OZ.AU, 06/12/90
*
*/
OSSetFA(pdir,fn,bm,fdp)
IDirP pdir;
char *fn;
word bm;
FileDirParm *fdp;
{
FileInfo *fi;
word attr,newattr;
extern int sessvers;
fi = os_getfi(pdir,fn);
if (bm & FP_ATTR) {
attr = fdp->fdp_attr;
/* limit: allowed alter some bits only & protocol vers. dependant */
newattr = (sessvers >= AFPVersion2DOT0) ? (FPA_RNI|FPA_DEI) : 0;
attr &= (FI_ATTR_READONLY|FI_ATTR_MUSER|FI_ATTR_INVISIBLE|newattr);
if (sessvers == AFPVersion1DOT1 && (attr & FI_ATTR_READONLY))
attr |= (FPA_RNI|FPA_DEI);
if (fdp->fdp_attr & FI_ATTR_SETCLEAR)
fi->fi_attr |= attr;
else
fi->fi_attr &= ~attr;
}
#ifdef USE_MAC_DATES
if (bm & FP_CDATE) {
fi->fi_datemagic = FI_MAGIC;
fi->fi_datevalid |= FI_CDATE;
bcopy(&fdp->fdp_cdate,fi->fi_ctime,sizeof(fi->fi_ctime));
}
if (bm & FP_MDATE) {
time_t when;
time(&when);
fi->fi_datemagic = FI_MAGIC;
fi->fi_datevalid |= FI_MDATE;
bcopy(&when,fi->fi_utime,sizeof(fi->fi_utime));
bcopy(&fdp->fdp_mdate,fi->fi_mtime,sizeof(fi->fi_mtime));
}
#endif USE_MAC_DATES
if (bm & FP_FINFO) {
bcopy(fdp->fdp_finfo,fi->fi_fndr,FINFOLEN);
if (!(bm & FP_PDOS)) /* setting finder info BUT NOT PRODOS */
mapFNDR2PDOS(fdp); /* derive suitable File and Aux types */
}
if (bm & FP_PDOS)
if (!(bm & FP_FINFO)) /* setting PRODOS info BUT NOT finder */
mapPDOS2FNDR(fdp,fi); /* derive suitable fdCreator & fdType */
#ifdef USE_MAC_DATES
if (bm & (FP_ATTR|FP_FINFO|FP_PDOS|FP_CDATE|FP_MDATE))
#else USE_MAC_DATES
if (bm & (FP_ATTR|FP_FINFO|FP_PDOS))
#endif USE_MAC_DATES
WriteFA(pdir,fn,fi);
return(noErr);
}
OSGetAttr(pdir,fn,attr)
IDirP pdir;
char *fn;
word *attr;
{
FileInfo *fi;
extern int sessvers;
fi = os_getfi(pdir,fn);
*attr = fi->fi_attr;
if (sessvers == AFPVersion1DOT1) {
if (*attr & (FPA_RNI|FPA_DEI))
*attr |= FI_ATTR_READONLY;
*attr &= FPA_MASK1; /* give only AFP 1.1 Attributes */
}
return(noErr);
}
OSSetAttr(pdir, fn, attr)
IDirP pdir;
char *fn;
word attr;
{
FileInfo *fi;
fi = os_getfi(pdir, fn);
fi->fi_attr = attr;
WriteFA(pdir, fn, fi);
return(noErr);
}
OSGetFNDR(pdir,fn,finfo)
IDirP pdir;
char *fn;
byte *finfo;
{
FileInfo *fi;
fi = os_getfi(pdir,fn);
bcopy(fi->fi_fndr,finfo,FINFOLEN);
return(noErr);
}
OSSetComment(pdir,fn,cs,cl)
IDirP pdir;
char *fn;
byte *cs;
byte cl;
{
FileInfo *fi;
fi = os_getfi(pdir,fn);
bcopy(cs,fi->fi_comnt,cl);
fi->fi_comln = cl;
WriteFA(pdir,fn,fi);
return(noErr);
}
OSGetComment(pdir,fn,cs,cl)
IDirP pdir;
char *fn;
byte *cs;
byte *cl;
{
FileInfo *fi;
fi = os_getfi(pdir,fn);
*cl = fi->fi_comln;
if (*cl == 0)
*cs = 0;
bcopy(fi->fi_comnt,cs,*cl);
return(noErr);
}
#ifdef USE_MAC_DATES
OSGetCDate(pdir,fn,cdate)
IDirP pdir;
char *fn;
time_t *cdate;
{
FileInfo *fi;
fi = os_getfi(pdir,fn);
if (fi->fi_datemagic != FI_MAGIC || (!(fi->fi_datevalid & FI_CDATE)))
return(-1);
bcopy(fi->fi_ctime,cdate,sizeof(fi->fi_ctime));
return(noErr);
}
OSGetMDate(pdir,fn,mdate,udate)
IDirP pdir;
char *fn;
time_t *mdate;
time_t *udate;
{
FileInfo *fi;
fi = os_getfi(pdir,fn);
if (fi->fi_datemagic != FI_MAGIC || (!(fi->fi_datevalid & FI_MDATE)))
return(-1);
bcopy(fi->fi_mtime,mdate,sizeof(fi->fi_mtime));
bcopy(fi->fi_utime,udate,sizeof(fi->fi_utime));
return(noErr);
}
#endif USE_MAC_DATES
/*
* Establish the mac file name after a os_move
*
*/
OSSetMacFileName(pdir, fn)
IDirP pdir;
char *fn;
{
FileInfo *fi;
fi = os_getfi(pdir,fn);
#ifdef SHORT_NAMES
ItoEName(fn, fi->fi_macfilename);
ItoEName_Short(pdir,fn, fi->fi_shortfilename);
#else SHORT_NAMES
ItoEName(fn, fi->fi_macfilename);
#endif SHORT_NAMES
WriteFA(pdir, fn, fi);
return(noErr);
}
/*
* mapPDOS2FNDR
*
* convert ProDOS File Type and Aux Type to Finder Info
* (even to have to contemplate doing this is disgusting)
*
*/
#define CTLEN 4
mapPDOS2FNDR(fdp,fi)
FileDirParm *fdp;
FileInfo *fi;
{
FinderInfo *fndr;
byte prodos_at[4];
byte prodos_ft[2];
if (fdp->fdp_flg == FDP_DIRFLG) /* directory, do nothing! */
return;
bcopy(&fdp->fdp_prodos_aux, prodos_at, sizeof(prodos_at));
bcopy(&fdp->fdp_prodos_ft, prodos_ft, sizeof(prodos_ft));
fndr = (FinderInfo *) fi->fi_fndr;
switch (prodos_ft[0]) {
case 0x00:
bcopy("BINA", fndr->file.fdType, CTLEN);
break;
case 0xb3:
bcopy("PS16", fndr->file.fdType, CTLEN);
break;
case 0xff:
bcopy("PSYS", fndr->file.fdType, CTLEN);
break;
case 0x04:
if (prodos_at[0] == 0x00 && prodos_at[1] == 0x00) {
bcopy("TEXT", fndr->file.fdType, CTLEN);
break;
} /* else fall thro' */
default:
/* some fdTypes will be unprintable */
fndr->file.fdType[0] = 'p';
fndr->file.fdType[1] = prodos_ft[0]; /* file type */
fndr->file.fdType[2] = prodos_at[1]; /* high byte */
fndr->file.fdType[3] = prodos_at[0]; /* low byte */
break;
}
bcopy("pdos", fndr->file.fdCreator, CTLEN);
}
/*
* mapFNDR2PDOS
*
* convert Finder Info to ProDOS File Type and Aux Type
* (even to have to contemplate doing this is disgusting)
*
*/
mapFNDR2PDOS(fdp)
FileDirParm *fdp;
{
FinderInfo *fndr;
byte prodos_at[4];
byte prodos_ft[2];
byte hex2num();
fndr = (FinderInfo *) fdp->fdp_finfo;
if (fdp->fdp_flg == FDP_DIRFLG) {
/* set specific ProDOS directory information */
prodos_ft[0] = 0x0f;
prodos_ft[1] = 0x00;
prodos_at[0] = 0x00;
prodos_at[1] = 0x02;
prodos_at[2] = 0x00;
prodos_at[3] = 0x00;
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
bcopy(prodos_at, &fdp->fdp_prodos_aux, sizeof(prodos_at));
return;
}
if (bcmp("TEXT", fndr->file.fdType, CTLEN) == 0) {
prodos_ft[0] = 0x04;
prodos_ft[1] = 0x00;
bzero(&fdp->fdp_prodos_aux, sizeof(prodos_at));
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
return;
}
if (bcmp("pdos", fndr->file.fdCreator, CTLEN) == 0) {
if (bcmp("PSYS", fndr->file.fdType, CTLEN) == 0) {
prodos_ft[0] = 0xff;
prodos_ft[1] = 0x00;
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
return;
}
if (bcmp("PS16", fndr->file.fdType, CTLEN) == 0) {
prodos_ft[0] = 0xb3;
prodos_ft[1] = 0x00;
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
return;
}
if (bcmp("BINA", fndr->file.fdType, CTLEN) == 0) {
prodos_ft[0] = 0x00;
prodos_ft[1] = 0x00;
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
return;
}
if (fndr->file.fdType[0] == 'p') { /* bizarre */
prodos_ft[0] = fndr->file.fdType[1];
prodos_ft[1] = 0x00;
prodos_at[0] = fndr->file.fdType[3]; /* low byte */
prodos_at[1] = fndr->file.fdType[2]; /* high byte */
prodos_at[2] = 0x00;
prodos_at[3] = 0x00;
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
bcopy(prodos_at, &fdp->fdp_prodos_aux, sizeof(prodos_at));
return;
}
if (fndr->file.fdType[2] == ' ' && fndr->file.fdType[3] == ' ') {
short num; /* much more bizarre */
num = hex2num(fndr->file.fdType[0]) << 4;
num |= hex2num(fndr->file.fdType[1]) & 0xf;
prodos_ft[0] = (byte) num & 0xff;
prodos_ft[1] = 0x00;
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
return;
}
}
/* otherwise */
prodos_ft[0] = 0x00;
prodos_ft[1] = 0x00;
bzero(&fdp->fdp_prodos_aux, sizeof(prodos_at));
bcopy(prodos_ft, &fdp->fdp_prodos_ft, sizeof(prodos_ft));
}
byte
hex2num(ch)
char ch;
{
if (ch >= '0' && ch <= '9')
return(ch - '0');
if (ch >= 'a' && ch <= 'f')
return(ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')
return(ch - 'A' + 10);
return(0);
}

View File

@ -0,0 +1,817 @@
/*
* $Author: djh $ $Date: 1996/03/11 12:34:09 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afposncs.c,v 2.9 1996/03/11 12:34:09 djh Rel djh $
* $Revision: 2.9 $
*/
/*
* afposncs.c - Appletalk Filing Protocol OS Normalizing for Character Sets
*
*
* afposncs contains the logic to normalize between an OS character
* set and a Macintosh character set. It decides when a translation
* is necessary (based on file extentions and file types) and does
* the actual translation. It is particularly useful for normalizing
* between unix files on machines that support an international
* character set and the macintosh character set.
* Note: logic to map between EOL chars was moved here as well.
*
*
* The intent is to provide some "transparency". Translation is done
* based on a the ncs_transtable which defines which file
* type/creators get translated. In addition, it possible to specify
* that files with particular suffixes (and file type/creators) get
* translated.
*
* Caveat: much more massive changes must be made to allow for mapping
* from a single character to multiple (or vice versa).
*
* Jan 1988 Dan Sahlin Transliteration tables for .ascii, .swe,
* .fin and .latin1
* Feb 1988 Charlie C. Kim Rewrite all but tables.
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <netat/appletalk.h>
#include <netat/afp.h>
#include "afposncs.h"
#include "afps.h"
#ifdef USR_FILE_TYPES
#include "afpudb.h"
#endif USR_FILE_TYPES
/* to_ tables are to unix from mac */
/* from_ tables are from unix to mac */
/* ASCII: only a CR-LF mapping is performed */
/* These are actually dummy table since it faster to compare than */
/* index and store for the simple translation involved */
private byte to_ascii[1]; /* mac to unix: dummy table */
private byte from_ascii[1]; /* unix to mac: dummy table */
#ifdef SHORT_NAMES
private byte pc_to_ascii[1];
private byte pc_from_ascii[1];
#endif SHORT_NAMES
#ifdef USR_FILE_TYPES
#ifdef ISO_TRANSLATE
private byte iso[1];
#endif ISO_TRANSLATE
private byte raw[1];
private byte text[1];
private byte ascii[1];
extern struct uft uft[];
#endif USR_FILE_TYPES
#ifdef ISO_TRANSLATE
extern u_char ISO2Mac[];
extern u_char Mac2ISO[];
#endif ISO_TRANSLATE
#ifdef notdef
private byte to_ascii[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, '\n', 0x0e, 0x0f, /*!*/
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
private byte from_ascii[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, '\r', 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*!*/
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif notdef
#ifdef FULL_NCS_SUPPORT
/*
* SWEdish standard D47, national characters {}|[]\ are mapped,
* characters with bit 8 set are untouched
*/
private byte to_swe[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, '\n', 0x0e, 0x0f, /*!*/
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
'[' , ']' , 0x82, 0x83, 0x84, '\\', 0x86, 0x87, /*!*/
0x88, 0x89, '{' , 0x8b, '}' , 0x8d, 0x8e, 0x8f, /*!*/
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, '|' , 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /*!*/
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
private byte from_swe[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, '\r', 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*!*/
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x80, 0x85, 0x81, 0x5e, 0x5f, /*!*/
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x8a, 0x9a, 0x8c, 0x7e, 0x7f, /*!*/
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
/*
* FINnish/Swedish standard D47, national characters {}|[]\~`@^ are mapped,
* characters with bit 8 set are untouched
*/
byte to_fin[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, '\n', 0x0e, 0x0f, /*!*/
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
'[' , ']' , 0x82, 0x40, 0x84, '\\', 0x5e, 0x87, /*!*/
0x88, 0x89, '{' , 0x8b, '}' , 0x8d, 0x60, 0x8f, /*!*/
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, '|' , 0x9b, 0x9c, 0x9d, 0x9e, 0x7e, /*!*/
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
private byte from_fin[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, '\r', 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*!*/
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x83, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x80, 0x85, 0x81, 0x86, 0x5f, /*!*/
0x8e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x8a, 0x9a, 0x8c, 0x9f, 0x7f, /*!*/
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
/*
* ISO 8859 Latin1, 8-bit code,
* an attempt is made to map all characters into something similar
* but some characters without a similar character in latin1
* are mapped into SUB (0x1a).
* Since it is not possible to map one character into two, no correct
* mapping CR <-> CRLF can be done here.
* This table has not been tested agains other software using latin1,
* so there might be some errors in the table.
*/
private byte to_latin1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, '\n', 0x0e, 0x0f, /*!*//*? really CRLF */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, /* ! */
0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, /* ! */
0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, /* ! */
0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, /* ! */
0x1a, 0xb0, 0xa2, 0xa3, 0xa7, 0xb7, 0xb6, 0xdf, /* ! */
0xae, 0xa9, 0x1a, 0xb4, 0xa8, 0x1a, 0xc6, 0xd8, /* ! */
0x1a, 0xb1, 0x1a, 0x1a, 0xa5, 0xb5, 0x1a, 0x1a, /* ! */
0x1a, 0x1a, 0x1a, 0xaa, 0xba, 0x1a, 0xe6, 0xf8, /* ! */
0xbf, 0xa1, 0xac, 0x1a, 0x1a, 0x1a, 0x1a, 0xab, /* ! */
0xbb, 0x1a, 0xa0, 0xc0, 0xc3, 0xd5, 0x1a, 0x1a, /* ! */
0x2d, 0x2d, 0x22, 0x22, 0x60, 0x27, 0xf7, 0x1a, /* ! */
0xff, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, /* ! */
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, /* ! */
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, /* ! */
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, /* ! */
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a /* ! */
};
/*
* if no similar character is found 0xff is returned
* 0x1a is also defined as 0xff
*/
private byte from_latin1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, '\r', 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*!*/
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0xff, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xca, 0xc1, 0xa2, 0xa3, 0xff, 0xb4, 0x7c, 0xa4,
0xac, 0xa9, 0xbb, 0xc7, 0xc2, 0xff, 0xa8, 0xff,
0xa1, 0xb1, 0xff, 0xff, 0x27, 0xb5, 0xa6, 0xa5,
0x2c, 0xff, 0xbc, 0xc8, 0xff, 0xff, 0xff, 0xc0,
0xcb, 'A' , 'A' , 0xcc, 0x80, 0x81, 0xae, 0x82,
'E' , 0x83, 'E' , 'E' , 'I' , 'I' , 'I' , 'I' ,
'D' , 0x84, 'O' , 'O' , 'O' , 0xcd, 0x85, 0xff,
0xaf, 'U' , 'U' , 'U' , 0x86, 'Y' , 0xff, 0xa7,
0x88, 0x87, 0x89, 0x8b, 0x8a, 0x8c, 0xbe, 0x8d,
0x8f, 0x8e, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
0xff, 0x96, 0x98, 0x97, 0x99, 0x9b, 0x9a, 0xd6,
0xbf, 0x9d, 0x9c, 0x9e, 0x9f, 'y' , 0xff, 0xd8
};
#endif /* FULL_NCS_SUPPORT */
#define NCS_entry(name, suf, conj, creator, type, totable, fromtable) \
{ name, suf, sizeof(suf)-1, conj, (byte *) creator, sizeof(creator)-1, \
(byte *) type, sizeof(type)-1, totable, fromtable }
/*
* NCS_entry:
* suffix to map on
* conj: AND for suffix and creator/type, OR for suffix or creator/type
* creator/type: macintosh file creator/type
* totable - translate to unix from macintosh
* fromtable - translate from unix to macintosh
*
* NULL entries for suffix or file type/creator always match
* Table is searched sequentially so put the more specific items near the
* start.
*
*/
NCS_TransTable ncs_transtables[] = {
#ifdef FULL_NCS_SUPPORT
/* Swedish standard D47 translation */
NCS_entry("Swedish D47",".swe",NCS_AND,NULL,NULL, to_swe, from_swe),
/* Swedish-Finnish standard E47 translation */
NCS_entry("Swedish-Finnish E47",".fin",NCS_AND,NULL, NULL, to_fin, from_fin),
/* ISO 8859-1 latin1 */
NCS_entry("ISO 8859-1 Latin 1", ".latin1", NCS_AND, NULL, NULL,
to_latin1, from_latin1),
#endif FULL_NCS_SUPPORT
#if defined (ISO_TRANSLATE) & defined (ISO_FILE_TRANS)
#ifdef NCS_ALL_TEXT
/* ISO 8859-1 latin1 translation for all TEXT files */
NCS_entry("ISO 8859-1 Latin 1", NULL, NCS_AND, NULL, "TEXT",
Mac2ISO, ISO2Mac),
#else NCS_ALL_TEXT
/* ISO 8859-1 latin1 translation for unix/TEXT files */
NCS_entry("ISO 8859-1 Latin 1", NULL, NCS_AND, "unix", "TEXT",
Mac2ISO, ISO2Mac),
#endif NCS_ALL_TEXT
#endif ISO_TRANSLATE & ISO_FILE_TRANS
#ifdef NCS_ALL_TEXT
/* ASCII translation for all TEXT files */
NCS_entry("ascii", NULL, NCS_AND, NULL, "TEXT",
to_ascii, from_ascii),
#else NCS_ALL_TEXT
/* ASCII translation for unix/TEXT files */
NCS_entry("ascii", NULL, NCS_AND, "unix", "TEXT",
to_ascii, from_ascii),
#endif NCS_ALL_TEXT
#ifdef SHORT_NAMES
NCS_entry("pc-ascii", NULL, NCS_AND, "unix", "TEXT",
pc_to_ascii, pc_from_ascii),
#endif SHORT_NAMES
{NULL}
};
#define NCS_TRANSTABLELEN ((sizeof(ncs_transtables)/sizeof(NCS_TransTable))-1)
/*
* find the translation table and return index. return -1 o.w.
*/
int
#ifdef SHORT_NAMES
ncs_istrans(finderinfo, file, ptype)
byte ptype;
#else SHORT_NAMES
ncs_istrans(finderinfo, file)
#endif SHORT_NAMES
fileFinderInfo *finderinfo;
char *file;
{
int i, idx;
register NCS_TransTable *tt;
int suffixmatch, finderinfomatch;
#ifdef USR_FILE_TYPES
/* check for file suffix */
if ((i = uft_match(file)) >= 0) {
/* must also be of the correct creator & type */
if (bcmp(uft[i].uft_creat, finderinfo->fdCreator, 4) == 0
&& bcmp(uft[i].uft_ftype, finderinfo->fdType, 4) == 0)
return(i+FNDR_UFT);
}
/* suffix check failed, so check table for file creator and type */
if ((i = uft_match_finfo(finderinfo->fdCreator, finderinfo->fdType)) >= 0)
return(i+FNDR_UFT);
#endif USR_FILE_TYPES
for (idx = 0, tt = ncs_transtables; idx < NCS_TRANSTABLELEN; tt++, idx++) {
suffixmatch = (tt->ncs_suffix == NULL) ||
(file && (i = strlen(file)) >= tt->ncs_suffix_len &&
strcmp(tt->ncs_suffix, file+i-tt->ncs_suffix_len)==0);
if (suffixmatch) {
if (tt->ncs_conj == NCS_OR)
return(idx);
} else {
if (tt->ncs_conj == NCS_AND)
continue;
}
/* see if file type and file creator match (except if null, then */
/* ignored). Partial matches are acceptable -- depends on what */
/* is specified */
finderinfomatch = FALSE;
if (tt->ncs_file_creator == NULL ||
bcmp(tt->ncs_file_creator, finderinfo->fdCreator, tt->ncs_fc_len) == 0)
if (tt->ncs_file_type == NULL ||
bcmp(tt->ncs_file_type, finderinfo->fdType, tt->ncs_ft_len) == 0)
finderinfomatch = TRUE;
#ifdef SHORT_NAMES
printf("suffixmatch %d, finderinfomatch %d, ptype 0x%x\n",suffixmatch,finderinfomatch,ptype);
#endif SHORT_NAMES
switch (tt->ncs_conj) {
case NCS_OR:
#ifdef SHORT_NAMES
if ((suffixmatch || finderinfomatch) && (ptype == 0x01))
return(idx+1);
/* so,,,, this is bad, and will only work when there
are 2 entries in the trans table. */
#endif SHORT_NAMES
if (suffixmatch || finderinfomatch)
return(idx);
break;
case NCS_AND:
#ifdef SHORT_NAMES
if (suffixmatch && finderinfomatch && (ptype == 0x01)) {
printf("returning idx+1 = %d\n",idx+1);
return(idx+1);
}
#endif SHORT_NAMES
if (suffixmatch && finderinfomatch)
return(idx);
break;
}
}
return(-1); /* no match */
}
/*
* return the name of a translation table given its index
*
*/
char *
ncs_tt_name(ttidx)
int ttidx;
{
#ifdef USR_FILE_TYPES
if (ttidx >= FNDR_UFT)
return("user specified translation");
#endif USR_FILE_TYPES
if (ttidx < 0 || ttidx >= NCS_TRANSTABLELEN)
return("no translation");
return(ncs_transtables[ttidx].ncs_trans_name);
}
ncs_translate(which, ttidx, buf, cnt)
int which;
int ttidx;
byte *buf;
register int cnt;
{
register byte *bp;
register byte *tt;
register byte tc, fc;
#ifdef USR_FILE_TYPES
int texttrans = 0;
#endif USR_FILE_TYPES
if (ttidx < 0 || ttidx >= NCS_TRANSTABLELEN)
#ifdef USR_FILE_TYPES
if (ttidx < FNDR_UFT)
#endif USR_FILE_TYPES
return;
switch (which) {
case NCS_TRANS_UNIXTOMAC:
#ifdef USR_FILE_TYPES
if (ttidx >= FNDR_UFT) {
tt = uft[ttidx-FNDR_UFT].uft_xlate;
if (tt == ascii || tt == text)
tt = from_ascii;
} else
#endif USR_FILE_TYPES
tt = ncs_transtables[ttidx].ncs_fromtable;
break;
case NCS_TRANS_MACTOUNIX:
#ifdef USR_FILE_TYPES
if (ttidx >= FNDR_UFT) {
tt = uft[ttidx-FNDR_UFT].uft_xlate;
if (tt == text)
texttrans = 1;
if (tt == ascii || tt == text)
tt = to_ascii;
} else
#endif USR_FILE_TYPES
tt = ncs_transtables[ttidx].ncs_totable;
break;
default:
return;
}
#ifdef USR_FILE_TYPES
if (tt == raw) /* no translation */
return;
#endif USR_FILE_TYPES
bp = buf;
if (tt == to_ascii || tt == from_ascii) {
/* by pass for to_ascii, and from_ascii to speed things up */
if (tt == to_ascii)
fc = ENEWLINE, tc = INEWLINE;
else
fc = INEWLINE, tc = ENEWLINE;
while (cnt--) {
#ifdef USR_FILE_TYPES
if (texttrans) {
switch (*bp) {
case ELDQUOTE:
case ERDQUOTE:
*bp++ = IDQUOTE;
continue;
break;
case ELSQUOTE:
case ERSQUOTE:
*bp++ = ISQUOTE;
continue;
break;
}
}
#endif USR_FILE_TYPES
#ifndef NONLXLATE
if (*bp == fc)
*bp = tc;
#endif NONLXLATE
bp++;
}
#ifdef SHORT_NAMES
} else if ((tt == pc_to_ascii) || (tt == pc_from_ascii)) {
while (cnt--)
bp++;
#endif SHORT_NAMES
#if defined (USR_FILE_TYPES) & defined (ISO_TRANSLATE)
} else if (tt == iso) {
while (cnt--) {
switch (which) {
case NCS_TRANS_UNIXTOMAC:
*bp = (*bp == INEWLINE) ? ENEWLINE :
(*bp & 0x80) ? ISO2Mac[*bp & 0x7f] : *bp;
break;
case NCS_TRANS_MACTOUNIX:
*bp = (*bp == ENEWLINE) ? INEWLINE :
(*bp & 0x80) ? Mac2ISO[*bp & 0x7f] : *bp;
break;
}
bp++;
}
#endif USR_FILE_TYPES & ISO_TRANSLATE
#if defined (ISO_TRANSLATE) & defined (ISO_FILE_TRANS)
} else if ((tt == ISO2Mac) || (tt == Mac2ISO)) {
while (cnt--) {
switch (which) {
case NCS_TRANS_UNIXTOMAC:
*bp = (*bp == INEWLINE) ? ENEWLINE :
(*bp & 0x80) ? ISO2Mac[*bp & 0x7f] : *bp;
break;
case NCS_TRANS_MACTOUNIX:
*bp = (*bp == ENEWLINE) ? INEWLINE :
(*bp & 0x80) ? Mac2ISO[*bp & 0x7f] : *bp;
break;
}
bp++;
}
#endif ISO_TRANSLATE & ISO_FILE_TRANS
} else {
/* standard */
while (cnt--) {
*bp = tt[*bp];
bp++;
}
}
}
#define strval(x) ((x) == NULL ? "<any>" : (x))
ncs_table_dump()
{
register NCS_TransTable *tt;
int idx;
for (idx = 0, tt = ncs_transtables; idx < NCS_TRANSTABLELEN; tt++, idx++) {
logit(0," %s: xlate on: suffix %s %s file type %s, creator %s",
tt->ncs_trans_name,
strval(tt->ncs_suffix),
(tt->ncs_conj == NCS_AND ? "and" : "or"),
strval((char *)tt->ncs_file_type),
strval((char *)tt->ncs_file_creator));
}
}
#ifdef USR_FILE_TYPES
/*
* The file .afpfile (or afpfile) in the user's home directory and/or
* the file denoted by the -F option specifies the treatment to be applied
* to UNIX files with certain file suffixes, eg: .c .h .gif
*
* The file data may be copied unchanged ('raw'), have NL characters
* converted to CR and vice-versa ('ascii') or have Mac quote characters
* converted to UNIX quotes (but not vice-versa, also implies 'ascii').
* If ISO_TRANSLATE is defined, also handle Mac <-> ISO translation ('iso').
*
* Each file may also have the Macintosh file Creator and Type specified.
* For example, .c files can be represented as 'MPS '/'TEXT' files and be
* double-clicked to open the MPW editor.
*
* Different comments may also be provided for different file suffixes.
* EG: "This is a UNIX GIF file." for .gif
*
* Weird behaviour:
* MicroSoft Word writes the file back as type 'WDBN' and later
* changes it to type 'TEXT' (when saving as text). This defeats
* the user file type code.
*
* The MPW editor writes a file back as file-N which defeats the
* suffix test. To get around this, files are also checked for
* a listed file creator and type. If found, the specified translation
* method is used.
*
* djh@munnari.OZ.AU
*
*/
int uftidx = 0;
char *lineptr;
/*
* read the user specified file mappings
*
*/
int
read_uft(file)
char *file;
{
char string[256];
char *p, line[256];
FILE *fp, *fopen();
if ((fp = fopen(file, "r")) != NULL) {
while (fgets(line, sizeof(line), fp) != NULL) {
if (line[0] == '#' || line[0] == '\n')
continue; /* ignore comments, blank lines */
if ((p = (char *)index(line, '\n')) != NULL)
*p = '\0'; /* kill line feeds from fgets() */
lineptr = line;
/* file suffix, use "*" as wildcard */
gettoken(uft[uftidx].uft_suffix, sizeof(uft[uftidx].uft_suffix));
if (uft[uftidx].uft_suffix[0] == '*')
uft[uftidx].uft_suffix[0] = '\0';
uft[uftidx].uft_suffixlen = strlen(uft[uftidx].uft_suffix);
/* translation requested */
gettoken(string, sizeof(string));
switch (string[0]) {
case 'R': case 'r': /* raw */
uft[uftidx].uft_xlate = raw;
break;
case 'T': case 't': /* text */
uft[uftidx].uft_xlate = text;
break;
case 'A': case 'a': /* ascii */
uft[uftidx].uft_xlate = ascii;
break;
#ifdef ISO_TRANSLATE
case 'I': case 'i': /* ISO */
uft[uftidx].uft_xlate = iso;
break;
#endif ISO_TRANSLATE
default: /* ignore */
continue;
break;
}
/* file creator */
gettoken(uft[uftidx].uft_creat, sizeof(uft[uftidx].uft_creat));
if (uft[uftidx].uft_creat[0] == '\0')
bcopy(DEFFCREATOR,uft[uftidx].uft_creat,sizeof(uft[uftidx].uft_creat));
/* file type */
gettoken(uft[uftidx].uft_ftype, sizeof(uft[uftidx].uft_ftype));
if (uft[uftidx].uft_ftype[0] == '\0')
bcopy(DEFFTYPE, uft[uftidx].uft_ftype, sizeof(uft[uftidx].uft_ftype));
/* user comment */
uft[uftidx].uft_comment = DEFCMNT;
gettoken(string, sizeof(string));
if (string[0] != '\0') {
if ((p = (char *)malloc(strlen(string)+1)) != NULL) {
bcopy(string, p, strlen(string)+1);
uft[uftidx].uft_comment = p;
}
}
uft[uftidx].uft_commentlen = strlen(uft[uftidx].uft_comment);
uftidx++;
}
fclose(fp);
}
uft[uftidx].uft_suffixlen = -1;
}
/*
* parse the user specified suffix/type mappings file
*
*/
int
gettoken(str, strn)
char *str;
int strn;
{
while (*lineptr == ' ' || *lineptr == '\t')
lineptr++; /* skip leading white space */
if (*lineptr == '\'' || *lineptr == '"') {
lineptr++; /* skip initial quote */
while (!(*lineptr == '\'' || *lineptr == '"')) {
if (strn-- > 0)
*str++ = *lineptr;
if (*lineptr == '\0')
return(0);
lineptr++;
}
lineptr++; /* skip trailing quote */
if (strn > 0) /* terminate if space */
*str = '\0';
return(0);
}
while (*lineptr != '\0' && *lineptr != ' ' && *lineptr != '\t') {
if (strn-- > 0)
*str++ = *lineptr;
if (*lineptr == '\0')
return(0);
lineptr++;
}
if (strn > 0) /* terminate if space */
*str = '\0';
}
#endif USR_FILE_TYPES

View File

@ -0,0 +1,40 @@
/*
* $Author: djh $ $Date: 91/02/15 21:08:58 $
* $Header: afposncs.h,v 2.1 91/02/15 21:08:58 djh Rel $
* $Revision: 2.1 $
*/
/*
* afposncs.h - Appletalk Filing Protocol OS Normalizing for Character Sets
*
* structures used to hold normalizing character set routines and declarations
*
*
* Feb 1988 Charlie C. Kim
*
*/
typedef struct { /* trans tab */
char *ncs_trans_name; /* Translation name */
char *ncs_suffix; /* Suffix to translate on */
int ncs_suffix_len;
int ncs_conj; /* conjunction (suffix <conj> creator/type */
byte *ncs_file_creator; /* File creator to xlate on */
int ncs_fc_len;
byte *ncs_file_type; /* File type to xlate on */
int ncs_ft_len;
byte *ncs_totable;
byte *ncs_fromtable;
} NCS_TransTable;
/* extern TransTab transtables[]; */
char *ncs_tt_name();
int ncs_istrans();
#define NCS_TRANS_UNIXTOMAC 1
#define NCS_TRANS_MACTOUNIX 2
#define NCS_AND 0
#define NCS_OR 1

View File

@ -0,0 +1,167 @@
/*
* $Author: djh $ $Date: 91/03/13 20:29:11 $
* $Header: afppasswd.c,v 2.2 91/03/13 20:29:11 djh Exp $
* $Revision: 2.2 $
*/
/*
* afppasswd.c - Appletalk Filing Protocol - support for internal password file
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* June 1987 CCKim Created.
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <netat/sysvcompat.h>
#define TRUE 1
#define FALSE 0
static char *mypasswdfile = NULL;
static FILE *pfp = NULL;
typedef struct {
char uname[9]; /* unix user name that name maps to */
char passwd[9]; /* password to use */
char name[40]; /* up 39 char user name */
} aufspasswd;
rewaufs()
{
if (pfp == NULL)
if ((pfp=fopen(mypasswdfile, "r")) == NULL)
return(FALSE);
rewind(pfp);
return(TRUE);
}
endaufspw()
{
if (pfp != NULL)
fclose(pfp);
}
static aufspasswd *
getaufspwent()
{
static aufspasswd apd;
char buf[128];
int cnt;
while (fgets(buf, 128, pfp) != NULL) {
cnt = sscanf(buf, "USER: %s\tUNIXUSER: %s\tPASSWORD: %s",
apd.name, apd.uname, apd.passwd);
if (cnt != 3)
continue;
if (strlen(apd.name) > 39 || strlen(apd.uname) > 8 ||
strlen(apd.passwd) > 8) {
logit(0,"Bad password file entry: %s", buf);
continue;
}
return(&apd);
}
return(NULL);
}
static aufspasswd *
getaufspwnam(nam)
char *nam;
{
static aufspasswd *apd;
if (apd && strcmp(apd->name, nam) == 0)
return(apd);
if (!rewaufs())
return(NULL);
while ((apd=getaufspwent()) != NULL)
/* should be case insensitive */
if (strcmp(nam, apd->name) == 0 && getpwnam(apd->uname) != NULL) {
endaufspw();
return(apd);
}
endaufspw();
apd = NULL;
return(NULL);
}
init_aufs_passwd(pw)
char *pw;
{
struct stat buf;
# ifndef NOLSTAT
if (lstat(pw, &buf) < 0) {
logit(0,"error: can't find aufs password file %s",pw);
return(FALSE);
}
# else
if (stat(pw, &buf) < 0) {
logit(0,"error: can't find aufs password file %s",pw);
return(FALSE);
}
#endif
if ((buf.st_mode & S_IFMT) != S_IFREG) {
logit(0,"error: aufs password file %s isn't a regular file", pw);
return(FALSE);
}
if (buf.st_uid != 0) {
#ifdef DEBUG
logit(0,"debug: aufs password file %s not owned by root", pw);
#else
logit(0,"error: aufs password file %s not owned by root", pw);
return(FALSE);
#endif
}
if (buf.st_mode & 002) {
logit(0,"error: aufs password file %s is writable by world",pw);
return(FALSE);
}
if (buf.st_mode & 020)
logit(0,"warning: aufs password file %s is writable by group",pw);
if (buf.st_mode & 004)
logit(0,"warning: aufs password file %s is readable by world",pw);
mypasswdfile = pw;
return(TRUE);
}
int
is_aufs_user(nam)
char *nam;
{
if (getaufspwnam(nam) == NULL)
return(FALSE);
return(TRUE);
}
char *
user_aufs_passwd(nam)
char *nam;
{
aufspasswd *apd;
if ((apd=getaufspwnam(nam)) == NULL)
return(NULL);
return(apd->passwd);
}
struct passwd *
aufs_unix_user(nam)
char *nam;
{
aufspasswd *apd;
if ((apd=getaufspwnam(nam)) == NULL)
return(NULL);
return(getpwnam(apd->uname));
}

View File

@ -0,0 +1,24 @@
/*
* $Author: djh $ $Date: 91/02/15 21:09:06 $
* $Header: afppasswd.h,v 2.1 91/02/15 21:09:06 djh Rel $
* $Revision: 2.1 $
*/
/*
* afppasswd.h - Appletalk Filing Protocol - support for internal password file
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* June 1987 CCKim Created.
*
*/
boolean init_aufs_passwd();
boolean is_aufs_user();
char *user_aufs_passwd();
struct passwd *aufs_unix_user();

259
applications/aufs/afps.h Normal file
View File

@ -0,0 +1,259 @@
/*
* $Author: djh $ $Date: 1996/06/19 04:04:29 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afps.h,v 2.11 1996/06/19 04:04:29 djh Rel djh $
* $Revision: 2.11 $
*
*/
/*
* afps.h - Appletalk Filing Protocol Common Server Definitions
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986,1987,1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* April 1987 Schilit Created.
*
*/
extern int statflg; /* external stats flag */
extern int afp_dbug; /* the debug flags */
#define uSEC 1000000 /* microseconds in a second */
typedef OSErr (*PFE)(); /* function returning OSErr */
/* volume bit map - limited to long by macros below */
typedef long VolBitMap; /* longer than long is a bad idea?*/
/* All File System Calls */
OSErr FPByteRangeLock(), FPCloseVol(), FPCloseDir(), FPCloseFork();
OSErr FPCopyFile(), FPCreateDir(), FPCreateFile(), FPDelete();
OSErr FPEnumerate(), FPFlush(), FPFlushFork(), FPGetForkParms();
OSErr FPGetSrvrInfo(), FPGetSrvrParms(), FPGetVolParms(), FPLogin();
OSErr FPLoginCont(), FPLogout(), FPMapID(), FPMapName();
OSErr FPMove(), FPOpenVol(), FPOpenDir(), FPOpenFork();
OSErr FPRead(), FPRename(), FPSetDirParms(), FPSetFileParms();
OSErr FPSetForkParms(), FPSetVolParms(), FPWrite(), FPGetFileDirParms();
OSErr FPSetFileDirParms(), FPOpenDT(), FPCloseDT(), FPGetIcon();
OSErr FPGetIconInfo(), FPAddAPPL(), FPRmvAPPL(), FPGetAPPL();
OSErr FPAddComment(), FPRmvComment(), FPGetComment(), FPAddIcon();
OSErr FPNop();
/* afp2.0 */
OSErr FPChgPasswd(), FPGetUserInfo();
/* afp2.1 */
OSErr FPExchangeFiles(), FPGetSrvrMsg();
OSErr FPCreateID(), FPDeleteID(), FPResolveID();
/* abafpserver.c */
char *SrvrInfo();
OSErr SrvrRegister();
#define F_RSRC 01 /* resource file */
#define F_DATA 02 /* data file */
#define F_FNDR 03 /* finder info file */
#define DBG_FILE 00001 /* debug file routines */
#define DBG_FORK 00002 /* debug fork routines */
#define DBG_SRVR 00004 /* debug server routines */
#define DBG_VOLS 00010 /* debug volume routines */
#define DBG_OSIN 00020 /* debug os interface routines */
#define DBG_DIRS 00040 /* debug directory routine */
#define DBG_DESK 00100 /* debug desktop routines */
#define DBG_DEBG 00200 /* in debug */
#define DBG_UNIX 00400 /* debug unix routines */
#define DBG_ENUM 01000 /* debug directory enumerations */
#define DBG_ALL (DBG_FILE|DBG_FORK|DBG_SRVR|DBG_VOLS| \
DBG_OSIN|DBG_DIRS|DBG_DESK|DBG_DEBG| \
DBG_UNIX|DBG_ENUM)
#define DBOSI (afp_dbug & DBG_OSIN)
#define DBFRK (afp_dbug & DBG_FORK)
#define DBSRV (afp_dbug & DBG_SRVR)
#define DBDIR (afp_dbug & DBG_DIRS)
#define DBVOL (afp_dbug & DBG_VOLS)
#define DBFIL (afp_dbug & DBG_FILE)
#define DBDSK (afp_dbug & DBG_DESK)
#define DBDEB (afp_dbug & DBG_DEBG)
#define DBUNX (afp_dbug & DBG_UNIX)
#define DBENU (afp_dbug & DBG_ENUM)
/* afpdid.c */
typedef struct idir { /* local directory info (internal) */
char *name; /* the directory name */
long hash; /* hash of the directory name */
struct idir *next; /* ptr to next at same level */
struct idir *subs; /* ptr to children */
struct idir *pdir; /* ptr to parent */
unsigned int modified; /* count of times modified */
VolBitMap volbm; /* vols that contain this dir */
sdword edirid; /* external dirid */
int eceidx; /* index into enum cache */
int flags; /* any flags */
#define DID_RESOURCE 0x1 /* remember there is resource subdir */
#define DID_FINDERINFO 0x2 /* remember there is finderinfo subdir */
#define DID_VALID 0x4 /* flags are valid? (always) */
#define DID_DATA 0x8 /* data - means dir. exists :-) */
#define DID_SYMLINKS 0x30 /* number of symbolic links in list */
/* allow up to 3 (0 means none, 1-3 in */
/* 3 bit field */
#define DID_MAXSYMLINKS 3
#define DID_SYMLINKS_SHIFT 4 /* shift from right */
} IDir, *IDirP;
#define NILDIR ((IDirP) 0) /* a null directory pointer */
#define EROOTD 02 /* external ID of volumes root directory */
#define EPROOTD 01 /* external ID of parent of root */
IDirP EtoIdirid(); /* external to internal translation */
sdword ItoEdirid(); /* internal to external translation */
IDirP Idirid(); /* return internal dirid given path */
IDirP Idndirid(); /* return internal dirid given dirid, name */
IDirP Ipdirid(); /* return parent of dirid given dirid */
char *pathstr(); /* return path given dirid */
void InitDID(); /* initialize directory id mechanism */
OSErr EtoIfile(); /* convert file names */
void Idmove(); /* rename a directory */
byte *ItoEName(); /* unix to mac name */
OSErr EtoIName(); /* mac to unix name */
int ENameLen(); /* length of mac name (arg is unix name) */
void EModified(); /* mark an entry as having been modified */
/* afpvols.c */
#define VOLFILE "afpvols" /* name of the file containing volume info */
#define VOLFILE1 ".afpvols" /* alternate afpvols file */
#define MAXLLEN 200 /* max line length in VOLFILE file */
/*
* We use a bitmap to record information about groupings of volumes
* The way we did things we are limited to sizeof(long)*8 bits in size
* (well, if you have a scalar type larger than long then you are
* limited to the number of bits in that type).
*
* Note however, that the logic behind things is such that you should
* be able to recode the macros to arbritrary sizes in the future
* without any problem, but for now just say we got lazy (actually the
* real issue was that the code gets a little long the other way...)
*
*/
#define MAXVOLS (sizeof(VolBitMap)*8) /* max number of volumes per user */
#define V_BITSET(item,bit) (item) |= (1<<(bit))
#define V_BITTST(item,bit) ((item) & (1<<(bit)))
#define V_BITCLR(item,bit) (item) &= ~(1<<(bit))
#define V_BITOR(res, i1, i2) (res) = ((i1) | (i2))
#define V_ZERO(item) bzero(&(item), sizeof(VolBitMap))
#define V_COPY(d,s) (d) = (s)
void VInit(); /* Initialize user volume structure */
IDirP VolRootD(); /* return root dirid for a volume */
word ItoEVolid();
int EtoIVolid();
/* afpdt.c */
sdword CurTime();
/* afpvols.c */
void VolModified();
/* afpcmd.c */
void PackWord();
void PackDWord();
/* afpdt.c */
void InitIconCache();
/* afposenum.c */
#define NOECIDX (-1)
#define NECSIZE 100 /* size of the enum cache */
void ECacheInit();
char *OSEnumGet();
int OSEnumInit();
void OSEnumDone();
#ifdef NOCASEMATCH
void noCaseFind();
void noCaseMatch();
#endif NOCASEMATCH
/* Portable library functions */
#if (!(defined(AIX) || defined(hpux) || defined(SOLARIS)))
char *malloc(),*strcpy(),*strcat(),*realloc();
#endif /* AIX || hpux || SOLARIS */
/* defined here so that enumerate can skip these entries when reading dirs */
#define DESKTOP_ICON ".IDeskTop"
#define DESKTOP_APPL ".ADeskTop"
#define RFDIRFN ".resource" /* subdir holding resource forks */
#define FIDIRFN ".finderinfo" /* subdir holding finder info */
#define RFDIR "/.resource"
#define FIDIR "/.finderinfo"
#define DIRRF ".resource/"
#define DIRFI ".finderinfo/"
#define DIRRFLEN 10
#define DIRFILEN 12
/* Finder info bits */
#define DEFCMNT "This is a Unix\252 created file."
#define DEFCMNTZ (sizeof(DEFCMNT)-1)
#ifdef notdef
#ifndef DEFFNDR
# define DEFFNDR "TEXTunix" /* type, creator */
#endif
#define DEFFNDRZ (sizeof(DEFFNDR)-1) /* size of above */
#endif
#define DEFATTR (0x00) /* get rid of "locked" bit */
#define DEFFCREATOR "unix"
#define DEFFTYPE "TEXT"
#define ENEWLINE '\r' /* external (mac) new line char */
#define INEWLINE '\n' /* internal (unix) new line char */
#ifdef USR_FILE_TYPES
#define ELDQUOTE 0xd2 /* external (mac) left double quote */
#define ERDQUOTE 0xd3 /* external (mac) right double quote */
#define ELSQUOTE 0xd4 /* external (mac) left single quote */
#define ERSQUOTE 0xd5 /* external (mac) right single quote */
#define IDQUOTE '\"' /* internal (unix) double quote */
#define ISQUOTE '\'' /* internal (unix) single quote */
#define TYPFILE "afpfile"
#define TYPFILE1 ".afpfile"
#endif USR_FILE_TYPES
/* used internally */
#define AFPVersionUnknown 0
#define AFPVersion1DOT0 100
#define AFPVersion1DOT1 110
#define AFPVersion2DOT0 200
#define AFPVersion2DOT1 210
#define AFPVersion2DOT2 220
#ifdef APPLICATION_MANAGER
struct flist {
char *filename; /* full pathname to resource fork */
int protected; /* we don't want it to be copied */
short incarnations; /* can be opened this many times */
struct flist *next; /* this is a sorted linked list */
};
#endif APPLICATION_MANAGER

File diff suppressed because it is too large Load Diff

410
applications/aufs/afpspd.c Normal file
View File

@ -0,0 +1,410 @@
/*
Speedup routines
Author: Dan Oscarsson (Dan@dna.lth.se)
*/
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h>
#endif
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <netat/appletalk.h>
#include <netat/compat.h>
#include "afps.h"
#ifdef STAT_CACHE
struct statobj {
char * NAME;
struct stat STAT;
int FN,RS;
time_t VAL_TIME;
};
#define VAL_OK 1
#define VAL_NO 0
#define VAL_INVALID 2
#define MAX_LEVEL 20
private struct statobj STATS[MAX_LEVEL+1];
private time_t CUR_TIME;
private struct timeval *Sched_Now = NULL; /* pointer to scheduler clock */
#define EXP_TIME 120;
private char CUR_DIR_STR[1024];
private char * CUR_DIR = NULL;
private int CUR_DIR_LEN;
private char CUR_STAT_STR[1024];
private int CUR_STAT_LEVEL = 0;
/*
* The following is used as a sentinel in a statobj to mark invalid
* entries. It is stored in the st_nlink field in the STAT substructure.
*
*/
#define BAD_LINK 0x7fff
OSStatInit()
{
register int P;
for (P = 0; P <= MAX_LEVEL; P++) {
STATS[P].NAME = NULL;
STATS[P].STAT.st_nlink = BAD_LINK;
STATS[P].FN = VAL_INVALID;
STATS[P].RS = VAL_INVALID;
}
getschedulerclock(&Sched_Now);
time(&CUR_TIME); /* since scheduler has not run yet */
}
OScd(path)
char * path;
{
if (CUR_DIR != NULL && strlen(path) == CUR_DIR_LEN-1 && strncmp(path,CUR_DIR,CUR_DIR_LEN-1) == 0)
return;
if (chdir(path) < 0)
return;
CUR_DIR = CUR_DIR_STR;
strcpy(CUR_DIR,path);
strcat(CUR_DIR,"/");
CUR_DIR_LEN = strlen(CUR_DIR);
if (DBOSI)
printf("OScd=%s\n",CUR_DIR);
}
cwd_stat(path,buf)
char * path;
struct stat *buf;
{
if (CUR_DIR != NULL && strncmp(path,CUR_DIR,CUR_DIR_LEN) == 0) {
if (DBOSI)
printf("OScwd_stat=%s\n",path+CUR_DIR_LEN);
return(stat(path+CUR_DIR_LEN,buf));
}
if (DBOSI)
printf("OScwd_stat=%s\n",path);
return(stat(path,buf));
}
cwd_open(path,flags,mode)
char * path;
int flags,mode;
{
if (CUR_DIR != NULL && strncmp(path,CUR_DIR,CUR_DIR_LEN) == 0) {
if (DBOSI)
printf("OScwd_open=%s\n",path+CUR_DIR_LEN);
return(open(path+CUR_DIR_LEN,flags,mode));
}
if (DBOSI)
printf("OScwd_open=%s\n",path);
return(open(path,flags,mode));
}
char * cwd_path(path)
char * path;
{
if (CUR_DIR != NULL && strncmp(path,CUR_DIR,CUR_DIR_LEN) == 0) {
if (DBOSI)
printf("OScwd_path=%s\n",path+CUR_DIR_LEN);
return path+CUR_DIR_LEN;
}
if (DBOSI)
printf("OScwd_path=%s\n",path);
return path;
}
private release_stats(K)
int K;
{
register int P;
if (DBOSI)
printf("release_stats=%d of %d\n",K,CUR_STAT_LEVEL);
for (P = K; P <= CUR_STAT_LEVEL; P++) {
STATS[P].STAT.st_nlink = BAD_LINK;
STATS[P].FN = VAL_INVALID;
STATS[P].RS = VAL_INVALID;
STATS[P].NAME = NULL;
}
if (K < CUR_STAT_LEVEL)
CUR_STAT_LEVEL = K;
}
private int EXPIRE_REQ;
private expire_stats()
{
register int K;
if (!EXPIRE_REQ)
return;
EXPIRE_REQ = 0;
for (K = 0; K <= CUR_STAT_LEVEL; K++) {
if (STATS[K].STAT.st_nlink == BAD_LINK)
continue;
if (STATS[K].VAL_TIME <= CUR_TIME) {
if (DBOSI)
printf("expired=%d(%s) t=%d\n",
K, STATS[K].NAME,
STATS[K].VAL_TIME - CUR_TIME);
STATS[K].STAT.st_nlink = BAD_LINK;
STATS[K].FN = VAL_INVALID;
STATS[K].RS = VAL_INVALID;
STATS[K].NAME = NULL;
}
}
}
private struct statobj * locate_statobj(path)
char * path;
{
register char *NEW, *OLD;
register char *TMP;
register int K;
char *REPLACE;
if (DBOSI)
printf("locate_statobj: path '%s'\n", path);
/* get the path and make sure it is an absolute one */
NEW = path;
if (*NEW++ != '/')
return(NULL);
/* get rid of old information */
expire_stats();
/* record what we are replacing */
REPLACE = CUR_STAT_STR;
/* loop thru each path component and check against current */
for(K=0;;) {
/* strip leading slashes */
while (*NEW == '/')
NEW++;
/* handle root */
if (K == 0) {
if (*NEW == '\0') {
if (DBOSI)
printf("locate_statobj: root\n");
STATS[0].NAME = "<root>";
return(&STATS[0]);
}
/* something more */
K++;
}
/* do we have info for this level? */
if (K > CUR_STAT_LEVEL)
break; /* nope */
/* do we have a name for this level */
if ((OLD = STATS[K].NAME) == NULL)
break; /* nope */
/* record buffer name */
REPLACE = OLD;
/* compare name */
TMP = NEW;
while (*OLD && *OLD == *TMP) {
OLD++;
TMP++;
}
/* did we end cleanly? */
if (*OLD != '\0')
break; /* nope */
/* did NEW path end? */
if (*TMP == '\0') {
/* yes */
if (DBOSI)
printf("locate_statobj: found %d: '%s'\n",
K,STATS[K].NAME);
return(&STATS[K]);
}
/* did NEW path end on slash? */
if (*TMP != '/')
break; /* nope */
/* about to loop, see if too many levels */
if (++K >= MAX_LEVEL) {
if (DBOSI)
printf("locate_statobj: too many '%s'\n",
path);
return(NULL);
}
/* loop again */
REPLACE = ++OLD;
NEW = TMP;
}
/* add components */
release_stats(K);
OLD = REPLACE;
for (;;) {
/* strip leading slashes */
while (*NEW == '/')
NEW++;
/* make sure we have something */
if (*NEW == '\0') {
/* must be trailing slash */
if (DBOSI)
printf("locate_statobj: trailing / in '%s'\n",
path);
return(NULL);
}
/* record and copy component */
STATS[K].NAME = OLD;
while (*NEW && *NEW != '/')
*OLD++ = *NEW++;
*OLD++ = '\0';
/* record new stat level */
CUR_STAT_LEVEL = K;
/* are we done? */
if (*NEW == '\0') {
/* yep */
if (DBOSI)
printf("locate_statobj: return %d: '%s'\n",
K,STATS[K].NAME);
return(&STATS[K]);
}
/* about to loop, see if too many levels */
if (++K >= MAX_LEVEL) {
if (DBOSI)
printf("locate_statobj: too many (add) '%s'\n",
path);
return(NULL);
}
/* loop again */
}
/* NEVER REACHED */
}
OSstat(path,buf)
char * path;
struct stat *buf;
{
struct statobj * CE;
if (DBOSI)
printf("OSstat=%s\n",path);
CE = locate_statobj(path);
if (CE != NULL) {
if (CE->STAT.st_nlink != BAD_LINK) {
if (DBOSI)
printf("OSstat=cache path\n");
bcopy(&CE->STAT,buf,sizeof(struct stat));
return 0;
}
if (cwd_stat(path,buf) == 0) {
if (DBOSI)
printf("OSstat=caching path\n");
bcopy(buf,&CE->STAT,sizeof(struct stat));
CE->VAL_TIME = CUR_TIME+EXP_TIME;
return 0;
}
if (DBOSI)
printf("OSstat=no cache\n");
return -1;
}
if (DBOSI)
printf("OSstat=not cached\n");
return cwd_stat(path,buf);
}
OSfinderinfo(path)
char * path;
{
char pp[MAXPATHLEN];
struct stat S;
struct statobj * CE;
CE = locate_statobj(path);
if (CE != NULL) {
if (CE->FN != VAL_INVALID)
return CE->FN;
strcpy(pp,path);
toFinderInfo(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
CE->FN = VAL_NO;
else
CE->FN = VAL_OK;
return CE->FN;
}
strcpy(pp,path);
toFinderInfo(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
return 0;
else
return 1;
}
OSresourcedir(path)
char * path;
{
char pp[MAXPATHLEN];
struct stat S;
struct statobj * CE;
CE = locate_statobj(path);
if (CE != NULL) {
if (CE->RS != VAL_INVALID)
return CE->RS;
strcpy(pp,path);
toResFork(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
CE->RS = VAL_NO;
else
CE->RS = VAL_OK;
return CE->RS;
}
strcpy(pp,path);
toResFork(pp,"");
if (cwd_stat(pp,&S) < 0 || !S_ISDIR(S.st_mode))
return 0;
else
return 1;
}
OSflush_stat()
{
CUR_TIME = Sched_Now->tv_sec;
if (DBOSI)
printf("OSflush_stat\n");
release_stats(0);
}
OSstat_cache_update()
{
CUR_TIME = Sched_Now->tv_sec;
EXPIRE_REQ = 1;
}
#endif STAT_CACHE

391
applications/aufs/afpudb.c Normal file
View File

@ -0,0 +1,391 @@
/*
* $Author: djh $ $Date: 1993/08/04 15:23:33 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpudb.c,v 2.3 1993/08/04 15:23:33 djh Rel djh $
* $Revision: 2.3 $
*/
/*
* afpudb.c - Appletalk Filing Protocol Unix Finder Information
* database.
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* August 1987 CCKim Created.
*
*/
/* PATCH: XENIX:file.3, djh@munnari.OZ.AU, 20/11/90 */
#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
# include <sys/types.h>
#endif
#include <sys/file.h>
#include <sys/stat.h>
#include <netat/appletalk.h>
#include "afpudb.h"
#ifdef NEEDFCNTLDOTH
# include <fcntl.h>
#endif
#ifdef bsd
# define BSDSYSTEM
#endif
#ifdef bsd4_2
# define BSDSYSTEM
#endif
/*
* Deal with unix file types
*
*/
/* This is the "file" icon - generic for unix files */
private byte unix_text[] = {
0x0f,0xff,0xfc,0x00, /* XXXXXXXXXXXXXXXXXX */
0x08,0x00,0x06,0x00, /* X XX */
0x08,0x00,0x05,0x00, /* X X X */
0x08,0x00,0x04,0x80, /* X X X */
0x08,0x00,0x04,0x40, /* X X X */
0x08,0x0c,0x04,0x20, /* X XX X X */
0x09,0xf8,0x87,0xf0, /* X XXXXXX X XXXXXXX */
0x0b,0xf9,0xc0,0x10, /* X XXXXXXX XXX X */
0x08,0x9b,0xe0,0x10, /* X X XX XXXXX X */
0x09,0x29,0x84,0x50, /* X X X X XX X X X */
0x0b,0x29,0x84,0x50, /* X XX X X XX X X X */
0x0b,0x29,0x85,0x50, /* X XX X X XX X X X X */
0x0b,0x69,0x85,0x50, /* X XX XX X XX X X X X */
0x0b,0x69,0x85,0x50, /* X XX XX X XX X X X X */
0x0b,0x49,0x85,0x50, /* X XX X X XX X X X X */
0x0b,0x89,0x85,0x50, /* X XXX X XX X X X X */
0x09,0x8b,0xa5,0x10, /* X XX X XXX X X X X */
0x09,0xfe,0xc5,0x50, /* X XXXXXXXX XX X X X X */
0x08,0x7c,0xc0,0x10, /* X XXXXX XX X */
0x08,0x00,0x00,0x10, /* X X */
0x08,0x40,0x44,0x50, /* X X X X X X */
0x09,0x54,0x45,0x50, /* X X X X X X X X X X */
0x09,0x55,0x55,0x50, /* X X X X X X X X X X X X */
0x09,0x51,0x55,0x50, /* X X X X X X X X X X X */
0x09,0x55,0x55,0x50, /* X X X X X X X X X X X X */
0x09,0x55,0x55,0x50, /* X X X X X X X X X X X X */
0x09,0x15,0x14,0x50, /* X X X X X X X X X */
0x09,0x55,0x54,0x10, /* X X X X X X X X X X */
0x09,0x41,0x50,0x10, /* X X X X X X X */
0x08,0x00,0x00,0x10, /* X X */
0x08,0x00,0x00,0x10, /* X X */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
/* mask */
0x0f,0xff,0xfc,0x00, /* XXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xfe,0x00, /* XXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0x00, /* XXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0x80, /* XXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xc0, /* XXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xe0, /* XXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0 /* XXXXXXXXXXXXXXXXXXXXXXXX */
};
#ifdef SMART_UNIX_FINDERINFO
private byte unix_framemaker[] = {
0x0F,0xFF,0xFE,0x00, /* XXXXXXXXXXXXXXXXXXX */
0x08,0x00,0x03,0x00, /* X XX */
0x0B,0xFF,0xFE,0x80, /* X XXXXXXXXXXXXXXXXX X */
0x0B,0xFF,0xFE,0x40, /* X XXXXXXXXXXXXXXXXX X */
0x0B,0xFF,0xFE,0x20, /* X XXXXXXXXXXXXXXXXX X */
0x08,0x00,0x02,0x10, /* X X X */
0x08,0x40,0x03,0xFA, /* X X XXXXXXX X */
0x38,0xA0,0x00,0x08, /* XXX X X X */
0x09,0x53,0xF7,0x8F, /* X X X X XXXXXXXXX X XXXX */
0xF9,0xB0,0x00,0x0B, /* XXXXX XX XX X XX */
0x19,0x53,0x7F,0x4B, /* XX X X X XX XXXXXXX X X XX */
0x18,0xA0,0x00,0x08, /* XX X X X */
0x18,0x40,0x00,0x0E, /* XX X XXX */
0x88,0x07,0xDF,0x48, /* X X XXXXX XXXXX X X */
0x28,0x00,0x00,0x0B, /* X X X XX */
0x09,0xBE,0xDF,0xCC, /* X XX XXXXX XX XXXXXXX XX */
0xA8,0x00,0x00,0x0E, /* X X X XXX */
0x49,0xEE,0xFB,0xC8, /* X X XXXX XXX XXXXX XXXX X */
0x08,0x00,0x00,0x08, /* X X */
0x09,0xDF,0x3D,0xC8, /* X XXX XXXXX XXXX XXX X */
0x08,0x00,0x00,0x08, /* X X */
0x08,0x00,0x03,0xC8, /* X XXXX X */
0x09,0xFA,0xEB,0xC8, /* X XXXXXX X XXX X XXXX X */
0x08,0x00,0x03,0xC9, /* X XXXX X X */
0x09,0xDF,0x5B,0xCD, /* X XXX XXXXX X XX XXXX XX X */
0x48,0x00,0x00,0x0B, /* X X X XX */
0x08,0x00,0x00,0x08, /* X X */
0x7B,0xFF,0xFF,0xEB, /* XXXX XXXXXXXXXXXXXXXXXXXXX X XX */
0x0B,0xFF,0xFF,0xE8, /* X XXXXXXXXXXXXXXXXXXXXX X */
0x7B,0xFF,0xFF,0xEE, /* XXXX XXXXXXXXXXXXXXXXXXXXX XXX */
0xC8,0x00,0x00,0x08, /* XX X X */
0x0F,0xFF,0xFF,0xF8, /* XXXXXXXXXXXXXXXXXXXXXXXXX */
/* mask */
0x0f,0xff,0xfc,0x00, /* XXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xfe,0x00, /* XXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0x00, /* XXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0x80, /* XXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xc0, /* XXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xe0, /* XXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0, /* XXXXXXXXXXXXXXXXXXXXXXXX */
0x0f,0xff,0xff,0xf0 /* XXXXXXXXXXXXXXXXXXXXXXXX */
};
/* other icons */
#endif SMART_UNIX_FINDERINFO
#define FNDR_NOFNDR 0
#define FNDR_DEF 1
#define FNDR_DEVICE 2
#define FNDR_SOCKET 3
#ifdef SMART_UNIX_FINDERINFO
#define FNDR_BIN 4
#define FNDR_UPGM 5
#define FNDR_UOBJ 6
#define FNDR_ARCHIVE 7
#define FNDR_CPIO 8
#define FNDR_LOCKED 9
#define FNDR_FRAME 10
#endif SMART_UNIX_FINDERINFO
#define deffinfo(C1,C2,C3,C4,c1,c2,c3,c4,com,icon) {{(C1),(C2),(C3),(C4)}, \
{(c1),(c2),(c3),(c4)}, \
(com), sizeof(com)-1, \
(icon), sizeof((icon))}
struct ufinderdb uf[] = {
{{0, 0, 0, 0}, {0, 0, 0, 0}, "", 0, NULL, 0},
deffinfo('u','n','i','x','T','E','X','T',
"This is a Unix\252 created file", unix_text),
deffinfo('u','n','i','x','D','E','V',' ',
"This is a Unix\252 device", NULL),
deffinfo('u','n','i','x','S','K','T',' ',
"This is a Unix\252 socket", NULL),
#ifdef SMART_UNIX_FINDERINFO
deffinfo('u','n','i','x','D','A','T','A',
"This is a Unix\252 binary file", NULL),
deffinfo('u','n','i','x','P','G','R','M',
"This is a Unix\252 program", NULL),
deffinfo('u','n','i','x','O','B','J',' ',
"This is a Unix\252 object file", NULL),
deffinfo('u','n','i','x','A','R',' ',' ',
"This is a Unix\252 archive file", NULL),
deffinfo('u','n','i','x','C','P','I','O',
"This is a Unix\252 cpio file", NULL),
deffinfo('u','n','i','x','L','C','K','D',
"This file is not readable", NULL),
deffinfo('F','r','a','m','F','A','S','L',
"This is a Unix\252 FrameMaker file", unix_framemaker)
#endif SMART_UNIX_FINDERINFO
};
export int uf_len = sizeof(uf)/sizeof(struct ufinderdb);
#ifdef USR_FILE_TYPES
struct uft uft[NUMUFT];
#endif USR_FILE_TYPES
int
os_getunixtype(path, stb)
char *path;
struct stat *stb;
{
#ifdef SMART_UNIX_FINDERINFO
char buf[BUFSIZ];
int fd, k, l;
#endif SMART_UNIX_FINDERINFO
int i;
if ((stb->st_mode & S_IFMT) == S_IFDIR) /* a directory? */
return(FNDR_NOFNDR);
switch (stb->st_mode & S_IFMT) {
case S_IFCHR:
case S_IFBLK:
/* super wanky thing to do would be to return an type */
/* based upon the device type */
return(FNDR_DEVICE);
break;
#ifdef S_IFSOCK
case S_IFSOCK:
return(FNDR_SOCKET);
break;
#endif S_IFSOCK
}
#ifdef SMART_UNIX_FINDERINFO
if ((fd=open(path,O_RDONLY)) < 0)
return(FNDR_DEF);
if ((i = read(fd, buf, BUFSIZ)) <= 0) {
(void)close(fd); /* ignore error here */
return(FNDR_DEF);
}
(void)close(fd); /* ignore error here */
switch (*(int *)buf) {
#ifdef BSDSYSTEM
case 0413:
case 0410:
case 0411:
case 0407:
return(FNDR_UPGM);
case 0177555:
case 0177545:
return(FNDR_ARCHIVE);
#endif BSDSYSTEM
case 070707:
return(FNDR_CPIO);
}
if (strncmp(buf, "<MakerFile", sizeof("<MakerFile")-1) == 0)
return(FNDR_FRAME);
#ifdef BSDSYSTEM
if (strncmp(buf, "!<arch>\n", sizeof("!<arch>\n")-1) == 0)
return(FNDR_ARCHIVE);
#endif BSDSYSTEM
#ifndef BIN_FUZZ
# define BIN_FUZZ BUFSIZ/3
#endif BIN_FUZZ
for (k = 0, l = 0; k < i; k++)
if (buf[k] & 0x80)
l++;
if (l > BIN_FUZZ)
return(FNDR_BIN);
#endif SMART_UNIX_FINDERINFO
#ifdef USR_FILE_TYPES
if ((i = uft_match(path)) >= 0)
return(i+FNDR_UFT);
#endif USR_FILE_TYPES
return(FNDR_DEF);
}
int
os_issmartunixfi()
{
#ifdef SMART_UNIX_FINDERINFO
return(1);
#else
return(0);
#endif
}
#ifdef USR_FILE_TYPES
/*
* initialize the UFT structure
*
*/
int
uft_init()
{
uft[0].uft_suffixlen = -1;
}
/*
* check the file name against the suffix list
*
*/
int
uft_match(file)
char *file;
{
int i = 0;
while (uft[i].uft_suffixlen >= 0) {
if (suffix_match(file, &uft[i]))
return(i);
i++;
}
return(-1);
}
int
suffix_match(file, uft)
char *file;
struct uft *uft;
{
int i;
if (uft->uft_suffixlen == 0) /* wildcard */
return(1);
if ((i = strlen(file)) >= uft->uft_suffixlen
&& strcmp(uft->uft_suffix, file+i-uft->uft_suffixlen) == 0)
return(1);
return(0);
}
/*
* check the file creator and type against the list
*
*/
int
uft_match_finfo(creat, ftype)
char *creat, *ftype;
{
int i = 0;
while (uft[i].uft_suffixlen >= 0) {
if (bcmp(creat, uft[i].uft_creat, 4) == 0
&& bcmp(ftype, uft[i].uft_ftype, 4) == 0)
return(i);
i++;
}
return(-1);
}
#endif USR_FILE_TYPES

View File

@ -0,0 +1,45 @@
/*
* $Author: djh $ $Date: 1993/08/04 15:23:33 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpudb.h,v 2.3 1993/08/04 15:23:33 djh Rel djh $
* $Revision: 2.3 $
*/
/*
* afpudb.c - Appletalk Filing Protocol Unix Finder Information
* database. Header file.
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* August 1987 CCKim Created.
*
*/
struct ufinderdb {
byte ufd_creat[4];
byte ufd_ftype[4];
char *ufd_comment;
int ufd_commentlen;
byte *ufd_icon;
int ufd_iconsize;
};
int os_getunixtype();
#ifdef USR_FILE_TYPES
struct uft {
byte uft_suffix[16]; /* unix filename suffix, ie: .tar */
short uft_suffixlen;
byte *uft_xlate; /* translation to perform ie: raw */
byte uft_creat[4]; /* creator to appear as ie: 'TAR ' */
byte uft_ftype[4]; /* macintosh file type ie: 'TEXT' */
char *uft_comment; /* "This is a UNIX tar file" */
short uft_commentlen;
};
#define NUMUFT 50
#define FNDR_UFT 100
#endif USR_FILE_TYPES

12
applications/aufs/afpvols Normal file
View File

@ -0,0 +1,12 @@
#
# This is Bill's Apple Filing Protocol Volume file
#
# Format:
# path:volume name[:password][:]
#
/usr/src/local/mac/Special:Special Mac Files::
/usr/src/local/mac:Macintosh Files:
~cck/mac:Chuck's Volume:

1043
applications/aufs/afpvols.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
/*
* $Author: djh $ $Date: 1994/02/16 05:09:02 $
* $Header: /mac/src/cap60/applications/aufs/RCS/afpvols.h,v 2.3 1994/02/16 05:09:02 djh Rel djh $
* $Revision: 2.3 $
*/
/*
* afpvols.h - Appletalk Filing Protocol Volume definitions
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* March 1987 Schilit Created.
*
*/
typedef struct { /* Volume Entry */
IDirP v_rootd; /* root directory (mount point) */
word v_bitmap; /* for packing purposes only */
char v_path[MAXDLEN]; /* path for this volume */
word v_attr; /* (lsb) read-only flag */
#define V_RONLY V_READONLY /* backward compat */
#define V_READONLY 0x0001 /* read only flag */
#define V_HASVOLUMEPASSWORD 0x0002 /* has a volume password */
#define V_SUPPORTSFILEIDS 0x0004 /* supports file IDs */
#define V_SUPPORTSCATSEARCH 0x0008 /* supports cat search */
#define V_SUPPORTSBLNKACCESS 0x0010 /* supports blank access privs */
char v_name[MAXVLEN]; /* advertised name */
char v_pwd[MAXPLEN]; /* volume password (unused) */
boolean v_mounted; /* mounted flag */
word v_sig; /* volume signature */
word v_volid; /* volume ID */
sdword v_cdate; /* volume creation date */
sdword v_mdate; /* volume modification date */
sdword v_bdate; /* volume backup date */
dword v_size; /* size of volume in bytes */
dword v_free; /* free bytes on volume */
byte v_esize[8]; /* size of volume in bytes */
byte v_efree[8]; /* free bytes on volume */
} VolEntry, *VolPtr; /* user volume table */
#define NILVOL ((VolPtr) 0)

1977
applications/aufs/aufs.c Normal file

File diff suppressed because it is too large Load Diff

1
applications/aufs/aufs_vers Executable file
View File

@ -0,0 +1 @@
Major 3 Minor 4

View File

@ -0,0 +1,17 @@
#!/bin/sh
echo "int aufs_version[2] = {" $2 "," $4 "};" > $6
if [ -f /usr/local/fdate ]; then
echo "char *aufs_versiondate = \""`fdate "%L %d, 19%y"`"\";" >> $6
else
echo "char *aufs_versiondate = \"" `date` "\";" >> $6
fi
if [ $5 != "useold" ]; then
newver=`expr $4 + 1`
echo $1 $2 $3 $newver > nv$$
mv nv$$ $5
else
echo "No version updating"
fi

File diff suppressed because it is too large Load Diff

2179
applications/aufs/aufsicon.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
int aufs_version[2] = { 3 , 4 };
char *aufs_versiondate = " Sat Feb 16 17:30:14 EST 1991 ";

View File

@ -0,0 +1,537 @@
Internal Directory IDs
----------------------
As of Sun Apr 26.
The current implementation of the Macintosh Hierarichal File System
uses "fixed dirids" which means that every directory has a unique id
fixed for the lifetime of the file system and which is never reused.
A directory id should to be fixed over invocations of the server
because the macintosh remembers directory ids. An example of this is
the standard file package which likes to pickup the selection in the
directory you last left off.
Unfortunately, Under unix there is no mechanism available for
generating consistent directory ids in the manner required. The
directory/file inode would be suitable since it is unique, but (a) it
is derived from the file's disk address and it is possible to see
recycled ids (even in the same session) and there is no efficient
"unix version independent" method of translating from inode to file.
We have determined that the minimum functionality that the AFP client
requires is that the directory IDs be unique and constant over the
lifetime of the server. It would be nice if a full function variable
dirid filesystem would be available on the macintosh side; however,
evidently Apple has no plans to do this.
The mechanism we choose is to return indices of a table which contains
pointers to nodes in an internal tree representing the volumes
directory structure. To minimize the effect of "same dirid, but
different directory" we randomly assign a "base" to the range of
dirids (e.g. pick a number like 300 out of the hat and add it to every
index of the table when translating from internal to external). The
internal structure is called an IDir:
typedef struct idir { /* local directory info (internal) */
char *name; /* the directory name */
struct idir *next; /* ptr to next at same level */
struct idir *subs; /* ptr to children */
struct idir *pdir; /* ptr to parent */
} IDir, *IDirP;
The name stored is the component name, not the full path name. The
next pointer links directories at the same level. The subs pointer is
a list of subdirectories, and the pdir pointer is a pointer to the
parent directory.
So, given an IDir you can generate the path by following the parent
links until pdir == rootd.
The mount point for a volume is not necessarily at "/" so there is
also the notion of the volume's root directory or mount point. This
is needed in order to translate between the special ids 1 and 2 which
are parent of root directory and root directory.
Using the IDir structure you can either build the tree completely by
scanning the unix filesystem at startup or you can add nodes as
needed. We choose to add nodes as needed.
The internal directory structure needs to be modified to be kept in
sync with the actual filesystem directory structure. Because of this
the FPMove and FPRename calls can result in the modification of the
internal representation.
There some large drawbacks in this design:
1. Does not handle the case of other servers or unix users changing
the directory structure.
2. Does not generate constant directory ids between invocations.
The benefits:
1. Very simple and quick resolution of directory ids to paths.
Given the alternatives we will be keeping this method for the time
being and including a validation word (or magic word) in the IDir
nodes to prevent random memory references.
We have considered other methods which include using the directory's
inode in the IDir node, and using the inode as the directory id. In
this case the IDir would have a second thread(s) for looking up by
inode number. This would marginally improve the situation and would
increase the complexity of the code substantially.
Folder groups and creators
--------------------------
As of Aug 1987
Under AFP a folder has a group and creator. These attributes are used
in resolving access privileges.
Unix maps AFP groups and creators into unix groups and creators. This
means that a file you would have access to under unix by virtue of
group/creator modes are also available under the server.
Under BSD unix you need to be su in order to change a files creator,
thus you may not change the owners (available under sys v machines).
Protections
-----------
As of Aug 1987
Under AFP only folders, aka directories, have protections. These
protections are: See Files (read), See Folders (search), write objects.
This does not map well into the unix protection scheme. Our
"solution" is simply to respect the unix protections as best as
possible. The ramifications are:
(1) we do not distinguish between see files and see folders
(2) read and write ability is based upon the protection of
individual files - not folders
We do not see (1) as a serious problem. (2) does not present any
problems if the user is not the owner of the file. (2) does present a
minor problem in that there is no way for the user to change the
permissions through AFP.
Specifically, when mapping from unix to mac protections:
Read access is translated to search folders/files (search, read)
Write access is translated to write access (write)
Note: The owner protection is the same as the user if the user owns
the file, else group if you have group access, else other access. The
elses are important because if you have write access as other, but not
as group or user, then you will not be able to write to a directory -
this is the way unix interprets the protections (right or wrong).
From Mac to unix, we take:
See Files (read), to be unix read/search(execute)
Make Changes (write), to be unix write
See Folders (search), is not mapped
When a "folder" protection is changed, all files in the folder also
have their protections changed to the same protection.
On file or folder creates, the protection is taken from the protection
of the superior "folder" (directory).
Newline conversion
As of Tue July 22, 1987
On Unix the newline character is \n (code 012, lf), however, most Macintosh
applications use \r (code 015, cr) as newline.
We now translate lf to cr on reads and cr to lfs on writes if the file
creator is unix and the file type is TEXT. These are the defaults for
"unix" files.
In addition, lf and cr are defined internally as INEWLINE (internal
unix newline) and ENEWLINE (external mac newline), and conversion
between them is carried out in the following case:
1. NONLXLATE must not be defined when compiling module afpos.c.
The symbol NONNLXLATE disables newline conversion.
2. If conversion code is enabled and FPRead is issued with
NewLineMask equal to 0xFF, NewLineChar equal to
ENEWLINE, then the read terminates on either an ENEWLINE
or INEWLINE, and the INEWLINE is converted to ENEWLINE.
In summary, for this method: conversion only occurs when reading from
the unix filesystem and FPRead is issued in the special break on
newline mode, and the requested break character is the expected
macintosh newline character. There is no conversion when writing to
the Unix filesystem.
Name Conversion
---------------
Filenames on the mac can contain characters which are illegal in unix
file names. These include all 8 bit characters and /. The only chars
which are illegal on the mac are ":" and null.
The current name conversion maps special mac characters to be ":"
followed by two hex digits. For example the name "Copy/Hey" on the
mac would convert to "Copy:2fHey" on unix. A ":" found on a unix file
which does not have 2 hex digits following is mapped into "|" on the
mac.
When a unix file name is encountered a check is made to see if the
converted name is longer than MAXLFLEN (31) chars. If the name is
longer than the mac allows, then it is skipped completely and is not
seen by the mac.
The algorithm for name conversion is more specifically:
Mac to Unix
if (char is ascii and not control and is printable and
is not "/") then
leave as is
else
replace with ":" followed by two hexidecimal
digits that is a direct encoding of the binary
value of the char
Unix to Mac:
if (":" followed by two hex digits) then
replace with binary value of hex digits
if (":" not followed by two hex digits) then
replace ":" with "|".
File Format (.finderinfo, .resources, data)
Macintosh files are currently stored in a directory in three main
files. We have the resource fork, the data fork, and various file
specific finder information to store. Since the data fork is the
closest match to a unix file, it is stored as-is in the
specified directory, the resource fork and the so
called "finder info" fork are "special" and can be
stored by the same name in special subdirectories of the specified
directory. To be concrete, the Mac file "keeper" stored in a
directory "stuff" would be stored by Aufs on the unix file system as:
stuff/keeper - data fork
stuff/.finderinfo/keeper - "finder info" fork
stuff/.resource/keeper - resource fork
It is important to note that the .finderinfo and .resource directories
are only created by a "create directory" afp (Finder new folder)
command. This prevents these directories from drifting into places
people probably don't want them. However, these directories are
created iff the superior directory also had them.
Getting to the finder info and resource fork is a pain under unix, but
how often do you really need to anyway?
The defaults for a file that has no finder information is
type: TEXT [first four bytes]
creator: unix [second four bytes]
rest is set to zeros
file attributes: none
comment:
"This is a Unix\252 created file." (\252 is the tm sign)
A directory with no finder information defaults the comment to one of:
This is a unix directory
This is an Aufs Macintosh directory
This is an Aufs unix directory (.finderinfo only)
if it has a no .finderinfo and .resource directory or just a resource
directory, both a .finderinfo and .resource directory, or just a
.finderinfo directory respectively.
Turning on SMART_FINDERINFO in afpudb.c will yield more information;
however, it is unix variant dependent and slows things down
considerably.
See MAJOR FILE FORMATS below for the finderinfo formats.
Desktop databases.
As of Feb 1988
The icon data base is stored in .IDeskTop in the volume's root. A new
Icon are always appended to end unless it replaces an old one in which
case the old space will be reused if possible. New icons are written
out when received. The .IDeskTop is only read on the inital
"open desk" call. Locking is done if possible to prevent corruption.
(cf. section on locking).
The APPL mappings are stored in .ADeskTop in the volume's root. We
store for each mapping the File creator, the path relative to the
volume root to the application, and the application name. Modified or
changed entries are appended to the .ADeskTop on every "flush" if you
have write access. It is possible for this database to grow rapidly
or be corrupted. The problems lie in the fact that we always append
(the solution for now is to rebuild the desktop now and then). It may
get corrupted because people move directories around (though we try to
minimize this). Also, note that entries are never deleted from the
.ADeskTop - there should be a mechanism to do this. Like the Icon
database, the APPL mappings are read only when the inital desktop open
is issued.
See MAJOR FILE FORMATS below for the .ADeskTop and .IDeskTop file formats.
MAJOR FILE FORMATS
Aufs Version 3 File Formats (CURRENT)
-------------------------------------
In the following:
byte: unsigned 8 bits
word: unsigned 16 bits
dword: unsigned 32 bits
sdword: signed 32 bits
Important: all items are stored in network order! This means on a vax
you use htons/ntohs on words and htonl/ntohl on dwords.
.ADeskTop format:
The Applications mapping database is kept as an array of the
APPLFileRecords and associated data as shown following. The
associated data is the parent directory name relative to the volume
root and the application name as null terminated strings.
/* never use zero or 0x1741 as the major version */
#define AFR_MAGIC 0x00010002
/* version 1.2 (don't use 1.1, 2.2, etc) */
/* version 1.0 (version 0x1741.0000/0x1741) */
typedef struct { /* APPL information */
byte a_FCreator[4]; /* creator of application */
byte a_ATag[4]; /* user bytes */
} APPLInfo;
typedef struct { /* File Format APPL record */
dword afr_magic; /* magic number for check */
APPLInfo afr_info; /* the appl info */
sdword afr_pdirlen; /* length of (relative) parent directory */
sdword afr_fnamlen; /* length of application name */
/* names follows */
} APPLFileRecord;
.IDeskTop format:
The Applications mapping database is kept as an array of the
ICONFileRecords and associated data as shown following. The
associated data is the bitmap.
IconInfo in the below is padded to a double word boundary. Hopefully,
this is good enough to prevent differences in structure size in
ICONFileRecord on different machines.
/* never use zero or 0x2136 as the major version */
#define IFR_MAGIC 0x00010002 /* Version 1.2, skip 1.1, 2.2, etc. */
/* version 1.0: 0x2136.0000/0x2136 */
#define FCreatorSize 4
#define FTypeSize 4
#define ITagSize 4
typedef struct { /* Icon Information */
sdword i_bmsize; /* 4: size of the icon bitmap */
byte i_FCreator[FCreatorSize]; /* 4[8]: file's creator type */
byte i_FType[FTypeSize]; /* 4[12] file's type */
byte i_IType; /* 1[13] icon type */
byte i_pad1; /* 1[14] */
byte i_ITag[ITagSize]; /* 4[18] user bytes */
byte i_pad2[2]; /* 2[20] pad to double word boundary */
} IconInfo;
typedef struct { /* File Format ICON record */
dword ifr_magic; /* the magic check */
IconInfo ifr_info; /* the icon info */
/* bitmap follows this */
} IconFileRecord;
.finderinfo format:
In the following space for all entries is allocated. The bitmap
merely tells us if the indicated items are valid.
#define FINFOLEN 32
#define MAXCLEN 199
typedef struct {
byte fi_fndr[FINFOLEN]; /* finder info */
word fi_attr; /* attributes */
#define FI_MAGIC1 255
byte fi_magic1; /* was: length of comment */
#define FI_VERSION 0x10 /* version major 1, minor 0 */
/* if more than 8 versions then */
/* something wrong anyway */
byte fi_version; /* version number */
#define FI_MAGIC 0xda
byte fi_magic; /* magic word check */
byte fi_bitmap; /* bitmap of included info */
#define FI_BM_SHORTFILENAME 0x1 /* is this included? */
#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
byte fi_shortfilename[12+1]; /* possible short file name */
byte fi_macfilename[32+1]; /* possible macintosh file name */
byte fi_comln; /* comment length */
byte fi_comnt[MAXCLEN+1]; /* comment string */
} FileInfo;
Aufs Version 1 and Version 2 FILE FORMATS
-----------------------------------------
In the following, "bit.x" defines a type of x bits. "str" means an
ascii string (256 character ascii set) terminated by a null. The
formats are defined below in the formats section.
IMPORTANT: THESE FILES WERE STORED IN THE HOST MACHINE ORDER. You
cannot transport a these files from a byte swapped machine to a
non-bytes swapped machine.
.ADeskTop format:
The .ADeskTop file contains an array of the following structure:
bit.32 afr_magic; /* magic number for check */
bit.8 a_FCreator[4]; /* creator of application */
bit.8 a_ATag[4]; /* user tag information */
bit.32 afr_pdirlen; /* length of parent directory name */
bit.32 afr_fnamlen; /* length of application name */
str pdir[afr_pdirlen]; /* path to directory holding */
/* appl. relative to volume root */
str file[afr_fnamlen]; /* file name */
The file names are stored are the unix file names. Note: the
directory path is relative to the volume root directory. The magic
number is a consistency check and is currently: AFR_MAGIC (8107+8556).
.IDeskTop format
The .IDeskTop file contains an array of the following structure:
bit.32 ifr_magic; /* the magic check */
bit.8 i_FCreator[4]; /* file's creator type */
bit.8 i_FType[4]; /* file's type */
bit.8 i_IType; /* icon type */
bit.8 i_ITag[4]; /* user bytes */
bit.32 i_bmsize; /* size of the icon bitmap */
bit.8 i_icon[i_bmsize]; /* icon */
The magic number is a consistency check and is currently: IFR_MAGIC
(8107+5750).
The .finderinfo files contain the following information:
bit.8 fi_fndr[32]; /* finder info */
bit.16 fi_attr; /* attributes */
bit.8 fi_comln; /* length of comment */
bit.8 fi_comnt[200]; /* comment string */
LOCKING
Draft 2: Jan, 1988
Charlie C. Kim
User Services
Columbia University
Coordination of multiple access to files is best done through system
calls that implement the locks internal to the system. Advisory locks
allow coordination of multiple Aufs processes (if they all honor the
locks), but processes external to Aufs may cause problems. "Hard"
locks would be real real nice, but we haven't seen them.
Two systems calls, "lockf" and "flock", are known to exist in a number
of different unix systems to allow "advisory" locks. Where these
exist, they can be used to coordinate Aufs processes (c.f.
INSTALLATION notes). The basic semantics of these calls (as known)
are:
flock - for an open file, establish a "shared" or "exclusive"
lock. A "exclusive lock" may be placed iff no locks are in place. A
shared lock may be upgraded to an exclusive lock iff no other locks
are in place. Multiple shared locks are allowed :-). Locks go away
when the file is closed. Allow locks to be tested and removed (can't
distingush between exclusive and shared on test though).
lockf - for an open file, allow exclusive locks at various
offsets for particular lengths. Also allow locking of the entire
file. Locks only allow if the file is open for read/write (sigh).
Locks can be removed and/or tested. (Do locks go away when file
closes?).
FPOpen
FPOpen allows "deny read", "deny write", and "deny r/w" and "deny
none" "locks" to be place on a file. We still do not implement these
(major pain because it requires access to lock information AND
previous open statuses).
File-locks
Certain files, such as, .ADeskTop, .IDeskTop and the file info files
must be coordinated between servers (ignore outside access). Two
system calls (exists in various unixs) help do this: flock and lockf.
Coordination can be easily accomplished by using the "flock" system
call if it exists. flock allows exclusive and shared locks.
Basically, when a file is "read", then a shared lock is set first. If
a file is to be written, then an exclusive lock must be set first -
this fails if a shared lock is already set. Some systems might have
"lockf" available which allows "exclusive" locks only. In theory this
would be okay (though you can't have multiple readers then) too;
however, "lockf" only works if the file is open for write, so if a
process has "read-only" access to one of the above files, then it
can't be guaranteed that the data is okay.
ByteRangeLock
The only available unix system call option for this is "lockf". This
allows pretty much what is necessary except you cannot lock
"read-only" files. (Reading Inside Mac Volume 4 seems to lead me to
believe that this is correct, but the AFP specification doesn't
really make this clear).
Warning: NFS systems may not allow locks across remotely mounted file
systems. Even when they are allowed, special daemons must be run
since locking is not within the NFS protocol.
NORMALIZING CHARACTER SETS
Dan Sahlin of the Swedish Institute of Computer Science pointed out
the need to normalize between Unix character sets and the Macintosh
character set. Previously, Aufs provided this feature in a very
limited fashion: it would map between cr and lf when the file type was
"TEXT" and creator was "unix" (defaults for unix files). This
provided "good" functionality in the US.
However, people outside the United States need to make use of various
international character sets that must be mapped to the Macintosh
character sets to be useful. The primary intent of this mapping is to
allow unix files to be mapped; however, it is also possible to allow a
large class of files to be mapped (such as all text files ending in
.swe, etc).
The design is quite simple: define a mac to unix and unix to mac table
of 256 entries each that contain a direct mapping (must be one
character to one since file sizes, etc. require this).
The routine that decides whether mapping is necessary or not bases it
decision on an internal table (should be per volume, not per server as
it is now). For each normalizing set of tables, Aufs records a file
extention, file creator, and file type of which any can be null. In
addition it stores a "conjuction" operator. It decides whether to
apply one when file has the specified extention "conjuction" file type
and file creator matches. null entries are treated as always true.
For the old unix files, the table entry is:
extension: NULL
creator: unix
type: TEXT
and for Swedish D47:
extension: .swe
creator: NULL
type: TEXT
which means any file of type TEXT with the extension .swe will have
normalization applied.
Note: the defaults for Swedish D47, Swedish-Finnish E47, and IOS
8859-1 Latin 1 were establish by Dan Sahlin.
Packing unpacking packets.
Enumeration cache.

168
applications/aufs/makefile Normal file
View File

@ -0,0 +1,168 @@
# Makefile autoconfigured for ...
# SunOS system on Fri Feb 15 14:00:17 EST 1991
MFLAGS=
LFLAGS=
CC=cc
LD=ld
SHELL=/bin/sh
INSTALLER=cp
CFLAGS= -O -DSHORT_NAMES -DMELBOURNE
I=/usr/include
#
# SEE INSTALLATION for documentation
#
# valid are NONXLATE,FULL_NCS_SUPPORT,USECHOWN
# USESTATFS or USEGETMNT
# USEQUOTA or USESUNQUOTA
# and GGTYPE="gid_t"
OSDEFS= -DUSESTATFS -DUSESUNQUOTA
AFPLIB=-lafp
CAPLIB=-lcap
# for other libraries (like BSD on hpux)
SLIB=
# used mainly for debugging
CAPFILES=
# aufs.c definitions: USEVPRINTF - use vprintf in logging
AUFSDEFS=-DUSEVPRINTF
# to get "more" information about files with a speed penalty
# Also, is specific to 4.2 BSD. May not work on some machines
#AFPUDB=-DSMART_UNIX_FINDERINFO
#For hpux (you have you may need to supply a routine that does rename)
# (Other limitations apply!!!!)
# RENAME=rename.o
# make sure that you define point getopt to att_getopt.o if your system
# doesn't have it builtin
GETOPT=
# This encodes the assumed location of certain directories
EXTRAS=../../extras
# Set the following approriately
DESTDIR=/usr/local/cap
#
# End of configurable options
#
SRCS=afpos.c afpvols.c afpfile.c afpdir.c afpfork.c \
afpmisc.c afpserver.c aufsicon.c abmisc2.c \
afpdt.c afpdid.c afposenum.c afpavl.c \
afposfi.c afpgc.c afppasswd.c afposlock.c aufsv.c \
afpudb.c afposncs.c afpspd.c sizeserver.c
OBJS=afpos.o afpvols.o afpfile.o \
afpmisc.o afpserver.o aufsicon.o abmisc2.o \
afpdt.o afpdir.o afpfork.o afpdid.o afposenum.o afpavl.o \
afposfi.o afpgc.o afppasswd.o aufsv.o \
afpudb.o afposncs.o afpspd.o sizeserver.o
SYMLINKS=att_getopt.c
all: aufs
aufs: aufs.o $(OBJS) $(CAPFILES) ${RENAME} $(GETOPT)
${CC} $(LFLAGS) -o aufs aufs.o $(OBJS) $(CAPFILES) ${RENAME} \
$(GETOPT) ${AFPLIB} ${CAPLIB} ${SLIB}
newver:
/bin/sh aufs_vers.sh `cat aufs_vers` aufs_vers aufsv.c
make all
aufsv.c: aufs_vers
/bin/sh aufs_vers.sh `cat aufs_vers` useold aufsv.c
clean:
-rm -f *.o aufs ${SYMLINKS}
lint: aufs.c $(SRCS)
lint aufs.c $(SRCS)
install: aufs
-strip aufs
${INSTALLER} aufs $(DESTDIR)
dist:
@cat todist
att_getopt.o: att_getopt.c
att_getopt.c:
ln -s ${EXTRAS}/att_getopt.c
afpos.o: afpos.c
${CC} ${OSDEFS} ${CFLAGS} -c afpos.c
afposncs.o: afposncs.c
${CC} ${OSDEFS} ${CFLAGS} -c afposncs.c
afpudb.o: afpudb.c
${CC} ${CFLAGS} ${AFPUDB} -c afpudb.c
aufs.o: aufs.c
${CC} ${OSDEFS} ${CFLAGS} ${AUFSDEFS} -c aufs.c
# Dependencies
afpos.o: afpos.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h \
afpvols.h $I/netat/afpcmd.h
afpudb.o: afpudb.c $I/netat/appletalk.h afpudb.h
afpfork.o: afpfork.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
afpdir.o: afpdir.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
afposfi.o: afposfi.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h afpgc.h afpudb.h
afpvols.o: afpvols.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpvols.h \
afpntoh.h
afpfile.o: afpfile.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
afpmisc.o: afpmisc.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h
afpserver.o: afpserver.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
$I/netat/afpcmd.h afpntoh.h
aufsicon.o: aufsicon.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h
afpcmd.o: afpcmd.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h $I/netat/afpcmd.h
abmisc2.o: abmisc2.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h \
$I/netat/afpcmd.h
afpdt.o: afpdt.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h \
$I/netat/afp.h $I/netat/afpcmd.h \
afpvols.h afpdt.h afpavl.h \
afpntoh.h afpudb.h
afpdid.o: afpdid.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h
afposenum.o: afposenum.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/afp.h \
afpdt.h afpavl.h
afppacks.o: afppacks.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h $I/netat/afpcmd.h
afpavl.o: afpavl.c afpavl.h
afperr.o: afperr.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/afp.h
afpgc.o: afpgc.c afpgc.h
afppasswd.o: afppasswd.c $I/netat/sysvcompat.h afppasswd.h
afposncs.o: afposncs.c $I/netat/appletalk.h $I/netat/afp.h \
afposncs.h afps.h
sizeserver.o: sizeserver.c sizeserver.h

View File

@ -0,0 +1,89 @@
#ifdef SIZESERVER
#include <stdio.h>
#include <fstab.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/stat.h>
#include <ufs/fs.h>
#include <ufs/inode.h>
/*
* files could be in
* /usr/include/sys
*
#include <sys/fs.h>
#include <sys/inode.h>
*
*/
#include "sizeserver.h"
main()
{
register int uid;
struct volsize vs;
char path[BUFSIZ];
uid = getuid();
for( ; ; ) {
if(read(0, path, BUFSIZ) <= 0)
exit(0);
volumesize(path, uid, &vs.total, &vs.free);
write(0, (char *)&vs, sizeof(vs));
}
}
volumesize(path, uid, ntot, nfree)
char *path;
int uid;
long *ntot, *nfree;
{
register int fd;
register long total, avail, used;
register int i;
struct stat statbuf, statbuf2;
struct fstab *fsp;
struct fs super;
if(stat(path, &statbuf) < 0) {
unknown:
*ntot = 0x1000000;
*nfree = 0x1000000;
return;
}
setfsent();
while(fsp = getfsent()) {
if(stat(fsp->fs_spec, &statbuf2) == 0 &&
statbuf2.st_rdev == statbuf.st_dev) {
path = fsp->fs_spec;
break;
}
}
endfsent();
if(fsp == NULL)
goto unknown;
if((fd = open(path, O_RDONLY, 0)) < 0)
goto unknown;
(void)lseek(fd, (long)(SBLOCK * DEV_BSIZE), 0);
i = read(fd, (char *)&super, sizeof(super));
(void)close(fd);
if(i != sizeof(super))
goto unknown;
total = super.fs_dsize;
used = total - (super.fs_cstotal.cs_nbfree * super.fs_frag +
super.fs_cstotal.cs_nffree);
avail = (avail = total * (100 - super.fs_minfree) / 100) > used ?
(avail - used) : 0;
*nfree = (uid == 0 ? (total - used) : avail) * super.fs_fsize;
*ntot = total * super.fs_fsize;
}
#else SIZESERVER
#include <stdio.h>
main()
{
printf("sizeserver: not compiled with -DSIZESERVER\n");
}
#endif SIZESERVER

View File

@ -0,0 +1,4 @@
struct volsize {
long total;
long free;
};

76
applications/aufs/todo Normal file
View File

@ -0,0 +1,76 @@
Tue Mar 31 19:33:34 1987
High:
Medium:
Setting directory owner is a bad idea under unix? (Allow under SysV)
do something to the DT if the magic number is wrong
Low:
make xbin do the correct file names and finder info format.
Add OpenDir, CloseDir
Make conflicting aufs processes handle conflicts with .finderinfo,
desktop for systems without flock, lockf
Clean:
run lint on the whole mess and get rid of any unused routines
cleanup interface
system admin manual page, user manual page
modules needing init should be called from InitServer(), name Init_xxx();
Bugs:
Folders gets locked/in use and can't get rid of it.
Done
4/1/87 Bill - move afperr() from aufs into (new) afperr.c do char *afperr()
4/1/87 Bill - error codes prefixed aeX to prevent conflict with other codes.
4/1/87 Bill - clean up command line args/help
4/2/87 Bill - Icon database resides in each volumes root directory
4/2/87 Bill - Make tilde available in path name on volumes in afpvols file.
4/2/87 Bill - Volume passwords.
4/2/87 Bill - Clean up os interface some.
4/2/87 Bill - don't show desktop files...
4/2/87 Bill - APPL database (afpdt) mostly working
4/3/87 Bill - default finder information should have TEXT...
4/3/87 Bill - if no finderinfo, item is locked, comment is "Unix created.."
4/3/87 Bill - Comment strings (afpdt).
4/3/87 Bill - write returns bad offset on return (cck fix)
4/3/87 Bill - abmisc2 should be moved into other ab modules (cck did most)
4/4/87 Bill - fpenumerate should use the max replysize instead of current hack
4/4/87 Bill - fpenumerate does not count an item when request bitmap is 0.
4/4/87 Bill - OSFileDirInfo doesn't consider bitmap, does unnecessary work
4/4/87 Bill - SetFileParms, SetDirParms, SetFileDirParms
4/4/87 Bill - SetDirParms for access mode
4/4/87 Bill - move/rename for dirs needs to modify IDir structure better!
4/4/87 Bill - volmodified should be set in more places.
4/4/87 Bill - APPL information should be written to disk.
4/4/87 Bill - some routines are doing packing by hand, they should be modified.
4/4/87 Bill - packing routines searches a table for AFPCmd... chuck it
4/6/87 B&C - name mapping... disallow characters which confuse unix.
4/6/87 CCK - add spawning on login. Debug server prevents this.
4/16/87 Bill - implement FPCopyFile
4/16/87 Bill - use a master afpvols files; switch is -V
4/16/87 CCK - log login/logout to a log file.
4/16/87 Bill - make very quite if debugging turned off.
4/16/87 Bill - allow newlinechar in read
4/16/87 Bill - see if most OS error codes are translated ok.
4/16/87 Bill - using the path name for volume problems; use component name
4/16/87 Bill - move table out of afpcmd.c
4/16/87 Bill - build a combined common header file... keep others seperate
6/24/87 cck - Add SetForkParms and allow setfiledirparms to set fork lengths.
bunch of other changes too.
6/24/87 cck - Setting directory group forks off the chgrp program if neces.
6/26/87 cck - allow guest login, cmd line option to set guest id?
7/22/87 cck - use citi mechanism for converting files - change default
file type to TEXT, creator "unix". Files like this will
have lf mapped to cr on read and vice versa on write
8/01/87 cck - time conversion is off because mac does not use AFP
time - only in Appleshare verison 1.0
1/88 - Fix problems with byte order in .ADeskTop, .IDeskTop and
.finderinfo files.

163
applications/aufs/user.doc Normal file
View File

@ -0,0 +1,163 @@
Brief introduction to the AppleShare Unix File Server (AUFS)
Introduction
This document explains what you must do before you attempt to use Aufs
from a mac. In addition, it explains some of the design decisions
that will affect you.
Setup
This describes the initial setup.
Create some subdirectory, let's assume it is "unix" in your top-level
directory. This will be the repository for your MacIntosh files.
Assuming you are connected to your top level directory, type:
"mkdir unix"
You must also create two subdirectories in this directory called
.finderinfo and .resource. e.g. type:
"mkdir unix/.finderinfo"
"mkdir unix/.resource"
AppleShare has a concept of something called volumes. Under the
MacIntosh AppleShare, each volume would be a different disk drive.
Under aufs, you are allowed to set various directories as "volumes".
Thus, you must create a file called "afpvols" or ".afpvols" (Aufs will
take "afpvols" over ".afpvols" first) in your top level (home) directory that
tells aufs what MacIntosh volumes you have. (Yes, you may have more
than one volume). The format of lines in this file is:
<path>:<name to show>[:<optional password>]
path is the specification of the directory that will store the unix
files. In the above example, it would be "~/unix". <name to show> is
the name the AppleShare client will show when it asks you which volume
to mount. The <optional password>, if set, is used when you attempt
to mount the volume. You probably don't want it - it is included for
system volumes.
We should note that ~/unix should be considered a "MacIntosh" volume
and you should be very careful about changes you make to it with unix
utilities. (If you're not sure, do a "Get Info" from the Finder on
the Folder/Volume) In generally, it's better to move things around,
delete things, etc. using the Mac AppleShare client.
Structure
o How MacIntosh files are stored
MacIntosh Operating System files have two parts known as the data and
resource "fork" (these forks have nothing to do with processes, etc).
Suffice it to say, that data is usually stored in the data fork and
programs and associated resources in the resources fork. In addition,
there is also an "information" fork which keeps information like the
file creator, file type, and location on the desktop, etc.
However, Unix doesn't expect a file to be of more than one part. So,
to get around this, we store a MacIntosh file in a particular
directory as follows. Each directory that stores MacIntosh files will
have a ".finderinfo" and ".resource" subdirectory created. The file
information and resource forks of a file are stored in the respective
subdirectories while the data fork is stored in the directory. For
example, given the MacIntosh file "MacWrite" stored in the directory
"macfiles", the listing of the directory would be as follows:
mac/MacWrite
mac/.resource/MacWrite
mac/.finderinfo/MacWrite
Normally, you will find it more difficult to use or see the resource
or finder information files; however, since the data in those files are
really very specific to the MacIntosh, this shouldn't pose a great
problem.
There is one more peculiar thing that happens. Directories need to
have "finder information" stored. Well, a directory is treated almost
the same as a file - we simply store the finder information in the
.finderinfo subdirectory of the containing directory. No resource
file/fork is created though. For example, suppose we create the
directory "paints" in the directory "mac", then the structure would
look like:
mac/paints <- a directory
mac/.finderinfo/paints <- finder infomation file
To obfusctiate the issue even more, we should note that the directory
paints also has ".finderinfo" and ".resource" forks.
o How Unix files and directories are treated
Unix directories are directories without a .finderinfo or .resource
subdirectory. The main things to know here are:
o you cannot copy a macintosh file with a resource fork to a
directory without a .resource subdirectory.
o "New Folder" will create a new directory. It will have a
.finderinfo or .resource directory if the superior directory does.
Unix-only files are essentially files with only a data fork.
Following are some notes about them.
- Unix files used to come up locked, THEY NO LONGER DO.
- Unix files come up with creator "unix" and type "TEXT" by default.
- Unix files use line feed (lf) as a line terminator while the
Macintosh Operating System uses carriage returns (cr) - this can
cause problems. To work around this, if a file has creator "unix"
and type "TEXT", then lf's are mapped to cr's on reads and vice
versa on writes. The way to stop this is to set the file's creator
or type to something else using DiskTop, ResEdit or whatever (note,
if it is a file in a directory without a .finderinfo directory,
then the modified file creator/type may reset to unix/TEXT at any
time).
- In the same vein, anytime "line at a time" reads with "cr"
(mac line terminator) as the end of line terminator are done, then
both "cr" and "lf" are used as end of line terminators regardless
of the file creator and type. An example of a program that does
this is BinHex.
- Copying a Unix file to or rewriting a Unix file in a directory
with .resource and .finderinfo subdirectories will cause the
resultant file to be a MacIntosh file.
- The Finder really needs to be able to store the finderinfo to work
efficiently. If you have a unix directory that you plan to
manipulate a lot, then you can speed up things a lot by creating a
.finderinfo subdirectory - however, remember this will cause Aufs
to create a .finderinfo file for each file in the directory.
o Volumes
As we noted before, volumes on a MacIntosh AppleShare server
correspond to disk drives and on under Aufs they correspond to
directories listed in the afpvols file.
If the top level directory of an Aufs volume has a .finderinfo
subdirectory, Aufs assumes that the volume will primarily be used for
Macintosh files. In this case, it will create two files in that
directory called: .ADeskTop and .IDeskTop. The two files correspond
to the "DeskTop" file on the MacIntosh and are seperated for efficency
reasons.
The .IDeskTop file maintains a database of the icons. The .ADeskTop
file records the file creator to application mappings - basically, it
tells what application to launch when you double click on a document
with that file creator. Like the Desktop on the Macintosh, neither of
these files shrink. Unlike the Desktop on the Macintosh, if you want
to rebuild the desktop with only entries on the volume, you must first
remove these files.
You can have volumes in your afpvols file that overlap. You should be
careful about operation between the two volumes when mounted at the
same time.
o Other notes
Unix distinguishes case when opening and getting information about
files. The MacIntosh Operating System doesn't. This will cause
problems with some applications (such as MPW).
The specification for the Appletalk Filing Protocol used by AppleShare
and AUFS and the specification for the Hierachial File System used by
MacIntoshes state that directory ids are fixed across the lifetime of
a volume. In addition, directory ids are not reused. Unfortunately,
aufs breaks this rule. Directory ids are unique only for a particular
session. Some programs and packages store away directory ids and you
may see some unexpected things happening (but it shoudn't be anything
bad).

View File

@ -0,0 +1,33 @@
Notes on files.
README - Generally useful information
INSTALLATION - Installation considerations
design.notes - design consideration
todo - things left to do or done
afpvols - sample volume file
user.doc - user documentation
abmisc2.c+ - server register routine
afpavl.[c,h] - implements balanced trees (general)
afpdid.[c,h]* - directory id routines
afpdir.c@ - Handles directories
afpdt.[c,h]*+@ - Handles desktop
afpfile.c@ - File handling routines
afpfork.c@+ - Fork handling routines
afpgc.[c,h] - Generalized caching management
afpmisc.c - miscellaneous, yet useful routines
afpntoh.h - translator file for packs
afpos.c*+ - Most os dependent routines
afposenum.c* - OS dependent part of file enumeration
afposfi.c* - OS dependent finder information handling
afposncs.[c,h] - OS dependent character set normalization
afppasswd.c - auxillary password routines
afpserver.c+@ - main server loop
afpvols.[c,h]@ - handles volumes
aufs.c+ - main driver
aufsicon.c - icon for aufs
afps.h - general header file
afpudb.[c,h]* - holds Unix desktop information
*'ed items are heavily os dependent
+'ed items have CAP library dependencies
@'ed items are primary AFP drivers

552
applications/lwsrv/DBfile Normal file
View File

@ -0,0 +1,552 @@
plain300 = (
Query ADOIsBinaryOK? True;
FeatureQuery *?Resolution 300dpi;
FeatureQuery *ColorDevice False;
FeatureQuery *FaxSupport None;
FeatureQuery *LanguageLevel '"1"';
FeatureQuery *TTRasterizer None;
Query ADOSpooler spooler;
);
"COMPAQ PAGEMARQ 15" = (
include "LaserWriter Plus";
FeatureQuery *PSVersion '"(2012.015) 13"';
FeatureQuery *?Resolution 400x800dpi;
FeatureQuery *ColorDevice Unknown;
FeatureQuery *FreeVM '"2397046"';
FeatureQuery *Product '"(COMPAQ PAGEMARQ 15)"';
Query Product '"(COMPAQ PAGEMARQ 15)"';
FeatureQuery *FaxSupport Base;
Query ADORamSize '"10485760"';
);
"Dataproducts LZR 1260" = (
include "LaserWriter Plus";
FeatureQuery *PSVersion '"(47.0) 0"';
FeatureQuery *FreeVM '"2389815"';
FeatureQuery *Product '"(Dataproducts LZR 1260)"';
Query Product '"(Dataproducts LZR 1260)"';
FeatureQuery *TTRasterizer Accept68K;
Query ADORamSize '"4194304"';
);
LaserWriter = (
include plain300;
font (
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Oblique,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
);
FeatureQuery *PSVersion '"(23.0) 0"';
FeatureQuery *FreeVM '"173936"';
FeatureQuery *Product '"(LaserWriter)"';
Query Product '"(LaserWriter)"';
Query ADORamSize '"2097152"';
);
"LaserWriter II NT" = (
include "LaserWriter Plus";
FeatureQuery *PSVersion '"(47.0) 1"';
FeatureQuery *FreeVM '"434204"';
FeatureQuery *Product '"(LaserWriter II NT)"';
Query Product '"(LaserWriter II NT)"';
FeatureQuery *TTRasterizer Accept68K;
);
"LaserWriter II NTX" = (
include "LaserWriter II NT";
FeatureQuery *PSVersion '"(47.0) 1"';
FeatureQuery *FreeVM '"433810"';
FeatureQuery *Product '"(LaserWriter II NTX)"';
Query Product '"(LaserWriter II NTX)"';
);
"LaserWriter IIf" = (
include "LaserWriter Plus";
FeatureQuery *ColorDevice Unknown;
FeatureQuery *LanguageLevel '"2"';
FeatureQuery *PSVersion '"(2010.113) 1"';
FeatureQuery *FreeVM '"2381689"';
FeatureQuery *TTRasterizer Type42;
FeatureQuery *Product '"(LaserWriter IIf)"';
Query Product '"(LaserWriter IIf)"';
Query ADORamSize '"8388608"';
);
"LaserWriter IIg" = (
include "LaserWriter IIf";
FeatureQuery *PSVersion '"(2010.130) 2"';
FeatureQuery *FreeVM '"2150107"';
FeatureQuery *Product '"(LaserWriter IIg)"';
Query Product '"(LaserWriter IIg)"';
);
"LaserWriter Plus" = (
include LaserWriter;
font (
AvantGarde-Book,
AvantGarde-BookOblique,
AvantGarde-Demi,
AvantGarde-DemiOblique,
Bookman-Demi,
Bookman-DemiItalic,
Bookman-Light,
Bookman-LightItalic,
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Narrow,
Helvetica-Narrow-Bold,
Helvetica-Narrow-BoldOblique,
Helvetica-Narrow-Oblique,
Helvetica-Oblique,
NewCenturySchlbk-Bold,
NewCenturySchlbk-BoldItalic,
NewCenturySchlbk-Italic,
NewCenturySchlbk-Roman,
Palatino-Bold,
Palatino-BoldItalic,
Palatino-Italic,
Palatino-Roman,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
ZapfChancery-MediumItalic,
ZapfDingbats,
);
FeatureQuery *PSVersion '"(42.2) 3"';
FeatureQuery *FreeVM '"172414"';
FeatureQuery *Product '"(LaserWriter Plus)"';
Query Product '"(LaserWriter Plus)"';
);
"LaserWriter Pro 630" = (
include "LaserWriter IIg";
FeatureQuery *PSVersion '"(2010.130) 1"';
FeatureQuery *FreeVM '"1698253"';
FeatureQuery *Product '"(LaserWriter Pro 630)"';
Query Product '"(LaserWriter Pro 630)"';
FeatureQuery *?Resolution 600dpi;
);
"PrintServer 20" = (
include "plain300";
FeatureQuery *PSVersion '"(48.3) 19"';
FeatureQuery *FreeVM '"964599"';
FeatureQuery *Product '"(PrintServer 20)"';
Query Product '"(PrintServer 20)"';
Query ADORamSize '"2621440"';
font (
AvantGarde-Book,
AvantGarde-BookOblique,
AvantGarde-Demi,
AvantGarde-DemiOblique,
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Oblique,
LubalinGraph-Book,
LubalinGraph-BookOblique,
LubalinGraph-Demi,
LubalinGraph-DemiOblique,
NewCenturySchlbk-Bold,
NewCenturySchlbk-BoldItalic,
NewCenturySchlbk-Italic,
NewCenturySchlbk-Roman,
Souvenir-Demi,
Souvenir-DemiItalic,
Souvenir-Light,
Souvenir-LightItalic,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
);
);
"QMS-PS 410" = (
include "LaserWriter Plus";
FeatureQuery *PSVersion '"(52.4) 94"';
FeatureQuery *FreeVM '"336596"';
FeatureQuery *Product '"(QMS-PS 410)"';
Query Product '"(QMS-PS 410)"';
font (
AGaramond-Bold,
AGaramond-BoldItalic,
AGaramond-Italic,
AGaramond-Regular,
AGaramond-Semibold,
AGaramond-SemiboldItalic,
AvantGarde-Book,
AvantGarde-BookOblique,
AvantGarde-Demi,
AvantGarde-DemiOblique,
Bookman-Demi,
Bookman-DemiItalic,
Bookman-Light,
Bookman-LightItalic,
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Condensed,
Helvetica-Condensed-Bold,
Helvetica-Condensed-BoldObl,
Helvetica-Condensed-Oblique,
Helvetica-Narrow,
Helvetica-Narrow-Bold,
Helvetica-Narrow-BoldOblique,
Helvetica-Narrow-Oblique,
Helvetica-Oblique,
NewCenturySchlbk-Bold,
NewCenturySchlbk-BoldItalic,
NewCenturySchlbk-Italic,
NewCenturySchlbk-Roman,
Palatino-Bold,
Palatino-BoldItalic,
Palatino-Italic,
Palatino-Roman,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
ZapfChancery-MediumItalic,
ZapfDingbats,
);
);
"Silentwriter 95" = (
include "LaserWriter IIg";
FeatureQuery *PSVersion '"(2010.121) 1"';
FeatureQuery *FreeVM '"251597"';
FeatureQuery *TTRasterizer None;
FeatureQuery *Product '"(Silentwriter 95)"';
Query Product '"(Silentwriter 95)"';
Query ADORamSize '"2097152"';
);
"Varityper" = (
include "LaserWriter Plus";
FeatureQuery *?Resolution 1270dpi;
FeatureQuery *PSVersion '"(52.3) 4.7"';
FeatureQuery *FreeVM '"2298400"';
FeatureQuery *Product '"(Varityper)"';
Query Product '"(Varityper)"';
FeatureQuery *ColorDevice Unknown;
Query ADORamSize '"16777212"';
);
"SPARCprinter" = (
include "LaserWriter Plus";
FeatureQuery *PSVersion '"(3.010) 0"';
FeatureQuery *FreeVM '"1147258"';
FeatureQuery *Product '"(NeWS Server)"';
Query Product '"(NeWS Server)"';
Query ADORamSize '"138936320"';
font (
AvantGarde-Book,
AvantGarde-BookOblique,
AvantGarde-Demi,
AvantGarde-DemiOblique,
Bembo,
Bembo-Bold,
Bembo-BoldItalic,
Bembo-Italic,
Bookman-Demi,
Bookman-DemiItalic,
Bookman-Light,
Bookman-LightItalic,
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
GillSans,
GillSans-Bold,
GillSans-BoldItalic,
GillSans-Italic,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Narrow,
Helvetica-Narrow-Bold,
Helvetica-Narrow-BoldOblique,
Helvetica-Narrow-Oblique,
Helvetica-Oblique,
LucidaBright,
LucidaBright-Demi,
LucidaBright-DemiItalic,
LucidaBright-Italic,
LucidaSans,
LucidaSans-Bold,
LucidaSans-BoldItalic,
LucidaSans-Italic,
LucidaSans-Typewriter,
LucidaSans-TypewriterBold,
NewCenturySchlbk-Bold,
NewCenturySchlbk-BoldItalic,
NewCenturySchlbk-Italic,
NewCenturySchlbk-Roman,
Palatino-Bold,
Palatino-BoldItalic,
Palatino-Italic,
Palatino-Roman,
Rockwell,
Rockwell-Bold,
Rockwell-BoldItalic,
Rockwell-Italic,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
ZapfChancery-MediumItalic,
ZapfDingbats,
);
);
"OKI ML801PS" = (
include "LaserWriter Plus";
FeatureQuery *PSVersion '"(52.3) 0"';
FeatureQuery *?Resolution 400dpi;
FeatureQuery *FreeVM '"3947324"';
FeatureQuery *TTRasterizer Accept68K;
FeatureQuery *Product '"(ML801PS)"';
Query Product '"(ML801PS)"';
Query ADORamSize '"8388608"';
font (
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Oblique,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
PCTimes-Roman,
PCHelvetica,
Mincho-PC-Hiragana,
Mincho-PC-Katakana,
NotDefFont,
Ryumin-Light-H,
Ryumin-Light-V,
Ryumin-Light-EUC-H,
Ryumin-Light-EUC-V,
Ryumin-Light-SuppA-H,
Ryumin-Light-SuppA-V,
Ryumin-Light-SuppB-HV,
Ryumin-Light-RKSJ-H,
Ryumin-Light-RKSJ-V,
Ryumin-Light-RKSJ-UserGaiji,
Ryumin-Light-83pv-SuppA-H,
Ryumin-Light-83pv-SuppB-H,
Ryumin-Light-83pv-RKSJ-H,
Ryumin-Light-NWP-H,
Ryumin-Light-NWP-V,
Ryumin-Light-Ext-H,
Ryumin-Light-Ext-V,
Ryumin-Light-Ext-SuppA-H,
Ryumin-Light-Ext-SuppA-V,
Ryumin-Light-Ext-SuppB-HV,
Ryumin-Light-Ext-RKSJ-H,
Ryumin-Light-Ext-RKSJ-V,
Ryumin-Light-Add-H,
Ryumin-Light-Add-V,
Ryumin-Light-Add-SuppA-H,
Ryumin-Light-Add-SuppA-V,
Ryumin-Light-Add-SuppB-HV,
Ryumin-Light-Add-RKSJ-H,
Ryumin-Light-Add-RKSJ-V,
GothicBBB-Medium-H,
GothicBBB-Medium-V,
GothicBBB-Medium-EUC-H,
GothicBBB-Medium-EUC-V,
GothicBBB-Medium-SuppA-H,
GothicBBB-Medium-SuppA-V,
GothicBBB-Medium-SuppB-HV,
GothicBBB-Medium-RKSJ-H,
GothicBBB-Medium-RKSJ-V,
GothicBBB-Medium-RKSJ-UserGaiji,
GothicBBB-Medium-83pv-SuppA-H,
GothicBBB-Medium-83pv-SuppB-H,
GothicBBB-Medium-83pv-RKSJ-H,
GothicBBB-Medium-NWP-H,
GothicBBB-Medium-NWP-V,
GothicBBB-Medium-Ext-H,
GothicBBB-Medium-Ext-V,
GothicBBB-Medium-Ext-SuppA-H,
GothicBBB-Medium-Ext-SuppA-V,
GothicBBB-Medium-Ext-SuppB-HV,
GothicBBB-Medium-Ext-RKSJ-H,
GothicBBB-Medium-Ext-RKSJ-V,
GothicBBB-Medium-Add-H,
GothicBBB-Medium-Add-V,
GothicBBB-Medium-Add-SuppA-H,
GothicBBB-Medium-Add-SuppA-V,
GothicBBB-Medium-Add-SuppB-HV,
GothicBBB-Medium-Add-RKSJ-H,
GothicBBB-Medium-Add-RKSJ-V,
Helvetica-Narrow,
Helvetica-Narrow-Bold,
Helvetica-Narrow-BoldOblique,
Helvetica-Narrow-Oblique,
Palatino-Bold,
Palatino-BoldItalic,
Palatino-Italic,
Palatino-Roman,
ZapfChancery-MediumItalic,
ZapfDingbats,
Bookman-Demi,
Bookman-DemiItalic,
Bookman-Light,
Bookman-LightItalic,
NewCenturySchlbk-Bold,
NewCenturySchlbk-BoldItalic,
NewCenturySchlbk-Italic,
NewCenturySchlbk-Roman,
AvantGarde-Book,
AvantGarde-BookOblique,
AvantGarde-Demi,
AvantGarde-DemiOblique,
);
);
"EPSON LP-9000PS2" = (
include "LaserWriter Plus";
FeatureQuery *PSVersion '"(2014.107) 1"';
FeatureQuery *?Resolution 600dpi;
FeatureQuery *FreeVM '"1880311"';
FeatureQuery *TTRasterizer Type42;
FeatureQuery *Product '"(EPSON LP-9000PS2)"';
Query Product '"(EPSON LP-9000PS2)"';
Query ADORamSize '"11534336"';
font (
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Oblique,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
PCTimes-Roman,
PCHelvetica,
Mincho-PC-Hiragana,
Mincho-PC-Katakana,
NotDefFont,
Ryumin-Light-H,
Ryumin-Light-V,
Ryumin-Light-EUC-H,
Ryumin-Light-EUC-V,
Ryumin-Light-SuppA-H,
Ryumin-Light-SuppA-V,
Ryumin-Light-SuppB-HV,
Ryumin-Light-RKSJ-H,
Ryumin-Light-RKSJ-V,
Ryumin-Light-RKSJ-UserGaiji,
Ryumin-Light-83pv-SuppA-H,
Ryumin-Light-83pv-SuppB-H,
Ryumin-Light-83pv-RKSJ-H,
Ryumin-Light-NWP-H,
Ryumin-Light-NWP-V,
Ryumin-Light-Ext-H,
Ryumin-Light-Ext-V,
Ryumin-Light-Ext-SuppA-H,
Ryumin-Light-Ext-SuppA-V,
Ryumin-Light-Ext-SuppB-HV,
Ryumin-Light-Ext-RKSJ-H,
Ryumin-Light-Ext-RKSJ-V,
Ryumin-Light-Add-H,
Ryumin-Light-Add-V,
Ryumin-Light-Add-SuppA-H,
Ryumin-Light-Add-SuppA-V,
Ryumin-Light-Add-SuppB-HV,
Ryumin-Light-Add-RKSJ-H,
Ryumin-Light-Add-RKSJ-V,
GothicBBB-Medium-H,
GothicBBB-Medium-V,
GothicBBB-Medium-EUC-H,
GothicBBB-Medium-EUC-V,
GothicBBB-Medium-SuppA-H,
GothicBBB-Medium-SuppA-V,
GothicBBB-Medium-SuppB-HV,
GothicBBB-Medium-RKSJ-H,
GothicBBB-Medium-RKSJ-V,
GothicBBB-Medium-RKSJ-UserGaiji,
GothicBBB-Medium-83pv-SuppA-H,
GothicBBB-Medium-83pv-SuppB-H,
GothicBBB-Medium-83pv-RKSJ-H,
GothicBBB-Medium-NWP-H,
GothicBBB-Medium-NWP-V,
GothicBBB-Medium-Ext-H,
GothicBBB-Medium-Ext-V,
GothicBBB-Medium-Ext-SuppA-H,
GothicBBB-Medium-Ext-SuppA-V,
GothicBBB-Medium-Ext-SuppB-HV,
GothicBBB-Medium-Ext-RKSJ-H,
GothicBBB-Medium-Ext-RKSJ-V,
GothicBBB-Medium-Add-H,
GothicBBB-Medium-Add-V,
GothicBBB-Medium-Add-SuppA-H,
GothicBBB-Medium-Add-SuppA-V,
GothicBBB-Medium-Add-SuppB-HV,
GothicBBB-Medium-Add-RKSJ-H,
GothicBBB-Medium-Add-RKSJ-V,
Helvetica-Narrow,
Helvetica-Narrow-Bold,
Helvetica-Narrow-BoldOblique,
Helvetica-Narrow-Oblique,
Palatino-Bold,
Palatino-BoldItalic,
Palatino-Italic,
Palatino-Roman,
ZapfChancery-MediumItalic,
ZapfDingbats,
Bookman-Demi,
Bookman-DemiItalic,
Bookman-Light,
Bookman-LightItalic,
NewCenturySchlbk-Bold,
NewCenturySchlbk-BoldItalic,
NewCenturySchlbk-Italic,
NewCenturySchlbk-Roman,
AvantGarde-Book,
AvantGarde-BookOblique,
AvantGarde-Demi,
AvantGarde-DemiOblique,
);
);

View File

@ -0,0 +1,18 @@
% Fonts returned by lsf for the LaserWriter
% AppleDict version 40
Times-Roman
Helvetica
Symbol
Courier-Bold
|______Seattle
Helvetica-Bold
Times-Bold
Courier-Oblique
Helvetica-BoldOblique
Times-Italic
Courier-BoldOblique
|______Courier
Courier
Helvetica-Oblique
Times-BoldItalic

View File

@ -0,0 +1,37 @@
NewCenturySchlbk-Italic
Bookman-LightItalic
Helvetica
Courier-Bold
Helvetica-Narrow-Bold
Courier-BoldOblique
Times-Italic
Times-Bold
NewCenturySchlbk-Roman
Helvetica-Narrow-Oblique
Bookman-DemiItalic
Symbol
Bookman-Demi
Helvetica-BoldOblique
Bookman-Light
Helvetica-Oblique
AvantGarde-Book
AvantGarde-DemiOblique
|______Seattle
AvantGarde-BookOblique
AvantGarde-Demi
|______Courier
Helvetica-Narrow
ZapfChancery-MediumItalic
|______Symbol
Courier-Oblique
NewCenturySchlbk-BoldItalic
Helvetica-Bold
Times-Roman
Times-BoldItalic
Helvetica-Narrow-BoldOblique
NewCenturySchlbk-Bold
Palatino-Bold
Courier
Palatino-Italic
Palatino-Roman
Palatino-BoldItalic

View File

@ -0,0 +1,38 @@
NewCenturySchlbk-Italic
Bookman-LightItalic
Helvetica
Courier-Bold
Helvetica-Narrow-Bold
Courier-BoldOblique
Times-Italic
Times-Bold
NewCenturySchlbk-Roman
Helvetica-Narrow-Oblique
Bookman-DemiItalic
Symbol
Bookman-Demi
Helvetica-BoldOblique
Bookman-Light
Helvetica-Oblique
AvantGarde-Book
AvantGarde-DemiOblique
|______Seattle
AvantGarde-BookOblique
AvantGarde-Demi
|______Courier
Helvetica-Narrow
ZapfChancery-MediumItalic
|______Symbol
Courier-Oblique
NewCenturySchlbk-BoldItalic
Helvetica-Bold
Times-Roman
Times-BoldItalic
Helvetica-Narrow-BoldOblique
NewCenturySchlbk-Bold
Palatino-Bold
Courier
Palatino-Italic
Palatino-Roman
Palatino-BoldItalic
ZapfDingbats

View File

@ -0,0 +1,144 @@
CFLAGS=cflags() specialcflags()
DESTDIR=capsrvrdestdir()
LWFLAGS=lwflags()
LIBCAP=libcap()
I=includedir()
YACC=yacc
LEX=lex
# Valid are: -DADOBE_DSC2_CONFORMANT
SIMPLEFLAGS=simpleflags()
LWSRVOBJS=fontlist.o lwsrv.o papstream.o procset.o simple.o spmisc.o
LWSRV8OBJS=fontlist8.o lwsrv8.o papstream8.o procset8.o simple8.o \
spmisc.o query.o list.o parse.o y.tab.o
LWSRVCONFIGOBJS=lwsrvconfig.o list.o packed.o parse.o y.tab.o
# for other libraries (like BSD on hpux)
SLIB=libspecial()
# lex library
LLIB= -ll
# make sure that you define point getopt to att_getopt.o if your system
# doesn't have it builtin
ATT_GETOPT=ifdef([needgetopt],[needgetopt])
all: lwsrv lwsrv8 lwsrvconfig
lwsrv: ${LWSRVOBJS} ${ATT_GETOPT}
${CC} -o lwsrv ${LFLAGS} ${LWSRVOBJS} ${ATT_GETOPT} ${LIBCAP} ${SLIB}
lwsrv8: ${LWSRV8OBJS} ${ATT_GETOPT}
${CC} -o lwsrv8 ${LFLAGS} ${LWSRV8OBJS} ${ATT_GETOPT} ${LIBCAP} \
${SLIB} ${LLIB}
lwsrvconfig: ${LWSRVCONFIGOBJS}
${CC} -o lwsrvconfig ${LFLAGS} ${LWSRVCONFIGOBJS} ${SLIB} ${LLIB}
clean:
-rm -f *.o lwsrv lwsrv8 lwsrvconfig att_getopt.c lex.yy.c y.tab.c
spotless:
-rm -f *.o *.orig lwsrv lwsrv8 lwsrvconfig att_getopt.c \
lex.yy.c y.tab.c Makefile makefile
install: lwsrv lwsrv8 lwsrvconfig
-strip lwsrv lwsrv8 lwsrvconfig
ifdef([sysvinstall],[install -f $(DESTDIR) lwsrv],
[${INSTALLER} lwsrv ${DESTDIR}])
ifdef([sysvinstall],[install -f $(DESTDIR) lwsrv8],
[${INSTALLER} lwsrv8 ${DESTDIR}])
ifdef([sysvinstall],[install -f $(DESTDIR) lwsrvconfig],
[${INSTALLER} lwsrvconfig ${DESTDIR}])
dist:
@cat todist
att_getopt.c:
ln -s ../../extras/att_getopt.c
simple.o: simple.c
${CC} ${CFLAGS} ${SIMPLEFLAGS} -c simple.c
lwsrv.o: lwsrv.c
${CC} ${CFLAGS} ${LWFLAGS} -c lwsrv.c
simple8.o: simple.c
${CC} -DLWSRV8 ${CFLAGS} ${SIMPLEFLAGS} -o simple8.o -c simple.c
lwsrv8.o: lwsrv.c
${CC} -DLWSRV8 ${CFLAGS} ${LWFLAGS} -o lwsrv8.o -c lwsrv.c
fontlist8.o: fontlist.c
${CC} -DLWSRV8 ${CFLAGS} ${LWFLAGS} -o fontlist8.o -c fontlist.c
papstream8.o: papstream.c
${CC} -DLWSRV8 ${CFLAGS} ${LWFLAGS} -o papstream8.o -c papstream.c
procset8.o: procset.c
${CC} -DLWSRV8 ${CFLAGS} ${LWFLAGS} -o procset8.o -c procset.c
lwsrvconfig.o: lwsrvconfig.c
${CC} ${CFLAGS} ${LWFLAGS} -c lwsrvconfig.c
y.tab.o: y.tab.c lex.yy.c
${CC} ${CFLAGS} ${LWFLAGS} -c y.tab.c
y.tab.c: parsey.y
${YACC} parsey.y
lex.yy.c: parsel.l
${LEX} parsel.l
query.o: query.c
${CC} ${CFLAGS} ${LWFLAGS} -c query.c
# Dependencies
lwsrv.o: lwsrv.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/compat.h papstream.h
lwsrv8.o: lwsrv.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/compat.h papstream.h fontlist.h \
list.h query.h parse.h procset.h
simple.o: simple.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
spmisc.h procset.h fontlist.h papstream.h
simple8.o: simple.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
spmisc.h procset.h fontlist.h papstream.h \
list.h query.h parse.h
fontlist.o: fontlist.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/sysvcompat.h fontlist.h \
spmisc.h papstream.h
fontlist8.o: fontlist.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/sysvcompat.h fontlist.h \
spmisc.h papstream.h list.h query.h parse.h
papstream.o: papstream.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/sysvcompat.h papstream.h
papstream8.o: papstream.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/sysvcompat.h papstream.h
procset.o: procset.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
procset.h spmisc.h
procset8.o: procset.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
procset.h spmisc.h list.h query.h
spmisc.o: spmisc.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
spmisc.h
query.o: query.c $I/netat/appletalk.h list.h query.h parse.h \
papstream.h
y.tab.c: parsey.y list.h parse.h
lwsrvconfig.o: lwsrvconfig.c list.h parse.h packed.h
parse.o: parse.c list.h parse.h
packed.o: packed.c packed.h

638
applications/lwsrv/README Normal file
View File

@ -0,0 +1,638 @@
cap60/applications/lwsrv/README
Last update:
Mon Aug 28 10:08:35 EST 1995
LWSRV is a LaserWriter print spooler that runs on a UNIX workstation.
In normal operation, LWSRV registers an NBP name (as specified by the -n
command line argument) of NBP type 'LaserWriter' on the local AppleTalk
Network. It accepts print jobs from Macintosh workstations and submits
them to the standard UNIX print queue (using lpr or lp) for printing.
A single LWSRV process may be used to advertise a number of LaserWriter
spoolers. LWSRV is also multi-threaded in that it accepts multiple
incoming print jobs.
This release of LWSRV builds as two versions, 'lwsrv' for use with
LaserWriter drivers version 7.N and earlier, and 'lwsrv8' for use with
LaserWriter drivers version 8.N and later that support level 3 DSC queries.
In some future release, 'lwsrv8' will replace the current 'lwsrv' which
is currently included for backward compatibility.
For more information, see:
cap60/man/lwsrv.8
cap60/man/papif.8
cap60/doc/print.cookbook
http://www.cs.mu.OZ.AU/appletalk/atalk.html
"Inside Appletalk, 2nd Edition", Sidhu/Andrews/Oppenheimer
Chapter 14, "Print Spooling Architecture".
Setting up
------- --
Before you can use LWSRV, you need to already have the ability to send
UNIX print jobs to a Postcript printer using the UNIX lpr(1) or lp(1)
print commands. You can do this with a serial-line connected printer,
or via the CAP 'papif' program to an AppleTalk connected LaserWriter
(see cap60/doc/print.cookbook or if on a Solaris host, use the script
cap60/applications/papif/add_at_printer).
The LWSRV program is normally started from the 'start-cap-servers' file
which is run at UNIX boot time by an 'rc' startup script. An example
file is provided in the CAP distribution as cap60/etc/start-cap-servers.
lwsrv for LaserWriter 7.N and below
----- --- ----------- --- --- -----
To use the 'lwsrv' program, you need to provide it with at least four,
usually five command-line arguments;
-n nameOfPrinter
-p unixPrintQueue
-a dictionaryDirectory
-f fontFile
The "nameOfPrinter" is the name to be advertised in the Macintosh Chooser.
It cannot be the same name as another LaserWriter or print spooler.
The "unixPrintQueue" is the string you normally provide as the lpr -P
option to send jobs to a Postscript printer.
"dictionaryDirectory" is a directory where LWSRV can keep copies of any
printer dictionaries (procsets) that it uploads. This would normally be
"/usr/local/lib/cap/procsets".
"fontFile" is the name of a file that lists the fonts available for the
printer. This would normally be "/usr/local/lib/cap/LWPlusFonts" which
you copy from cap60/applications/lwsrv/LWPlusFonts.
When using 'lwsrv' with System 7, you should also specify the -N option
which indicates to 'lwsrv' that it should not collect new Procsets.
There are other possible command line options, including the -k option to
prevent DDP checksums from breaking some printers, see cap60/man/lwsrv.8.
lwsrv8 for LaserWriter 8.N
------ --- ----------- ---
This is the version of LWSRV that supports level 3 DSC queries as used
by the Macintosh LaserWriter 8.N drivers.
'lwsrv8' also supports use of a configuration file which can contain
the normal command line options to LWSRV, answers for level 3 DSC
queries and a pointer to a library database of templates that describe
the features associated with each printer.
To set up 'lwsrv8', copy the file 'DBfile' to /usr/local/lib/cap, then
cd /usr/local/lib/cap
lwsrvconfig -c DB DBfile
mkdir procsets
This creates an ndbm(3) database of the printer descriptions available
in DBfile. If the printer you have is not included in DBfile, send
the Postscript file 'query.ps' to your printer, transcribe the printed
settings to DBFile and re-run 'lwsrvconfig'. See the 'lwsrvconfig'
description below.
You then need to edit the file "lwsrv.conf" to add your printer NBP
name, include an appropriate printer description and UNIX printer queue.
The following is an example of a simple "lwsrv.conf" configuration file
that contains an entry naming the library database, the 'lwsrv8' options
and the specification for spooler name and name of the UNIX print queue.
Library = /usr/local/lib/cap/DB;
Options = (
DontCollect;
ProcsetDir /usr/local/lib/cap/procsets;
FontFile /usr/local/lib/cap/LW+Fonts;
);
"Technical Services Spool" = (
include "LaserWriter IIf";
printerqueue lw.tsa;
);
This would be run as
lwsrv8 /usr/local/lib/cap/lwsrv.conf
and is approximately equivalent to running 'lwsrv' as
lwsrv -N -a /usr/local/lib/cap/procsets
-f /usr/local/lib/cap/LW+Fonts
-n "Technical Services Spool"
-p lw.tsa
The 'include "LaserWriter IIf"' entry includes information from the DB
database that describes features associated with the printer, in this
case a LaserWriter IIf. The DBfile entry for a IIf is
"LaserWriter IIf" = (
include "LaserWriter Plus";
FeatureQuery *ColorDevice Unknown;
FeatureQuery *LanguageLevel '"2"';
FeatureQuery *PSVersion '"(2010.113) 1"';
FeatureQuery *FreeVM '"2381689"';
FeatureQuery *TTRasterizer Type42;
FeatureQuery *Product '"(LaserWriter IIf)"';
Query ADORamSize '"8388608"';
);
Note that a base set of entries, including a font list, is included
from the "LaserWriter Plus" DBfile description.
There are some new compile time options for 'lwsrv8'. One new option is
-DJOBNOPAREN (append to CFLAGS in makefile). This option replaces any
parenthesis () in the job string with square brackets []. The only reason
for this if you have a spooler (like that for the DEC PrintServer 20)
that doesn't handle parenthesis very intelligently when printing the
job string on the banner page.
Another new compile time option is -DTIMESTAMP (append to LWFLAGS in
makefile). This puts a time stamp on log messages.
lwsrvconfig
-----------
The program 'lwsrvconfig' has two main uses. First, it is used to create
databases of templates, using the ndbm routines (if you don't have ndbm,
but do have the older dbm routines, use -DNONDBM).
% lwsrvconfig -c DB DBfile
will read the file "DBfile" and then create a set of dbm database DB.dat,
DB.dir and DB.pag (where the "DB" root in the name is the argument after
the -c).
Secondly, 'lwsrvconfig' can be used to scan configuration files for syntax
errors. 'lwsrvconfig' reads a configuration file and parses it the same
way as 'lwsrv8' does and reports any errors it finds. It outputs the
printer options to standard output. The -v option will, in addition,
output all templates used.
% lwsrvconfig lwsrv.conf
% lwsrvconfig -v lwsrv.conf
Terminology
-----------
Options are divided into two types. Global options pertain to all printers
spooled by a lwsrv process. Per-printer options usually pertain to each
particular printer spooled by a lwsrv process. Refer to the lwsrv.8 manual
entry for command line option details.
Global Option
Options Name
-C LPRCommand
-S Singlefork
-X AUFSSecurity
-d Debug
-l Logfile
-v Verbose
Per-Printer Option
Options Name
-A DSC
-L LPRArgument
-N NoCollect
-P PassThru
-R NeXTResolution
-T TranScriptOption
-a ProcsetDir
-e AllowEEXEC
-f FontFile
-h SuppressBanner
-k NoChecksum
-q QueryFile
-r KeepSpoolFile
-t TraceFile
Each 'lwsrv8' spooler is specified by a spooler name and a lpr printer name.
These correspond with the -n and -p options. Global options are those that
come before the first -n and -p options. The per-printer options come
after the -n and -p options, but before the next -n and -p set.
A per-printer option specified before the first -n and -p options becomes
global and so applies to all printers, unless overridden by on a per-printer
basis. A global option specified after the first -n and -p options still
has global scope. (Note: there is currently no way to turn off the effect
of a per-printer option used globally on a per-printer basis.)
Examples
--------
% lwsrv8 -S -n "My Spooler" -p lp2 -a myprocsets -f myfonts \
-n "Another Spooler" -p lp4 -a procset3 -f morefonts
The two spoolers have their own set of procset directories and font files.
The -S specifies singleforking for both spoolers.
% lwsrv8 -a procsets -f fonts -n "Jane's Spooler" -p janelp \
-n "John's Spooler" -p johnlp -f johnfonts -l logfile -T crtolf
The two spoolers share the same procset directory and would have shared the
same font file if "John's Spooler" had not overridden the font file using
"johnfonts". "John's Spooler" also specifies the -T crtolf option, whereas
"Jane's Spooler" does not. Even though -l logfile is specified for
"John's Spooler", since it is a global option, it still applies to both
spoolers.
Using a Configuration File
----- - ------------- ----
You can specify a configuration file which lwsrv uses for all its options:
% lwsrv lwsrv.conf [db]
where db is an optional library of templates (created by lwsrvconfig).
In the configuration file, statements have the following syntax:
Name = Value;
Statements with multiple values are included in parenthesis or curly brackets:
Name = (
Value1;
Value2 argument;
(etc...)
);
(The parser is free-form; indentation is used for readability only.)
Names, values and arguments can be quoted if they contain whitespace or other
special characters. Either single or double quotes can be used, especially
to quote the other kind:
Value '"Quoted Argument"';
Two single or double quotes in a row means a single occurrence of that
character:
Value John''s;
The configuration file is composed of three parts, of which only the last
part is required. The first (optional) part is the Library section, specified
with the "Library" keyword:
Library = DB;
If specified, the Library option specifies a library of templates (this is
overridden by the command line argument). In this example, DB is taken to
be the root of the ndbm files, DB.dat, DB.dir and DB.pag.
The second (option) part are the global options, specified with the "Options"
keyword:
Options = (
-S;
LogFile logfile;
);
Options can be either the commandline option (like -S) or the option name
(like SingleFork, matched case-insensitively).
The last part of the configuration file includes templates and printer
definitions. Here is the above examples in configuration file format:
Options = -S;
"My Spooler" = (
-p lp2;
-a myprocsets;
-f myfonts;
);
"Another Spooler" = (
-p lp4;
-a procset3;
-f morefonts;
);
Using option names for the second example:
Options = (
ProcsetDir procsets;
FontFile fonts;
);
"Jane's Spooler" = PrinterQueue janelp;
"John's Spooler" = (
PrinterQueue johnlp;
FontFile johnfonts;
LogFile logfile;
TranScriptOption crtolf;
);
These examples don't use templates, nor do they include the ability to
respond to LaserWriter 8.0 queries. Here is an example of both the use
of templates and queries:
Options = (
ProcsetDir procsets;
LogFile logfile;
);
"LaserWriter Plus" = (
Query ADOIsBinaryOK? True;
FeatureQuery *ColorDevice False;
FeatureQuery *FaxSupport None;
FeatureQuery *LanguageLevel '"1"';
FeatureQuery *TTRasterizer None;
Query ADOSpooler spooler;
FeatureQuery *?Resolution 300dpi;
FeatureQuery *PSVersion '"(42.2) 3"';
FeatureQuery *FreeVM '"172414"';
FeatureQuery *Product '"(LaserWriter Plus)"';
font (
AvantGarde-Book,
AvantGarde-BookOblique,
AvantGarde-Demi,
AvantGarde-DemiOblique,
Bookman-Demi,
Bookman-DemiItalic,
Bookman-Light,
Bookman-LightItalic,
Courier,
Courier-Bold,
Courier-BoldOblique,
Courier-Oblique,
Helvetica,
Helvetica-Bold,
Helvetica-BoldOblique,
Helvetica-Narrow,
Helvetica-Narrow-Bold,
Helvetica-Narrow-BoldOblique,
Helvetica-Narrow-Oblique,
Helvetica-Oblique,
NewCenturySchlbk-Bold,
NewCenturySchlbk-BoldItalic,
NewCenturySchlbk-Italic,
NewCenturySchlbk-Roman,
Palatino-Bold,
Palatino-BoldItalic,
Palatino-Italic,
Palatino-Roman,
Symbol,
Times-Bold,
Times-BoldItalic,
Times-Italic,
Times-Roman,
ZapfChancery-MediumItalic,
ZapfDingbats,
);
);
"My Spooler" = (
include "LaserWriter Plus";
printerqueue lp1;
);
"LaserWriter Plus" is a template, because it does not include a printerqueue
(-p) option, and so does not correspond to a real printer. Templates can
be included in the definition of a real printer (or another template) by
the use of the include keyword. Templates can be nested to any depth, and
can even be forward-referenced in the file (the scan is two pass in nature,
so forward references are taken care of).
Note that the "font" resource definition is used instead of
the FontFile option.
An important aspect of templates is that when a printer (or another template)
definition includes a template, the value structures in memory are actually
shared, thus saving on memory usage. When a value is overridden, a new
value structure is created in memory.
Note that printers can also be included, like any other template:
"My Trace Spooler" = (
include "My Spooler";
TraceFile TRACE;
);
The library file contains printer template definitions, which can be used
by a configuration file:
Library = DB;
Options = (
LogFile logfile;
ProcsetDir procsets;
);
"My Printer" = (
include "QMS-PS 410";
printerqueue qmslp;
);
"Another Printer" = (
include "LaserWriter IIg";
printerqueue lp5;
FeatureQuery *FreeVM '"3579932"';
Query ADORamSize '"5242880"';
);
Note that you can override queries, as in the above example, where "Another
Printer" has only 5 MB of memory instead of the 8 MB specified in the database.
Creating Templates
-------- ---------
There is a file, "query.ps", that contains PostScript code that will print
the answers to the LaserWriter 8.0 queries. Just send the file to the printer.
Or you can edit the query.ps file and remove the beginning section of the
file, so that the responses go to the printer's standard output and then
(usually) into the log file. This is especially useful if you have lots
of fonts.
Edit your database file (DBfile in the above examples, and as shipped with
this software), and add the next template. Then run lwsrvconfig to rebuild
the database:
% lwsrvconfig -c DB DBfile
Future Possibilities
------ -------------
lwsrvconfig could be made to build its database from a set of files in a
directory rather than a single file. This could make maintaining the database
a bit easier.
lwsrvconfig should have a option to dump the contents of the database into
a text format that can be used to recreate the database.
Summary of Changes from the Original lwsrv
------- -- ------- ---- --- -------- -----
Many existing routines, as well as all the new routines rely on a set of
functions provided in list.c. The List structure is a variable length list
of arbitrary objects. Normally, the order of objects in a List is significant,
or it can be sorted and a binary search can be used to search through the List.
The KVTree structure is an AVL (self-balancing, binary) tree of key-value pairs.
This is used for binary searching and replacement of key-values.
The printer_instance structure has been moved to query.h, and has been expanded
to allow many more options to be specified on a per-printer basis. Now only
the -X, -C, -S, -d, -v and -l options apply to all printers, while -T, -e, -N,
-r, -h, -k, -a, -f, -t, -A, -L, -P and -R are per-printer flags. The -n and -p
flags are used to specify a printer. When the other per-printer flags are
specified before the first -n or -p, they are taken as defaults values for all
subsequent printers. The per-printer options used after the -n and -p options
will override the default options.
lwsrv8 can be called without options as in:
lwsrv8 lwsrv.config [database]
where "lwsrv.config" is the name of a text file that contains configuration
information. This not only includes the normal options to lwsrv, but also
the answers to PostScript queries, as used in LaserWriter 8.0. For example,
the line:
FeatureQuery *ColorDevice False;
in "lwsrv.config" for a particular printer, causes the PostScript query:
%%?BeginFeatureQuery: *ColorDevice
(PostScript code...)
%%?EndFeatureQuery: Unknown
to be answered with "False". Resources (such as fonts, patterns, but not
procsets, since we still use the original lwsrv way of doing this, namely
to scan a specified directory for procset resources) can also be specified:
font = (
Times-Roman,
Times-Italics,
...
);
A template is a set of options and/or query responses, and may include other
templates and override values, but can not specify a Unix printer name (-p).
"LaserWriter Plus" = (
include LaserWriter;
FeatureQuery *Product '"LaserWriter Plus"';
...
);
A printer is like a template, but does include the Unix printer name.
"My Spooler" = (
include "LaserWriter IIg";
PrinterQueue lp;
...
);
Options can be entered using the original lwsrv option (like -p) or with a
case-insensitive name (like PrinterQueue).
The option second argument "database" is a ndbm (or dbm) database of templates
that will be used to satisfy unknown template references in the "config" file.
The database can also be specified in the configuration file itself, as the
first line:
Database db;
The reading of the configuration file and the building of the templates and
printers is handled by parse.c, parsey.y (yacc) and parsel.l (lex). There is
also an include file parse.h.
The program lwsrvconfig is designed to do several things. First, it reads a
configuration file the same way that lwsrv would, and can be used to detect
syntax errors and other problems (syntax error checking is primitive, as it
aborts on the first error). lwsrvconfig can also be used to create the ndbm
(or dbm) database of templates.
Set mode 0600 on normal temp file and 0644 on trace file.
Variable "tracing" set to true if we are doing tracing.
Tracing now includes responses sent back to client. These lines begin with
"--lwsrv=>".
scantoken() has been totally re-written, mainly to support binary data that
can be sent by LaserWriter 8.0, but also to make it more modular and efficient.
In addition, tokens are normally passed through (before, some were and some
were not passed through) so that better post-processing of the document
structure can be done.
tokval() was rewritten to do binary searching of the toktbl[] (it was a linear
search before).
The toktbl[] has been changed to include a variable called changeecho, which
tells scantoken() to either leave echoing the same (ECHO_UNCHANGED), turn
off echoing before dumping out the current token (ECHO_OFF) or turn on echoing
but after trying to dump out the current token (ECHO_ON).
A new flag -q specifies a file in which unknown queries are written. This can
show you when you haven't specified all the necessary queries for a printer,
should allow more easy updates to the query responses when future LaserWriter
driver come out.
NewStatus() now works even multi-forked. Status is written to a shared file
named .lwsrvstatusXXXXX, where XXXXX is the process id of the original server.
abpaps.c has been modified to provide a callback function when a status reply
or an open reply occur. The callback function for the status calls checks to
see if the requesting node is one with an open connection. If so, the status
is read from the shared file and returned. For all other nodes, the status
is either "idle" if there are no children running for that spooler, or
"processing job(s)" if it is. scantoken() was also changed so that NewStatus()
is called at the beginning of each page.
The open reply callback function is used for LWSRV_AUFS_SECURITY. Just as the
connection is to be opened, the callback does the usual LWSRV_AUFS_SECURITY
checks and returns an error message if it fails, or sets a boolean in the
aufssecurity array. The array is checked in the main loop, and the connection
closed if the appropriate flag is not set. (This has not been tested.)
childjob() was modified to set requname if LWSRV_AUFS_SECURITY is not set
and LWSRV_LPR_LOG is set (otherwise, requname is never set and the log
message contains <unknown> as the user).
unparen() is a routine that removes the leading left and trailing right
parenthesis from a string. This is used in getjob() to remove the parenthesis
in the %%For: and %%Title: fields, which LaserWriter 8.0 now adds. Without
this, RUN_AS_USER fails, since there isn't a user name with parenthesis.
If you define JOBNOPAREN, all (remaining) parenthesis are converted to
square brackets. This is useful for spooler that print the jobname on
the banner page, but don't handle parenthesis well (the DEC PrintServer 20
has problems with this, so changing to square brackets fixes the problem).
You can specify a printer specified denied access message (LWSRV_AUFS_SECURITY)
by specifying a "DeniedMessage" line in the configuration file:
printer = (
AUFSSecurity /tmp/xxx;
DeniedMessage "No can do from %s";
...
);
This string is passed through fprintf, with %s being replaced by the hostname.
(Note: you will need to escape percent signs by doubling %%.)
Now, when a child is forked, all other PAP connections are closed. Before,
one child would wait until another child was done, even if the children
were for different printers. Now the children act independently, as they
should.

View File

@ -0,0 +1,29 @@
%!
% fix.serial.ps
%
% This file changes the parity setting of a serially-connected PostScript
% printer to 8-bit, no parity, so that the upper 128 characters of a font
% (the special characters like bullets, diacritics, etc) will print and so
% binary data (usually color and gray-scale images produced by some programs)
% will also work.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Change the 0 below to match the system administrator password of the printer
% (zero is the default)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
serverdict begin 0 exitserver
statusdict begin
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Change the 25 below to 9 if you are using the 9-pin serial connector
% instead of the 25-pin.
%
% Change the 9600 below if needed to match the baud rate of the serial
% connection (see the printer's user manual for appropriate values).
%
% The 3 below specifies 8-bit, no parity.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 9600 3 setsccbatch
end

View File

@ -0,0 +1,150 @@
static char rcsid[] = "$Author: djh $ $Date: 1995/08/30 08:13:25 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/fontlist.c,v 2.3 1995/08/30 08:13:25 djh Rel djh $";
static char revision[] = "$Revision: 2.3 $";
/*
* fontlist - UNIX AppleTalk spooling program: act as a laserwriter
* handles simple font list - assumes we can place in a file
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
* Created Sept 5, 1987 by cck from lwsrv.
*
*
*/
#include <stdio.h>
#include <sys/time.h>
#include <sys/param.h>
#include <netat/appletalk.h>
#include <netat/sysvcompat.h>
#include <netat/compat.h>
#ifdef USESTRINGDOTH
# include <string.h>
#else /* USESTRINGDOTH */
# include <strings.h>
#endif /* USESTRINGDOTH */
#ifdef LWSRV8
#include "list.h"
#include "query.h"
#include "parse.h"
#endif /* LWSRV8 */
#include "fontlist.h"
#include "spmisc.h"
#include "papstream.h"
#ifndef LWSRV8
FontList *fontlist = (FontList *)NULL; /* fontlist header */
#endif /* not LWSRV8 */
#define FBMAX 100
extern char *myname;
#ifndef LWSRV8
boolean
#else /* LWSRV8 */
List *
#endif /* LWSRV8 */
LoadFontList(fn)
char *fn;
{
char fb[FBMAX];
#ifdef LWSRV8
register List *lp;
register FILE *ff;
register char *cp;
#else /* LWSRV8 */
FILE *ff;
FontList *fp = NULL;
if (fontlist) /* already loaded */
return(TRUE);
#endif /* LWSRV8 */
if ((ff = fopen(fn,"r")) == NULL)
#ifndef LWSRV8
return(FALSE);
#else /* LWSRV8 */
return(NULL);
lp = CreateList();
#endif /* LWSRV8 */
while (fgets(fb,FBMAX,ff) != NULL)
if (fb[0] != '%' && fb[0] != '\n') {
#ifndef LWSRV8
fp = (FontList *) malloc(sizeof(FontList));
fp->fl_name = (char *) malloc(strlen(fb)+1);
strcpy(fp->fl_name,fb);
fp->fl_next = fontlist;
fontlist = fp;
#else /* LWSRV8 */
if (cp = (char *)index(fb, '\n'))
*cp = '\0';
AddToList(lp, strdup(fb));
#endif /* LWSRV8 */
}
fclose(ff);
#ifndef LWSRV8
return(TRUE);
#else /* LWSRV8 */
SortList(lp, StringSortItemCmp);
return(lp);
#endif /* LWSRV8 */
}
#ifdef LWSRV8
private char newline[] = "\n";
private char star[] = "*\n";
#endif /* LWSRV8 */
void
SendFontList(pf)
PFILE *pf;
{
#ifndef LWSRV8
int i = 0;
FontList *fl = fontlist;
char status[255];
#else /* LWSRV8 */
register int i;
register char **ip;
register char *cp;
register List *fp;
char buf[256];
#endif /* LWSRV8 */
/* won't do much good unless single fork */
NewStatus("initializing fonts");
#ifndef LWSRV8
while (fl != NULL) {
i++;
p_write(pf,fl->fl_name,strlen(fl->fl_name),FALSE);
fl = fl->fl_next;
}
#else /* LWSRV8 */
if (fp = (List *)SearchKVTree(thequery, "font", strcmp)) {
cp = buf;
for (ip = (char **)AddrList(fp), i = NList(fp); i > 0; ip++, i--) {
strcpy(cp, *ip);
strcat(cp, newline);
p_write(pf,buf,strlen(buf),FALSE);
}
fprintf(stderr,"%s: Sending fontList: %d entries\n", myname, NList(fp));
}
#endif /* LWSRV8 */
#ifndef LWSRV8
p_write(pf,"*\n",strlen("*\n"),FALSE);
fprintf(stderr,"lwsrv: Sending fontList: %d entries\n",i);
sprintf(status,"receiving job");
NewStatus(status);
#else /* LWSRV8 */
p_write(pf,star,strlen(star),FALSE);
NewStatus("receiving job");
#endif /* LWSRV8 */
}

View File

@ -0,0 +1,30 @@
/* "$Author: djh $ $Date: 1995/08/28 11:10:14 $" */
/* "$Header: /mac/src/cap60/applications/lwsrv/RCS/fontlist.h,v 2.2 1995/08/28 11:10:14 djh Rel djh $" */
/* "$Revision: 2.2 $" */
/*
* fontlist - UNIX AppleTalk spooling program: act as a laserwriter
* handles simple font list - assumes we can place in a file
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986,1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* Created sept 5, 1987 by cck from lwsrv
*
*/
#ifndef LWSRV8
typedef struct Font_List { /* fontlist as read from fonts file */
struct Font_List *fl_next; /* pointer to next font name */
char *fl_name; /* the name itself */
} FontList;
boolean LoadFontList();
#else /* LWSRV8 */
List *LoadFontList();
#endif /* LWSRV8 */
void SendFontList();

373
applications/lwsrv/list.c Normal file
View File

@ -0,0 +1,373 @@
static char rcsid[] = "$Author: djh $ $Date: 1996/05/08 04:19:28 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/list.c,v 2.2 1996/05/08 04:19:28 djh Rel djh $";
static char revision[] = "$Revision: 2.2 $";
/*
* list.c - general list package-simple and key-value lists
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#include <stdio.h>
#include <netat/sysvcompat.h>
#ifdef USESTRINGDOTH
#include <string.h>
#else USESTRINGDOTH
#include <strings.h>
#endif USESTRINGDOTH
#include "list.h"
#define FALSE 0
#define TRUE 1
static int listcmp();
static void sendKVTree();
static int _AddToKVTree(/* KVTree **ent, void *key, void *val,
int (*keycmp)() */);
static KVTree *_DupKVTree(/* KVTree *lf */);
static void _FreeKVTree(/* KVTree *lp, int (*keyfree)(), int (*valfree)() */);
static void _ListKVTree(/* KVTree *kp, List *lp */);
static void *_SearchKVTree(/* KVTree *lp, void *key, int (*keycmp)() */);
char *malloc();
char *realloc();
void
AddToKVTree(ent, key, val, keycmp)
KVTree **ent;
void *key, *val;
int (*keycmp)();
{
_AddToKVTree(ent, key, val, keycmp);
}
/*
* Modified from "Algorithms + Data Structures = Programs", Niklaus Wirth,
* 1976, section 4.4.7 Balanced Tree Insertion, page 220-221 (AVL).
*
*/
#define L_EQUILIBRATED 2
#define LEFTSLANTED 1
#define L_REBALANCE 0
#define R_EQUILIBRATED 0
#define RIGHTSLANTED 1
#define R_REBALANCE 2
static int
_AddToKVTree(ent, key, val, keycmp)
register KVTree **ent;
void *key, *val;
int (*keycmp)();
{
register KVTree *ent1, *ent2;
register int cmp;
char *malloc();
if (*ent == NULL) { /* not in tree, insert it */
if ((*ent = (KVTree *)malloc(sizeof(KVTree))) == NULL)
errorexit(1, "_AddToKVTree: Out of memory\n");
(*ent)->left = (*ent)->right = NULL;
(*ent)->bal = LEFTSLANTED;
(*ent)->key = key;
(*ent)->val = val;
return(1);
}
if ((cmp = (*keycmp)(key, (*ent)->key)) == 0) { /* match */
(*ent)->val = val;
return(0);
}
if (cmp < 0) {
if (!_AddToKVTree(&(*ent)->left, key, val, keycmp))
return(0);
/* left branch has grown higher */
switch((*ent)->bal) {
case L_EQUILIBRATED:
(*ent)->bal = LEFTSLANTED;
return(0);
case LEFTSLANTED:
(*ent)->bal = L_REBALANCE;
return(1);
case L_REBALANCE: /* rebalance */
if ((ent1 = (*ent)->left)->bal == L_REBALANCE) {
/* single LL rotation */
(*ent)->left = ent1->right;
ent1->right = *ent;
(*ent)->bal = LEFTSLANTED;
*ent = ent1;
} else {
/* double LR rotation */
ent2 = ent1->right;
ent1->right = ent2->left;
ent2->left = ent1;
(*ent)->left = ent2->right;
ent2->right = *ent;
(*ent)->bal = (ent2->bal == L_REBALANCE) ? L_EQUILIBRATED : LEFTSLANTED;
ent1->bal = (ent2->bal == L_EQUILIBRATED) ? L_REBALANCE : LEFTSLANTED;
*ent = ent2;
}
(*ent)->bal = LEFTSLANTED;
return(0);
}
}
if (!_AddToKVTree(&(*ent)->right, key, val, keycmp))
return(0);
/* right branch has grown higher */
switch((*ent)->bal) {
case R_EQUILIBRATED:
(*ent)->bal = RIGHTSLANTED;
return(0);
case RIGHTSLANTED:
(*ent)->bal = R_REBALANCE;
return(1);
case R_REBALANCE: /* rebalance */
if ((ent1 = (*ent)->right)->bal == R_REBALANCE) {
/* single RR rotation */
(*ent)->right = ent1->left;
ent1->left = *ent;
(*ent)->bal = RIGHTSLANTED;
*ent = ent1;
} else {
/* double RL rotation */
ent2 = ent1->left;
ent1->left = ent2->right;
ent2->right = ent1;
(*ent)->right = ent2->left;
ent2->left = *ent;
(*ent)->bal = (ent2->bal == R_REBALANCE) ? R_EQUILIBRATED : RIGHTSLANTED;
ent1->bal = (ent2->bal == R_EQUILIBRATED) ? R_REBALANCE : RIGHTSLANTED;
*ent = ent2;
}
(*ent)->bal = RIGHTSLANTED;
return(0);
}
}
void
AddToList(lp, item)
register List *lp;
void *item;
{
if (lp->n >= lp->lmax && (lp->list = (void **)realloc((char *)lp->list,
(lp->lmax += LISTDELTA) * sizeof(void *))) == NULL)
errorexit(1, "AddToList: Out of memory\n");
lp->list[lp->n++] = item;
}
KVTree **
CreateKVTree()
{
register KVTree **kp;
if ((kp = (KVTree **)malloc(sizeof(KVTree *))) == NULL)
errorexit(1, "AddToKVTree: Out of memory\n");
*kp = NULL;
return(kp);
}
void
CatList(to, from)
register List *to;
List *from;
{
register int n;
register void **vp;
for (n = from->n, vp = from->list; n > 0; n--)
AddToList(to, *vp++);
}
List *
CreateList()
{
register List *lp;
static char errstr[] = "CreateList: Out of memory\n";
if ((lp = (List *)malloc(sizeof(List))) == NULL)
errorexit(1, errstr);
if ((lp->list = (void **)malloc((lp->lmax = LISTDELTA) * sizeof(void *)))
== NULL)
errorexit(2, errstr);
lp->n = 0;
return(lp);
}
KVTree **
DupKVTree(lf)
register KVTree **lf;
{
register KVTree **kp;
if ((kp = (KVTree **)malloc(sizeof(KVTree *))) == NULL)
errorexit(1, "DupKVTree: Out of memory\n");
*kp = *lf ? _DupKVTree(*lf) : NULL;
return(kp);
}
static KVTree *
_DupKVTree(lf)
register KVTree *lf;
{
register KVTree *lt;
if ((lt = (KVTree *)malloc(sizeof(KVTree))) == NULL)
errorexit(1, "_DupKVTree: Out of memory\n");
lt->bal = lf->bal;
lt->key = lf->key;
lt->val = lf->val;
lt->left = lf->left ? _DupKVTree(lf->left) : NULL;
lt->right = lf->right ? _DupKVTree(lf->right) : NULL;
return(lt);
}
List *
DupList(lf)
register List *lf;
{
register List *lt;
register void **vp;
register int i;
lt = CreateList();
for (i = lf->n, vp = lf->list; i > 0; i--)
AddToList(lt, *vp++);
return(lt);
}
void
FreeKVTree(lp, keyfree, valfree)
KVTree **lp;
int (*keyfree)(), (*valfree)();
{
if (*lp)
_FreeKVTree(*lp, keyfree, valfree);
free((char *)lp);
}
static void
_FreeKVTree(lp, keyfree, valfree)
register KVTree *lp;
int (*keyfree)(), (*valfree)();
{
if (lp->left)
_FreeKVTree(lp->left, keyfree, valfree);
if (lp->right)
_FreeKVTree(lp->right, keyfree, valfree);
if (keyfree)
(*keyfree)(lp->key);
if (valfree)
(*valfree)(lp->val);
free((char *)lp);
}
void
FreeList(lp, itemfree)
List *lp;
int (*itemfree)();
{
register void **vp;
register int i;
if (itemfree)
for (i = lp->n, vp = lp->list; i > 0; i--)
(*itemfree)(*vp++);
free((char *)lp->list);
free((char *)lp);
}
List *
ListKVTree(kp)
KVTree **kp;
{
register List *lp;
lp = CreateList();
if (*kp)
_ListKVTree(*kp, lp);
return(lp);
}
static void
_ListKVTree(kp, lp)
register KVTree *kp;
register List *lp;
{
if (kp->left)
_ListKVTree(kp->left, lp);
AddToList(lp, kp);
if (kp->right)
_ListKVTree(kp->right, lp);
}
void *
SearchKVTree(lp, key, keycmp)
KVTree **lp;
void *key;
int (*keycmp)();
{
return(*lp ? _SearchKVTree(*lp, key, keycmp) : NULL);
}
static void *
_SearchKVTree(lp, key, keycmp)
KVTree *lp;
register void *key;
int (*keycmp)();
{
register int cmp;
if ((cmp = (*keycmp)(key, lp->key)) == 0)
return(lp->val);
if (cmp > 0)
return(lp->right ? _SearchKVTree(lp->right, key, keycmp) : NULL);
else
return(lp->left ? _SearchKVTree(lp->left, key, keycmp) : NULL);
}
void *
SearchList(lp, item, itemcmp)
register List *lp;
register void *item;
int (*itemcmp)();
{
register void **ip = lp->list;
register int i, low, high, cmp;
low = 0;
high = lp->n - 1;
while (low <= high) {
i = (low + high) / 2;
if ((cmp = (*itemcmp)(ip[i], item)) == 0)
return(ip[i]);
if (cmp > 0)
high = i - 1;
else
low = i + 1;
}
return(NULL);
}
void
SortList(lp, itemcmp)
register List *lp;
int (*itemcmp)();
{
qsort((char *)lp->list, lp->n, sizeof(void *), itemcmp);
}
int
StringSortItemCmp(a, b)
char **a, **b;
{
return(strcmp(*a, *b));
}
errorexit(status, str)
int status;
char *str;
{
fputs(str, stderr);
exit(status);
}

49
applications/lwsrv/list.h Normal file
View File

@ -0,0 +1,49 @@
/* "$Author: djh $ $Date: 1995/08/28 10:38:35 $" */
/* "$Header: /mac/src/cap60/applications/lwsrv/RCS/list.h,v 2.1 1995/08/28 10:38:35 djh Rel djh $" */
/* "$Revision: 2.1 $" */
/*
* list.h - general list package-simple and key-value lists
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#ifndef _LIST_H_
#define _LIST_H_
#define LISTDELTA 10
typedef struct KVTree {
struct KVTree *left;
struct KVTree *right;
void *key;
void *val;
unsigned char bal; /* for AVL tree balancing */
} KVTree;
typedef struct List {
int n;
int lmax;
void **list;
} List;
#define AddrList(lp) (((List *)(lp))->list)
#define NList(lp) (((List *)(lp))->n)
void AddToKVTree(/* KVTree **lp, void *key, void *val, int (*keycmp)() */);
void AddToList(/* List *lp, void *item */);
void CatList(/* List *to, List *from */);
KVTree **CreateKVTree();
List *CreateList();
KVTree **DupKVTree(/* KVTree **lf */);
List *DupList(/* List *lf */);
void FreeKVTree(/* KVTree **lp, int (*keyfree)(), int (*valfree)() */);
void FreeList(/* List *lp, int (*itemfree)() */);
List *ListKVTree(/* KVTree **kp */);
void *SearchKVTree(/* KVTree **lp, void *key, int (*keycmp)() */);
void *SearchList(/* List *lp, void *item, int (*itemcmp)() */);
void SortList(/* List *lp, int (*itemcmp)() */);
int StringSortItemCmp(/* char **a, char **b */);
#endif /* _LIST_H_ */

2765
applications/lwsrv/lwsrv.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
Library = DB;
Options = (
DontCollect;
ProcsetDir /usr/local/lib/cap/procsets;
FontFile /usr/local/lib/cap/LW+Fonts;
);
"Technical Services Spool Test" = (
include "LaserWriter IIf";
printerqueue lw.tsa;
);

View File

@ -0,0 +1,710 @@
static char rcsid[] = "$Author: djh $ $Date: 1996/09/10 14:33:00 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/lwsrvconfig.c,v 2.3 1996/09/10 14:33:00 djh Rel djh $";
static char revision[] = "$Revision: 2.3 $";
/*
* lwsrvconfig - auxiliary program for testing configuration files
* and creating printer description databases
*
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/file.h>
#include <netat/appletalk.h>
#include <netat/sysvcompat.h>
#include <netat/compat.h>
#ifdef USESTRINGDOTH
# include <string.h>
#else /* USESTRINGDOTH */
# include <strings.h>
#endif /* USESTRINGDOTH */
#ifdef NEEDFCNTLDOTH
# include <sys/fcntl.h>
#endif NEEDFCNTLDOTH
#ifndef NONDBM
# include <ndbm.h>
#else NONDBM
# include <dbm.h>
#endif NONDBM
#include "list.h"
#include "packed.h"
#include "parse.h"
char *myname;
#define F_GLOBAL (1 << F_GLOBAL_BIT)
#define F_GLOBAL_BIT 0
#define F_HASARG (1 << F_HASARG_BIT)
#define F_HASARG_BIT 1
#define hasarg(f) ((f) & F_HASARG)
#define isglobal(f) ((f) & F_GLOBAL)
#define sf(a,g) (((a) << F_HASARG_BIT) | ((g) << F_GLOBAL_BIT))
struct descrip {
char *name;
short flags;
};
static KVTree **argname;
static struct argnamebuf {
char *arg;
struct descrip d;
} argnamebuf[] = {
{"-A", {"DSC", sf(1, 0)}},
{"-C", {"LPRCommand", sf(1, 1)}},
#ifdef LPRARGS
{"-L", {"LPRArgument", sf(1, 0)}},
#endif LPRARGS
{"-N", {"DontCollect", sf(0, 0)}},
#ifdef PASS_THRU
{"-P", {"PassThru", sf(0, 0)}},
#endif PASS_THRU
#ifdef NeXT
{"-R", {"NeXTResolution", sf(1, 0)}},
#endif NeXT
{"-S", {"SingleFork", sf(0, 1)}},
{"-T", {"TranScriptOption", sf(1, 0)}},
#ifdef LWSRV_AUFS_SECURITY
{"-X", {"AUFSSecurity", sf(1, 1)}},
#endif LWSRV_AUFS_SECURITY
#ifdef LW_TYPE
{"-Y", {"AppleTalkType", sf(1, 0)}},
#endif LW_TYPE
{"-a", {"ProcsetDir", sf(1, 0)}},
{"-d", {"Debug", sf(1, 1)}},
{"-e", {"Alloweexec", sf(0, 0)}},
{"-f", {"FontFile", sf(1, 0)}},
{"-h", {"SuppressBanner", sf(0, 0)}},
{"-k", {"NoChecksum", sf(0, 0)}},
{"-l", {"LogFile", sf(1, 1)}},
{"-p", {"PrinterQueue", sf(1, 0)}},
{"-q", {"QueryFile", sf(1, 1)}},
{"-r", {"KeepSpoolFile", sf(0, 0)}},
{"-t", {"TraceFile", sf(1, 0)}},
{"-v", {"Verbose", sf(0, 1)}},
{NULL, NULL},
};
static char *createdb = NULL;
static int datafd;
long dataoffset = 0;
#ifndef NONDBM
static DBM *db;
#endif NONDBM
static char *dbname = NULL;
static KVTree **_default;
static int firstargs = 1;
static int firstprinter = 1;
static char firsttime[127];
static char *headerstr = NULL;
static char null[] = "";
static int oldformat = 0;
static char *printername;
static int verbose = 0;
int doargs();
static void addback(/* int argc, char **argv */);
static void display(/* char *str, KVTree **kp */);
static void displaytemplates();
static void docreatedb();
static KVTree **initargname();
static int getflags(/* char *str */);
static char *keyname(/* char *str */);
static char *quotestr(/* char *str */);
static void setfirsttime(/* char *str */);
static void storedata(/* char *name, int n, char *ptr, int size */);
static unshort *ushortdup(/* int i */);
static char *untab(/* char *str */);
static void usage();
main(argc, argv)
int argc;
char **argv;
{
register int c;
register KVTree **kp;
register List *lp;
register FILE *fp;
extern FILE *yyin;
extern char *optarg;
extern int optind;
if (myname = rindex(*argv, '/'))
myname++;
else
myname = *argv;
while ((c = getopt(argc, argv, "c:l:ov?")) != EOF) {
switch(c) {
case 'c':
createdb = optarg;
break;
case 'l':
dbname = optarg;
break;
case 'o':
oldformat++;
break;
case 'v':
verbose++;
break;
case '?':
default:
usage();
}
}
if (createdb && dbname)
usage();
if (optind < argc) {
if ((argc - optind) > 1)
usage();
if ((fp = fopen(argv[optind], "r")) == NULL) {
fprintf(stderr, "%s: Can't open %s\n", myname, argv[optind]);
exit(1);
}
} else
fp = stdin;
yyin = fp; /* set for flex(1) */
argname = initargname();
initkeyword(fp);
umask(0133);
if (yyparse())
exit(1);
if (!dbname && libraryfile)
dbname = libraryfile;
if (createdb)
docreatedb();
else {
_default = thequery = CreateKVTree();
setfirsttime(specialOpts);
configargs(dbname);
}
exit(0);
}
static void
addback(argc, argv)
register int argc;
register char **argv;
{
register void *n;
register List *lp;
register int f;
while (argc-- > 0) {
f = getflags(*argv);
if (hasarg(f)) {
n = (void *)*argv++;
if (isSpecialOpt(n)) {
if (firsttime[Option(n)]) {
firsttime[Option(n)] = 0;
if (lp = (List *)SearchKVTree(thequery, n, strcmp)) {
if (thequery == _default) {
AddToList(lp, (void *)*argv);
} else {
lp = DupList(lp);
AddToList(lp, (void *)*argv);
AddToKVTree(thequery, n, (void *)lp, strcmp);
}
} else {
lp = CreateList();
AddToList(lp, (void *)*argv);
AddToKVTree(thequery, n, (void *)lp, strcmp);
}
} else {
lp = (List *)SearchKVTree(thequery, n, strcmp);
AddToList(lp, (void *)*argv);
}
} else
AddToKVTree(thequery, n, (void *)*argv, strcmp);
argv++;
argc--;
} else
AddToKVTree(thequery, (void *)*argv++, NULL, strcmp);
}
}
/*
* doargs would normally set the arguments in lwsrv. We intercept this
* to do our printing.
*/
doargs(argc, argv)
int argc;
char **argv;
{
register int n, i, f;
register char **a;
argc--;
argv++;
if (firstargs && strcmp(*argv, "-n") != 0) { /* options */
firstargs = 0;
if (verbose) {
addback(argc, argv);
display("Options", thequery);
} else {
n = argc;
a = argv;
i = 0;
while (n-- > 0) {
f = getflags(*a);
if (isglobal(f))
i++;
if (hasarg(f)) {
a++;
n--;
}
a++;
}
if (i > 0) {
printf("Options = %s", i > 1 ? "(\n" : null);
n = argc;
a = argv;
while (n-- > 0) {
f = getflags(*a);
if (isglobal(f)) {
printf("%s%s", i > 1 ? "\t" : null, keyname(*a));
if (hasarg(f)) {
printf(" %s;\n", quotestr(*++a));
n--;
} else
fputs(";\n", stdout);
if (i == 1)
break;
} else {
if (hasarg(f)) {
a++;
n--;
}
}
a++;
}
if (i > 1)
fputs(");\n\n", stdout);
else
putchar('\n');
}
addback(argc, argv);
}
} else if (strcmp(*argv, "-n") == 0) {
/* setup thequery so setargs will insert the queries in the right one */
firstargs = 0;
if (thequery != _default)
FreeKVTree(thequery, NULL, NULL);
thequery = DupKVTree(_default);
if (verbose && firstprinter) { /* print the templates */
firstprinter = 0;
displaytemplates();
}
setfirsttime(specialOpts);
printername = *++argv;
} else { /* actually do the printer */
addback(argc, argv);
display(printername, thequery);
}
}
static void
docreatedb()
{
register KVTree **keys;
register PackedChar *ckeys;
register PackedChar *pc;
register PackedShort *ps;
register void **v2, **v3, **vp;
register int i, j, k;
register unshort *sp, *sp2;
register char *name;
char buf[BUFSIZ];
if (verbose)
printf("Creating database %s\n", createdb);
strcpy(buf, createdb);
strcat(buf, ".dir");
unlink(buf);
strcpy(buf, createdb);
strcat(buf, ".pag");
unlink(buf);
#ifndef NONDBM
if ((db = dbm_open(createdb, O_RDWR | O_CREAT, 0755)) == NULL) {
fprintf(stderr, "%s: Can't create database %s\n", myname, createdb);
exit(1);
}
#else NONDBM
if ((i = creat(buf, 0755)) < 0) {
fprintf(stderr, "%s: Can't create %s\n", myname, buf);
exit(1);
}
if ((i = creat(buf, 0755)) < 0) {
fprintf(stderr, "%s: Can't create %s\n", myname, buf);
exit(1);
}
if (dbminit(creatdb) < 0) {
fprintf(stderr, "%s: Can't open database %s\n", myname, createdb);
exit(1);
}
#endif NONDBM
strcpy(buf, createdb);
strcat(buf, datasuffix);
unlink(buf);
if ((datafd = open(buf, O_WRONLY | O_CREAT, 0755)) < 0) {
fprintf(stderr, "%s: Can't create %s\n", myname, buf);
exit(1);
}
keys = CreateKVTree();
ckeys = CreatePackedChar();
for (i = NList(printerlist), vp = AddrList(printerlist); i > 0; i -= 2) {
name = (char *)*vp++;
if (verbose)
printf("\tCreating template %s\n", name);
pc = CreatePackedChar();
/*
* Since a zero means the a string value is null, we "use up"
* the zero so that it can never occur in our data (except to mean
* that the string is NULL
*/
AddToPackedChar(pc, null);
ps = CreatePackedShort();
AddToPackedShort(ps, (j = NList(*vp) / 2));
sp = AllocatePackedShort(ps, 2 * j);
for (v2 = AddrList(*vp); j > 0; j--) {
if (verbose)
printf("\t\tAdding keyword %s\n", untab((char *)*v2));
if ((sp2 = (unshort *)SearchKVTree(keys, *v2, strcmp)) == NULL) {
k = AddToPackedChar(ckeys, (char *)*v2);
sp2 = ushortdup(k);
AddToKVTree(keys, *v2, (void *)sp2, strcmp);
}
*sp++ = *sp2;
if (StringVal(*v2)) {
v2++;
*sp++ = *v2 ? AddToPackedChar(pc, (char *)*v2) : 0;
} else {
v2++;
k = NList(*v2);
*sp++ = AddToPackedShort(ps, k);
for (v3 = AddrList(*v2); k > 0; k--)
AddToPackedShort(ps, AddToPackedChar(pc, (char *)*v3++));
}
v2++;
}
j = (NPackedShort(ps) + 1) * sizeof(unshort);
k = NPackedChar(pc) * sizeof(char);
if ((sp = (unshort *)malloc(j + k)) == NULL)
errorexit(1, "docreatedb: Out of memory\n");
*sp = j;
bcopy((char *)AddrPackedShort(ps), (char *)(sp + 1),
NPackedShort(ps) * sizeof(unshort));
bcopy((char *)AddrPackedChar(pc), (char *)sp + j, k);
storedata(name, strlen(name), (char *)sp, j + k);
vp++;
}
if (verbose)
printf("Adding keywords to database %s\n", createdb);
storedata(keywords_key, KEYWORDSKEYSIZE, AddrPackedChar(ckeys),
NPackedChar(ckeys) * sizeof(char), db);
#ifndef NONDBM
dbm_close(db);
if (verbose)
printf("Closing database %s\n", createdb);
#else NONDBM
/*
* There does not seem to be a way to close the old dbm file!
*/
#endif NONDBM
}
static void
storedata(name, n, ptr, size)
char *name;
register int n;
register char *ptr;
register int size;
{
register char *cp;
datum key, data;
Location loc;
key.dptr = name;
key.dsize = n;
loc.magic = MagicNumber; /* to identify a real lwsrvconfig database */
loc.offset = dataoffset;
loc.size = size;
data.dptr = (char *)&loc;
data.dsize = sizeof(Location);
#ifndef NONDBM
if (dbm_store(db, key, data, DBM_REPLACE) < 0) {
fprintf(stderr, "%s: Failed to insert %s into database %s \n", myname,
name, createdb);
exit(1);
}
#else NONDBM
if (store(key, data) < 0) {
fprintf(stderr, "%s: Failed to insert %s into database %s \n", myname,
name, createdb);
exit(1);
}
#endif NONDBM
dataoffset += size;
while (size > 0) {
if ((n = write(datafd, ptr, size)) <= 0) {
fprintf(stderr, "%s: write error on %d%s\n", myname, createdb,
datasuffix);
exit(1);
}
size -= n;
ptr += n;
}
}
static void
display(name, kp)
char *name;
register KVTree **kp;
{
register List *lp;
register char **cp;
register int n, i;
lp = ListKVTree(kp);
if (headerstr) {
fputs(headerstr, stdout);
headerstr = NULL;
}
printf("%s = ", quotestr(name));
kp = (KVTree **)AddrList(lp);
if ((n = NList(lp)) == 1) {
fputs(untab((char *)(*kp)->key), stdout);
if (ListVal((*kp)->key)) {
cp = (char **)AddrList((*kp)->val);
if ((i = NList((*kp)->val)) == 1)
printf(" %s;\n", quotestr(*cp));
else if (isSpecialOpt((*kp)->key)) {
printf(" %s;\n", quotestr(*cp));
while (--i > 0) {
fputs(untab((char *)(*kp)->key), stdout);
printf(" %s;\n", quotestr(*++cp));
}
} else {
fputs(" (\n", stdout);
while (i--) {
printf("\t%s,\n", quotestr(*cp));
cp++;
}
fputs(");\n", stdout);
}
} else {
if ((*kp)->val)
printf(" %s;\n", quotestr((char *)(*kp)->val));
else
fputs(";\n", stdout);
}
} else {
fputs("(\n", stdout);
for (;n-- > 0; kp++) {
printf("\t%s", untab((char *)(*kp)->key));
if (ListVal((*kp)->key)) {
cp = (char **)AddrList((*kp)->val);
if ((i = NList((*kp)->val)) == 1)
printf(" %s;\n", quotestr(*cp));
else if (isSpecialOpt((*kp)->key)) {
printf(" %s;\n", quotestr(*cp));
while (--i > 0) {
printf("\t%s", untab((char *)(*kp)->key));
printf(" %s;\n", quotestr(*++cp));
}
} else {
fputs(" (\n", stdout);
while (i--) {
printf("\t\t%s,\n", quotestr(*cp));
cp++;
}
fputs("\t);\n", stdout);
}
} else {
if ((*kp)->val)
printf(" %s;\n", quotestr((char *)(*kp)->val));
else
fputs(";\n", stdout);
}
}
fputs(");\n", stdout);
}
}
static void
displaytemplates()
{
register List *lp;
register KVTree **kp;
register int n;
lp = ListKVTree(_printers);
headerstr = "\nTemplates:\n";
for (kp = (KVTree **)AddrList(lp), n = NList(lp); n > 0; kp++, n--) {
if (SearchKVTree((*kp)->val, "-p", strcmp) == NULL)
display((*kp)->key, (*kp)->val, 0);
}
headerstr = "\nPrinters:\n";
FreeList(lp, NULL);
}
static KVTree **
initargname()
{
register KVTree **kp;
register struct argnamebuf *ap;
kp = CreateKVTree();
for (ap = argnamebuf; ap->arg; ap++)
AddToKVTree(kp, (void *)ap->arg, (void *)&ap->d, strcmp);
return(kp);
}
static int
getflags(str)
char *str;
{
register struct descrip *sp;
if ((sp = (struct descrip *)SearchKVTree(argname, str, strcmp)) == NULL) {
fprintf(stderr, "%s: Unknown lwsrv argument %s\n", myname, str);
exit(1);
}
return(sp->flags);
}
static char *
keyname(str)
char *str;
{
register struct descrip *sp;
if (strcmp(str, includename) == 0)
return("Include");
if (oldformat)
return(str);
return((sp = (struct descrip *)SearchKVTree(argname, str, strcmp)) ?
sp->name : str);
}
#define DQUOTE (1 << 0)
#define SQUOTE (1 << 1)
static char *
quotestr(str)
register char *str;
{
static char buf[256];
register char *fp, *tp, *bp;
register int quote;
if (!str)
return("");
quote = 0;
if (index(str, '"'))
quote |= DQUOTE;
if (index(str, '\''))
quote |= SQUOTE;
if (!quote && !index(str, ' ') && !index(str, '\t')) {
bp = str;
if (index(bp, '\n')) {
strcpy(bp = buf, str);
if (fp = index(bp, '\n'))
*fp = 0;
}
if (strlen(bp) == 2 && *bp == '-' && isalpha(bp[1])) {
sprintf(buf, "\"-%c\"", bp[1]);
bp = buf;
}
return(bp);
}
switch(quote) {
case 0:
case (DQUOTE | SQUOTE):
quote = '"';
break;
default:
quote = (quote & SQUOTE) ? '"' : '\'';
break;
}
fp = str;
tp = buf;
*tp++ = quote;
while (*fp) {
if (*fp == '\n') {
fp++;
continue;
}
if (*fp == quote)
*tp++ = quote;
*tp++ = *fp++;
}
*tp++ = quote;
*tp = 0;
return(buf);
}
static void
setfirsttime(str)
register char *str;
{
while (*str)
firsttime[*str++] = 1;
}
static unshort *
ushortdup(i)
int i;
{
register unshort *sp;
if ((sp = (unshort *)malloc(sizeof(unshort))) == NULL)
errorexit(1, "ushortdup: Out of memory\n");
*sp = i;
return(sp);
}
#if (!(defined(SOLARIS)||defined(bsdi)||defined(__NetBSD__)||defined(__FreeBSD__)||defined(linux)))
char *
strdup(str)
char *str;
{
register char *cp;
if ((cp = (char *)malloc(strlen(str) + 1)) == NULL)
errorexit(1, "strdup: Out of memory\n");
strcpy(cp, str);
return(cp);
}
#endif /* SOLARIS || bsdi || __NetBSD__ */
static void
usage()
{
fprintf(stderr, "Usage: %s [-l] dbname [-o] [-v] [file]\n", myname);
fprintf(stderr, " %s -c newdbname [-o] [-v] [file]\n", myname);
exit(1);
}
static char *
untab(str)
char *str;
{
register char *cp, *bp;
register int i;
static char buf[256];
if (!(bp = index(str, '\t')))
return(keyname(str));
strncpy(buf, str, (i = bp - str));
buf[i] = 0;
if ((cp = keyname(str)) != str)
strcpy(buf, cp);
strcat(buf, " ");
strcat(buf, quotestr(bp + 1));
return(buf);
}

View File

@ -0,0 +1,76 @@
# Makefile autoconfigured for ...
# SunOS system on Fri Feb 15 14:00:21 EST 1991
MFLAGS=
LFLAGS=
CC=cc
LD=ld
SHELL=/bin/sh
INSTALLER=cp
CFLAGS= -O -DSHORT_NAMES -DMELBOURNE
DESTDIR=/usr/local/cap
LWFLAGS=-DDOCNAME -DPAGECOUNT=512
LIBCAP=-lcap
I=/usr/include
# Valid are: -DADOBE_DSC2_CONFORMANT
SIMPLEFLAGS=
LWSRVOBJS=fontlist.o lwsrv.o papstream.o procset.o simple.o spmisc.o
# for other libraries (like BSD on hpux)
SLIB=
# make sure that you define point getopt to att_getopt.o if your system
# doesn't have it builtin
ATT_GETOPT=
lwsrv: ${LWSRVOBJS} ${ATT_GETOPT}
${CC} -o lwsrv ${LFLAGS} ${LWSRVOBJS} ${ATT_GETOPT} ${LIBCAP} ${SLIB}
clean:
-rm -f *.o lwsrv att_getopt.c
install: lwsrv
-strip lwsrv
${INSTALLER} lwsrv ${DESTDIR}
dist:
@cat todist
att_getopt.c:
ln -s ../../extras/att_getopt.c
simple.o: simple.c
${CC} ${CFLAGS} ${SIMPLEFLAGS} -c simple.c
lwsrv.o: lwsrv.c
${CC} ${CFLAGS} ${LWFLAGS} -c lwsrv.c
# Dependencies
lwsrv.o: lwsrv.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/compat.h papstream.h
simple.o: simple.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
spmisc.h \
procset.h fontlist.h papstream.h
fontlist.o: fontlist.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/sysvcompat.h fontlist.h \
spmisc.h papstream.h
papstream.o: papstream.c $I/netat/appletalk.h \
$I/netat/aberrors.h $I/netat/abqueue.h \
$I/netat/sysvcompat.h papstream.h
procset.o: procset.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
procset.h \
spmisc.h
spmisc.o: spmisc.c $I/netat/appletalk.h $I/netat/aberrors.h \
$I/netat/abqueue.h $I/netat/sysvcompat.h \
$I/netat/sysvcompat.h $I/netat/compat.h \
spmisc.h

118
applications/lwsrv/packed.c Normal file
View File

@ -0,0 +1,118 @@
static char rcsid[] = "$Author: djh $ $Date: 1995/08/28 10:38:35 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/packed.c,v 2.1 1995/08/28 10:38:35 djh Rel djh $";
static char revision[] = "$Revision: 2.1 $";
/*
* packed.c - create packed printer descriptions
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#include <stdio.h>
#include <sys/param.h>
#include <netat/appletalk.h>
#include <netat/sysvcompat.h>
#include <netat/compat.h>
#ifdef USESTRINGDOTH
#include <string.h>
#else /* USESTRINGDOTH */
#include <strings.h>
#endif /* USESTRINGDOTH */
#include "packed.h"
char *malloc();
char *realloc();
unsigned
AddToPackedChar(pc, str)
register PackedChar *pc;
char *str;
{
register int l, n;
l = strlen(str) + 1;
if ((n = pc->n) + l > pc->cmax && (pc->pc = realloc(pc->pc,
(pc->cmax += l + PACKEDCHARDELTA) * sizeof(char))) == NULL)
errorexit(1, "AddToPackedChar: Out of memory\n");
strcpy(pc->pc + n, str);
/*
* This doesn't work on machines with 16 bit ints!
*/
if ((pc->n += l) > MAXPACKEDSIZE)
errorexit(2, "AddToPackedChar: PackedChar overflow\n");
return(n);
}
unsigned
AddToPackedShort(ps, i)
register PackedShort *ps;
unsigned i;
{
if (ps->n >= ps->smax && (ps->ps = (unshort *)realloc(ps->ps,
(ps->smax += PACKEDSHORTDELTA) * sizeof(unshort))) == NULL)
errorexit(1, "AddToPackedShort: Out of memory\n");
ps->ps[ps->n] = i;
return(ps->n++);
}
unshort *
AllocatePackedShort(ps, nshort)
register PackedShort *ps;
int nshort;
{
register int n;
if ((n = ps->n) + nshort > ps->smax && (ps->ps = (unshort *)realloc(ps->ps,
(ps->smax += nshort + PACKEDSHORTDELTA) * sizeof(unshort))) == NULL)
errorexit(1, "AllocatePackedShort: Out of memory\n");
ps->n += nshort;
return(ps->ps + n);
}
PackedChar *
CreatePackedChar()
{
register PackedChar *pc;
static char errstr[] = "CreatePackedChar: Out of memory\n";
if ((pc = (PackedChar *)malloc(sizeof(PackedChar))) == NULL)
errorexit(1, errstr);
if ((pc->pc = malloc((pc->cmax = PACKEDCHARDELTA) * sizeof(char)))
== NULL)
errorexit(2, errstr);
pc->n = 0;
return(pc);
}
PackedShort *
CreatePackedShort()
{
register PackedShort *ps;
static char errstr[] = "CreatePackedChar: Out of memory\n";
if ((ps = (PackedShort *)malloc(sizeof(PackedShort))) == NULL)
errorexit(1, errstr);
if ((ps->ps = (unshort *)malloc((ps->smax = PACKEDCHARDELTA) * sizeof(unshort)))
== NULL)
errorexit(2, errstr);
ps->n = 0;
return(ps);
}
void
FreePackedChar(pc)
register PackedChar *pc;
{
free(pc->pc);
free((char *)pc);
}
void
FreePackedShort(ps)
register PackedShort *ps;
{
free((char *)ps->ps);
free((char *)ps);
}

View File

@ -0,0 +1,46 @@
/* "$Author: djh $ $Date: 1995/08/28 10:38:35 $" */
/* "$Header: /mac/src/cap60/applications/lwsrv/RCS/packed.h,v 2.1 1995/08/28 10:38:35 djh Rel djh $" */
/* "$Revision: 2.1 $" */
/*
* packed.h - create packed printer descriptions
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#ifndef _PACKED_H_
#define _PACKED_H_
#define MAXPACKEDSIZE ((unsigned)0xffff)
#define PACKEDCHARDELTA 256
#define PACKEDSHORTDELTA 128
typedef unsigned short unshort;
typedef struct PackedChar {
unsigned n;
unsigned cmax;
char *pc;
} PackedChar;
typedef struct PackedShort {
unsigned n;
unsigned smax;
unshort *ps;
} PackedShort;
#define AddrPackedChar(p) ((p)->pc)
#define AddrPackedShort(p) ((p)->ps)
#define NPackedChar(p) ((p)->n)
#define NPackedShort(p) ((p)->n)
unsigned AddToPackedChar(/* PackedChar *pc, char *str */);
unsigned AddToPackedShort(/* PackedShort *ps, unsigned i */);
unshort *AllocatePackedShort(/* PackedShort *ps, int nshort */);
PackedChar *CreatePackedChar();
PackedShort *CreatePackedShort();
void FreePackedChar(/* PackedChar *pc */);
void FreePackedShort(/* PackedShort *ps */);
#endif /* _PACKED_H_ */

View File

@ -0,0 +1,182 @@
static char rcsid[] = "$Author: djh $ $Date: 1995/08/28 11:10:14 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/papstream.c,v 2.2 1995/08/28 11:10:14 djh Rel djh $";
static char revision[] = "$Revision: 2.2 $";
/*
* papstream - UNIX AppleTalk: simple stream handling for pap connections
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986,1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* Created sept 5, 1987 by cck from lwsrv
*
*/
#include <stdio.h>
#include <netat/appletalk.h>
#include "papstream.h"
extern char *myname;
void
p_clreof(p)
PFILE *p;
{
p->p_flg &= ~P_IOEOF;
p->p_cnt = 0;
}
/*
* PFILE *p_opn(int cno)
*
* Initialize a stream interface for the PAP connection specified by cno.
* All buffers are dynamically allocated. Use p_cls() to close the stream
* and deallocate buffers.
*
*/
PFILE *
p_opn(cno, bufsiz)
int cno;
int bufsiz;
{
PFILE *p;
p = (PFILE *)malloc(sizeof(PFILE)); /* allocate io block */
p->p_buf = (byte *)malloc(bufsiz); /* pointer to input buffer */
p->p_bufsiz = bufsiz;
p->p_cno = cno; /* save pap connection number */
p->p_cnt = 0; /* count in buffer is zero */
p->p_flg = 0; /* no flags are set */
return(p); /* return io block */
}
/*
* void p_cls(PFILE *p)
*
* Close the PAP stream; deallocate buffers and do a PAPClose.
*
*/
void
p_cls(p)
PFILE *p;
{
PAPClose(p->p_cno,TRUE); /* close out connection */
free((char *)p->p_buf); /* release input buffer */
free((char *)p); /* release io block */
}
/*
* void p_write(PFILE *p, char *buf, int len, int sendeof)
*
* Write len characters from buf to the PAP connection specified by p.
* If sendeof is TRUE then pass along the EOF indicator to the remote
* client.
*
*/
void
p_write(p,buf,len,sendeof)
PFILE *p;
char *buf;
int len,sendeof;
{
int err,cmp;
#ifdef LWSRV8
import boolean tracing;
#endif /* LWSRV8 */
err = PAPWrite(p->p_cno,buf,len,sendeof,&cmp);
#ifdef LWSRV8
if (tracing)
tracewrite(buf, len);
#endif /* LWSRV8 */
if (err != noErr) {
p->p_flg |= P_IOCLS;
fprintf(stderr,"%s: p_write error %d on write to Connection %d\n",
myname, err, p->p_cno);
} else
while (cmp > 0) /* wait for completion */
abSleep(100,TRUE); /* returns on event anyway */
if (cmp != noErr)
p->p_flg |= P_IOCLS;
}
/*
* int p_fillbuf(PFILE *p)
*
* Called by p_getc to refill the input buffer for a PAP stream connection.
* Returns the next character read or EOF.
*
*/
int
p_fillbuf(p)
PFILE *p;
{
int peof, pcmp;
if (p_iscls(p))
return(EOF);
/* if end of file set and nothing left in buffer */
if (p_eof(p) && p->p_cnt <= 0) {
/* return eof after clearing */
p_clreof(p);
return(EOF);
}
if (PAPRead(p->p_cno,p->p_buf,&p->p_cnt,&peof,&pcmp) != noErr) {
p->p_flg |= P_IOCLS;
return(EOF);
}
while (pcmp > 0) /* wait until completion */
abSleep(100,TRUE); /* returns upon packet event */
#ifdef notdef /* removed by somebody once, when, who or why ? */
if (pcmp != noErr) {
fprintf(stderr,"%s: p_fillbuf PAPRead error %d\n", myname, pcmp);
p->p_flg |= P_IOCLS;
/* always return eof in this case */
return(EOF); /* what else to do? */
}
#endif notdef
if (peof) {
p->p_flg |= P_IOEOF;
if (p->p_cnt <= 0) { /* another way to get eof... */
p_clreof(p);
return(EOF);
}
}
p->p_ptr = p->p_buf; /* reset pointer to start of buffer */
return(p_getc(p));
}
/*
* int p_getc(PFILE *p)
*
* Read a character from the PAP stream specified by p. Return the
* character or EOF.
*
*/
#ifndef p_getc
int p_getc(p)
PFILE *p;
{
if (--(p->p_cnt) >= 0) {
if ((p->p_cnt % ((p->p_bufsiz/RFLOWQ)/2)) == 0)
abSleep(0,TRUE); /* make sure protocol runs */
return(*p->p_ptr++);
} else
return(p_fillbuf(p));
}
#endif

View File

@ -0,0 +1,55 @@
/* "$Author: djh $ $Date: 1995/08/28 11:10:14 $" */
/* "$Header: /mac/src/cap60/applications/lwsrv/RCS/papstream.h,v 2.2 1995/08/28 11:10:14 djh Rel djh $" */
/* "$Revision: 2.2 $" */
/*
* papstream - UNIX AppleTalk: simple stream handling for pap connections
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986,1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* Created sept 5, 1987 by cck from lwsrv
*
*/
typedef struct { /* PAP stream interface PFILE */
int p_cno; /* pap connection number */
int p_cnt; /* count of chars in ptr */
int p_flg; /* flags */
byte *p_ptr; /* ptr to input chars */
byte *p_buf; /* buf for input */
int p_bufsiz; /* size of buffer */
} p_iobuf, PFILE;
#define P_IOEOF 020 /* eof occured */
#define P_IOCLS 040 /* pap stream is closed */
#define P_IOERR 0100 /* error occured */
#define p_eof(p) (((p)->p_flg & P_IOEOF) != 0)
#define p_iscls(p) (((p)->p_flg & P_IOCLS) != 0)
#define p_clrcls(p) (((p)->p_flg &= ~P_IOCLS))
#define p_isopn(p) (((p)->p_flg & P_IOCLS) == 0)
#define p_papcno(p) ((p)->p_cno)
/* Fast mode - just comment out if you want to use routine instead */
#define p_getc(p) ((--((p)->p_cnt) < 0) ? p_fillbuf(p) : *(p)->p_ptr++)
void p_clreof();
PFILE *p_opn();
void p_cls();
void p_write();
int p_fillbuf();
#ifndef p_getc
int p_getc();
#endif
#ifdef LWSRV8
#define T_NEEDQUOTE (1 << 0)
#define T_CRTOLF (1 << 1)
#define T_NODSC (1 << 2)
#endif /* LWSRV8 */

402
applications/lwsrv/parse.c Normal file
View File

@ -0,0 +1,402 @@
static char rcsid[] = "$Author: djh $ $Date: 1995/08/28 10:38:35 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/parse.c,v 2.1 1995/08/28 10:38:35 djh Rel djh $";
static char revision[] = "$Revision: 2.1 $";
/*
* parse.c - read a configuration file and parse the information
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#include <stdio.h>
#include <sys/param.h>
#include <sys/file.h>
#include <netat/sysvcompat.h>
#include <netat/compat.h>
#ifdef USESTRINGDOTH
#include <string.h>
#else /* USESTRINGDOTH */
#include <strings.h>
#endif /* USESTRINGDOTH */
#ifdef NEEDFCNTLDOTH
#include <sys/fcntl.h>
#endif /* NEEDFCNTLDOTH */
#ifndef NONDBM
# include <ndbm.h>
#else /* NONDBM */
# include <dbm.h>
#endif /* NONDBM */
#include "list.h"
#include "parse.h"
typedef unsigned short unshort;
char datasuffix[] = ".dat";
char includename[] = "-";
char keywords_key[] = "keywords\0001.0.0";
KVTree **_printers;
char specialOpts[] = "LT";
KVTree **thequery;
extern char *myname;
extern List *optionlist;
extern List *printerlist;
static char *keywords = NULL;
static KVTree **pass1;
#ifndef NONDBM
static DBM *printerdb;
#endif NONDBM
static int printerfd;
char *malloc();
static void Construct();
static char *FetchData();
static void Include();
static void _Include();
static List *UnpackList();
static List *Unpackdb();
static void _configargs();
static void setargs();
static void
Construct(name, kp, lp)
char *name;
register KVTree **kp;
List *lp;
{
register void **vp;
register int i;
register void *np;
for (vp = (void **)AddrList(lp), i = NList(lp); i > 0; i -= 2) {
if (strcmp((char *)*vp, includename) == 0) { /* include */
Include(name, (char *)*++vp, kp);
vp++;
continue;
}
np = *vp++;
if (isOption(np) && isSpecialOpt(np)) {
if ((lp = (List *)SearchKVTree(kp, np, strcmp)) == NULL) {
lp = CreateList();
AddToKVTree(kp, np, lp, strcmp);
}
AddToList(lp, *vp++);
} else
AddToKVTree(kp, np, *vp++, strcmp);
}
}
static char *
FetchData(name, n)
char *name;
register int n;
{
register char *ptr, *cp;
register int size;
datum key, data;
Location loc;
key.dptr = name;
key.dsize = n;
#ifndef NONDBM
data = dbm_fetch(printerdb, key);
#else NONDBM
data = fetch(key);
#endif NONDBM
if (!data.dptr)
return(NULL);
if (data.dsize != sizeof(Location)) {
fprintf(stderr, "%s: location data for %s is wrong size\n",
myname, name);
exit(1);
}
bcopy((char *)data.dptr, (char *)&loc, sizeof(Location));
if (loc.magic != MagicNumber || (size = loc.size) <= 0) {
fprintf(stderr, "%s: location data mismatch for %s\n", myname, name);
exit(1);
}
if (lseek(printerfd, loc.offset, L_SET) < 0) {
fprintf(stderr, "%s: unable to position in data file for %s\n",
myname, name);
exit(1);
}
if ((cp = ptr = malloc(size)) == NULL) {
fprintf(stderr, "%s: out of memory for %s\n", myname, name);
exit(1);
}
while (size > 0) {
if ((n = read(printerfd, cp, size)) < 0) {
fprintf(stderr, "%s: read error on %s\n", myname, name);
exit(1);
}
if (n == 0) {
fprintf(stderr, " %s: premature end of file on %s\n", myname, name);
exit(1);
}
size -= n;
cp += n;
}
return(ptr);
}
static void
Include(name, cp, kp)
char *name, *cp;
KVTree **kp;
{
register KVTree **ip;
register List *lp;
register char *dp;
if (ip = (KVTree **)SearchKVTree(_printers, (void *)cp, strcmp)) {
_Include(kp, *ip);
return;
}
/* not in printer list, so try pass1 */
if (lp = (List *)SearchKVTree(pass1, (void *)cp, strcmp)) {
ip = CreateKVTree();
/*
* We add the new (empty) tree into master printer tree before
* constructing it so as to prevent infinite include loops.
*/
AddToKVTree(_printers, (void *)cp, ip, strcmp);
Construct(cp, ip, lp);
if (*ip)
_Include(kp, *ip);
NList(lp) = 0; /* mark the list as already processed */
return;
}
/* not in pass1, so try database */
if (keywords && (dp = FetchData(cp, strlen(cp)))) {
lp = Unpackdb(dp);
ip = CreateKVTree();
/*
* We add the new (empty) tree into master printer tree before
* constructing it so as to prevent infinite include loops.
*/
AddToKVTree(_printers, cp, ip, strcmp);
Construct(cp, ip, lp);
if (*ip)
_Include(kp, *ip);
return;
}
fprintf(stderr, "%s: %s: Can't include %s\n", myname, name, cp);
exit(1);
}
static void
_Include(kp, ip)
KVTree **kp;
register KVTree *ip;
{
register List *lp;
if (ip == NULL)
return;
if (isOption(ip->key) && isSpecialOpt(ip->key) &&
(lp = (List *)SearchKVTree(kp, ip->key, strcmp))) {
CatList(lp, (List *)ip->val);
} else
AddToKVTree(kp, ip->key, ip->val, strcmp);
if (ip->left)
_Include(kp, ip->left);
if (ip->right)
_Include(kp, ip->right);
}
static List *
UnpackList(sp, c)
register unshort *sp;
register char *c;
{
register List *lp;
register int n;
lp = CreateList();
for (n = *sp++; n > 0; n--)
AddToList(lp, c + *sp++);
return(lp);
}
static List *
Unpackdb(c)
register char *c;
{
register unshort *sp, *s;
register char *cp;
register List *lp;
register int n;
lp = CreateList();
s = (unshort *)c;
/*
* The first unshort is offset to string section. s is now pointing to
* beginning of packed ushorts
*/
c += *s++;
/*
* The first unshort is the number of pairs in the list. Then each following
* pair of ushorts points to a name string and the value, which may be another
* string or another list.
*/
sp = s;
for (n = *sp++; n > 0; n--) {
AddToList(lp, cp = keywords + *sp++);
if (StringVal(cp)) /* value is just a string */
AddToList(lp, *sp == 0 ? NULL : c + *sp);
else /* value is another list */
AddToList(lp, UnpackList(s + *sp, c));
sp++;
}
return(lp);
}
void
configargs(dbname)
char *dbname;
{
register KVTree **kp;
register List *lp;
register void **vp;
register int i;
register char *cp;
KVTree **_default;
char buf[BUFSIZ];
if (dbname) {
#ifndef NONDBM
if ((printerdb = dbm_open(dbname, O_RDONLY, 0)) == NULL) {
fprintf(stderr, "%s: Can't open dbm %s\n", myname, dbname);
exit(1);
}
#else NONDBM
if (dbminit(dbname) < 0) {
fprintf(stderr, "%s: Can't open dbm %s\n", myname, dbname);
exit(1);
}
#endif NONDBM
strcpy(buf, dbname);
strcat(buf, datasuffix);
if ((printerfd = open(buf, O_RDONLY, 0)) < 0) {
fprintf(stderr, "%s: Can't open data file %s%s\n", myname, dbname,
datasuffix);
exit(1);
}
if ((keywords = FetchData(keywords_key, KEYWORDSKEYSIZE)) == NULL) {
fprintf(stderr, "%s: %s does not contain printer templates\n",
myname, dbname);
exit(1);
}
}
if (optionlist) {
_default = CreateKVTree();
Construct("Default", _default, optionlist);
if (NList(optionlist) > 0)
setargs(NULL, _default);
FreeKVTree(_default, NULL, NULL);
}
_printers = CreateKVTree();
/* Pass 1 */
pass1 = CreateKVTree();
for (vp = AddrList(printerlist), i = NList(printerlist); i > 0; i -= 2){
cp = (char *)*vp++;
AddToKVTree(pass1, (void *)cp, *vp++, strcmp);
}
/* Pass 2 */
for (vp = AddrList(printerlist), i = NList(printerlist); i > 0; vp++, i -= 2) {
if (NList(*vp) <= 0) /* already processed */
continue;
kp = CreateKVTree();
cp = (char *)*vp++;
/*
* We add the new (empty) tree into master printer tree before
* constructing it so as to prevent infinite include loops.
*/
AddToKVTree(_printers, (void *)cp, kp, strcmp);
Construct(cp, kp, (List *)*vp);
}
if (*_printers)
_configargs(*_printers);
#ifndef NONDBM
if (printerdb)
dbm_close(printerdb);
#else NONDBM
/*
* There does not seem to be a way to close the old dbm file!
*/
#endif NONDBM
}
static void
_configargs(kp)
register KVTree *kp;
{
if (kp == NULL)
return;
if (kp->left)
_configargs(kp->left);
if (SearchKVTree(kp->val, "-p", strcmp))
setargs(kp->key, kp->val);
if (kp->right)
_configargs(kp->right);
}
static void
setargs(name, kp)
char *name;
register KVTree **kp;
{
register int i, j;
register List *lp, *lk;
register void **vp;
extern int optind;
lp = CreateList();
AddToList(lp, myname); /* simulating argc, argv, so this is argv[0] */
if (name) {
/*
* Just do "-n name" to force thequery to be set to the correct value.
*/
AddToList(lp, "-n");
AddToList(lp, name);
AddToList(lp, NULL); /* Just in case */
optind = 1;
doargs(NList(lp) - 1, AddrList(lp));
FreeList(lp, NULL);
lp = CreateList();
AddToList(lp, myname);
}
lk = ListKVTree(kp);
for (kp = (KVTree **)AddrList(lk), i = NList(lk); i > 0; kp++, i--) {
if (!isOption((*kp)->key))
break;
if (isSpecialOpt((*kp)->key)) {
for (j = NList((*kp)->val), vp = AddrList((*kp)->val); j > 0; j--) {
AddToList(lp, (*kp)->key);
AddToList(lp, *vp++);
}
} else {
AddToList(lp, (*kp)->key);
if ((*kp)->val)
AddToList(lp, (*kp)->val);
}
}
if (i > 0) {
while (i-- > 0) {
AddToKVTree(thequery, (*kp)->key, (*kp)->val, strcmp);
kp++;
}
}
FreeList(lk, NULL);
if (NList(lp) > 1) {
AddToList(lp, NULL); /* Just in case */
optind = 1;
doargs(NList(lp) - 1, AddrList(lp));
}
FreeList(lp, NULL);
}

View File

@ -0,0 +1,45 @@
/* "$Author: djh $ $Date: 1995/08/30 00:53:28 $" */
/* "$Header: /local/mulga/mac/src/cap60/applications/lwsrv/RCS/parse.h,v 2.1 1995/08/30 00:53:28 djh Rel djh $" */
/* "$Revision: 2.1 $" */
/*
* parse.h - read a configuration file and parse the information
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#ifndef _PARSE_H_
#define _PARSE_H_
typedef struct Location {
int magic;
int offset;
int size;
} Location;
#define KEYWORDSKEYSIZE 14
#define OPTIONCHAR '-'
#define MagicNumber 0x4c77436f /* 'LwCo' */
#define StringVal(a) (isOption(a) && !isSpecialOpt(a))
#define ListVal(a) (!isOption(a) || isSpecialOpt(a))
#define isOption(a) (*(char *)(a) == OPTIONCHAR)
#define isSpecialOpt(a) (Option(a) && index(specialOpts, Option(a)))
#define Option(a) (((char *)(a))[1])
extern char datasuffix[];
extern char includename[];
extern char keywords_key[];
extern char *libraryfile;
extern List *optionlist;
extern List *printerlist;
extern KVTree **_printers;
extern char specialOpts[];
extern KVTree **thequery;
void configargs(/* char *dbname */);
void initkeyword(/* FILE *fp */);
#endif /* _PARSE_H_ */

226
applications/lwsrv/parsel.l Normal file
View File

@ -0,0 +1,226 @@
%%
\"[^"]*\" {
register int c;
#ifdef __cplusplus
unput(c = yyinput());
#else
unput(c = input());
#endif
yytext[--yyleng] = 0;
if (c != '"') {
yylval.string = strdup(yytext + 1);
return(STRING);
}
yymore();
}
'[^']*' {
register int c;
#ifdef __cplusplus
unput(c = yyinput());
#else
unput(c = input());
#endif
yytext[--yyleng] = 0;
if (c != '\'') {
yylval.string = strdup(yytext + 1);
return(STRING);
}
yymore();
}
"," {
return(COMMA);
}
";" {
return(EOS);
}
"=" {
return(EQUAL);
}
[{(] {
return(LPAREN);
}
[})] {
return(RPAREN);
}
[ \t\n]+ {
/* just ignore whitespace */
}
"#"[^\n]*\n {
/* just ignore comments */
}
[^ \t\n,;=(){}"'#]+ {
static int searchkeywords();
return(searchkeywords(yytext, &yylval.string));
}
%%
#undef input
#undef unput
static unsigned char backbuf[256];
static unsigned char *backp = backbuf;
static FILE *infp;
static List *keylist;
static struct keywordbuf {
char *key;
char *sval;
int ival;
} keywordbuf[] = {
{"-A", "-A", DSC},
{"-C", "-C", LPRCMD},
#ifdef LPRARGS
{"-L", "-L", LPRARGUMENT},
#endif LPRARGS
{"-N", "-N", NOCOLLECT},
#ifdef PASS_THRU
{"-P", "-P", PASSTHRU},
#endif PASS_THRU
#ifdef NeXT
{"-R", "-R", NEXT},
#endif NeXT
{"-S", "-S", SINGLEFORK},
{"-T", "-T", TRANSCRIPT},
#ifdef LWSRV_AUFS_SECURITY
{"-X", "-X", AUFSSECURITY},
#endif LWSRV_AUFS_SECURITY
#ifdef LW_TYPE
{"-Y", "-Y", ATTYPE},
#endif LW_TYPE
{"-a", "-a", DIRDICT},
{"-d", "-d", DEBUG},
{"-e", "-e", EEXEC},
{"-f", "-f", FONTFILE},
{"-h", "-h", BANNER},
{"-k", "-k", CHECKSUM},
{"-l", "-l", LOGFILE},
{"-p", "-p", PRINTERQUEUE},
{"-q", "-q", QUERYFILE},
{"-r", "-r", KEEPFILE},
{"-t", "-t", TRACEFILE},
{"-v", "-v", VERBOSE},
{"alloweexec", "-e", EEXEC},
#ifdef LW_TYPE
{"appletalktype", "-Y", ATTYPE},
#endif LW_TYPE
#ifdef LWSRV_AUFS_SECURITY
{"aufssecurity", "-X", AUFSSECURITY},
#endif LWSRV_AUFS_SECURITY
{"debug", "-d", DEBUG},
{"deniedmessage", "DeniedMessage", DENIEDMESSAGE},
{"dontcollect", "-N", NOCOLLECT},
{"dsc", "-A", DSC},
{"encoding", "encoding", ENCODING},
{"featurequery", "FeatureQuery", FEATUREQUERY},
{"file", "file", FILERES},
{"font", "font", FONT},
{"fontfile", "-f", FONTFILE},
{"form", "form", FORM},
{"include", "-", INCLUDE},
{"keepspoolfile", "-r", KEEPFILE},
{"library", NULL, LIBRARY},
{"logfile", "-l", LOGFILE},
#ifdef LPRARGS
{"lprargument", "-L", LPRARGUMENT},
#endif LPRARGS
{"lprcommand", "-C", LPRCMD},
#ifdef NeXT
{"nextresolution", "-R", NEXT},
#endif NeXT
{"nochecksum", "-k", CHECKSUM},
{"options", NULL, OPTIONS},
#ifdef PASS_THRU
{"passthru", "-P", PASSTHRU},
#endif PASS_THRU
{"pattern", "pattern", PATTERN},
{"printerquery", "PrinterQuery", PRINTERQUERY},
{"printerqueue", "-p", PRINTERQUEUE},
{"procsetdir", "-a", DIRDICT},
{"query", "Query", QUERY},
{"queryfile", "-q", QUERYFILE},
{"singlefork", "-S", SINGLEFORK},
{"suppressbanner", "-h", BANNER},
{"tracefile", "-t", TRACEFILE},
{"transcriptoption", "-T", TRANSCRIPT},
{"verbose", "-v", VERBOSE},
{"vmstatus", "VMStatus", VMSTATUS},
{NULL, NULL, 0},
};
void
initkeyword(fp)
FILE *fp;
{
register List *lp;
register struct keywordbuf *kp;
lp = CreateList();
for (kp = keywordbuf; kp->key; kp++)
AddToList(lp, (void *)kp);
keylist = lp;
infp = fp;
}
static unsigned char input_linebuf[BUFSIZ] = "";
static unsigned char *input_lineptr = input_linebuf;
#ifndef YY_INPUT
static int
input()
{
register int c;
if (backp > backbuf)
return(*--backp);
if (*input_lineptr) {
/* putc(*input_lineptr, stderr); /* DEBUG */
return(*input_lineptr++);
}
if (fgets((char *)input_linebuf, BUFSIZ, infp) == NULL)
return(0);
linenum++;
input_lineptr = input_linebuf;
/* putc(*input_lineptr, stderr); /* DEBUG */
return(*input_lineptr++);
}
#endif
static int
keycmp(kp, cp)
struct keywordbuf *kp;
char *cp;
{
return(strcmp(kp->key, cp));
}
static int
searchkeywords(str, outstr)
char *str, **outstr;
{
register struct keywordbuf *kp;
register char *cp;
char buf[BUFSIZ];
static int keycmp();
if (*str != '-') {
strcpy(buf, str);
for (cp = buf; *cp; cp++)
if (isupper(*cp))
*cp = tolower(*cp);
cp = buf;
} else
cp = str;
if (kp = (struct keywordbuf *)SearchList(keylist, cp, keycmp)) {
*outstr = kp->sval;
return(kp->ival);
}
*outstr = strdup(str);
return(STRING);
}
static int
unput(c)
int c;
{
*backp++ = c;
}

478
applications/lwsrv/parsey.y Normal file
View File

@ -0,0 +1,478 @@
%{
/*
* parsey - UNIX AppleTalk spooling program: act as a laserwriter
* yacc configuration file parser
*
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
#include "list.h"
#include "parse.h"
typedef struct NameVal {
char *name;
void *val;
} NameVal;
/*
* Globals
*/
char *libraryfile = 0;
List *optionlist = 0;
List *printerlist = 0;
/*
* Function typecasts
*/
static char *addnl();
static NameVal *CreateNameVal();
int strcmp();
char *strdup();
%}
%union {
char *string;
List *list;
NameVal *nameval;
}
%token ATTYPE AUFSSECURITY BANNER CHECKSUM COMMA DEBUG DENIEDMESSAGE DIRDICT
%token DSC EEXEC ENCODING EOS EQUAL FEATUREQUERY FILERES FONT FONTFILE FORM
%token INCLUDE KEEPFILE LIBRARY LOGFILE LPAREN LPRARGUMENT LPRCMD NEXT
%token NOCOLLECT OPTIONS PASSTHRU PATTERN PRINTERQUERY PRINTERQUEUE QUERY
%token QUERYFILE RPAREN SINGLEFORK STRING TRACEFILE TRANSCRIPT VERBOSE VMSTATUS
%type <string> ATTYPE AUFSSECURITY BANNER CHECKSUM DEBUG DENIEDMESSAGE DIRDICT
%type <string> DSC EEXEC ENCODING FEATUREQUERY FILERES FONT FONTFILE FORM
%type <string> INCLUDE KEEPFILE LOGFILE LPRARGUMENT LPRCMD NEXT NOCOLLECT
%type <string> PASSTHRU PATTERN PRINTERQUERY PRINTERQUEUE QUERY QUERYFILE
%type <string> SINGLEFORK STRING TRACEFILE TRANSCRIPT VERBOSE VMSTATUS
%type <string> lwsrvnoarg lwsrvwitharg optnoarg optwitharg queryargtype
%type <string> querynoargtype querytype shortresource special
%type <list> block clause list optionblock optionclause optlist stringcomma
%type <list> stringlist stringnlcomma stringnllist stringnlset stringset
%type <nameval> aprinter include lwsrvoption optstatement printeroption
%type <nameval> printerqueue query resource specialstrings statement
%start configuration
%%
configuration : library options printers
;
library : /* empty */
| LIBRARY EQUAL STRING EOS
{
libraryfile = $3;
}
options : /* empty */
| OPTIONS EQUAL optionblock
{
optionlist = $3;
}
;
optionblock : optstatement
{
register List *lp;
lp = CreateList();
AddToList(lp, (void *)$1->name);
AddToList(lp, (void *)$1->val);
free((char *)$1);
$$ = lp;
}
| optionclause EOS
;
optionclause : LPAREN optlist RPAREN
{
$$ = $2;
}
;
optlist : optstatement
{
register List *lp;
lp = CreateList();
AddToList(lp, (void *)$1->name);
AddToList(lp, (void *)$1->val);
free((char *)$1);
$$ = lp;
}
| optlist optstatement
{
AddToList($1, (void *)$2->name);
AddToList($1, (void *)$2->val);
free((char *)$2);
$$ = $1;
}
;
optstatement : lwsrvoption EOS
| printeroption EOS
| query EOS
| resource EOS
| specialstrings EOS
;
lwsrvoption : lwsrvwitharg STRING
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = (void *)$2;
$$ = np;
}
| lwsrvnoarg
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = NULL;
$$ = np;
}
;
lwsrvwitharg : LOGFILE
| DEBUG
| AUFSSECURITY
| LPRCMD
| QUERYFILE
;
lwsrvnoarg : VERBOSE
| SINGLEFORK
;
printers : aprinter
{
printerlist = CreateList();
AddToList(printerlist, (void *)$1->name);
AddToList(printerlist, (void *)$1->val);
free((char *)$1);
}
| printers aprinter
{
AddToList(printerlist, (void *)$2->name);
AddToList(printerlist, (void *)$2->val);
free((char *)$2);
}
;
aprinter : STRING EQUAL block
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = (void *)$3;
$$ = np;
}
;
block : statement
{
register List *lp;
lp = CreateList();
AddToList(lp, (void *)$1->name);
AddToList(lp, (void *)$1->val);
free((char *)$1);
$$ = lp;
}
| clause EOS
;
clause : LPAREN list RPAREN
{
$$ = $2;
}
;
list : statement
{
register List *lp;
lp = CreateList();
AddToList(lp, (void *)$1->name);
AddToList(lp, (void *)$1->val);
free((char *)$1);
$$ = lp;
}
| list statement
{
AddToList($1, (void *)$2->name);
AddToList($1, (void *)$2->val);
free((char *)$2);
$$ = $1;
}
;
statement : printerqueue EOS
| printeroption EOS
| include EOS
| query EOS
| resource EOS
| specialstrings EOS
;
printerqueue : PRINTERQUEUE STRING
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = (void *)$2;
$$ = np;
}
;
printeroption : optwitharg STRING
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = (void *)$2;
$$ = np;
}
| optnoarg
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = NULL;
$$ = np;
}
;
optwitharg : DIRDICT
| FONTFILE
| DSC
| TRANSCRIPT
| NEXT
| ATTYPE
| LPRARGUMENT
| TRACEFILE
;
optnoarg : EEXEC
| BANNER
| CHECKSUM
| NOCOLLECT
| PASSTHRU
| KEEPFILE
;
include : INCLUDE STRING
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = (void *)$2;
$$ = np;
}
;
query : querytype stringnlset
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = (void *)$2;
$$ = np;
}
;
querytype : queryargtype STRING
{
register char *cp;
if((cp = (char *)malloc(strlen($1) + strlen($2) + 2))
== NULL)
errorexit(1, "parse: Out of memory\n");
sprintf(cp, "%s\t%s", $1, $2);
free($2);
$$ = cp;
}
| querynoargtype
;
queryargtype : FEATUREQUERY
| QUERY
;
querynoargtype : PRINTERQUERY
| VMSTATUS
;
resource : shortresource stringset
{
register NameVal *np;
SortList($2, StringSortItemCmp);
np = CreateNameVal();
np->name = $1;
np->val = (void *)$2;
$$ = np;
}
;
shortresource : FONT
| FILERES
| PATTERN
| FORM
| ENCODING
;
stringnlset : STRING
{
register List *list;
list = CreateList();
AddToList(list, (void *)addnl($1));
$$ = list;
}
| LPAREN stringnlcomma RPAREN
{
$$ = $2;
}
;
stringnlcomma : stringnllist
| stringnllist COMMA
;
stringnllist : STRING
{
register List *list;
list = CreateList();
AddToList(list, (void *)addnl($1));
$$ = list;
}
| stringnllist COMMA STRING
{
AddToList($1, (void *)addnl($3));
$$ = $1;
}
;
stringset : STRING
{
register List *list;
list = CreateList();
AddToList(list, (void *)$1);
$$ = list;
}
| LPAREN stringcomma RPAREN
{
$$ = $2;
}
;
stringcomma : stringlist
| stringlist COMMA
;
stringlist : STRING
{
register List *list;
list = CreateList();
AddToList(list, (void *)$1);
$$ = list;
}
| stringlist COMMA STRING
{
AddToList($1, (void *)$3);
$$ = $1;
}
;
specialstrings : special stringnlset
{
register NameVal *np;
np = CreateNameVal();
np->name = $1;
np->val = (void *)$2;
$$ = np;
}
;
special : DENIEDMESSAGE
;
%%
static char strbuf[256];
int linenum = 0;
static void _Include(/* KVTree **kp, KVTree *ip */);
#include "lex.yy.c"
static NameVal *
CreateNameVal()
{
register NameVal *np;
if((np = (NameVal *)malloc(sizeof(NameVal))) == NULL)
errorexit(1, "CreateNameVal: Out of memory\n");
return(np);
}
static char *
addnl(str)
char *str;
{
register char *cp;
if((cp = (char *)malloc(strlen(str) + 2)) == NULL)
errorexit(1, "addnl:Out of memory\n");
strcpy(cp, str);
strcat(cp, "\n");
free(str);
return(cp);
}
yyerror(s)
char *s;
{
register int i, j;
register unsigned char *tp, *fp, *cp;
unsigned char buf[BUFSIZ];
i = 0;
for(tp = buf, fp = input_linebuf; fp < input_lineptr; fp++) {
if(*fp == '\t') {
i += (j = 8 - (i % 8));
while(j-- > 0)
*tp++ = ' ';
continue;
}
*tp++ = *fp;
i++;
}
cp = tp;
while(*cp++ = *fp++);
fprintf(stderr, "*** %s in configuration file on or before line %d\n", s,
linenum);
fputs((char *)buf, stderr);
if((i = (tp - buf) - 2) < 0)
i = 0;
while(i-- > 0)
putc('-', stderr);
fputs("^\n", stderr);
}

View File

@ -0,0 +1,396 @@
static char rcsid[] = "$Author: djh $ $Date: 1996/06/18 10:50:20 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/procset.c,v 2.13 1996/06/18 10:50:20 djh Rel djh $";
static char revision[] = "$Revision: 2.13 $";
/*
* procset - UNIX AppleTalk spooling program: act as a laserwriter
* handles simple procset list - assumes procsets in a directory
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
* Created Sept 5, 1987 by cck from lwsrv.
*
*
*/
#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
# include <sys/types.h> /* assume included by param.h */
#endif /* _TYPES */
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netat/appletalk.h>
#include <netat/sysvcompat.h>
#include <netat/compat.h>
#ifdef USESTRINGDOTH
# include <string.h>
#else USESTRINGDOTH
# include <strings.h>
#endif USESTRINGDOTH
#ifdef USEDIRENT
# include <dirent.h>
#else USEDIRENT
# ifdef xenix5
# include <sys/ndir.h>
# else xenix5
# include <sys/dir.h>
# endif xenix5
#endif USEDIRENT
#if defined(xenix5) || defined(SOLARIS)
# include <unistd.h>
#endif /* xenix5 || SOLARIS */
#ifdef linux
# include <unistd.h>
#endif /* linux */
#ifdef LWSRV8
#include "list.h"
#include "query.h"
#endif /* LWSRV8 */
#include "procset.h"
#include "spmisc.h"
extern char *myname;
extern int verbose;
#ifndef LWSRV8
DictList *dicthead = (DictList *)NULL; /* dictionary list header */
#else /* LWSRV8 */
private KVTree **dictlist = NULL; /* dictionary list header */
#endif /* LWSRV8 */
void
#ifndef LWSRV8
newdictionary(dl)
#else /* LWSRV8 */
set_dict_list(dl)
KVTree **dl;
{
dictlist = dl;
}
void
newdictionary(name, dl)
char *name;
#endif /* LWSRV8 */
DictList *dl;
{
#ifndef LWSRV8
dl->ad_next = dicthead; /* link it into the list */
dicthead = dl;
#else /* LWSRV8 */
AddToKVTree(dictlist, (void *)name, (void *)dl, strcmp);
#endif /* LWSRV8 */
}
DictList *
GetProcSet(psn)
char *psn;
{
#ifndef LWSRV8
DictList *dl;
for (dl = dicthead; dl != (DictList *) NULL; dl = dl->ad_next)
if (strcmp(psn,dl->ad_ver) == 0)
return(dl);
return(NULL);
#else /* LWSRV8 */
return((DictList *)SearchKVTree(dictlist, psn, strcmp));
#endif /* LWSRV8 */
}
void
ClearProcSetsSent()
{
#ifdef LWSRV8
private void clearprocsent();
clearprocsent(*dictlist);
#else /* LWSRV8 */
DictList *dl;
for (dl = dicthead; dl != (DictList *) NULL; dl = dl->ad_next) {
dl->ad_sent = FALSE;
}
#endif /* LWSRV8 */
}
#ifdef LWSRV8
private void
clearprocsent(dl)
register KVTree *dl;
{
((DictList *)dl->val)->ad_sent = FALSE;
if (dl->left)
clearprocsent(dl->left);
if (dl->right)
clearprocsent(dl->right);
return;
}
#endif /* LWSRV8 */
/*
* checks if the file is there and should be readable
*
*/
private boolean
checkfile(fn)
char *fn;
{
struct stat stb;
if (stat(fn, &stb) < 0)
return(FALSE);
#ifdef USEDIRENT
#if defined (AIX) || defined (drsnx) || defined(__osf__) || defined(SOLARIS)
if (S_ISREG(stb.st_mode) == 0) /* make sure regular file */
return(FALSE);
#else /* AIX || drsnx || __osf__ || SOLARIS */
/* sysv follows xpg standards */
if (S_ISREG(&stb) == 0) /* make sure regular file */
return(FALSE);
#endif /* AIX || drsnx || __osf__ || SOLARIS */
#else USEDIRENT
if (S_ISREG(stb.st_mode) == 0) /* make sure regular file */
return(FALSE);
#endif USEDIRENT
if (access(fn, R_OK) < 0)
return(FALSE);
return(TRUE);
}
private boolean
dictselect(d)
#ifdef USEDIRENT
struct dirent *d;
#else USEDIRENT
struct direct *d;
#endif USEDIRENT
{
return(checkfile(d->d_name));
}
#ifdef LWSRV8
DictList *
CreateDict()
{
register DictList *dl;
if ((dl = (DictList *)malloc(sizeof(DictList))) == NULL)
errorexit(1, "CreateDict: Out of memory\n");
return(dl);
}
private void
verbosedict(lp, dfn)
register KVTree *lp;
char *dfn;
{
if (lp->left)
verbosedict(lp->left, dfn);
fprintf(stderr,"%s: ProcSet '%s' file is '%s/%s'\n",
myname,(char *)lp->key,dfn,((DictList *)lp->val)->ad_fn);
if (lp->right)
verbosedict(lp->right, dfn);
}
#endif /* LWSRV8 */
/*
* scan dict dir for valid proc sets
*
*/
#ifndef LWSRV8
void
scandicts(dfn)
char *dfn;
#else /* LWSRV8 */
KVTree **
scandicts(dfn, lastried)
char *dfn;
time_t *lastried;
#endif /* LWSRV8 */
{
DictList *dl;
#ifdef USEDIRENT
struct dirent **namelist;
register struct dirent *dp;
#else USEDIRENT
struct direct **namelist;
register struct direct *dp;
#endif USEDIRENT
struct stat stb;
int i, j, nlst;
char path[MAXPATHLEN];
char line[1024]; /* reasonable size */
char *psn;
FILE *fp;
#ifndef LWSRV8
static time_t lastried = 0;
#else /* LWSRV8 */
register KVTree **lp;
int free();
#endif /* LWSRV8 */
if (stat(dfn, &stb) >= 0) {
#ifndef LWSRV8
if (lastried == stb.st_mtime) /* directory modified? */
return; /* no, nothing to do */
lastried = stb.st_mtime;
#else /* LWSRV8 */
if (*lastried == stb.st_mtime) /* directory modified? */
return(NULL); /* no, nothing to do */
*lastried = stb.st_mtime;
#endif /* LWSRV8 */
}
if (verbose)
fprintf(stderr, "%s: (Re)scanning for Procsets\n", myname);
#ifdef USEGETCWD
if (getcwd(path,sizeof(path)-1) == 0) {
fprintf(stderr, "%s: Can't get working directory: %s\n", myname, path);
#ifndef LWSRV8
return;
#else /* LWSRV8 */
return(NULL);
#endif /* LWSRV8 */
}
#else /* USEGETCWD */
if (getwd(path) == 0) {
fprintf(stderr, "%s: Can't get working directory: %s\n", myname, path);
#ifndef LWSRV8
return;
#else /* LWSRV8 */
return(NULL);
#endif /* LWSRV8 */
}
#endif /* USEGETCWD */
if (chdir(dfn) < 0) {
perror("chdir");
fprintf(stderr, "on path %s\n",dfn);
(void)chdir(path); /* try to go back in case... */
#ifndef LWSRV8
return;
#else /* LWSRV8 */
return(NULL);
#endif /* LWSRV8 */
}
if ((nlst = scandir(".", &namelist, dictselect, NULL)) < 0) {
perror(dfn);
fprintf(stderr, "Can't find dictionary files!\n");
#ifndef LWSRV8
return;
#else /* LWSRV8 */
return(NULL);
#endif /* LWSRV8 */
}
#ifdef LWSRV8
lp = CreateKVTree();
#endif /* LWSRV8 */
for (i = 0, dp = namelist[0]; i < nlst ; i++, dp = namelist[i]) {
if ((fp = fopen(dp->d_name, "r")) == NULL)
goto baddict;
if (fgets(line, sizeof(line)-1, fp) == NULL) {
fclose(fp);
goto baddict;
}
if (strncmp(line, "%%BeginProcSet: ",sizeof("%%BeginProcSet: ")-1) != 0) {
fclose(fp);
goto baddict;
}
fclose(fp);
for (j = 0; line[j] != '\0'; j++) /* treat '\r' as eol */
if (line[j] == '\r' || line[j] == '\n') {
line[j] = '\0';
break;
}
psn = line+sizeof("%%BeginProcSet:");
stripspaces(psn);
if (*psn == '\0')
goto baddict;
#ifndef LWSRV8
if ((dl=GetProcSet(psn)) != NULL) {
if (checkfile(dl->ad_fn))
goto baddict;
free(dl->ad_fn); /* reuse old dl, but drop fn space */
free(dl->ad_ver); /* drop ver space */
dl->ad_fn = NULL;
} else {
if ((dl = (DictList *)malloc(sizeof(DictList))) == NULL)
goto baddict;
newdictionary(dl); /* link it into the list */
}
dl->ad_ver = strdup(psn); /* remember proc set name */
#else /* LWSRV8 */
dl = CreateDict();
#endif /* LWSRV8 */
dl->ad_fn = strdup(dp->d_name); /* remember file name */
dl->ad_sent = FALSE;
#ifdef LWSRV8
AddToKVTree(lp, strdup(psn), dl, strcmp);
#endif /* LWSRV8 */
baddict:
free(dp);
}
free(namelist);
(void)chdir(path);
#ifndef LWSRV8
if (verbose) {
for (dl = dicthead; dl != (DictList *) NULL; dl = dl->ad_next)
fprintf(stderr,"lwsrv: ProcSet '%s' file is '%s/%s'\n",
dl->ad_ver,dfn,dl->ad_fn);
}
#else /* LWSRV8 */
if (verbose)
verbosedict(*lp, dfn);
return(lp);
#endif /* LWSRV8 */
}
#define ADBUFZ MAXPATHLEN
private int domultijob = FALSE;
void
setflag_encrypted_instream(flg)
int flg;
{
domultijob = flg;
}
void
ListProcSet(fn, dictdir, outfile, patchprocset)
char *fn;
char *dictdir;
FILE *outfile;
int patchprocset;
{
char adbuf[ADBUFZ+1];
FILE *fd;
int cnt;
sprintf(adbuf, "%s/%s",dictdir,fn);
if ((fd = fopen(adbuf,"r")) != NULL) {
if (patchprocset && domultijob) {
fprintf(stderr, "%s: Running in eexec mode\n", myname);
fprintf(outfile, "%%The following fixes problems where the prep file\n");
fprintf(outfile, "%%assumes that it is permanently downloaded and an\n");
fprintf(outfile, "%%eof occurs at the end of the prep (e.g. eexec)\n");
fprintf(outfile, "2 {(%%stdin) (r) file cvx exec } repeat\n");
}
while ((cnt = fread(adbuf,sizeof(char),ADBUFZ,fd)) > 0)
fwrite(adbuf,sizeof(char),cnt,outfile);
if (patchprocset && domultijob)
fprintf(outfile, "%%%%EOF\n");
fclose(fd);
} else {
fprintf(stderr,"%s: ListProcSet: file not found %s\n", myname, adbuf);
fprintf(outfile,"%% ** ProcSet file %s not found **\n",adbuf);
}
}

View File

@ -0,0 +1,38 @@
/* "$Author: djh $ $Date: 1995/08/28 11:10:14 $" */
/* "$Header: /mac/src/cap60/applications/lwsrv/RCS/procset.h,v 2.3 1995/08/28 11:10:14 djh Rel djh $" */
/* "$Revision: 2.3 $" */
/*
* procset - UNIX AppleTalk spooling program: act as a laserwriter
* handles simple procset list - assumes procsets in a directory
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986,1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* Created sept 5, 1987 by cck from lwsrv
*
*/
typedef struct Dict_List { /* known dictionary list */
#ifndef LWSRV8
struct Dict_List *ad_next; /* pointer to next */
char *ad_ver; /* the version number */
#endif /* not LWSRV8 */
char *ad_fn; /* the file name */
int ad_sent; /* downloaded during this job? */
} DictList;
DictList *GetProcSet(); /* DictList *GetProcSet(char *) */
void ClearProcSetsSent();
void newdictionary(); /* void newdictionary(DictList *) */
void ListProcSet();
#ifdef LWSRV8
DictList *CreateDict();
KVTree **scandicts();
void set_dict_list();
#endif /* LWSRV8 */

201
applications/lwsrv/query.c Normal file
View File

@ -0,0 +1,201 @@
static char rcsid[] = "$Author: djh $ $Date: 1995/08/30 08:13:25 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/query.c,v 2.2 1995/08/30 08:13:25 djh Rel djh $";
static char revision[] = "$Revision: 2.2 $";
/*
* query.c - handle the LaserWriter 8 printer queries
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#include <stdio.h>
#include <sys/time.h>
#include <netat/appletalk.h>
#include <netat/sysvcompat.h>
#ifdef USESTRINGDOTH
#include <string.h>
#else /* USESTRINGDOTH */
#include <strings.h>
#endif /* USESTRINGDOTH */
#include "list.h"
#include "query.h"
#include "papstream.h"
import char *myname;
private char newline[] = "\n";
private char no[] = ":No\n";
private char star[] = "*\n";
private char yes[] = ":Yes\n";
private void _SendResourceKVTree();
private char *buildProc();
void
SendMatchedKVTree(pf, list, prefix, str) /* only used by procset */
PFILE *pf;
KVTree **list;
char *prefix, *str;
{
register char *cp, *tp;
char buf[256], proc[256];
if (prefix == NULL)
cp = buf;
else {
strcpy(buf, prefix);
cp = buf + strlen(buf);
}
while (buildProc(&str, proc)) {
strcpy(cp, proc);
strcat(cp, SearchKVTree(list, proc, strcmp) ? yes : no);
p_write(pf,buf,strlen(buf),FALSE);
}
p_write(pf,star,strlen(star),FALSE);
}
void
SendMatchedResources(pf, list, prefix, str)
PFILE *pf;
List *list;
char *prefix, *str;
{
register char *cp, *tp;
char buf[256];
if (prefix == NULL)
cp = buf;
else {
strcpy(buf, prefix);
cp = buf + strlen(buf);
}
while (tp = nextoken(&str)) {
strcpy(cp, tp);
strcat(cp, SearchList(list, tp, strcmp) ? yes : no);
p_write(pf,buf,strlen(buf),FALSE);
}
p_write(pf,star,strlen(star),FALSE);
}
void
SendResourceKVTree(pf, list, prefix)
PFILE *pf;
KVTree **list;
char *prefix;
{
register char *cp;
char buf[256];
if (prefix == NULL)
cp = buf;
else {
strcpy(buf, prefix);
cp = buf + strlen(buf);
}
_SendResourceKVTree(pf, *list, buf, cp);
p_write(pf,star,strlen(star),FALSE);
}
private void
_SendResourceKVTree(pf, lp, buf, cp)
PFILE *pf;
register KVTree *lp;
char *buf, *cp;
{
if (lp == NULL)
return;
if (lp->left)
_SendResourceKVTree(pf, lp->left, buf, cp);
strcpy(cp, (char *)lp->key);
strcat(cp, newline);
p_write(pf,buf,strlen(buf),FALSE);
if (lp->right)
_SendResourceKVTree(pf, lp->right, buf, cp);
}
void
SendResourceList(pf, list, prefix)
PFILE *pf;
List *list;
char *prefix;
{
register int i;
register char **ip;
register char *cp;
char buf[256];
if (prefix == NULL)
cp = buf;
else {
strcpy(buf, prefix);
cp = buf + strlen(buf);
}
for (ip = (char **)AddrList(list), i = NList(list); i > 0; ip++, i--) {
strcpy(cp, *ip);
strcat(cp, newline);
p_write(pf,buf,strlen(buf),FALSE);
}
p_write(pf,star,strlen(star),FALSE);
}
void
SendQueryResponse(pf, list)
PFILE *pf;
List *list;
{
register char **lp;
register int i;
for (i = NList(list), lp = (char **)AddrList(list); i > 0; lp++, i--)
p_write(pf, *lp, strlen(*lp), FALSE);
}
private char *
buildProc(str, buf)
char **str;
char *buf;
{
register char *tp;
if (!(tp = nextoken(str)))
return(NULL);
strcpy(buf, tp);
if (!(tp = nextoken(str)))
return(buf);
strcat(buf, " ");
strcat(buf, tp);
if (!(tp = nextoken(str)))
return(buf);
strcat(buf, " ");
strcat(buf, tp);
return(buf);
}
char *
nextoken(cp)
char **cp;
{
register char *bp, *ep;
bp = *cp;
while (isspace(*bp))
bp++;
if (*bp == 0)
return(NULL);
ep = bp + 1;
if (*bp == '"') {
while (*ep && *ep != '"')
ep++;
if (*ep)
ep++;
} else {
while (*ep && !isspace(*ep))
ep++;
}
if (*ep)
*ep++ = 0;
*cp = ep;
return(bp);
}

View File

@ -0,0 +1,64 @@
/* "$Author: djh $ $Date: 1995/08/28 10:38:35 $" */
/* "$Header: /mac/src/cap60/applications/lwsrv/RCS/query.h,v 2.1 1995/08/28 10:38:35 djh Rel djh $" */
/* "$Revision: 2.1 $" */
/*
* query.h - handle the LaserWriter 8 printer queries
*
* UNIX AppleTalk spooling program: act as a laserwriter
* AppleTalk package for UNIX (4.2 BSD).
*
*/
#ifndef _QUERY_H_
#define _QUERY_H_
struct printer_instance {
char *dictdir; /* dictionary directory (-a) */
time_t lastried; /* dictdir last modified */
KVTree **dictlist; /* dictionary list */
int dochecksum; /* doing checksum (-k) */
int hflag; /* print banner (-h) */
int rflag; /* don't remove file (-r) */
char *tracefile; /* tracefile (-t) */
int eflag; /* maybe "eexec" in code(-e) */
int toptions; /* Transcript options (-T) */
int dsc2; /* DSC2 compatibility (-A) */
#ifdef LPRARGS
List *lprargs; /* lpr arguments (-L) */
#endif LPRARGS
#ifdef PASS_THRU
int passthru; /* pass through (-P) */
#endif PASS_THRU
#ifdef NeXT
char* nextdpi; /* NeXT resolution (-R) */
#endif NeXT
#ifdef LW_TYPE
char *prttype; /* AppleTalk type (-Y) */
#endif LW_TYPE
int capture; /* capture procset (-N) */
/* NBP and UNIX name required */
char *prtname; /* NBP registered printername */
char *unixpname; /* UNIX printer name */
/* Query list */
KVTree **querylist;
/* AppleTalk stuff */
PAPStatusRec statbuf;
int srefnum; /* returned by SLInit */
char nbpbuf[128]; /* registered name:type@zone */
int rcomp; /* flag: waiting for job? */
int cno; /* connection number of next job */
int children; /* number of active children */
};
void SendMatchedKVTree(/* PFILE *pf, KVTree **list, char *prefix,
char *str */);
void SendMatchedResources(/* PFILE *pf, List *list, char *prefix,
char *str */);
void SendQueryResponse(/* PFILE *pf, List *list */);
void SendResourceKVTree(/* PFILE *pf, KVTree **list, char *prefix */);
void SendResourceList(/* PFILE *pf, List *list, char *prefix */);
void SendQueryResponse(/* PFILE *pf, List *list */);
char *nextoken(/* char **cp */);
#endif /* _QUERY_H_ */

207
applications/lwsrv/query.ps Normal file
View File

@ -0,0 +1,207 @@
%!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file prints the responses to the standard LaserWriter 8.0 driver
% queries. (Note: the ADOSpooler query has been modified to output "spooler"
% rather than "0". This is to avoid confusion in what to enter in the
% database, since lwsrv should response with "spooler", not the default "0".)
%
% Remove the beginning part of the file, up to (but not including) the line
% beginning with "%!PS-Adobe 3.0 Query" if you want the query responses to
% be sent to the printer's standard output (and probably captured in a log
% file) rather than being printed.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/D 6 dict def
D begin
/in {72 mul} def
/top 10.5 in def
/bottom .5 in def
/left 1 in def
/ypos top def
/lf 10 def
end
/Courier findfont 9 scalefont setfont
/Str 256 string def
/flush {showpage} def
/INITGRAPHICS {initgraphics} bind def
/initgraphics {currentpoint INITGRAPHICS moveto} def
/RESTORE {restore} bind def
/restore {D begin ypos end currentpoint 4 -1 roll RESTORE
moveto D begin /ypos exch def end} def
/newline {D begin /ypos ypos lf sub dup bottom lt {pop showpage top}if def
left ypos moveto end} def
D begin left ypos moveto end
/= {Str cvs show newline} def
/== {Str cvs show newline} def
/print {Str cvs (\n) search {show pop newline}if show} def
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%!PS-Adobe-3.0 Query
%%?BeginFeatureQuery: *LanguageLevel
(==>FeatureQuery *LanguageLevel) =
/languagelevel where
{
pop languagelevel dup 2 ge{(")print 3 string cvs print("\n)}{pop("1"\n)}ifelse
}{
("1"\n)
}ifelse
print
%%?EndFeatureQuery: Unknown
%%?BeginFeatureQuery: *PSVersion
(==>FeatureQuery *PSVersion) =
statusdict begin
("\()print version print(\) )print revision 40 string cvs print("\n)print
end
%%?EndFeatureQuery: Unknown
%%?BeginQuery: ADOSpooler
(==>Query ADOSpooler) =
(spooler) ==
%%?EndQuery: spooler
%%?BeginFeatureQuery: *?Resolution
(==>FeatureQuery *?Resolution) =
/mstr 40 string def
initgraphics
72 0 dtransform
dup mul exch dup mul add sqrt .25 add round
cvi
0 72 dtransform
dup mul exch dup mul add sqrt .25 add round
cvi 2 copy eq
{
pop
mstr cvs print
}{
exch
mstr cvs print(x)print
mstr cvs print
}ifelse
(dpi\n)print
%%?EndFeatureQuery: Unknown
%%?BeginQuery: ADOIsBinaryOK?
(==>Query ADOIsBinaryOK?) =
(True\n)
/currentdevparams where
{
pop
[
{
currentsystemparams/CurInputDevice get
currentdevparams
}stopped
{
cleartomark 0 dict
}{
exch pop
}ifelse
dup/Filtering known
{
/Filtering get
/None ne
{pop(False\n)}if
}{
pop
}ifelse
}if
print
%%?EndQuery: Unknown
%%?BeginFeatureQuery: *FreeVM
(==>FeatureQuery *FreeVM) =
(")print vmstatus exch sub 40 string cvs print("\n)print pop
%%?EndFeatureQuery: Unknown
%%?BeginFeatureQuery: *TTRasterizer
(==>FeatureQuery *TTRasterizer) =
save
true
{
systemdict/resourcestatus known{
42/FontType resourcestatus{pop pop false(Type42)=}{true}ifelse
}{true}ifelse
}{false}ifelse
{
statusdict begin product end dup(LaserWriter)ne exch(LaserWriter Plus)ne and
systemdict/eexec known and
systemdict/cexec known and{
countdictstack mark
false
<1861AEDAE118A9F95F1629C0137F8FE656811DD93DFBEA65E947502E78BA12284B8A58EF0A3
2E272778DAA2ABEC72A84102D591E11D96BA61F57877B895A752D9BEAAC3DFD7D3220E2BDE7
C036467464E0E836748F1DE7AB6216866F130CE7CFCEC8CE050B870C11881EE3E9D70919>
{eexec}stopped{
cleartomark
countdictstack exch sub dup 0 gt{{end}repeat}{pop}ifelse
false
}{
{cleartomark pop true}{cleartomark pop false}ifelse
}ifelse
}{false}ifelse{
false
(Accept68K)=
}{true}ifelse
}{false}ifelse
{
(None)=
}if
restore
%%?EndFeatureQuery: Unknown
%%?BeginFeatureQuery: *Product
(==>FeatureQuery *Product) =
statusdict begin
("\()print product print(\)"\n)print
end
%%?EndFeatureQuery: Unknown
%%?BeginQuery: Product
(==>Query Product) =
statusdict begin
("\()print product print(\)"\n)print
end
%%?EndQuery: Unknown
%%?BeginFeatureQuery: *ColorDevice
(==>FeatureQuery *ColorDevice) =
systemdict/colorimage known
{
statusdict begin
/processcolors where
{
pop processcolors 1 eq
{
(Unknown)
}{
(True)
}ifelse
}{
(Unknown)
}ifelse
end
}{
(False)
}ifelse
print(\n)print
%%?EndFeatureQuery: Unknown
%%?BeginQuery: ADORamSize
(==>Query ADORamSize) =
/languagelevel where{pop languagelevel}{1}ifelse 2 ge{
currentsystemparams dup/RamSize known{/RamSize get}{pop -1}ifelse
}{
statusdict/ramsize known{statusdict begin ramsize end}{-1}ifelse
}ifelse dup 0 le{
pop vmstatus exch pop exch pop
gsave newpath matrix setmatrix clippath pathbbox grestore
mul 8 div cvi
statusdict/processcolors known{statusdict/processcolors get exec mul}if
exch pop exch pop add
cachestatus pop exch pop add exch pop add exch pop add
524288 div ceiling cvi 524288 mul
}if(")print 40 string cvs print("\n)print
%%?EndQuery: Unknown
%%?BeginFeatureQuery: *FaxSupport
(==>FeatureQuery *FaxSupport) =
(None)/resourcestatus where{pop
/HWOptions/Category resourcestatus{pop pop
/Fax/HWOptions resourcestatus{pop pop pop(Base)}if
}if
}if print(\n)print
%%?EndFeatureQuery: Unknown
%%?BeginFontListQuery
(==>FontListQuery) =
save/scratch 100 string def FontDirectory{pop =}forall systemdict/filenameforall known{(fonts/*){(.)search {pop pop pop}{dup length 6 sub 6 exch getinterval =}ifelse}scratch filenameforall}if(*) = restore
%%?EndFontListQuery: *
flush
%%EOF

1739
applications/lwsrv/simple.c Normal file

File diff suppressed because it is too large Load Diff

117
applications/lwsrv/spmisc.c Normal file
View File

@ -0,0 +1,117 @@
static char rcsid[] = "$Author: djh $ $Date: 1995/08/28 11:10:14 $";
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/spmisc.c,v 2.2 1995/08/28 11:10:14 djh Rel djh $";
static char revision[] = "$Revision: 2.2 $";
/*
* spmisc - UNIX AppleTalk spooling program: act as a laserwriter
* some misc. functions useful for spooler
* (some should be put in abmisc)
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
* Created Sept 5, 1987 by cck from lwsrv.
*
*
*/
#include <stdio.h>
#include <sys/param.h>
#ifndef _TYPES
/* assume included by param.h */
# include <sys/types.h> /* don't include types if param.h */
#endif /* _TYPES */ /* is included - probs on some */
#include <netat/appletalk.h>
#include <netat/sysvcompat.h>
#include <netat/compat.h>
#ifdef USESTRINGDOTH
# include <string.h>
#else /* USESTRINGDOTH */
# include <strings.h>
#endif /* USESTRINGDOTH */
#include "spmisc.h"
extern char *myname;
/*
* string input string of extra spaces and any leading and trailing ones
* (spaces defined as space or tab)
*
*/
void
stripspaces(inp)
char *inp;
{
char *p, *p2;
for (p = inp; *p == ' ' && *p != '\0'; p++) /* strip leading */
/* NULL */;
for (p2 = p; *p2 != '\0'; p2++) /* convert tabs to space */
if (*p2 == '\t')
*p2 = ' ';
while (*p != '\0')
if (*p == ' ' && (*(p+1) == ' ' || *(p+1) == '\0'))
p++;
else
*inp++ = *p++;
*inp = '\0';
}
/*
* Simple stack for tokens
*
*
*/
#define STKSIZ 10
int mystack[STKSIZ];
int sp = 0;
boolean
push(val)
int val;
{
mystack[sp++] = val;
if (sp >= STKSIZ) {
fprintf(stderr, "%s: stack push: STACK OVERFLOW!\n", myname);
sp = STKSIZ-1;
return(FALSE);
}
return(TRUE);
}
int
pop()
{
sp--; /* decrement stack pointer */
if (sp < 0) {
fprintf(stderr, "%s: stack pop: STACK UNDERFLOW\n", myname);
sp = 0;
return(-1);
}
return(mystack[sp]);
}
boolean
isstackempty()
{
return(sp == 0);
}
void
clearstack()
{
sp = 0;
}
void
dumpstack()
{
while (sp--) {
fprintf(stderr, "%d\n", mystack[sp]);
}
}

View File

@ -0,0 +1,27 @@
/* "$Author: djh $ $Date: 91/02/15 21:15:59 $" */
/* "$Header: spmisc.h,v 2.1 91/02/15 21:15:59 djh Rel $" */
/* "$Revision: 2.1 $" */
/*
* spmisc - UNIX AppleTalk spooling program: act as a laserwriter
* some misc. functions useful for spooler
* (some should be put in abmisc)
*
* AppleTalk package for UNIX (4.2 BSD).
*
* Copyright (c) 1986,1987 by The Trustees of Columbia University in the
* City of New York.
*
* Edit History:
*
* Created sept 5, 1987 by cck from lwsrv
*
*/
void stripspaces(); /* void stripspaces(char *) */
boolean push(); /* boolean push(int) */
int pop();
boolean isstackempty();
void clearstack();
void dumpstack();
char *strdup(); /* char *strdup(char *) */

View File

@ -0,0 +1,12 @@
lwsrv.c - driver for lw spooler (semi-generic)
fontlist.c - simple fontlist handling
fontlist.h
papstream.c - pap streams code
papstream.h
procset.c - simple proc set handler
procset.h
simple.c - simple spooler
spmisc.c - auxillary routines
spmisc.h
LWFonts,LWPlusFonts - font coordination lists for LaserWriter
and LaserWriter Plus with no added fonts

34
applications/makefile Normal file
View File

@ -0,0 +1,34 @@
# Makefile autoconfigured for ...
# SunOS system on Fri Feb 15 14:00:15 EST 1991
MFLAGS=
LFLAGS=
CC=cc
LD=ld
SHELL=/bin/sh
INSTALLER=cp
all:
(cd lwsrv; make)
(cd papif; make)
(cd aufs; make)
install:
(cd lwsrv; make install)
(cd papif; make install)
(cd aufs; make install)
clean:
-(cd lwsrv; make clean)
-(cd papif; make clean)
-(cd aufs; make clean)
dist:
@cat todist
@(cd papif; make dist)
@(cd lwsrv; make dist)
@(cd aufs; make dist)

View File

@ -0,0 +1,80 @@
CFLAGS=cflags() specialcflags()
LWFLAGS=lwflags()
I=includedir()
CAPLIB=libcap()
DESTDIR=capsrvrdestdir()
# for other libraries (like BSD on hpux)
SLIB=libspecial()
# See README file for notes about defines
# Valid: SFLOWQ=[1,2,3,4,5,6,7,8]
# Valid: IDLESTUFF, NO_STRUCT, NOACCT, CAPPRINTERS=location
PAPFLAGS=papflags() ifdef([capprinters],[-DCAPPRINTERS=]capprinters())
PAPBANNER=papbanner()
# USEVPRINTF - use vprintf in logging
ifdef([usevprintf],[],[#])VPRINTF=-DUSEVPRINTF
# If you have Transcript from Adobe for your laserWriter and want to
# print text files, uncomment the next line and set the location properly
ifdef([pstextloc],[WPSTEXT="-DPSTEXT=pstextloc()"],
[# WPSTEXT=-DPSTEXT=\"/usr/local/lib/ps/pstext\"])
# This is if you have transcript and and want page reversal if possible
ifdef([psrevloc],[WPSREVERSE=-DPSREVERSE=psrevloc()],
[# WPSREVERSE=-DPSREVERSE=\"/usr/local/lib/ps/psrv\"])
ifdef([columbia],[all: pstest ps8 ps7 papof],[all: papif papof])
papif: papif.o $(O)
${CC} ${LFLAGS} -o papif papif.o $(O) $(CAPLIB) ${SLIB}
papif.o: papif.c
${CC} ${CFLAGS} ${VPRINTF} ${PAPBANNER} ${PAPFLAGS} ${LWFLAGS} \
${WPSTEXT} ${WPSREVERSE} -c papif.c
ifdef([columbia],[
pstest: papif.c ${LIBCAP}
${CC} -O ${VPRINTF} -DIDLESTUFF -DSFLOWQ=1 papif.c -o pstest -lcap
ps7: papif.c ${LIBCAP}
${CC} -O ${VPRINTF} -DIDLESTUFF -DNO_STRUCT -DSFLOWQ=1 -DPSTEXT=\"/usr/local/lib/ps/pstext\" -DPSREVERSE=\"/usr/local/lib/ps/psrev\" papif.c -o ps7 -lcap
ps8: papif ${LIBCAP}
cp papif ps8
strip ps8
])
ifelse(os,[hpux],[
papof:
echo "papof doesn't compile under hpux, but you don't really"
echo "need it anyway"
],[
papof.o: papof.c
${CC} -c ${CFLAGS} ${PAPBANNER} papof.c
papof: papof.o
${CC} ${LFLAGS} -o papof papof.o ${SLIB}
])
clean:
-rm -f papif papof *.o
spotless:
-rm -f papif papof *.o *.orig Makefile makefile
ifelse(os,[hpux],[
install: papif papof
-strip papif papof
ifdef([sysvinstall],[install -f $(DESTDIR) papif],
[${INSTALLER} papif $(DESTDIR)])
],[
install: papif papof
-strip papif papof
ifdef([sysvinstall],[install -f $(DESTDIR) papif papof],
[${INSTALLER} papif papof $(DESTDIR)])
])
dist:
@cat todist

Some files were not shown because too many files have changed in this diff Show More