mirror of https://github.com/mabam/CAP.git
CAP 6.0 pl198 + asip1
This commit is contained in:
parent
de21798186
commit
743b427168
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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)
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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".
|
||||
|
|
@ -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.
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
}
|
|
@ -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();
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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[];
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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();
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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:
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
Major 3 Minor 4
|
|
@ -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
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,2 @@
|
|||
int aufs_version[2] = { 3 , 4 };
|
||||
char *aufs_versiondate = " Sat Feb 16 17:30:14 EST 1991 ";
|
|
@ -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.
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
struct volsize {
|
||||
long total;
|
||||
long free;
|
||||
};
|
|
@ -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.
|
|
@ -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).
|
||||
|
||||
|
|
@ -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
|
|
@ -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,
|
||||
);
|
||||
);
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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 */
|
||||
}
|
|
@ -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();
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
);
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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]);
|
||||
}
|
||||
}
|
|
@ -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 *) */
|
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -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
Loading…
Reference in New Issue