mirror of
https://github.com/RasppleII/a2server.git
synced 2025-01-10 19:29:54 +00:00
docs/ivanx: Delete, see RasppleII/orig-archive
Having an outdated copy of the source code in a subdir of the source code was proving to be annoying--it's bitten both Ivan and I a time or two, and we have a GitHub organization to put repositories for these kinds of things. As such, this stuff is neither needed nor particularly desirable where it is. It lives on here: <https://github.com/RasppleII/orig-archive/>
This commit is contained in:
parent
5fab6a21af
commit
22020603f6
@ -1,19 +0,0 @@
|
||||
# Ivan Drucker's A2SERVER documentation
|
||||
|
||||
A2SERVER was not so much planned as it was evolved. It began as a project to
|
||||
boot an Apple //e card in a Macintosh over AppleTalk using a small embedded
|
||||
Linux-based computer and evolved over time into what it is today.
|
||||
|
||||
So too has its documentation. And while one of the goals of this project is
|
||||
to produce a full manual for A2SERVER, the pages on Ivan's website effectively
|
||||
are a manual if you dig through them a bit.
|
||||
|
||||
More than that, Ivan's pages are a piece of recent Apple // history. Future
|
||||
endeavors may improve upon what is contained within those pages, but it will
|
||||
not and indeed cannot replace them.
|
||||
|
||||
Thus the content of those pages as of mid-October 2015 (version 1.2.4) is
|
||||
reproduced here in Markdown format in order to be most widely readable. Where
|
||||
unconvertable HTML with no direct non-HTML equivalent exists, this archive
|
||||
will prefer readability to source accuracy. Examples of this include things
|
||||
such as replacing formatting using non-breaking spaces with an unordered list.
|
@ -1,43 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
You probably want to be able to get stuff on and off of A2SERVER, so that
|
||||
means connecting to it from other computers.
|
||||
|
||||
You can browse your network and you should see either "raspberrypi" or
|
||||
"a2server" as a server you can connect to. You can log in as Guest if asked.
|
||||
|
||||
On Mac OS X, it should appear under Shared in the sidebar of a Finder window,
|
||||
or under "Network" from the "Go" menu of the Finder.
|
||||
|
||||
On Windows, it should appear under Network.
|
||||
|
||||
On Mac OS 7 through 9, open Chooser from the Apple menu and click on
|
||||
AppleShare.
|
||||
|
||||
(If you can't browse to the server on your network, you may need to [log in
|
||||
to A2SERVER](a2server_commands.md) to update, and if that doesn't work, to
|
||||
find its IP address. On Mac OS X, enter the IP address under "Connect To
|
||||
Server..." from the Go menu of the Finder; on Windows, type the IP address
|
||||
following two backslash characters (\\) in an Explorer window.)
|
||||
|
||||
<!--
|
||||
Content edit: Make sure both Markdown source and HTML target renderings of how
|
||||
to specify a backslash-delimited UNC path are understandable. -Joseph
|
||||
-->
|
||||
|
||||
You will see two or three shared volumes: A2FILES, GSFILES, and, if you have
|
||||
A2CLOUD installed, ADTDISKS. Avoid the A2FILES volume except for copying
|
||||
things off of it. If you do want to put stuff on it, be careful to only use
|
||||
ProDOS-compliant filenames (all caps, 15 characters max, starts with a letter,
|
||||
and only contains letters/numbers/periods). Otherwise, you'll get unexpected
|
||||
behavior like invisible files.
|
||||
|
||||
Unix-type computers can also use `scp` to copy files to and from A2SERVER;
|
||||
Windows computers can also do so in the command window by using `pscp` in
|
||||
[PuTTY][1]. The shared volumes are within /srv/A2SERVER.
|
||||
|
||||
If you need to set the ProDOS file type of a file you have copied to A2SERVER,
|
||||
[log in to A2SERVER](a2server_commands.md) and use `afptype`.
|
||||
|
||||
|
||||
[1]: http://www.chiark.greenend.org.uk/~sgtatham/putty/
|
@ -1,128 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
Sometimes you need to access the A2SERVER command line to set up network boot
|
||||
or do other stuff. A list of commands is below.
|
||||
|
||||
If you are running A2SERVER on a Raspberry Pi without a screen and keyboard
|
||||
attached, see how to
|
||||
[log in to a Raspberry Pi](a2server_raspberrypi_login.md).
|
||||
|
||||
Otherwise, log in on your local console or virtual machine window, or via SSH
|
||||
on another computer. On Mac OS X, or Windows with [Bonjour Print Services][1]
|
||||
installed, you can use "raspberrypi.local" for your SSH address, or
|
||||
"a2server.local" if not on a Pi. If that doesn't work, try updating
|
||||
A2SERVER by typing `a2server-setup`.
|
||||
|
||||
If it still doesn't work, or you don't want to install Bonjour Print
|
||||
services for Windows, you will need to use A2SERVER's IP address instead,
|
||||
which you can see by typing `showip`. You can create a DHCP reservation in
|
||||
your router to give A2SERVER the same IP address every time. To do this,
|
||||
you'll need the MAC (Ethernet) address of the machine (or virtual machine)
|
||||
running A2SERVER, which you can see by typing `showmac`. If you are using the
|
||||
premade virtual machine, the MAC is 08:00:03:F2:FF:59 .
|
||||
|
||||
The default username is either "pi" for Raspberry Pi, and otherwise
|
||||
"user1". The password is "apple2". (The password is "raspberry" for an
|
||||
standard installation of Raspbian; you can use the
|
||||
[installer script](a2server_installer.md) to install A2SERVER.)
|
||||
|
||||
Shared volumes can be found at /srv/A2SERVER. Netatalk configuration files
|
||||
are in /usr/local/etc/netatalk.
|
||||
|
||||
Once logged in, you can enter the following commands.
|
||||
|
||||
(If any of these yield "command not found", refresh the command list by
|
||||
typing `a2server-setup`, answering "no" to all prompts if you like.)
|
||||
|
||||
|
||||
~~~
|
||||
A2SERVER commands:
|
||||
(note: new commands may be added; use a2server-setup to refresh)
|
||||
|
||||
a2server-help: show this list of commands
|
||||
a2server-setup: set up network boot, Windows access, Farallon fix,
|
||||
refresh command list
|
||||
a2server-version: see installed version of A2SERVER
|
||||
a2server-update: check for update to A2SERVER
|
||||
|
||||
system-shutdown: shut down the server
|
||||
system-restart: shut down and restart the server
|
||||
|
||||
Raspberry Pi commands, if you're using one:
|
||||
raspi-config: utilize all space on RPi SD card & other options
|
||||
raspbian-update : update Raspbian operating system
|
||||
rasppleii-update : update Raspbian OS, A2CLOUD, A2SERVER, Apple II Pi
|
||||
|
||||
welcome-message-edit: change the welcome message
|
||||
|
||||
showip: show the current ethernet IP address of the server
|
||||
showmac: show the MAC (Ethernet hardware) address of the server
|
||||
showip-wifi: show the current wifi IP address of the server
|
||||
showmac-wifi: show the MAC (wifi hardware) address of the server
|
||||
ifreset: reset all network interfaces (requires restart)
|
||||
|
||||
netatalk-stop: stop the netatalk service until reboot
|
||||
netatalk-start: start the netatalk service
|
||||
netatalk-restart: restart the netatalk service
|
||||
netatalk-off: disable the netatalk service (even after reboot)
|
||||
netatalk-on: enable the netatalk service
|
||||
|
||||
bonjour-off: disable advertisement of shared folders to OS X
|
||||
bonjour-on : enable advertisement of shared folders to OS X
|
||||
(these are automatically set by the netatalk commands above)
|
||||
|
||||
netatalk-router-on: use netatalk in router mode (default)
|
||||
netatalk-router-off: use netatalk in node mode
|
||||
(use if there is an AppleTalk router such as a GatorBox present)
|
||||
|
||||
netatalk-eth: use wired ethernet interface for netatalk (default)
|
||||
netatalk-wifi: use wifi interface for netatalk
|
||||
note: if an interface isn't available, netatalk will be reset with
|
||||
router mode off; use "netatalk-router-on" to correct this if needed
|
||||
|
||||
appletalk-off: disable AppleTalk networking (even after reboot)
|
||||
appletalk-on : enable AppleTalk networking
|
||||
|
||||
environment variables:
|
||||
$NETATALK: directory containing netatalk configuration files
|
||||
$A2FILES : directory containing A2FILES shared volume
|
||||
$GSFILES : directory containing GSFILES shared volume
|
||||
|
||||
netboot-gsos: set the current user to netboot into GS/OS (default)
|
||||
netboot-gsos-guest: set guests to netboot into GS/OS
|
||||
netboot-p8: set the current user to netboot into ProDOS 8
|
||||
netboot-p8-guest: set guests to netboot into ProDOS 8 (default)
|
||||
note: when a IIgs is set to network boot into GS/OS, using the Network
|
||||
control panel or the NETBOOT.GSOS utility, guests will behave like
|
||||
registered users, and ignore the netboot setting of the guest user
|
||||
|
||||
guest-off: disallow guest access to A2SERVER
|
||||
guest-on: allow guest access to A2SERVER (default)
|
||||
note: by default, Guest access is the only way to network boot into
|
||||
ProDOS 8. For registered user boot into ProDOS 8, type "netboot-p8"
|
||||
|
||||
samba-off: disable Windows file sharing (even after reboot)
|
||||
samba-on: enable Windows file Sharing
|
||||
samba-stop: stop Windows file sharing until reboot
|
||||
samba-start: start Windows file sharing
|
||||
samba-restart: stop and restart Windows file sharing
|
||||
|
||||
gsfiles-share: disable the GSFILES shared volume
|
||||
gsfiles-unshare: enable the GSFILES shared volume
|
||||
a2files-share: disable the A2FILES shared volume
|
||||
a2files-unshare: enable the A2FILES shared volume
|
||||
|
||||
nulib2: create, extract, and work with NuFX (ShrinkIt) archive files
|
||||
unar: extract other archive files (multiformat)
|
||||
lsar: list contents of other archive files (multiformat)
|
||||
|
||||
afptype: set the ProDOS type/auxtype or Mac OS type/creator of a file
|
||||
afpsync: register files introduced outside of AFP with netatalk
|
||||
mkatinit: set up network boot configuration files
|
||||
cppo: catalog and copy files from ProDOS image file (slow, but works)
|
||||
(add -h to show help for the above four commands, e.g. "afptype -h")
|
||||
|
||||
~~~
|
||||
|
||||
|
||||
[1]: http://support.apple.com/kb/dl999
|
@ -1,84 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
A2SERVER's central capability, sharing files to an Apple II, is provided by
|
||||
[Netatalk][1] 2.2.4.
|
||||
|
||||
Here's the extra sauce that A2SERVER provides:
|
||||
|
||||
* available as a ready-to-use [Raspberry Pi][2] operating system installer
|
||||
|
||||
(plus new [Pi Filler][3] and [Pi Copier][3] utilities for easy SD card
|
||||
creation and backup)
|
||||
|
||||
* available as a ready-to-use [VirtualBox][4] appliance for Mac OS X, Windows,
|
||||
Linux, and Solari
|
||||
|
||||
* simple downloadable installation script for Ubuntu Linux or Raspbian takes
|
||||
care of setting up and configuring *everything*
|
||||
|
||||
* enables reliable operation by Asante, Farallon and Dayna bridges on both IIe
|
||||
*and* IIgs \[fixes contributed by Steven Hirsch and Geoff Body\]
|
||||
|
||||
* easy to configure for network boot, including ProDOS 8 and GS/OS download
|
||||
and installation
|
||||
|
||||
* can network boot both IIe and IIgs computers on the same network
|
||||
|
||||
* new ProDOS 8 tools (NETBOOT.P8 and NETBOOT.GSOS) for setting the IIg network
|
||||
boot default
|
||||
|
||||
* temporary ProDOS 8 network boot without changing GS/OS default \[contributed
|
||||
by Geoff Body\]
|
||||
|
||||
* GS/OS installer that can be run from folders rather than disk
|
||||
|
||||
* installs ProDOS 8 and GS/OS utilities for working with archive (ShrinkIt and
|
||||
GSHK), disk images ([DSK2FILE][5] / [Asimov][6] / [MountIt][7]), and file
|
||||
(Apple ProDOS System Utilities)
|
||||
|
||||
* supports Wi-Fi when used with Apple AirPort or Time Capsul
|
||||
|
||||
* maintains correct dates during GS/OS folder copy \[fix contributed by Steven
|
||||
Hirsch\]
|
||||
|
||||
* uses randnum authentication for registered user sign-in (which alway works,
|
||||
unlike cleartext)
|
||||
|
||||
* supports login to shared volumes from latest versions of OS X and Window
|
||||
|
||||
* new Linux tool ([afptype](scripts/tools/afptype.txt)) for setting ProDOS or
|
||||
classic Mac file types on shared volume
|
||||
|
||||
* new Linux tool ([cppo](scripts/tools/cppo.txt)) for cataloging and copying
|
||||
files (with optional resource forks) out of ProDOS disk image
|
||||
|
||||
* [Linux commands](a2server_commands.md) to ease server maintenanc
|
||||
|
||||
* installs Linux tools for working with ShrinkIt and other old and new archive
|
||||
formats ([nulib2][8] and [unar/lsar][9])
|
||||
|
||||
<!--
|
||||
* sets up Raspberry Pi for shell login from Apple II via USB-serial cable or
|
||||
Raspberry Pi console cable
|
||||
-->
|
||||
|
||||
* blinks Raspberry Pi OK/ACT LED for ten seconds when netatalk has just
|
||||
started
|
||||
|
||||
* good documentation (or so I hope)
|
||||
|
||||
|
||||
Any content unique to A2SERVER and not covered under a specific license is
|
||||
licensed under the [WTFPL][10].
|
||||
|
||||
|
||||
[1]: http://netatalk.sourceforge.net
|
||||
[2]: http://www.raspberrypi.org
|
||||
[3]: http://ivanx.com/raspberrypi/
|
||||
[4]: http://www.virtualbox.org
|
||||
[5]: http://www.dwheeler.com/6502/oneelkruns/dsk2file.html
|
||||
[6]: http://www.ninjaforce.com/html/products.html
|
||||
[7]: http://www.brutaldeluxe.fr/products/apple2gs/mountit.html
|
||||
[8]: http://www.nulib.com
|
||||
[9]: http://unarchiver.c3.cx
|
||||
[10]: http://www.wtfpl.net
|
@ -1,63 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
To connect to A2SERVER from your Apple II:
|
||||
|
||||
(An alternative to the below is to [boot your Apple II over the
|
||||
network](a2server_netboot.md) -- check that out too.)
|
||||
|
||||
Start up A2SERVER and wait (potentially up to a minute) until you get to the
|
||||
login prompt. You do not need to log in. On a Raspberry Pi, you can see that
|
||||
it's ready when the the normally irregular ACT or OK LED blinks steadily and
|
||||
rapidly for ten seconds.
|
||||
|
||||
If you are on a IIe, boot from the [Workstation Card disk](#wsdisks), and
|
||||
choose "Log On".
|
||||
|
||||
If you are on a IIgs, open the AppleShare control panel. If you don't have
|
||||
it, use the GS/OS installer disks to custom install the script called
|
||||
"Network: AppleShare" to your startup disk. If you are on a floppy-only
|
||||
system, you can instead use the script "Network: AppleShare, 3.5" disk" to
|
||||
make a bootable disk, or consider setting up
|
||||
[network boot](a2server_netboot.md).
|
||||
|
||||
(There is also an obsolete [IIgs Workstation Disk](#wsdisks) that boots into
|
||||
ProDOS 16 rather than GS/OS, and has the same ProDOS 8 applications for server
|
||||
access as the IIe disk. You probably don't want to use it.)
|
||||
|
||||
"a2server" or "raspberrypi" should appear in the list of server names. Log
|
||||
in as Guest and select the A2FILES volume, for ProDOS 8 storage, and/or the
|
||||
GSFILES volume, for GS/OS storage. (You can also log in as a registered user,
|
||||
but it's exactly the same.)
|
||||
|
||||
On the A2FILES volume, filenames need to be all caps and are subject to the
|
||||
usual ProDOS restrictions (letters/numbers/periods only, first character must
|
||||
be a letter, 15 characters max). IIgs users can store files on GSFILES with
|
||||
mixed case, punctuated names of up to 31 characters (same as a classic Mac).
|
||||
|
||||
The network volumes hosted by A2SERVER will appear on the Finder desktop in
|
||||
GS/OS; in ProDOS 8, you can type `PREFIX /A2FILES`.
|
||||
|
||||
### Workstation Software: {#wsdisk}
|
||||
|
||||
<!--
|
||||
FIXME: These disk images are not (at present) contained within this archive.
|
||||
Moreover, they cannot be directly included in properly "Open Source" packages
|
||||
of A2SERVER which ought to include this archive. They'll have to be external
|
||||
links, but I'm not fixing that right now. -tjcarter,2015-10-22
|
||||
-->
|
||||
|
||||
* IIe Workstation Card, 800K:
|
||||
[raw image](files/a2ws/A2E.WS.FULL.HDV)
|
||||
[ShrinkIt image](files/a2ws/A2E.WS.FULL.BXY)
|
||||
|
||||
* IIe Workstation Card, Logon/Logoff/BASIC only, 140K:
|
||||
[raw image](files/a2ws/A2E.WS.LITE.DSK)
|
||||
[ShrinkIt image](files/a2ws/A2E.WS.LITE.BXY)
|
||||
|
||||
* IIe Workstation Card, System Utilities/BASIC only, 140K:
|
||||
[raw image](files/a2ws/A2E.WS.UTIL.DSK)
|
||||
[ShrinkIt image](files/a2ws/A2E.WS.UTIL.BXY)
|
||||
|
||||
* IIgs Workstation, 800K \[superseded by GS/OS AppleShare software\]:
|
||||
[raw image](files/a2ws/A2GS.WS.HDV)
|
||||
[ShrinkIt image](files/a2ws/A2E.WS.BXY)
|
@ -1,53 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
You can easily install A2SERVER on Debian, Ubuntu, or Raspbian Linux by using
|
||||
the A2SERVER install scripts.
|
||||
|
||||
While these are the only Linux distributions the scripts have been tested on,
|
||||
other Debian-derived distributions may work as well, provided they're not
|
||||
based on Debian 8, don't use kernel 3.12 through 3.15, have AppleTalk
|
||||
networking support available as a kernel module or compiled into the kernel
|
||||
itself, and their repositories contain the packages the scripts require. The
|
||||
user running the scripts needs a bash shell, sudo privileges, and a search
|
||||
path containing all the "bin" and "sbin" directories.
|
||||
|
||||
|
||||
### Debian or Ubuntu Linux
|
||||
|
||||
(Tested on Debian 7.8.0 and Ubuntu Server 12.04 LTS. Note that Ubuntu 14.04
|
||||
LTS includes kernel 3.13, which is *not* compatible with A2SERVER; you will
|
||||
need to upgrade it to 3.16 or later. Debian 8 and Ubuntu 15 *cannot* be used
|
||||
at this time.)
|
||||
|
||||
1. [Create a new virtual machine](a2server_prepvm.md) (skip if installing on a
|
||||
real machine)
|
||||
2. [Install Debian](a2server_installubuntu.md) (or Ubuntu) on the virtual or
|
||||
real machine
|
||||
|
||||
|
||||
### Raspberry Pi
|
||||
|
||||
1. [Download Raspbian][1]
|
||||
2. [Perform Raspberry Pi setup](a2server_raspberrypi.md)
|
||||
|
||||
|
||||
Once you are up and running in Linux, you can execute the automated setup
|
||||
scripts to download, install, and configure the A2SERVER software. To use
|
||||
these, [log in to Linux](a2server_commands.md), and type:
|
||||
|
||||
~~~ bash
|
||||
wget appleii.ivanx.com/a2server/setup; source setup
|
||||
~~~
|
||||
|
||||
Confirm that you want to proceed, enter the password again, and go get a
|
||||
sandwich, but come back so you can answer questions when prompted.
|
||||
|
||||
Once it's done, check out the links on the [A2SERVER home page](index.md) for
|
||||
next steps.
|
||||
|
||||
If you'd like to set things up manually, or are curious as to what's
|
||||
happening, you can
|
||||
[view the contents of the setup scripts](a2server_scriptdetails.md).
|
||||
|
||||
|
||||
[1]: http://www.raspberrypi.org/downloads
|
@ -1,58 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
These steps cover how to install Ubuntu Server Linux into your empty virtual or real machine. (The instructions are similar, but may vary somewhat, for Debian Linux.)
|
||||
|
||||
* Download [Ubuntu Server 12.04 LTS][1], and burn it to a CD if
|
||||
installing on a real machine; otherwise, attach the download to your
|
||||
virtual machine's CD/DVD drive.
|
||||
|
||||
* Click Start.
|
||||
|
||||
* Answer all the region related questions and choose to Install Ubuntu
|
||||
Server.
|
||||
|
||||
* For hostname, enter *a2server*
|
||||
|
||||
* Under Partition Disks, choose "Guided - use entire disk" (no LVM).
|
||||
|
||||
* Choose SCSI1 (or whatever other disk appears), and (two screens later)
|
||||
confirm "Write the changes to disks."
|
||||
|
||||
* If you are installing Debian, and are prompted for a domain name or
|
||||
the root user password, leave them blank.
|
||||
|
||||
* Enter *user1* as the full name for the new user, and as the username
|
||||
for your account
|
||||
|
||||
* Choose *apple2* as the password, verify by retyping, and then confirm
|
||||
weak password
|
||||
|
||||
* Choose not to encrypt your home directory
|
||||
|
||||
* If you require an HTTP proxy, enter it, or leave it blank if not.
|
||||
|
||||
* Choose yes to Install the GRUB boot loader to the master boot record
|
||||
|
||||
* Choose no automatic updates
|
||||
|
||||
* Choose OpenSSH under Software Selection (and, for Debian, Standard
|
||||
System Utilities)
|
||||
|
||||
* Click Continue to reboot
|
||||
|
||||
* When prompted, log in with username *user1* and password *apple2*.
|
||||
|
||||
* If you installed Debian rather than Ubuntu, type:
|
||||
|
||||
~~~ bash
|
||||
sudo sed -i '0,/-eq 0/s/-eq 0/-ge 0/' /etc/profile
|
||||
~~~
|
||||
|
||||
* When you're back at the prompt, type `sudo shutdown -h now` which
|
||||
will turn off the (virtual) machine.
|
||||
|
||||
* Recommended: If you are using a virtual machine, take a snapshot you
|
||||
can return to this point if necessary.
|
||||
|
||||
|
||||
[1]: http://www.ubuntu.com/download/server/download
|
@ -1,122 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
In order to connect your Apple II to the network, you need a LocalTalk to
|
||||
Ethernet bridge. (Unfortunately, the [Uthernet card][1] will not work, as
|
||||
Apple's network drivers don't know what it is.)
|
||||
|
||||
If you have an enhanced Apple IIe, you will also need an [Apple II Workstation
|
||||
Card][2], and, if you're not booting over the network, the [Workstation Card
|
||||
software](a2server_howtouse.html#wsdisks). Make sure you buy one with the
|
||||
dongle. \[ <!-- [Blujay][3] --> [eBay][4] \]
|
||||
|
||||
These are the commonly available bridges; be sure you read below about their
|
||||
idiosyncracies before you buy one.
|
||||
|
||||
* Asante [AsanteTalk][5] and AsantePrint \[ [Asante][6] [eBay][7] \]
|
||||
|
||||
* Dayna EtherPrint and Mini EtherPrint (any model with an Ethernet port)
|
||||
\[ [eBay][8] \]
|
||||
|
||||
* Farallon EtherWave/EtherMac/iPrint LT with LocalTalk (PN842, PN848 or
|
||||
PN559) \[ [eBay][9] \]
|
||||
|
||||
* A pre-USB Mac with any kind of Ethernet, and the [LocalTalk Bridge][10]
|
||||
control panel installed \[ [eBay][11] \]
|
||||
|
||||
You'll also need an ImageWriter II printer cable (or any other 8-pin mini-DIN
|
||||
null-modem serial cable), or two LocalTalk transceivers joined by either a
|
||||
LocalTalk cable or four-wire phone cord, depending on whether you have Apple
|
||||
or PhoneNet transceivers. (PhoneNet transceivers also require a terminator at
|
||||
both ends; it looks like a phone plug with a resistor sticking out of it.)
|
||||
Connect each end to your Apple II and the bridge, and an Ethernet cable
|
||||
between the bridge and your router.
|
||||
|
||||
For an Apple IIgs, go to the Slots control panel by pressing ctrl-Apple-ESC,
|
||||
and set slot 1 or 2, depending on whether you are using the printer or modem
|
||||
port for networking, to "Your Card" (ROM 01 machines) or "AppleTalk" (ROM
|
||||
3 machines), and set slot 7 to "AppleTalk" (ROM 01 machines only). For an
|
||||
Apple IIe, install the Workstation Card in any slot, and be sure to connect
|
||||
your LocalTalk cable to the port with the double-arrow icon.
|
||||
|
||||
If you have multiple Apple II's you'd like to network, you can use a bridge
|
||||
for each, or a single bridge attached to daisy-chained LocalTalk transceivers.
|
||||
|
||||
Wired ethernet is recommended, but if you have an Apple AirPort or Time
|
||||
Capsule, you can use Wi-Fi by attaching your LocalTalk-to-Ethernet bridge to a
|
||||
another AirPort, and setting up an [extended network][12] (if all AirPorts are
|
||||
802.11n models), or a [WDS][13] (if any AirPort is an 802.11g model). (Most
|
||||
non-Apple routers and access points will not work because they are not
|
||||
designed to handle AppleTalk networking.)
|
||||
|
||||
|
||||
Caveat emptor:
|
||||
|
||||
* The AsanteTalk must be powered on while A2SERVER is up and running, or it
|
||||
will enter a mode where it won't operate correctly. (On the AsanteTalk, you
|
||||
will know it entered the right mode if the TX light blinks a lot during
|
||||
power-up. If it instead pulses only two or three times, then goes dark for a
|
||||
little while, and then pulses very rapidly for about three seconds, you'll
|
||||
need to remove power, make sure A2SERVER is running, and try again.)
|
||||
|
||||
* At least some of the Dayna bridges must be attached to a 10Base-T Ethernet
|
||||
port; they won't work if attached to an autosensing 10/100 or Gigabit
|
||||
Ethernet port such as those found on modern routers and switches. You can
|
||||
[buy a 10Base-T hub on eBay][14] for around $10 to go between your router
|
||||
and the bridge.
|
||||
|
||||
* Farallon bridges work fine with an Apple IIe. To prevent them from freezing
|
||||
a IIgs after a couple of minutes, you can download a fix for GS/OS ([disk
|
||||
image][15] or [ShrinkIt][16] format) and put it into SYSTEM/SYSTEM.SETUP, or
|
||||
you can [log in to the A2SERVER console](a2server_commands.html) and type
|
||||
`a2server-setup` and you will be asked if you want to install it. Because
|
||||
the fix is for GS/OS only, Farallon bridges will *not* work with a IIgs
|
||||
booted directly into ProDOS 8. (Also note: the PN842 has a built-in 8-pin
|
||||
cable, and the PN848 and PN559 have a built-in PhoneNet terminated
|
||||
transceiver, so you might not need all the cabling described above.)
|
||||
|
||||
* Using a classic Mac as a bridge works perfectly in all cases. Set AppleTalk
|
||||
to use the Ethernet port, attach the LocalTalk tranceiver or serial cable to
|
||||
the printer port (or printer/modem port), and install [LocalTalk
|
||||
Bridge][10]. (Recommended models: PowerBook 3400 with Ethernet, PowerBook G3
|
||||
with black keyboard. Any model with both a round serial port and any kind of
|
||||
Ethernet, including via expansion card, AAUI adapter, or SCSI adapter,
|
||||
should work.)
|
||||
|
||||
And finally:
|
||||
|
||||
* The Cayman GatorBox CS and the Shiva FastPath IV and V have been reported to
|
||||
work, but it's hard to find these, so I have been unable to test. If you
|
||||
have one of these and it doesn't work, [log in](a2server_commands.html) to
|
||||
A2SERVER and type `netatalk-router-off` (if you get "command not found",
|
||||
type `a2server-setup` to refresh the command list).
|
||||
|
||||
* Other LocalTalk-to-Ethernet routers and bridges may work too, but haven't
|
||||
been tested by me.
|
||||
|
||||
|
||||
Thank you:
|
||||
|
||||
Many thanks to Steven Hirsch, who fixed the Netatalk code in A2SERVER to make
|
||||
the Asante bridges start up reliably, and prevent the Dayna bridges from
|
||||
crashing the computer in GS/OS; and many thanks to Geoff Body, who contributed
|
||||
the patch to GS/OS to make Farallon bridges work reliably without freezing a
|
||||
IIgs after a few minutes. Also, thanks to all who have tested and sent reports
|
||||
on using A2SERVER with their bridges.
|
||||
|
||||
|
||||
[1]: http://a2retrosystems.com/
|
||||
[2]: http://www.apple2info.net/hardware/a2ews/a2ews.htm
|
||||
[3]: http://www.blujay.com/?keywords=workstation+card&Search.x=0&Search.y=0&Search=Search&page=search
|
||||
[4]: http://www.ebay.com/sch/i.html?_nkw=apple+workstation+card+-portrait
|
||||
[5]: http://www.asante.com/products/Asantetalk/Asantetalk.asp
|
||||
[6]: http://www.asante.com/shop/shopdisplayproducts.asp?id=16&cat=+AsanteTalk
|
||||
[7]: http://www.ebay.com/sch/i.html?_nkw=%28asantetalk%2C+asanteprint%29
|
||||
[8]: http://www.ebay.com/sch/i.html?_nkw=etherprint
|
||||
[9]: http://www.ebay.com/sch/i.html?_nkw=farallon+%28etherwave%2Cethermac%2Ciprint%29+-sl+-aui+-aaui+-pci+-nubus+-pds+-card
|
||||
[10]: http://archive.org/download/download.info.apple.com.2012.11/download.info.apple.com.2012.11.zip/download.info.apple.com%2FApple_Support_Area%2FApple_Software_Updates%2FEnglish-North_American%2FMacintosh%2FNetworking-Communications%2FOther_N-C%2FLocalTalk_Bridge_2.1.smi.bin
|
||||
[11]: http://www.ebay.com/sch/i.html?_nkw=powerbook%20(3400c%2Cg3)%20-adapter%20-pismo%20-lombard%20-bronze%20-ibook%20-g4%20-333%20-333mhz%20-400%20-400mhz%20-500%20-500mhz
|
||||
[12]: http://support.apple.com/kb/HT4259
|
||||
[13]: http://support.apple.com/kb/HT4262
|
||||
[14]: http://www.ebay.com/sch/i.html?_odkw=10base-t+%28hub%2Cswitch%29+-fast+-100+-1000+-gigabit
|
||||
[15]: http://appleii.ivanx.com/a2server/files/FARALLON.B1.PO
|
||||
[16]: http://appleii.ivanx.com/a2server/files/FARALLON.B1.BXY
|
@ -1,48 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
You can set up A2SERVER to let your Apple IIgs or IIe boot into GS/OS or
|
||||
ProDOS 8 over the network, rather than from a local drive. It can even
|
||||
download and install ProDOS 8 and GS/OS for you, meaning you can get up and
|
||||
running from "bare metal" if you wanted to.
|
||||
|
||||
To do this, [log into the a2server console](a2server_commands.md), and type:
|
||||
|
||||
~~~ bash
|
||||
a2server-setup
|
||||
~~~
|
||||
|
||||
After confirming that you want to proceed, you will be asked if you want to
|
||||
set up A2SERVER for network boot. Just follow the prompts. If you elect to
|
||||
install GS/OS, be prepared to wait for a while. You will also be given the
|
||||
option to install various utilities (GSHK, Asimov, and MountIt for GS/OS;
|
||||
ShrinkIt, DSK2FILE, and Apple System Utilities for ProDOS 8.)
|
||||
|
||||
For an Apple IIgs, set the startup slot to Slot 7 (ROM 01) or AppleTalk (ROM
|
||||
3). For an Apple IIe, put the Workstation Card in a slot higher than any other
|
||||
drive interface card, or type PR#x where x is the slot number; you must hold
|
||||
down the Open-Apple key when you press return.
|
||||
|
||||
When your Apple II boots up, it will try to boot from the network. If it's
|
||||
working, you'll see a flashing asterisk on a IIe, or a progression of periods
|
||||
at the upper left of the screen on a IIgs. You may or may not be asked to
|
||||
choose "a2server" or "raspberrypi" as your server.
|
||||
|
||||
Log in as Guest and select the A2FILES volume, and also the GSFILES volume if
|
||||
you're using a IIgs. (If you are booting into GS/OS, you can also log in as a
|
||||
registered user, but it's exactly the same.)
|
||||
|
||||
ProDOS 8 and GS/OS are stored on the volume /A2FILES; filenames are all caps
|
||||
and subject to the usual ProDOS restrictions. IIgs users can store files on
|
||||
the volume /GSFILES with mixed case, punctuated names of up to 31 characters.
|
||||
|
||||
If you installed GS/OS, you'll see a folder called GSOS.INSTALLER. In there,
|
||||
IMAGES contains all the GS/OS floppies, which can be turned back into disks by
|
||||
using Asimov in the IMAGE.TOOLS folder. You can also use run the GS/OS
|
||||
installer from the NET.INSTALL folder instead of using disks.
|
||||
|
||||
A IIgs can network boot into either GS/OS or ProDOS 8 by default, which you
|
||||
specify in the Network control panel of GS/OS, or within ProDOS 8 by running
|
||||
NETBOOT.GSOS or NETBOOT.P8, which you'll find in A2FILES (both reboot the
|
||||
computer immediately). You can temporarily network boot into ProDOS 8, without
|
||||
changing the GS/OS default, by pressing "8" while the dots are filling in
|
||||
during the first phase of the network boot (thanks to Geoff Body for this).
|
@ -1,68 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
The following steps explain how to prep the A2SERVER virtual machine,
|
||||
specifically [VirtualBox][1], which has the notable virtue of being free.
|
||||
However, you can also use other virtual machine products, such as those from
|
||||
[Parallels][2] and [VMware][3], and the process should be similar.
|
||||
|
||||
If you're comfortable doing so, you may also customize the steps below as you
|
||||
wish, or install Ubuntu Linux natively rather than in a VM.
|
||||
|
||||
* Download [VirtualBox 4.2.10][4].
|
||||
|
||||
* Download [Ubuntu Server 12.04 LTS][5] (A2SERVER has been tested with the
|
||||
32-bit version only).
|
||||
|
||||
* Start VirtualBox, and go to Preferences.
|
||||
|
||||
* Click Input. Set the host key to right-alt, and uncheck Auto Capture
|
||||
Keyboard.
|
||||
|
||||
* Click OK.
|
||||
|
||||
* Click New to create a new virtual machine.
|
||||
|
||||
* Enter *A2SERVER* as the VM name, and select Linux/Ubuntu as the operating
|
||||
system.
|
||||
|
||||
* Enter 256 MB for memory.
|
||||
|
||||
* Under Virtual Hard Disk, leave the defaults (Start-up Disk, and Create new
|
||||
hard disk).
|
||||
|
||||
* Choose VMDK for hard disk file type.
|
||||
|
||||
* Leave the virtual disk file as Dynamically allocated.
|
||||
|
||||
* Leave the virtual disk file location as A2SERVER, and set the disk size to
|
||||
32 GB.
|
||||
|
||||
* Click Create, and then again in the next window.
|
||||
|
||||
* Click Settings.
|
||||
|
||||
* Click Storage. Click on \"Empty\" under \"IDE Controller\".
|
||||
|
||||
* Click on the small CD icon on the far right of the window, select \"Choose a
|
||||
virtual CD/DVD disk file...\", and choose the Ubuntu Server file you
|
||||
downloaded.
|
||||
|
||||
* Click Network.
|
||||
|
||||
* Change \"Attached To:\" to \"Bridged Adapter\".
|
||||
|
||||
* Change \"Name:\" to a **wired** network interface on your computer. If you
|
||||
don't have one, use a USB-to-Ethernet adapter. (A2SERVER won't work over
|
||||
Wi-Fi when running in a VM.)
|
||||
|
||||
* Optional but recommended: Under Advanced, change the MAC Address to
|
||||
080003F2FF59.
|
||||
|
||||
* Click OK.
|
||||
|
||||
|
||||
[1]: http://www.virtualbox.org/
|
||||
[2]: http://www.parallels.com/
|
||||
[3]: http://www.vmware.com/
|
||||
[4]: https://www.virtualbox.org/wiki/Downloads/
|
||||
[5]: http://www.ubuntu.com/download/server/
|
@ -1,68 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
So you got a [Raspberry Pi][1]. Congratulations!
|
||||
Are you ready to turn it into a file server for your Apple II? Here's how.
|
||||
|
||||
<!--
|
||||
*Important: As of 11-Aug-14, A2SERVER 1.2.0 is now compatible with the latest
|
||||
version of Raspbian (NOOBS 1.3.9/2014-Jun-20), and the Raspberry Pi Model B+.
|
||||
Type `a2server-setup` to update. If you are already running A2SERVER, and it
|
||||
stopped working after a Raspbian update, see the
|
||||
[recovery page](a2server_recovery.md).*
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### Starting fresh:
|
||||
|
||||
If you haven't already started working with a Raspberry Pi, then [download
|
||||
Raspple II][2], a distribution of the Raspbian operating system which includes
|
||||
A2SERVER, [A2CLOUD][3], and David Schmenk's [Apple II Pi][4].
|
||||
|
||||
Expand the RasppleII.zip file, and copy all of its files to a 4 GB or larger
|
||||
SD card. Then put the SD card in your Pi, and attach power. The operating
|
||||
system will automatically install, which will take about 20 minutes.
|
||||
|
||||
When it's done, your Pi will reboot into Raspbian. If you don't have a
|
||||
screen attached, you'll know when it's done when the ACT/OK lamp on the
|
||||
Raspberry Pi board stops flickering.
|
||||
|
||||
(If you are starting over with the same SD card, or want to ensure the card is
|
||||
formatted correctly, you can use the official [SD Formatter][5] utility --
|
||||
carefully! -- before copying the files.)
|
||||
|
||||
If you wish to log in (you don't need to to use A2SERVER), the username is
|
||||
"pi" and password "apple2". (If you do not have a screen and keyboard
|
||||
attached to your Raspberry Pi, read about [logging into a Raspberry Pi from
|
||||
another computer](a2server_raspberrypi_login.md), including an Apple II.) If
|
||||
you wish to change any configuration options, type `raspi-config`.
|
||||
|
||||
For next steps, check out the links on the [A2SERVER home page](index.md).
|
||||
|
||||
|
||||
### Already using a Raspberry Pi?
|
||||
|
||||
If you're already using Raspbian, you can install A2SERVER by typing at a
|
||||
Linux prompt:
|
||||
|
||||
~~~ bash
|
||||
wget appleii.ivanx.com/a2server/setup; source setup
|
||||
~~~
|
||||
|
||||
The process is straightforward -- just respond to the prompts.
|
||||
|
||||
For next steps, check out the links on the [A2SERVER home page](index.md).
|
||||
|
||||
|
||||
<!--
|
||||
(If you wish, you can read detailed technical information about the [AppleTalk
|
||||
networking support on the Raspberry Pi](a2server_raspberrypi_kernel.md) that
|
||||
A2SERVER installs.)
|
||||
-->
|
||||
|
||||
|
||||
[1]: http://www.raspberrypi.org
|
||||
[2]: http://appleii.ivanx.com/rasppleii/
|
||||
[3]: http://appleii.ivanx.com/a2cloud
|
||||
[4]: http://schmenk.is-a-geek.com/wordpress
|
||||
[5]: https://www.sdcard.org/downloads/formatter_4/
|
@ -1,56 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
You need to access the Raspberry Pi's command prompt in order set up A2SERVER
|
||||
for network boot, and [do other stuff](a2server_commands.md).
|
||||
|
||||
The default username is "pi" and default password is "apple2". If you
|
||||
don't have a screen and keyboard attached, you can:
|
||||
|
||||
|
||||
### Log in via SSH from another computer
|
||||
|
||||
On a Mac, open Terminal (in the Utilities folder of the Applications folder),
|
||||
and type `ssh pi@raspberrypi.local` to connect. If you have Windows, you can
|
||||
install [Bonjour Print Services][1], and then use [PuTTY][2] to connect to the
|
||||
address "raspberrypi.local".
|
||||
|
||||
If that doesn't work, or you don't want to install Bonjour Print Services
|
||||
for Windows, you will need to find your Pi's IP address and use that instead.
|
||||
If you have a Mac, you can use [Pi Finder][3] to help with this; if you have
|
||||
Windows, you can use [Advanced IP Scanner][4]. Once logged in, you can type
|
||||
`showmac` to see your Pi's MAC (Ethernet) address, and you can use this to
|
||||
reserve an IP address in your router so the Pi gets the same IP address every
|
||||
time.
|
||||
|
||||
|
||||
### Log in from an Apple II
|
||||
|
||||
There are a few different options for logging in from an Apple II. They are:
|
||||
|
||||
* Apple II serial: With the appropriate cables, you can use a terminal
|
||||
communications program such as [ProTERM][5], [Spectrum][6], or Z-Link
|
||||
to log into and control your Raspberry Pi. All this is set up
|
||||
automatically with [A2CLOUD][7], so head over there to read about how
|
||||
to install it and find out what cables you need to get.
|
||||
|
||||
|
||||
* Apple II Ethernet: If you have an [Uthernet Card][8] in an Apple IIgs, you
|
||||
can log into your Raspberry Pi with [Spectrum][6] using VT100 emulation
|
||||
(once logged in, type `TERM=vt100`). To make this work you will need to
|
||||
first log into your Pi by one of the above methods, and type `sudo apt-get
|
||||
-y install telnetd` (you may not wish to do this if your Pi is on a network
|
||||
with any untrusted users, as Telnet is unencrypted). Also, note your Pi's
|
||||
IP address (you can type `showip` once logged in) so you can provide it to
|
||||
Spectrum Internet Suite; you might want to put a DHCP reservation into your
|
||||
router (type `showmac` to get your Pi's MAC address) so you don't have to
|
||||
figure it out again.
|
||||
|
||||
|
||||
[1]: http://support.apple.com/kb/dl999
|
||||
[2]: http://www.chiark.greenend.org.uk/~sgtatham/putty/
|
||||
[3]: http://ivanx.com/raspberrypi/files/PiFinder.zip
|
||||
[4]: http://www.advanced-ip-scanner.com
|
||||
[5]: http://lostclassics.apple2.info/downloads/?dl_cat=11
|
||||
[6]: http://www.wannop.info/speccie/Site/Speccies_Home_Pages.html
|
||||
[7]: http://appleii.ivanx.com/a2cloud/
|
||||
[8]: http://a2retrosystems.com
|
@ -1,109 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
If you had A2SERVER running, and you typed either `apt-get update` or
|
||||
`rpi-update`, you may have received Linux kernel version 3.12 through 3.15.
|
||||
These, unfortunately, include a defective AppleTalk kernel module which will
|
||||
kernel panic (crash) your system on startup when A2SERVER tries to activate
|
||||
AppleTalk networking.
|
||||
|
||||
If you have a screen or console cable attached, you will see some debugging
|
||||
information that concludes with "Kernel panic." If you don't have a screen
|
||||
attached, there will be no visible signs other than that you simply can't
|
||||
connect from another computer on your network.
|
||||
|
||||
To prevent this from happening, type `a2server-setup` *before* updating the
|
||||
software on your computer. If it's too late, and you need to recover from
|
||||
this situation, you could [start over][1]. Or, if you want to keep your
|
||||
current installation, you have a few options, depending on your setup:
|
||||
|
||||
|
||||
### A2SERVER virtual machine, or on other non-Raspberry Pi Linux computer
|
||||
|
||||
* Start up the virtual or real machine.
|
||||
|
||||
* On the GRUB startup screen, choose the Recovery kernel.
|
||||
|
||||
* At the Linux prompt, type `a2server-setup`
|
||||
|
||||
|
||||
### A2SERVER on Raspberry Pi with screen/keyboard/mouse attached
|
||||
|
||||
* Press the shift key rapidly and repeatedly while your Pi starts up. If you
|
||||
have an HDMI monitor, you can stop when you see the installer screen. If you
|
||||
have a composite monitor, stop after about a minute, and then press 3 (PAL,
|
||||
e.g. Europe) or 4 (NTSC, e.g. North America and Japan), and you should see
|
||||
the installer screen.
|
||||
|
||||
* Press E for Edit, then click the *cmdline.txt* tab.
|
||||
|
||||
* At the end of the line, append `single` (preceded by a space).
|
||||
|
||||
* Press OK to save, then ESC to reboot.
|
||||
|
||||
* Log in with username "pi" and password "apple2".
|
||||
|
||||
* At the Linux prompt, type `a2server-setup`
|
||||
|
||||
|
||||
### A2SERVER on Raspberry Pi without screen/keyboard mouse, and a Mac
|
||||
|
||||
* Remove the SD card from your Pi and insert it in your Mac.
|
||||
|
||||
* Look for a volume named BOOT to appear.
|
||||
|
||||
* Within it, open *cmdline.txt* in a text editor (the default is TextEdit).
|
||||
|
||||
* At the end of the line, append `single` (preceded by a space), then save it.
|
||||
|
||||
* Eject the SD card and put it back in your Pi, then start up your Pi.
|
||||
|
||||
* [Log in to your Pi](a2server_raspberrypi_login.md) and type `a2server-setup`
|
||||
|
||||
|
||||
### A2SERVER on Raspberry Pi without screen/keyboard mouse, and a Linux computer
|
||||
|
||||
* Remove the SD card from your Pi.
|
||||
|
||||
* On your Linux computer, type:
|
||||
|
||||
~~~ bash
|
||||
wget ivanx.com/a2server/fix; source fix
|
||||
~~~
|
||||
|
||||
* Follow the on-screen instructions.
|
||||
|
||||
* If after using the fix tool, you still can't connect from your Apple II,
|
||||
[log in to your Pi][2], and type `a2server-setup`
|
||||
|
||||
* (Alternative approach: Follow the Mac method above, though the volume may
|
||||
not appear as BOOT.)
|
||||
|
||||
|
||||
### A2SERVER on Raspberry Pi without screen/keyboard/mouse, and a Windows computer
|
||||
|
||||
* Remove the SD card from your Pi.
|
||||
|
||||
* Install the [A2SERVER virtual machine](a2server_virtualbox.md) on your
|
||||
Windows computer.
|
||||
|
||||
* Start the virtual machine, and log in with user name "user1" and
|
||||
password "apple2".
|
||||
|
||||
* In the virtual machine window, type:
|
||||
|
||||
~~~ bash
|
||||
wget ivanx.com/a2server/fix;source fix
|
||||
~~~
|
||||
|
||||
* Follow the on-screen instructions.
|
||||
|
||||
* Type `system-shutdown` in the virtual machine window.
|
||||
|
||||
* Quit VirtualBox.
|
||||
|
||||
* If after using the fix tool, you still can't connect from your Apple
|
||||
II, [Log in to your Pi](a2server_raspberrypi_login.md) and type
|
||||
`a2server-setup`
|
||||
|
||||
|
||||
[1]: http://ivanx.com/a2server/
|
@ -1,123 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
When you type A2SERVER-setup, a series of scripts are downloaded from
|
||||
appleii.ivanx.com and executed, some with root privileges. They are run from
|
||||
the /tmp folder, and deleted upon completion.
|
||||
|
||||
Here is what they do, in the order shown (click the links to view the scripts
|
||||
themselves):
|
||||
|
||||
[Master setup script](setup/index.txt)
|
||||
|
||||
* checks for supported OS and warns if it isn't
|
||||
|
||||
* offers to change user password (Raspberry Pi only)
|
||||
|
||||
* runs all of the scripts below
|
||||
|
||||
* offers to download a replacement kernel with AppleTalk support (Raspberry Pi
|
||||
only)
|
||||
|
||||
|
||||
[Storage setup](scripts/a2server-1-storage.txt) (runs during initial setup, skipped on subsequent runs)
|
||||
|
||||
* Make the /srv/A2SERVER directory
|
||||
|
||||
|
||||
[A2SERVER tools install](scripts/a2server-2-tools.txt) (always runs)
|
||||
|
||||
<!--
|
||||
* update package list and upgrade packages (apt-get update/upgrade)
|
||||
-->
|
||||
|
||||
* download, compile, and install nulib2 (ShrinkIt archive utility), into
|
||||
/usr/local/bin
|
||||
|
||||
* install libraries required for compiling [The Unarchiver][1]
|
||||
|
||||
* download, compile, and install unar/lsar (The Unarchiver), into
|
||||
/usr/local/bin
|
||||
|
||||
* install A2SERVER tools into /usr/local/bin and /usr/local/etc:
|
||||
[afpsync](scripts/tools/afpsync.txt),
|
||||
[afptype](scripts/tools/afptype.txt),
|
||||
[cppo](scripts/tools/cppo.txt),
|
||||
[mkatinit](scripts/tools/mkatinit.txt),
|
||||
[volnifo](scripts/tools/mkvolinfo.txt),
|
||||
[aliases](scripts/tools/a2server-aliases.txt) (described at the bottom of
|
||||
[this page](a2server_commands.html))
|
||||
|
||||
* set up aliases file to be read at each login (/etc/profile)
|
||||
|
||||
* customize pre-login message on Ubuntu (/etc/issue), or post-login message on
|
||||
non-Ubuntu (/etc/motd)
|
||||
|
||||
|
||||
[Netatalk install and configure](scripts/a2server-3-sharing.txt) (runs during
|
||||
initial setup and if upgrade to Netatalk is required; otherwise skipped)
|
||||
|
||||
* stop Netatalk service if it is running
|
||||
|
||||
* update package list and upgrade packages
|
||||
|
||||
* download and install libraries required for compiling Netatalk
|
||||
|
||||
* download Netatalk source code
|
||||
|
||||
* modify source code to make dates work correctly
|
||||
|
||||
* compile and install Netatalk
|
||||
|
||||
* set up Netatalk configuration files for Apple II use
|
||||
|
||||
* start Netatalk service
|
||||
|
||||
|
||||
[Network boot setup](scripts/a2server-5-netboot.txt) (always runs)
|
||||
|
||||
* ask whether user wants network boot (skips to the last step in this section
|
||||
if not)
|
||||
|
||||
* download boot blocks disk from Apple and convert it to raw block dump file
|
||||
|
||||
* copy boot blocks files and BASIC.SYSTEM
|
||||
|
||||
* use mkatinit to enable Apple II network boot
|
||||
|
||||
* patch boot block files to support cleartext passwords, and typing "8"
|
||||
during IIGS network startup to force ProDOS 8 boot
|
||||
|
||||
* ask user whether to download and install GS/OS
|
||||
|
||||
* ask whether user wants to download disk image and file utilities
|
||||
|
||||
* ask whether user wants to install Farallon bridge patch
|
||||
|
||||
|
||||
[Windows file sharing](scripts/a2server-6-samba.txt) (always runs)
|
||||
|
||||
* ask whether user wants Windows file sharing, and if so:
|
||||
|
||||
* download and install samba, and start the service
|
||||
|
||||
* set up samba configuration files
|
||||
|
||||
* if user doesn't want Windows file sharing, stop the samba service
|
||||
|
||||
|
||||
[Console optimizing](scripts/a2server-7-console.txt) (runs during initial
|
||||
setup, skipped on subsequent runs)
|
||||
|
||||
* disable default Ubuntu Server login message
|
||||
|
||||
* make console clear boot messages before initial login prompt
|
||||
|
||||
* eliminate piix4\_smbus error message before initial login prompt
|
||||
|
||||
* prevent console from going blank after ten minutes of inactivity (after
|
||||
login)
|
||||
|
||||
* resolve a slow-scrolling problem in Ubuntu Server 10.04 (only)
|
||||
|
||||
|
||||
[1]: http://wakaba.c3.cx/s/apps/unarchiver.html
|
@ -1,234 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
|
||||
The A2SERVER Odyssey
|
||||
|
||||
A2SERVER has been a multi-year labor of love.
|
||||
|
||||
Way back in 2010, my primary Apple II was a Mac Color Classic with an Apple
|
||||
IIe compatibility card.
|
||||
|
||||
One of the things this card could do was emulate something called a
|
||||
Workstation Card, which appeared to let Apple II computers access files on a
|
||||
Mac file server. This was intriguing; I hadn't imagined it was possible.
|
||||
|
||||
And it was also potentially valuable as a way of providing mass storage for an
|
||||
Apple II, with the bonus that other computers could easily access it as a
|
||||
means of getting stuff to and from an otherwise isolated machine.
|
||||
|
||||
After some experimenting, I discovered that was exactly what it did, and I
|
||||
bought an actual Workstation Card for my IIe, because that would be much, much
|
||||
cooler. And it appeared that you could even *boot* the Apple II into ProDOS
|
||||
from the network, which blew my mind. Using AppleShare 3.0 on another Mac as a
|
||||
host, I made this happen, and there was much rejoicing.
|
||||
|
||||
Then, I got an idea into my head: this is great and everything, but you still
|
||||
need an old Mac around. How great would it be if you could just have an
|
||||
always-on network drive for an Apple II, with all the storage you might ever
|
||||
need, and accessible from other computers on the LAN?
|
||||
|
||||
(It's true that there were Compact Flash storage cards at the time, and I
|
||||
actually bought CFFA #16, but these didn't appeal to me quite as much because
|
||||
of their relative lack of accessibility on other platforms. I'd need some
|
||||
sort of CF extender to get the card outside the machine, then run CiderPress
|
||||
in a Windows emulator...)
|
||||
|
||||
It so happens that I had purchased a Western Digital My Book World Edition,
|
||||
which was one of the first popular NAS products available. It was basically a
|
||||
small Linux computer in a drive enclosure, and it was widely hacked to make it
|
||||
do all kinds of tricks, one of which was providing native file sharing for
|
||||
Macs.
|
||||
|
||||
This was possible by installing Netatalk, an open-source implentation of AFP
|
||||
(AppleShare). I immediately wondered if it would be possible to somehow get my
|
||||
IIe to talk to it. So I looked into it, and it appeared that Netatalk running
|
||||
on Linux still supported the older AppleTalk networking protocol required by
|
||||
an Apple II, and it even supported network boot into ProDOS.
|
||||
|
||||
There was the issue of how to actually interface my Apple II to the network;
|
||||
this turned out to be relatively easy, by using an Apple-provide control panel
|
||||
for classic Macs called LocalTalk Bridge, which indeed bridged AppleTalk from
|
||||
its LocalTalk port (connected to an Apple II) to its Ethernet port (connected
|
||||
to my network, which was connected to the NAS). But this was clumsy, so I
|
||||
invested in an AsanteTalk, which is a dedicated (if finicky)
|
||||
LocalTalk-to-Ethernet bridge.
|
||||
|
||||
What I discovered, after some time, was that a) the version of Linux that
|
||||
shipped on that NAS did not include support for AppleTalk networking, and b)
|
||||
the easily-installed Netatalk package didn't include the components required
|
||||
for network boot, which I absolutely wanted.
|
||||
|
||||
I wasn't terribly Linux-savvy at the time, but I eventually figured out that
|
||||
to get network boot support, I would need to download Netatalk and compile it
|
||||
myself, from source. Ok. But once I learned that adding AppleTalk support
|
||||
overall would require recompiling a kernel for the drive, I kind of put the
|
||||
idea aside, figuring I'd bring it to KFest and hack on it with someone there
|
||||
who knows what they're doing.
|
||||
|
||||
In the meantime, I decided to see if I could make things work exactly as I
|
||||
wanted with a "proper" Linux installation. Ubuntu Linux was well-known for
|
||||
its relative ease of use, so I installed that into VMWare Fusion running on my
|
||||
(modern) Mac. I installed the Netatalk package, and that worked -- though it
|
||||
was still missing the network boot component, and there were other issues like
|
||||
password login not working correctly.
|
||||
|
||||
So I had to figure out how to recompile Netatalk to make it do what I needed.
|
||||
I managed to figure this out after much effort and studying of posts and
|
||||
contributions to comp.sys.apple2, but wasn't able to get it to actually
|
||||
netboot to ProDOS.
|
||||
|
||||
So this led me to comp.sys.apple2, and there met two people who turned out to
|
||||
be two enormous contributors to A2SERVER: Steven Hirsch, who wrote much of the
|
||||
actual network boot support in Netatalk, and Geoff Body, who knows everything
|
||||
about the "boot blocks" that get transferred to the Apple IIe or IIgs during
|
||||
network startup. Both Steven and Geoff have also helped figure out and work
|
||||
around the idiosyncracies of many of the dedicated LocalTalk-to-Ethernet
|
||||
bridges, and have been essential contributors to the execution of A2SERVER.
|
||||
|
||||
The initial conversation is chronicled in perpetuity here:
|
||||
https://groups.google.com/forum/#!topic/comp.sys.apple2/b\_TzESci6Kg
|
||||
|
||||
With their help, I finally succeeded in network booting my Apple IIe from my
|
||||
Linux virtual machine. The first proto-version of A2SERVER was a step-by-step
|
||||
guide to manually set it up, as posted here:
|
||||
https://groups.google.com/forum/#!topic/comp.sys.apple2/lkh4hXqmJbE
|
||||
|
||||
I could have left it at that, but I didn't like it. It wasn't all THAT easy
|
||||
for a non-Linux person, network boot relied on Apple software from a "secret
|
||||
archive" and hand-hacked binary code from within the guide itself, and the
|
||||
final setup was hard-coded to a specific user name. I wanted a version that
|
||||
was general-purpose, easy for anyone to install, and which obtained any
|
||||
copyrighted software from 100% public, authorized sources.
|
||||
|
||||
And which, in a perfect world, could be configured to netboot from "bare
|
||||
metal" -- that is, a bare computer with nothing but Linux would be able to
|
||||
boot an Apple IIe or IIgs with no operating system, software, or even any
|
||||
drives at all.
|
||||
|
||||
I hadn't forgotten about wanting it to run on a NAS, either, but I figured
|
||||
I'd circle back to that, since it was so much easier working in a VM. For the
|
||||
time being, what I'd ship would be both a premade VM, and a complete
|
||||
installer script for actual Linux installations. And that would be A2SERVER.
|
||||
|
||||
Then it was a matter of locating what I could, from anyone I could, to make it
|
||||
work. I discovered that the boot blocks and BASIC.SYSTEM -- the essential
|
||||
pieces for netbooting ProDOS 8 -- were ensconced with the GSOS "Disk 7"
|
||||
image available from Apple's Older Software downloads page. But that disk
|
||||
image was a DiskDoubler self-extracting archive. Fortunately, The Unarchiver
|
||||
could uncompress it, and is open-source, and builds on Linux. The disk image
|
||||
was actually an HFS disk, which Linux has support for, so I was able to mount
|
||||
it and copy the files out.
|
||||
|
||||
Steven contributed a huge fix to the Netatalk source code so ProDOS dates get
|
||||
handled correctly. Geoff gave me patches to the Boot Blocks to fix a cleartext
|
||||
login bug and allow an on-demand startup option to boot into ProDOS 8 on a
|
||||
IIgs.
|
||||
|
||||
Then I had to hack a bunch of stuff together. I wrote mkatinit to create the
|
||||
very specific user login files required for netboot; afpsync to simplify
|
||||
Netatalk's handling of new shared files introduced from Linux; afptype to
|
||||
allow setting the ProDOS (or classic Mac) file type of a file shared by
|
||||
Netatalk.
|
||||
|
||||
These tools, plus a properly-compiled-and-configured Netatalk, made it
|
||||
possible for a Linux server to entirely download ProDOS 8 and set it up for
|
||||
network boot by an Apple II. Nothing had to be done on the Apple II side. Bare
|
||||
metal!
|
||||
|
||||
I then shaped my guide into an actual executable script which could be
|
||||
downloaded from my web site and executed on any Ubuntu installation. I
|
||||
expanded the script to download and install the necessary tools, apply the
|
||||
necessary patches, and everything else I felt was needed for click-and-go
|
||||
server Apple II server setup, such as optional Windows file sharing (since one
|
||||
of the goals was easy file interchange with modern computers).
|
||||
|
||||
And that was kinda that -- almost. I'd conquered the IIe, but the real Mt.
|
||||
Everest was bare metal GS/OS netboot. This was much more challenging: it meant
|
||||
I'd have to get the files out of the ProDOS-formatted GSOS installer disk
|
||||
images, with resource forks intact and made usable by Netatalk. This is what I
|
||||
wanted to show off when I introduced A2SERVER at KansasFest 2011.
|
||||
|
||||
There was no off-the-shelf solution for this, so I spent pretty much every
|
||||
waking hour in Kansas City furiously creating cppo, which would copy files out
|
||||
of a ProDOS disk image. And...I failed. I just ran out of time before my
|
||||
presentation.
|
||||
|
||||
So I installed a Network Startup instalation of GS/OS the conventional way --
|
||||
using the IIgs installer disks running on a IIgs, with the Netatalk shared
|
||||
volume as the target. (The CFFA3000, which was also introduced that same
|
||||
KansasFest, was absolutely invaluable for this.)
|
||||
|
||||
And it worked. In my presentation, I was able to network boot Peter
|
||||
Neubauer's Apple IIe with nothing but the Workstation Card; and my IIgs with
|
||||
nothing but a RAM card.
|
||||
|
||||
Then I came back home. I completed cppo, and it worked, mostly; with that
|
||||
done, I then set about writing something to interpret the GS/OS installer
|
||||
scripts and cppo the right pieces to the right places. And...it worked too.
|
||||
Except that it didn't. It all started up, but the Finder had random
|
||||
filenames, the Trash was full when there was nothing in it. It was corrupt.
|
||||
Who knows why. I gave up.
|
||||
|
||||
I wasn't satisfied with not being able to start up a IIgs at all if you
|
||||
didn't have the installer disks; so I made it netboot into ProDOS 8, from
|
||||
where you could use DSK2FILE (which the A2SERVER installer script offers to
|
||||
download) to convert the disk images to actual disks, which you could then use
|
||||
to make an AppleShare startup floppy, which you could THEN use to mount the
|
||||
shared volume and use it as a target for a full Network Startup install. Icky,
|
||||
and of possible benefit to no one (really, who doesn't have GS/OS install
|
||||
disks and a drive?), but it was some kind of solution. I packaged up the VM,
|
||||
put up these web pages, and decided it was Done.
|
||||
|
||||
But the NAS thing itched at me. I wanted to be able to suggest an easily
|
||||
obtained product. By now, WD had replaced my NAS with the My Book Live, which
|
||||
featured a much faster processor, and was based on Debian Linux, which is what
|
||||
Ubuntu is derived from. This was a promising starting point. I figured out how
|
||||
to compile an AppleTalk kernel module for it. And then I already had these
|
||||
turnkey scripts ready to go, so I hacked, and hacked, and...I couldn't get it
|
||||
to work. I'd sometimes get gibberish for volume names, and network boot would
|
||||
load the boot blocks, and then never stop loading, filling the Apple II's
|
||||
memory with zeroes until it crashed. (My suspicion is that the big-endianness
|
||||
of the PowerPC CPU in the newer NAS may have been a factor.) Fixing that would
|
||||
have taken me deep into the packetized heart of Netatalk, which is beyond my
|
||||
pay grade. I gave up, and decided A2SERVER was Done. Again.
|
||||
|
||||
Until I went to KansasFest 2012, and Eric Rucker showed me something I had
|
||||
never heard of: a Raspberry Pi. Somewhere, the gears started turning, and
|
||||
months later I checked it out, and saw that its primary operating system
|
||||
was...a Debian derivative. Could this be my long-sought-after NAS?
|
||||
|
||||
It was. The install scripts ran with only a little tweaking. I did have to
|
||||
compile AppleTalk in the kernel, but eventually I had what I wanted. And it
|
||||
was only $35!
|
||||
|
||||
I revisited the corrupted GS/OS installation. I couldn't put my finger on
|
||||
what was wrong. But I noticed that the Finder showed a different length on its
|
||||
source disk and after copying. So I followed its index blocks, and discovered
|
||||
that contained in those were 0000's. ProDOS knew to fill blocks with zeros,
|
||||
but cppo was dutifully copying Block 0, the ProDOS boot block, thereby
|
||||
corrupting the Finder. I fixed this, and then I HAD IT: Bare metal install
|
||||
GS/OS from Linux. Yeah, man.
|
||||
|
||||
And, so, then it was just tweaking and refining and tweaking and refining. The
|
||||
big bummer as far as general use goes was that all the common
|
||||
LocalTalk-to-Ethernet bridges (Dayna, AsanteTalk, and Farallon) were partially
|
||||
or completely inoperable with a IIgs, and the Workstation Card required for a
|
||||
IIe is hardly in great abundance. But Geoff Body came up with a fix for the
|
||||
Farallon, I came up with a workaround for the AsanteTalk, and Steven Hirsch
|
||||
came up with an actual fix for both the AsanteTalk and the Dayna, meaning
|
||||
*all* of those bridges are now options for a IIgs owner!
|
||||
|
||||
So this was it: bare IIgs (even without memory card, if you're OK with ProDOS
|
||||
8) + Raspberry Pi + readily available bridge = Apple II file server. Yeah!
|
||||
|
||||
And I discovered that with a USB cable or RPi console cable, you could
|
||||
actually log in and control it with ProTERM. With Hugh Hood's clever ProTERM
|
||||
patch for 115,200 bps on a IIgs, I could actually see my Raspberry Pi start
|
||||
up...on my Apple II. I can't explain how joyous this made me.
|
||||
|
||||
And, I wrote ProDOS 8 utilities to switch the IIgs boot mode, which is
|
||||
normally only possible under GS/OS.
|
||||
|
||||
I could go on and on, but basically the ideas kept coming, and I think I was
|
||||
able I was able to polish most of A2SERVER's rough edges so that it could be
|
||||
fun and/or useful for a few people. I hope you enjoy it!
|
@ -1,44 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
|
||||
To set up A2SERVER, follow these steps:
|
||||
|
||||
* Download and install [VirtualBox][1]. It's free. (If you prefer different
|
||||
virtual machine software, [you can instead use the A2SERVER installer
|
||||
script](a2server_installer.md).)
|
||||
|
||||
* Download the [A2SERVER virtual machine](files/A2SERVER.ova) (~750 MB), or
|
||||
the [A2SERVER+A2CLOUD virtual machine](files/A2SERVER_A2CLOUD.ova) (~1.7
|
||||
GB).
|
||||
|
||||
* Open VirtualBox, and choose "Import Appliance..." from the File menu.
|
||||
Select the file you downloaded (A2SERVER.ova).
|
||||
|
||||
* Leave the "Reinitialize the MAC address of all network cards" box
|
||||
unchecked. Click Import.
|
||||
|
||||
* When it's done importing, click A2SERVER, then click Settings, then click
|
||||
Network.
|
||||
|
||||
* Ensure that "Attached To:" is set to "Bridged Adapter".
|
||||
|
||||
* Set "Name:" to a _wired_ network interface on your computer. If you don't
|
||||
have one, use a USB-to-Ethernet adapter. (A2SERVER won't work over Wi-Fi in
|
||||
a virtual machine.)
|
||||
|
||||
* Click OK.
|
||||
|
||||
|
||||
You're all set up. For next steps, check out the links on the [A2SERVER home
|
||||
page](index.md).
|
||||
|
||||
|
||||
SHA-1 for A2SERVER VM: d6c60b0ab14f14ddd49b7e5cdac39503db96a903
|
||||
SHA-1 for A2SERVER+A2CLOUD VM: 69df7c28fa21e4e4cc01b106398936f23559a64b
|
||||
<!--
|
||||
v1.1.3: a8927d6fba9dfa9c2015918cdc61122bb2c95ea5
|
||||
v1.1.0: 63eebfcfe9fbbeb17aa4ab3226e849289072d396
|
||||
-->
|
||||
|
||||
|
||||
[1]: https://www.virtualbox.org/wiki/Downloads
|
@ -1,78 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
While wired Ethernet is recommended, it's possible to use A2SERVER with Wi-Fi
|
||||
if you have an Apple AirPort or Time Capsule. (A2SERVER won't work with most
|
||||
non-Apple router and access point models, as they are not designed to handle
|
||||
AppleTalk networking.)
|
||||
|
||||
To connect your Apple II via Wi-Fi, read how to [attach your Apple II to your
|
||||
local network](a2server_lan.md).
|
||||
|
||||
If you want your A2SERVER machine (whether virtual, real, or Raspberry Pi) to
|
||||
connect to your network via Wi-Fi, you first need to configure a Wi-Fi network
|
||||
adapter via the instructions below. Once you've got that up and running, [log
|
||||
in](a2server_commands.md) to A2SERVER and type `netatalk-wifi` to tell
|
||||
A2SERVER to use the Wi-Fi interface (if you get "command not found", type
|
||||
`a2server-setup` to refresh the command list).
|
||||
|
||||
|
||||
Setting up Wi-Fi on your A2SERVER machine:
|
||||
|
||||
### Multiple AirPorts
|
||||
|
||||
As an alternative to using a Wi-Fi network adapter, any of the machine types
|
||||
below can work with Wi-Fi simply by connecting the wired Ethernet interface to
|
||||
another AirPort and setting up an [extended network][1] (if all AirPorts are
|
||||
802.11n models), or a [WDS][2] (if any AirPort is an 802.11g model).
|
||||
|
||||
|
||||
### Raspberry Pi
|
||||
|
||||
[We got a whole page about that.][3]
|
||||
|
||||
|
||||
### Virtual machine
|
||||
|
||||
On a virtual machine, A2SERVER won't work over Wi-Fi with the virtual network
|
||||
interface, but you may, or may not, be able to use a USB Wi-Fi adapter
|
||||
attached your VM's emulated USB port, and then follow the instructions below
|
||||
for a real machine. Some adapters may have issues with specific virtual
|
||||
machine software; for example, Atheros 9K based adapters [do not work with
|
||||
VirtualBox][4] or VMWare Fusion, though they do work with Parallels Desktop;
|
||||
Realtek 81xx based adapters seem to work with VirtualBox (at minimum).
|
||||
|
||||
|
||||
### Real machine (Intel or compatible)
|
||||
|
||||
On a standard computer with a native Linux installation, if you can get a
|
||||
Wi-Fi adapter working, it will probably work with A2SERVER. Instructions will
|
||||
vary by distribution, but should be similar to [the guide for Raspberry
|
||||
Pi][3], with a much wider range of usable adapters.
|
||||
|
||||
If those steps don't work, type `sudo nano /etc/network/interfaces`, and edit
|
||||
the file so it contains a sequence of lines that look like this:
|
||||
`allow-hotplug wlan0 iface wlan0 inet dhcp wpa-ssid MyNetworkName` (substitute
|
||||
your Wi-Fi network name) `wpa-psk abcdefgh` (substitute your WPA password, or
|
||||
its 64-character hex equivalent)
|
||||
|
||||
If you are using WEP encryption instead of WPA, replace the last two lines
|
||||
with:
|
||||
`wireless-essid MyNetworkName` (substitute your Wi-Fi network name)
|
||||
`wireless-key abcde` (substitute your 5 or 13 character, or 10 or 26 hex byte,
|
||||
WEP password)
|
||||
|
||||
Spaces in the Wi-Fi network name or password may not work.
|
||||
|
||||
Remove any other chunks which mention wlan0, and save the file (press
|
||||
control-w). Then type: `sudo ifdown wlan0; sudo ifup wlan0`
|
||||
|
||||
Finally, type `ip addr`. If you see an IP address for wlan0 (next to
|
||||
"inet"), your Wi-Fi adapter is on your network, and you can disconnect your
|
||||
Ethernet or serial cable. (If you don't seem to have internet access, type
|
||||
`sudo shutdown -r now` to restart.)
|
||||
|
||||
|
||||
[1]: http://support.apple.com/kb/HT4259
|
||||
[2]: http://support.apple.com/kb/HT4262
|
||||
[3]: http://ivanx.com/raspberrypi/raspberrypi_wifi.html
|
||||
[4]: https://www.virtualbox.org/ticket/9511
|
@ -1,114 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo
|
||||
echo "A2SERVER fix: This utility will make a Raspberry Pi SD card boot if it"
|
||||
echo "kernel panics (crashes) on startup after updating its operating system"
|
||||
echo "while A2SERVER is installed."
|
||||
echo
|
||||
echo -n "Continue? "
|
||||
read
|
||||
doFix=
|
||||
if [[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]]; then
|
||||
while true; do
|
||||
echo
|
||||
echo "If attached, remove the Raspberry Pi's SD card from this computer."
|
||||
echo -n "Press return to continue..."; read; echo
|
||||
|
||||
ls -1 /dev/sd? > /tmp/sd1 2> /dev/null
|
||||
|
||||
echo "Insert the Raspberry Pi's SD card into this computer, using a USB"
|
||||
echo "reader if you don't have an SD slot. If this is a virtual machine,"
|
||||
echo "make sure you select the reader or SD slot from its USB menu."
|
||||
echo -n "Press return to continue..."; read; echo
|
||||
|
||||
ls -1 /dev/sd? > /tmp/sd2 2> /dev/null
|
||||
|
||||
# if exactly one drive has been inserted, exit loop
|
||||
if { ! diff /tmp/sd1 /tmp/sd2 &> /dev/null; }; then
|
||||
# files are different, get dev name
|
||||
if [[ $(wc -c /tmp/sd1 | cut -f 1 -d ' ') -eq 0 ]]; then
|
||||
if [[ $(wc -l /tmp/sd2 | cut -f 1 -d ' ') -eq 1 ]]; then
|
||||
devName=$(cat /tmp/sd2)
|
||||
break
|
||||
else
|
||||
echo "More than one volume seems to have appeared. Trying again..."
|
||||
echo
|
||||
fi
|
||||
else
|
||||
devName=$(grep -v "$(cat /tmp/sd1)" /tmp/sd2)
|
||||
if [[ $(wc -l <<< $devName) -eq 1 ]]; then
|
||||
break
|
||||
else
|
||||
echo "More than one volume seems to have appeared. Trying again..."
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "No SD card found. Trying again..."
|
||||
echo
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
mkdir -p /tmp/sd
|
||||
sudo mount ${devName}6 /tmp/sd
|
||||
|
||||
raspbianDate=$(date -d "$(zcat /tmp/sd/usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz | grep -m 1 ' --' | rev | cut -f 1-6 -d ' ' | rev)" +%s)
|
||||
doFix=
|
||||
if [[ $raspbianDate -lt 1403204265 ]]; then
|
||||
echo "This doesn't appear to be a version of Raspbian that requires fixing."
|
||||
echo -n "Are you sure you want to continue? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]]; then
|
||||
doFix=1
|
||||
fi
|
||||
else
|
||||
doFix=1
|
||||
fi
|
||||
|
||||
if [[ $doFix ]]; then
|
||||
while read kernelRelease; do
|
||||
kernelReplaced=
|
||||
kernelMajorRelease=$(cut -d '.' -f 1 <<< $kernelRelease)
|
||||
kernelMinorRelease=$(cut -d '.' -f 2 <<< $kernelRelease | sed 's/\(^[0-9]*\)[^0-9].*$/\1/')
|
||||
kernelPatchRelease=$(cut -d '.' -f 3- <<< $kernelRelease | sed 's/\(^[0-9]*\)[^0-9].*$/\1/')
|
||||
# if kernel 3.12 below 3.12.25+, delete defective AppleTalk kernel
|
||||
if [[ $kernelMajorRelease -eq 3 && $kernelMinorRelease -eq 12 && $kernelPatchRelease -lt 25 ]]; then
|
||||
if [[ -f /tmp/sd/lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko ]]; then
|
||||
if [[ $(sha1sum /tmp/sd/lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko | cut -f 1 -d ' ') != "ecb239fc084c36de93f6926e7749b80f6024f269" ]]; then
|
||||
echo "Removing defective AppleTalk module from kernel $kernelRelease..."
|
||||
sudo rm -rf /tmp/sd/lib/modules/$kernelRelease/kernel/net/appletalk 2> /dev/null
|
||||
wget -qO /tmp/appletalk.ko.gz appleii.ivanx.com/a2server/files/appletalk-$kernelRelease.ko.gz
|
||||
if [[ $? -eq 0 ]]; then
|
||||
# if we found a prebuilt one on a2server site, so install it
|
||||
gunzip -f /tmp/appletalk.ko.gz
|
||||
sudo mkdir -p /tmp/sd/lib/modules/$kernelRelease/kernel/net/appletalk
|
||||
sudo mv /tmp/appletalk.ko /tmp/sd/lib/modules/$kernelRelease/kernel/net/appletalk
|
||||
echo "Installed fixed AppleTalk module for kernel $kernelRelease."
|
||||
kernelReplaced=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done <<< "$(ls -1 /tmp/sd/lib/modules | sort -V)"
|
||||
sudo umount /tmp/sd
|
||||
|
||||
echo kern:$kernelReplaced
|
||||
if [[ $kernelReplaced ]]; then
|
||||
echo
|
||||
echo "All set. Remove your SD card, put it back in your Pi, and boot it."
|
||||
echo
|
||||
echo "You should be able to connect from your Apple II, but if you can't,"
|
||||
echo "log in to your Pi and type 'a2server-setup' to complete the fix."
|
||||
else
|
||||
echo
|
||||
echo "Okey doke. Half done. Remove your SD card, and put it back in your Pi."
|
||||
echo "After it boots, log in and type 'a2server-setup' to complete the fix."
|
||||
fi
|
||||
echo "See the A2SERVER web site at http://ivanx.com/a2server for more help."
|
||||
echo "(You can type 'sudo shutdown -h now' if you're done on this machine.)"
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
rm fix &> /dev/null
|
@ -1,91 +0,0 @@
|
||||
## A2SERVER
|
||||
|
||||
A2SERVER lets you use a [Raspberry Pi][1], or almost any other computer, to
|
||||
serve files to Apple IIgs and enhanced IIe computers on your network. You'll
|
||||
also be able to boot into GS/OS or ProDOS 8 directly from tne network (no
|
||||
drives needed). A2SERVER has been designed to be as easy to set up and use as
|
||||
possible, and it's free.
|
||||
|
||||
<!--
|
||||
A2SERVER is available as a Raspberry Pi installer, or a virtual machine which
|
||||
runs on Mac OS X, Windows, Linux, or Solaris computers, or as an easy-to-use
|
||||
installer for Ubuntu or Debian Linux.
|
||||
-->
|
||||
|
||||
A2SERVER is based on open-source software, primarily [Netatalk][2] 2.2.4,
|
||||
with [many utilities and enhancements](a2server_features.md) to make
|
||||
everything as easy as possible. (If you like A2SERVER, you might also want to
|
||||
check out [A2CLOUD][3].)
|
||||
|
||||
<!--
|
||||
If you haven't checked out A2SERVER in a while: it now runs on something
|
||||
small, cheap, and silent, and every common LocalTalk-to-Ethernet bridge now
|
||||
works easily with a IIgs (as opposed to none previously). And A2SERVER
|
||||
supports Wi-Fi, and can download and install GS/OS on your network drive for
|
||||
you. Cool stuff!
|
||||
-->
|
||||
|
||||
*Update 19-Mar-15: A2SERVER 1.2.2 is available. It has support for Raspberry
|
||||
Pi 2 Model B and every other Raspberry Pi, and new command line options for
|
||||
the installer script. To update, type `a2server-setup`.*
|
||||
|
||||
Choose how you'd like to use A2SERVER, and you'll be up and running shortly.
|
||||
|
||||
* [Raspberry Pi](a2server_raspberrypi.md)
|
||||
* [Virtual Machine](a2server_virtualbox.md) (for Mac OS X, Windows, Linux,
|
||||
Solaris)
|
||||
* [Installer for Ubuntu or Debian Linux](a2server_installer.md)
|
||||
|
||||
|
||||
Once you've got it set up, here are next steps:
|
||||
|
||||
[Attach your Apple II to your local network](a2server_lan.md)
|
||||
|
||||
[Connect to A2SERVER from your Apple II](a2server_howtouse.md)
|
||||
|
||||
[Boot into ProDOS 8 or GS/OS over the network](a2server_netboot.md)
|
||||
|
||||
[Log into, shut down, and do stuff in the A2SERVER
|
||||
console](a2server_commands.md)
|
||||
|
||||
[Access A2SERVER files from a Mac or Windows computer](a2server_access.md)
|
||||
|
||||
[Use A2SERVER with Wi-Fi](a2server_wifi.md)
|
||||
|
||||
|
||||
And some other stuff that might (or might not) be helpful or interesting:
|
||||
|
||||
[A2SERVER feature list](a2server_features.md)
|
||||
|
||||
[A2SERVER version history](update/versionhistory.txt)
|
||||
|
||||
[Recover from a crashed A2SERVER](a2server_recovery.md)
|
||||
|
||||
[Details of what the "a2server-setup" script
|
||||
does](a2server_scriptdetails.md)
|
||||
|
||||
[See the March 2013 cover of Juiced.GS][4], featuring A2SERVER
|
||||
|
||||
[Watch me introduce A2SERVER at KansasFest 2011][5] (note: this contains some
|
||||
outdated information)
|
||||
|
||||
[The A2SERVER odyssey](a2server_story.md) (warning: long)
|
||||
|
||||
|
||||
Buckets of thanks to Steven Hirsch and Geoff Body, whose invaluable assistance
|
||||
and contributions have made A2SERVER exist, along with Tony Diaz, Antoine
|
||||
Vignau, Peter Wong, Martin Haye, Ken Gagne, Peter Neubauer, Anthony Martino,
|
||||
James Littlejohn, and others at comp.sys.apple2 and KansasFest. (As well as
|
||||
the creators, past and present, of Netatalk and Raspberry Pi.) Apple II
|
||||
Forever!
|
||||
|
||||
Questions? Comments? email [ivan@ivanx.com](mailto:ivan@ivanx.com)
|
||||
|
||||
[Apple II Extravaganza home page](http://appleii.ivanx.com/)
|
||||
|
||||
|
||||
[1]: http://www.raspberrypi.org
|
||||
[2]: http://netatalk.sourceforge.net
|
||||
[3]: http://ivanx.com/a2cloud
|
||||
[4]: http://juiced.gs/2013/03/v18i1-now-shipping/
|
||||
[5]: http://www.youtube.com/watch?v=w88NjWRK7Kk
|
@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# --- Setting up the share volume
|
||||
|
||||
|
||||
# skip if we're already set up
|
||||
if [[ -d /srv/A2SERVER ]]; then
|
||||
|
||||
echo "A2SERVER: Shared disk is already prepared for use."
|
||||
|
||||
else
|
||||
|
||||
echo "A2SERVER: Preparing the shared files disk..."
|
||||
|
||||
sudo mkdir /srv/A2SERVER
|
||||
|
||||
sudo chown $USER:$USER /srv/A2SERVER
|
||||
|
||||
fi
|
@ -1,126 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# download and install a2server tools:
|
||||
# mkatinit, mkvolinfo, afptype, afpsync, aliases, nulib2
|
||||
|
||||
isRpi=
|
||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1
|
||||
|
||||
isDebian=
|
||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "7." ) && ( $(uname -m) == "i686" ) ]] && isDebian=1
|
||||
|
||||
echo "A2SERVER: Installing A2SERVER tools..."
|
||||
|
||||
if [[ ! -f /usr/local/bin/nulib2 ]]; then
|
||||
|
||||
echo "A2SERVER: Installing nulib2..."
|
||||
|
||||
cd /tmp
|
||||
if [[ $isRpi ]]; then
|
||||
wget -qO- ivanx.com/a2server/files/nulib2-rpi.tgz | sudo tar Pzx
|
||||
elif [[ $isDebian ]]; then
|
||||
wget -qO- ivanx.com/a2server/files/nulib2-debian7_x86.tgz | sudo tar Pzx
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/bin/nulib2 ]]; then
|
||||
|
||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||
# prepare for installing packages
|
||||
sudo apt-get -y update
|
||||
touch /tmp/a2server-packageReposUpdated
|
||||
fi
|
||||
|
||||
sudo apt-get -y install build-essential
|
||||
sudo apt-get -y install zlib1g-dev
|
||||
sudo apt-get -y clean
|
||||
cd /tmp
|
||||
rm -rf /tmp/nulib &> /dev/null
|
||||
mkdir /tmp/nulib
|
||||
cd /tmp/nulib
|
||||
wget -q -O nulib.tgz http://web.archive.org/web/20131031160750/http://www.nulib.com/downloads/nulibdist.tar.gz
|
||||
tar zxf nulib.tgz
|
||||
cd nufxlib*
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd ../nulib2*
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
cd
|
||||
rm -rf /tmp/nulib
|
||||
fi
|
||||
|
||||
else
|
||||
echo "A2SERVER: Nulib2 has already been installed."
|
||||
fi
|
||||
|
||||
# download and install The Unarchiver, for expanding Apple disk images
|
||||
# http://wakaba.c3.cx/s/apps/unarchiver.html
|
||||
|
||||
if [[ ! -f /usr/local/bin/unar ]]; then
|
||||
|
||||
echo "A2SERVER: Installing The Unarchiver..."
|
||||
|
||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||
# prepare for installing packages
|
||||
sudo apt-get -y update
|
||||
touch /tmp/a2server-packageReposUpdated
|
||||
fi
|
||||
|
||||
if [[ $isRpi || $isDebian ]]; then
|
||||
sudo apt-get -y install libgnustep-base1.22
|
||||
sudo apt-get clean
|
||||
if [[ $isRpi ]]; then
|
||||
wget -qO- ivanx.com/a2server/files/unar-rpi.tgz | sudo tar Pzx
|
||||
elif [[ $isDebian ]]; then
|
||||
wget -qO- ivanx.com/a2server/files/unar-debian7_x86.tgz | sudo tar Pzx
|
||||
fi
|
||||
fi
|
||||
if [[ ! -f /usr/local/bin/unar ]]; then
|
||||
sudo apt-get -y install build-essential
|
||||
sudo apt-get -y install libgnustep-base-dev libz-dev libbz2-dev
|
||||
sudo apt-get -y install libssl-dev libicu-dev unzip
|
||||
sudo apt-get clean
|
||||
rm -rf /tmp/unar &> /dev/null
|
||||
mkdir /tmp/unar
|
||||
cd /tmp/unar
|
||||
wget -qO unar1.7_src.zip http://theunarchiver.googlecode.com/files/unar1.7_src.zip
|
||||
unzip -o unar1.7_src.zip
|
||||
cd The\ Unarchiver/XADMaster
|
||||
make -f Makefile.linux
|
||||
sudo mv lsar unar /usr/local/bin
|
||||
cd ../Extra
|
||||
sudo mv lsar.1 unar.1 /usr/local/man/man1
|
||||
cd
|
||||
rm -rf /tmp/unar
|
||||
fi
|
||||
sudo mandb &> /dev/null
|
||||
else
|
||||
echo "A2SERVER: The Unarchiver has already been installed."
|
||||
fi
|
||||
|
||||
sudo wget -q -O /usr/local/bin/afpsync appleii.ivanx.com/a2server/scripts/tools/afpsync.txt
|
||||
sudo chmod ugo+x /usr/local/bin/afpsync
|
||||
sudo wget -q -O /usr/local/bin/afptype appleii.ivanx.com/a2server/scripts/tools/afptype.txt
|
||||
sudo chmod ugo+x /usr/local/bin/afptype
|
||||
sudo wget -q -O /usr/local/bin/mkatinit appleii.ivanx.com/a2server/scripts/tools/mkatinit.txt
|
||||
sudo chmod ugo+x /usr/local/bin/mkatinit
|
||||
sudo wget -q -O /usr/local/bin/mkvolinfo appleii.ivanx.com/a2server/scripts/tools/mkvolinfo.txt
|
||||
sudo chmod ugo+x /usr/local/bin/mkvolinfo
|
||||
sudo wget -q -O /usr/local/bin/cppo appleii.ivanx.com/a2server/scripts/tools/cppo.txt
|
||||
sudo chmod ugo+x /usr/local/bin/cppo
|
||||
sudo wget -q -O /usr/local/etc/a2server-help.txt appleii.ivanx.com/a2server/scripts/tools/a2server-help.txt
|
||||
sudo wget -q -O /usr/local/etc/a2server-aliases appleii.ivanx.com/a2server/scripts/tools/a2server-aliases.txt
|
||||
|
||||
grep a2server-aliases /etc/bash.bashrc > /dev/null || \
|
||||
echo "source /usr/local/etc/a2server-aliases" | sudo tee -a /etc/bash.bashrc > /dev/null
|
||||
|
||||
[[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]] && motd="/etc/issue" || motd="/etc/motd"
|
||||
if [[ ! $(grep A2SERVER $motd) ]]; then
|
||||
echo | sudo tee -a $motd > /dev/null
|
||||
echo "Type 'system-shutdown' to turn off A2SERVER." | sudo tee -a $motd > /dev/null
|
||||
echo "Type 'a2server-setup' to configure network boot." | sudo tee -a $motd > /dev/null
|
||||
echo "Type 'a2server-help' for a list of other commands." | sudo tee -a $motd > /dev/null
|
||||
echo | sudo tee -a $motd > /dev/null
|
||||
fi
|
@ -1,415 +0,0 @@
|
||||
#!/bin/bash
|
||||
# A2SERVER -- a virtual machine for sharing files to Apple II clients
|
||||
# by Ivan X, ivan@ivanx.com
|
||||
|
||||
# Installs Netatalk 2.2.4 for debian/raspbian (Wheezy) or Ubuntu (12.04)
|
||||
# last update: 3-Mar-15
|
||||
|
||||
# The lastest version of this document, and the ready-to-use premade
|
||||
# virtual machine, will be at http://appleii.ivanx.com .
|
||||
|
||||
# Please send corrections and comments to ivan@ivanx.com
|
||||
|
||||
# Thanks to Steven Hirsch, Geoff Body, Peter Wong, Tony Diaz, and others
|
||||
# at comp.sys.apple2 for the work they've done and insight they've
|
||||
# offered which made it possible to put this together.
|
||||
|
||||
|
||||
|
||||
# --- Installing netatalk
|
||||
|
||||
isRpi=
|
||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1
|
||||
|
||||
isDebian=
|
||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "7." ) && ( $(uname -m) == "i686" ) ]] && isDebian=1
|
||||
|
||||
# skip this if already done
|
||||
if [[ -f /usr/local/etc/A2SERVER-version ]] && (( $(cat /usr/local/etc/A2SERVER-version) >= 101 )); then
|
||||
|
||||
echo "A2SERVER: Netatalk is already installed."
|
||||
|
||||
else
|
||||
|
||||
echo "A2SERVER: Installing Netatalk (this will take a while)..."
|
||||
|
||||
# stop Netatalk if running (during upgrade)
|
||||
[[ $(ps --no-headers -C afpd) ]] && sudo /etc/init.d/netatalk stop
|
||||
|
||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||
# prepare for installing packages
|
||||
sudo apt-get -y update
|
||||
touch /tmp/a2server-packageReposUpdated
|
||||
fi
|
||||
|
||||
compileFromSource=1
|
||||
while [[ $isRpi || $isDebian ]]; do
|
||||
# Install runtime libraries needed by Netatalk
|
||||
if [[ $(apt-cache search '^libdb4.8$') ]]; then
|
||||
sudo apt-get -y install libdb4.8
|
||||
elif [[ $(apt-cache search '^libdb5.1$') ]]; then
|
||||
sudo apt-get -y install libdb5.1
|
||||
else
|
||||
break
|
||||
fi
|
||||
if [[ $(apt-cache search '^libssl1.0.0$') ]]; then
|
||||
sudo apt-get -y install libssl1.0.0
|
||||
elif [[ $(apt-cache search '^libssl0.9.8$') ]]; then
|
||||
sudo apt-get -y install libssl0.9.8
|
||||
else
|
||||
break
|
||||
fi
|
||||
if [[ $(apt-cache search '^libgcrypt11$') ]]; then
|
||||
sudo apt-get -y install libgcrypt11
|
||||
else
|
||||
break
|
||||
fi
|
||||
|
||||
# install Netatalk
|
||||
if [[ $isRpi ]]; then
|
||||
{ wget -qO- /tmp/netatalk.tgz ivanx.com/a2server/files/netatalk224-rpi.tgz | sudo tar Pzx; } 2> /dev/null
|
||||
elif [[ $isDebian ]]; then
|
||||
{ wget -qO- /tmp/netatalk.tgz ivanx.com/a2server/files/netatalk224-debian7_x86.tgz | sudo tar Pzx; } 2> /dev/null
|
||||
fi
|
||||
sudo mandb &> /dev/null
|
||||
|
||||
[[ -f /usr/local/sbin/atalkd ]] && compileFromSource=
|
||||
|
||||
break
|
||||
done
|
||||
|
||||
if [[ $compileFromSource ]]; then
|
||||
# Install development libraries needed by Netatalk
|
||||
sudo apt-get -y install build-essential
|
||||
if [[ $(apt-cache search '^libdb4.8-dev$') ]]; then
|
||||
sudo apt-get -y install libdb4.8-dev
|
||||
elif [[ $(apt-cache search '^libdb5.1-dev$') ]]; then
|
||||
sudo apt-get -y install libdb5.1-dev
|
||||
else
|
||||
echo "A2SERVER: WARNING: unknown version of libdb-dev is being installed"
|
||||
sudo apt-get -y install libdb-dev
|
||||
fi
|
||||
sudo apt-get -y install libssl-dev
|
||||
sudo apt-get -y install libgcrypt11-dev
|
||||
sudo apt-get clean
|
||||
|
||||
# get Netatalk
|
||||
rm -rf /tmp/netatalk &> /dev/null
|
||||
mkdir /tmp/netatalk
|
||||
cd /tmp/netatalk
|
||||
|
||||
wget -q "http://downloads.sourceforge.net/project/netatalk/netatalk/2.2.4/netatalk-2.2.4.tar.gz"
|
||||
tar zxf netatalk-2.2.4.tar.gz
|
||||
cd netatalk-2.2.4
|
||||
|
||||
# Patch the source so file dates are preserved during a GS/OS folder copy,
|
||||
# and the AsanteTalk bridge consistently starts up in AppleTalk Phase 2
|
||||
# and the Dayna bridge doesn't crash GS/OS
|
||||
# props to Steven Hirsch for these
|
||||
sed -i ':a;N;$!ba;s/case FILPBIT_ATTR :\n *change_mdate = 1;\n/case FILPBIT_ATTR :\n/g' etc/afpd/file.c
|
||||
sed -i 's/rtmp->rt_iface == iface/rtmp->rt_iface != iface/g' etc/atalkd/main.c
|
||||
|
||||
# prepare to build Netatalk
|
||||
./configure --enable-debian --enable-ddp --enable-a2boot
|
||||
|
||||
# uninstall Netatalk if already installed
|
||||
[[ -f /usr/local/sbin/afpd ]] && sudo make uninstall
|
||||
|
||||
# compile and install Netatalk
|
||||
make
|
||||
sudo make install
|
||||
|
||||
# to remove the Netatalk source code (optional), type:
|
||||
cd
|
||||
rm -rf /tmp/netatalk
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Configuring Netatalk
|
||||
|
||||
echo "A2SERVER: Configuring Netatalk..."
|
||||
|
||||
# if missing Netatalk startup file, download a fresh one
|
||||
if [ ! -f /etc/init.d/netatalk ]; then
|
||||
echo "A2SERVER: Downloading new Netatalk startup script..."
|
||||
sudo wget -qO /etc/init.d/netatalk ivanx.com/a2server/files/netatalk-init.d-clean.txt
|
||||
fi
|
||||
|
||||
# make the Netatalk startup script work correctly
|
||||
sudo sed -i 's/bin\/sh/bin\/bash/' /etc/init.d/netatalk
|
||||
|
||||
# enable AppleTalk networking support in Netatalk, and run in background
|
||||
sudo sed -i 's/#ATALKD_RUN=no/ATALKD_RUN=yes/' /etc/default/netatalk
|
||||
sudo sed -i 's/#ATALK_BGROUND=no/ATALK_BGROUND=yes/' /etc/default/netatalk
|
||||
if [[ ! $(grep 'kernelRelease' /etc/init.d/netatalk) ]]; then
|
||||
sudo sed -i 's@\(\tif \[ x\"$ATALKD_RUN\)@\n\t# check for valid AppleTalk kernel module\n\t[[ $ATALKD_RUN == "yes" ]] \&\& { kernelRelease=$(uname -r); kernelMajorRelease=$(cut -d "." -f 1 <<< $kernelRelease); kernelMinorRelease=$(cut -d "." -f 2 <<< $kernelRelease | sed '"'"'s/\\(^[0-9]*\\)[^0-9].*$/\\1/'"'"'); kernelPatchRelease=$(cut -d "." -f 3- <<< $kernelRelease | sed '"'"'s/\\(^[0-9]*\\)[^0-9].*$/\\1/'"'"'); [[ ( $kernelMajorRelease -eq 3 \&\& $kernelMinorRelease -ge 12 \&\& $kernelMinorRelease -le 15 ) \&\& ( ! ( -f /usr/bin/raspi-config \&\& $kernelMinorRelease -eq 12 \&\& $kernelPatchRelease -ge 25 ) ) \&\& ( ( ! -f /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko ) || $(sha1sum /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko | cut -f 1 -d " ") != "ecb239fc084c36de93f6926e7749b80f6024f269" ) ]] \&\& { ATALKD_RUN=no; echo "[AppleTalk networking is not available.]" 1>\&2; } }\n\n\1@' /etc/init.d/netatalk
|
||||
fi
|
||||
|
||||
# enable network boot support in netatalk
|
||||
sudo sed -i 's/timelord/a2boot/g' /etc/init.d/netatalk
|
||||
sudo sed -i 's/TIMELORD/A2BOOT/g' /etc/init.d/netatalk
|
||||
sudo sed -i 's/#A2BOOT_RUN=no/A2BOOT_RUN=yes/' /etc/default/netatalk
|
||||
|
||||
# allow Guest users to be able to network boot
|
||||
sudo sed -i "s/#AFPD_GUEST=nobody/AFPD_GUEST=$USER/" /etc/default/netatalk
|
||||
# (For a Guest user with different permissions than the compile-time user, create a
|
||||
# Linux user, and then specify that user for AFPD_GUEST instead.)
|
||||
|
||||
# create a symbolic link to the startup configuration file in netatalk configuration folder
|
||||
[[ -L /usr/local/etc/netatalk/netatalk.conf ]] \
|
||||
|| sudo ln -s /etc/default/netatalk /usr/local/etc/netatalk/netatalk.conf
|
||||
|
||||
# create a symbolic link to the netatalk configuration folder in /etc
|
||||
[[ -L /etc/netatalk ]] || sudo ln -s /usr/local/etc/netatalk /etc/netatalk
|
||||
|
||||
if [[ ! $(grep '^- -ddp.*uams_randnum.so' /usr/local/etc/netatalk/afpd.conf) ]]; then
|
||||
# set up to allow Guest, Cleartext, RandNum, DHX, and DHX2 login
|
||||
# disable DHX (DHCAST128) on Raspberry Pi, which refuses uams if the config string is too long
|
||||
[[ -f /usr/bin/raspi-config ]] && dhx="" || dhx="uams_dhx.so,"
|
||||
echo -n -e \
|
||||
"- -ddp -tcp -uamlist uams_guest.so,uams_clrtxt.so,uams_randnum.so" \
|
||||
| sudo tee -a /usr/local/etc/netatalk/afpd.conf > /dev/null
|
||||
echo -e ",${dhx}uams_dhx2.so" \
|
||||
| sudo tee -a /usr/local/etc/netatalk/afpd.conf > /dev/null
|
||||
fi
|
||||
|
||||
# replace home folder share and end of file mark with share placeholders
|
||||
sudo sed -i 's/^~/#share1\n\n#share2/' \
|
||||
/usr/local/etc/netatalk/AppleVolumes.default
|
||||
|
||||
# disable default volume options for Mac OS X clients
|
||||
sudo sed -i 's/^:DEFAULT/#:DEFAULT/' \
|
||||
/usr/local/etc/netatalk/AppleVolumes.default
|
||||
|
||||
if [[ ! $(grep ^eth0 /usr/local/etc/netatalk/atalkd.conf) && ! $(grep ^wlan0 /usr/local/etc/netatalk/atalkd.conf) ]]; then
|
||||
# enable netatalk on the default network interface
|
||||
# needs -router and -zone to prevent GS/OS AppleShare CDEV crash when used
|
||||
# with Dayna or Asante bridges
|
||||
echo -e 'eth0 -router -phase 2 -net 1 -zone "A2SERVER"' \
|
||||
| sudo tee -a /usr/local/etc/netatalk/atalkd.conf > /dev/null
|
||||
fi
|
||||
|
||||
# Raspberry Pi
|
||||
if [[ $isRpi ]]; then
|
||||
# blink LED upon netatalk startup so you know when to attach power to an AsanteTalk bridge
|
||||
if [[ ! $(grep 'led0' /etc/init.d/netatalk) ]]; then
|
||||
sudo sed -i ':a;N;$!ba;s/fi\n}/fi\n\n # blink LED on Raspberry Pi\n ([[ -e \/sys\/class\/leds\/ACT ]] \&\& led=ACT || led=led0; echo none > \/sys\/class\/leds\/$led\/trigger; for i in {1..20}; do echo 1 > \/sys\/class\/leds\/$led\/brightness; sleep 0.25; echo 0 > \/sys\/class\/leds\/$led\/brightness; sleep 0.25; done; echo mmc0 > \/sys\/class\/leds\/$led\/trigger) \&\n}/' /etc/init.d/netatalk
|
||||
fi
|
||||
|
||||
# set console port login to 4800 bps for usage with Apple II (using RPi console cable)
|
||||
sudo sed -i 's/ttyAMA0 115200/ttyAMA0 4800/' /etc/inittab
|
||||
|
||||
# enable serial console login with USB-serial adapter
|
||||
# 10-4-13: creates unwanted console messages if no adapter present,
|
||||
# and physical port isn't predictable with more than one adapter present, so
|
||||
# has been superseded by scanttyUSB supplied by A2CLOUD install
|
||||
#if [[ ! $(grep 'ttyUSB0 19200' /etc/inittab) ]]; then
|
||||
# echo -e "\n\n#for USB-to-serial adapter with Prolific PL2303 chipset\nT1:23:respawn:/sbin/getty -L ttyUSB0 19200 vt100" | sudo tee -a /etc/inittab > /dev/null
|
||||
#fi
|
||||
fi
|
||||
|
||||
# set up GSFILES share (for GS data files, not GSOS system)
|
||||
# classic Mac OS file names are allowed (31 chars, mixed case, everything but colons)
|
||||
sudo sed -i \
|
||||
's/^#share1/\/media\/A2SHARED\/GSFILES\ GSFILES ea:ad/' \
|
||||
/usr/local/etc/netatalk/AppleVolumes.default
|
||||
[[ -d /srv/A2SERVER/GSFILES ]] || mkdir -p /srv/A2SERVER/GSFILES
|
||||
|
||||
# set up A2FILES share (for ProDOS 8 files, and GS/OS system)
|
||||
# file names must be ProDOS 8 compliant (all caps, 15 chars, letters/numbers/periods only)
|
||||
# lowercase filenames will be converted to upper automatically
|
||||
# need for GS/OS system because it may refer to files by either upper or lower
|
||||
sudo sed -i \
|
||||
's/^#share2/\/media\/A2SHARED\/A2FILES\ A2FILES options:prodos\ casefold:toupper ea:ad/' \
|
||||
/usr/local/etc/netatalk/AppleVolumes.default
|
||||
[[ -d /srv/A2SERVER/A2FILES ]] || mkdir -p /srv/A2SERVER/A2FILES
|
||||
if [[ ! -d /srv/A2SERVER/A2FILES/.AppleDesktop ]]; then
|
||||
cd /srv/A2SERVER/A2FILES
|
||||
mkdir .AppleDesktop
|
||||
ln -s .AppleDesktop .APPLEDESKTOP
|
||||
fi
|
||||
|
||||
# set up ADTDISKS share (ADTPro disk image folder, if A2CLOUD is installed)
|
||||
# classic Mac OS file names are allowed (31 chars, mixed case, everything but colons)
|
||||
if [[ -d /usr/local/adtpro/disks ]]; then # A2CLOUD/ADTPro installed
|
||||
if [[ ! -d /srv/A2SERVER/ADTDISKS ]]; then
|
||||
ln -s /usr/local/adtpro/disks /srv/A2SERVER/ADTDISKS
|
||||
fi
|
||||
if [[ ! $(grep ADTDISKS /usr/local/etc/netatalk/AppleVolumes.default) ]]; then
|
||||
sudo sed -i 's@^# End of File@/srv/A2SERVER/ADTDISKS ADTDISKS ea:ad\n\n# End of File@' /usr/local/etc/netatalk/AppleVolumes.default
|
||||
fi
|
||||
fi
|
||||
|
||||
# to make Netatalk start up when the server boots:
|
||||
sudo update-rc.d netatalk defaults &> /dev/null
|
||||
|
||||
|
||||
# --- Setting up users
|
||||
|
||||
# At this point, the server is usable for Guest access.
|
||||
|
||||
# skip if we've already done this
|
||||
if [[ -f /usr/local/etc/netatalk/afppasswd ]]; then
|
||||
|
||||
echo "A2SERVER: Netatalk user logins have already been set up."
|
||||
|
||||
else
|
||||
|
||||
echo
|
||||
echo "A2SERVER: Setting up AFP password 'apple2' for Apple II and Mac clients."
|
||||
# echo "A2SERVER: Enter 'apple2' or another password of up to eight characters."
|
||||
echo
|
||||
# set registered user login using RandNum authentication
|
||||
sudo afppasswd -c
|
||||
sudo sed -i 's/^pi.*$/pi:6170706C65320000:****************:********/' /usr/local/etc/netatalk/afppasswd
|
||||
# while [[ ! $(sudo afppasswd -a $USER) ]]; do
|
||||
# true
|
||||
# done
|
||||
# (The afppasswd -c only needs to ever be done once. You can repeat
|
||||
# the afppasswd -a to make Netatalk logins for other Linux users.)
|
||||
|
||||
fi
|
||||
|
||||
# Check AppleTalk kernel module for existence and validity
|
||||
|
||||
# get Kernel release (e.g. 3.6.11+) and version (e.g. #557)
|
||||
kernelRelease=$(uname -r)
|
||||
kernelMajorRelease=$(cut -d '.' -f 1 <<< $kernelRelease)
|
||||
kernelMinorRelease=$(cut -d '.' -f 2 <<< $kernelRelease | sed 's/\(^[0-9]*\)[^0-9].*$/\1/')
|
||||
kernelPatchRelease=$(cut -d '.' -f 3- <<< $kernelRelease | sed 's/\(^[0-9]*\)[^0-9].*$/\1/')
|
||||
|
||||
# if on kernel 3.12 through 3.15, check if we need to delete AppleTalk module to prevent kernel panics
|
||||
if [[ $kernelMajorRelease -eq 3 && $kernelMinorRelease -ge 12 && $kernelMinorRelease -le 15 ]]; then
|
||||
# if not RPi, or RPi without ivanx-fixed AppleTalk module, delete the module
|
||||
if [[ ! ( $isRpi && $kernelMinorRelease -eq 12 && $kernelPatchRelease -ge 25 ) ]]; then
|
||||
if [[ -f /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko ]]; then
|
||||
if [[ $(sha1sum /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko | cut -f 1 -d ' ') != "ecb239fc084c36de93f6926e7749b80f6024f269" ]]; then
|
||||
# stop Netatalk
|
||||
sudo /etc/init.d/netatalk stop &> /dev/null
|
||||
echo "A2SERVER: Deleting defective AppleTalk kernel module."
|
||||
sudo rmmod appletalk 2> /dev/null
|
||||
sudo rm -r /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||
# disable single-user mode on Pi (other Linux can use Recovery boot)
|
||||
if [[ $isRpi && $(grep ' single' /boot/cmdline.txt 2> /dev/null) ]]; then
|
||||
echo "A2SERVER: Disabling single-user mode for next boot."
|
||||
sudo sed -i 's/ single//' /boot/cmdline.txt
|
||||
touch /tmp/singleUser # so note to restart can display following install
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Start Netatalk (if not running)
|
||||
|
||||
bground=
|
||||
if [[ $(grep 'ATALK_BGROUND=yes' /etc/default/netatalk) ]]; then
|
||||
bground=1
|
||||
sudo sed -i 's/ATALK_BGROUND=yes/ATALK_BGROUND=no/' /etc/default/netatalk
|
||||
fi
|
||||
|
||||
[[ $(ps --no-headers -C afpd) ]] || sudo /etc/init.d/netatalk start 2> /dev/null
|
||||
|
||||
echo
|
||||
echo "A2SERVER: Netatalk is installed, configured, and running."
|
||||
echo
|
||||
|
||||
# if atalkd isn't running (no AppleTalk), and this is a Rasbperry Pi:
|
||||
if [[ ( ! $(ps aux | grep [a]talkd) ) && ( $isRpi ) ]]; then
|
||||
|
||||
# if AppleTalk module exists, try to load it
|
||||
if [[ -f /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko ]]; then # module present, but not loaded?
|
||||
sudo depmod
|
||||
sudo modprobe appletalk
|
||||
if [[ $(lsmod | grep appletalk) ]]; then
|
||||
# if it loaded, restart netatalk
|
||||
sudo sed -i "s/ATALKD_RUN=no/ATALKD_RUN=yes/" /etc/default/netatalk; sudo /etc/init.d/netatalk restart
|
||||
else
|
||||
# if we didn't load it successfully, delete it
|
||||
sudo rm -r /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||
fi
|
||||
fi
|
||||
|
||||
# if no AppleTalk module, try to download it from a2server site
|
||||
if [[ ! -f /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko ]]; then # check for rpi kernel module
|
||||
echo "A2SERVER: Attempting to install AppleTalk kernel module for Raspbian..."
|
||||
wget -qO /tmp/appletalk.ko.gz appleii.ivanx.com/a2server/files/appletalk-$kernelRelease.ko.gz
|
||||
if [[ $? -eq 0 ]]; then
|
||||
# if we found a prebuilt one on a2server site, install it and load it
|
||||
gunzip -f /tmp/appletalk.ko.gz
|
||||
sudo mkdir -p /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||
sudo mv /tmp/appletalk.ko /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||
sudo depmod
|
||||
sudo modprobe appletalk
|
||||
if [[ $(lsmod | grep appletalk) ]]; then
|
||||
# if it loaded, restart netatalk
|
||||
sudo sed -i "s/ATALKD_RUN=no/ATALKD_RUN=yes/" /etc/default/netatalk; sudo /etc/init.d/netatalk restart
|
||||
else
|
||||
# if we didn't load it successfully, remove it
|
||||
sudo rm -r /lib/modules/$kernelRelease/kernel/net/appletalk 2> /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# if we still don't have AppleTalk, try to use rpi-update
|
||||
rm /tmp/rpiUpdate 2> /dev/null
|
||||
if [[ ! $(ps aux | grep [a]talkd) ]]; then
|
||||
# use specific rpi-update commit (at https://github.com/Hexxeh/rpi-firmware/)
|
||||
# from when AppleTalk was added/fixed, so we have a consistent firmware that
|
||||
# we're loading until the next proper release of Raspbian that includes it
|
||||
#
|
||||
# 10-26-13: when AppleTalk was added to Raspbian:
|
||||
# sudo rpi-update 9530adbe31fe6b8e05b3bd5cfadfc90f067f5362
|
||||
# sudo modprobe appletalk 2> /dev/null
|
||||
# if [[ $(lsmod | grep appletalk) ]]; then
|
||||
# if it loaded, restart netatalk
|
||||
# sudo sed -i "s/ATALKD_RUN=no/ATALKD_RUN=yes/" /etc/default/netatalk; sudo /etc/init.d/netatalk restart
|
||||
# fi
|
||||
#
|
||||
# 07-23-14: when AppleTalk was fixed after kernel panics in Raspbian 2014-06-20 (kernel 3.12.22+)
|
||||
sudo rm /boot/.firmware_revision
|
||||
sudo rpi-update cfd9a203590737f9536de70a1e01db25a3e8e069
|
||||
touch /tmp/rpiUpdate # so note to restart can display following install
|
||||
fi
|
||||
|
||||
if [[ ! $(ps aux | grep [a]talkd) ]]; then
|
||||
if [[ -f /tmp/rpiUpdate ]]; then
|
||||
echo
|
||||
echo "AppleTalk networking is installed but not yet active."
|
||||
echo "When installation is complete, please restart your Raspberry Pi"
|
||||
echo "when asked or by typing 'system-restart' at the Linux prompt"
|
||||
echo "to allow Apple II computers to connect."
|
||||
echo
|
||||
else
|
||||
echo
|
||||
echo "AppleTalk networking could not be activated"
|
||||
echo "for your Raspbian kernel version ($kernelRelease)."
|
||||
echo "Please try restarting with 'system-restart'. If that doesn't work,"
|
||||
echo "you're not going to be able to connect from an Apple II."
|
||||
echo "See http://appleii.ivanx.com/a2server for help."
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $bground ]]; then
|
||||
sudo sed -i 's/ATALK_BGROUND=no/ATALK_BGROUND=yes/' /etc/default/netatalk
|
||||
fi
|
||||
|
||||
# --- Set up Avahi-Daemon (Bonjour/mDNS)
|
||||
# thanks to: http://missingreadme.wordpress.com/2010/05/08/how-to-set-up-afp-filesharing-on-ubuntu
|
||||
|
||||
if [[ ! $(dpkg -l avahi-daemon 2> /dev/null | grep ^ii) || ! $(dpkg -l libnss-mdns 2> /dev/null | grep ^ii) ]]; then
|
||||
echo "A2SERVER: Installing Avahi-Daemon (Bonjour/mDNS)..."
|
||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||
# prepare for installing packages
|
||||
sudo apt-get -y update
|
||||
touch /tmp/a2server-packageReposUpdated
|
||||
fi
|
||||
sudo apt-get -y install avahi-daemon libnss-mdns &> /dev/null
|
||||
fi
|
||||
sudo sed -i 's/^\(hosts.*\)$/\1 mdns/' /etc/nsswitch.conf
|
||||
if [[ ! -f /etc/avahi/services/afpd.service && ! -f /etc/avahi/services/afpd.service_disabled ]]; then
|
||||
echo -e '<?xml version="1.0" standalone="no"?><!--*-nxml-*-->\n<!DOCTYPE service-group SYSTEM "avahi-service.dtd">\n<service-group>\n <name replace-wildcards="yes">%h</name>\n <service>\n <type>_afpovertcp._tcp</type>\n <port>548</port>\n </service>\n <service>\n <type>_device-info._tcp</type>\n <port>0</port>\n <txt-record>model=MacPro</txt-record>\n </service>\n</service-group>' | sudo tee /etc/avahi/services/afpd.service > /dev/null
|
||||
fi
|
||||
sudo /etc/init.d/avahi-daemon restart &> /dev/null
|
@ -1,444 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# this script downloads and installs the Apple boot blocks required
|
||||
# for booting an Apple II client over the network, and places
|
||||
# BASIC.SYSTEM on the shared drive and configures it to be the startup
|
||||
# program (for Apple IIe users, and IIgs users in ProDOS network mode).
|
||||
# It also can download and install GS/OS for a network boot configuration.
|
||||
|
||||
gsosDir="/srv/A2SERVER/A2FILES"
|
||||
imagesDir=$gsosDir/GSOS.INSTALLER/IMAGES
|
||||
imageToolsDir=$gsosDir/GSOS.INSTALLER/IMAGE.TOOLS
|
||||
netInstallDir=$gsosDir/GSOS.INSTALLER/NET.INSTALL
|
||||
|
||||
p8Dir="/srv/A2SERVER/A2FILES"
|
||||
diskToolsP8Dir=$p8Dir/DISK.TOOLS.P8
|
||||
|
||||
commDir="/srv/A2SERVER/A2FILES/COMM"
|
||||
spectrumDir=$commDir/SPECTRUM
|
||||
protermDir=$commDir/PROTERM
|
||||
zlinkDir=$commDir/Z.LINK
|
||||
adtproDir=$commDir/ADTPRO
|
||||
|
||||
# bail out on automated netboot setup unless -b is also specified
|
||||
[[ -f /tmp/a2server-autoAnswerYes ]] && autoAnswerYes=1 || autoAnswerYes=
|
||||
if [[ ! $autoAnswerYes || -f /tmp/a2server-setupNetBoot ]]; then
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo "Do you want to set up A2SERVER to be able to boot Apple II"
|
||||
echo -n "computers over the network? "
|
||||
read
|
||||
fi
|
||||
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
nbmode=1
|
||||
echo
|
||||
|
||||
sudo true
|
||||
mkdir -p /tmp/netboot
|
||||
cd /tmp/netboot
|
||||
|
||||
# this will get "Disk 7" (Apple II Setup) as a raw (block dump) image
|
||||
if [[ ! -f /usr/local/etc/netatalk/a2boot/ProDOS16\ Boot\ Blocks ]] \
|
||||
|| [[ ! -f /usr/local/etc/netatalk/a2boot/ProDOS16\ Image ]] \
|
||||
|| [[ ! -f /usr/local/etc/netatalk/a2boot/Apple\ :2f:2fe\ Boot\ Blocks ]]; then
|
||||
echo "A2SERVER: Downloading Apple II Boot Blocks..."
|
||||
cd /tmp/netboot
|
||||
|
||||
wget -qO Disk_7_of_7-Apple_II_Setup.sea.bin http://archive.org/download/download.info.apple.com.2012.11/download.info.apple.com.2012.11.zip/download.info.apple.com%2FApple_Support_Area%2FApple_Software_Updates%2FEnglish-North_American%2FApple_II%2FApple_IIGS_System_6.0.1%2FDisk_7_of_7-Apple_II_Setup.sea.bin
|
||||
unar -k skip Disk_7_of_7-Apple_II_Setup.sea.bin &> /dev/null
|
||||
truncate -s 819284 'Disk 7 of 7-Apple II Setup.sea'
|
||||
dd if='Disk 7 of 7-Apple II Setup.sea' of=APPLE2SETUP.HDV bs=84 skip=1 2> /dev/null
|
||||
|
||||
# copy the Boot Blocks into the right place
|
||||
mkdir -p a2setup
|
||||
sudo mount -t hfs -o ro,loop APPLE2SETUP.HDV a2setup
|
||||
sudo mkdir -p /usr/local/etc/netatalk/a2boot
|
||||
sudo cp -p a2setup/System\ Folder/* /usr/local/etc/netatalk/a2boot
|
||||
sudo umount a2setup
|
||||
sudo mv /usr/local/etc/netatalk/a2boot/Apple* /usr/local/etc/netatalk/a2boot/'Apple :2f:2fe Boot Blocks'
|
||||
|
||||
cd /usr/local/etc/netatalk/a2boot
|
||||
# thanks to Geoff Body for these Boot Blocks patches
|
||||
# fix cleartext password login bug
|
||||
echo -n -e "\xA8\xA2\x01\xBD\x80\x38\x99\xA0\x38\xC8\xE8\xE0\x09\x90\xF4" | \
|
||||
sudo dd of='Apple :2f:2fe Boot Blocks' bs=19779 seek=1 conv=notrunc 2> /dev/null
|
||||
echo -n -e "\xA8\xA2\x01\xBD\x80\x10\x99\xA0\x10\xC8\xE8\xE0\x09\x90\xF4" | \
|
||||
sudo dd of='ProDOS16 Image' bs=22583 seek=1 conv=notrunc 2> /dev/null
|
||||
# enable typing "8" during GS/OS netboot to force ProDOS 8 boot
|
||||
echo -n -e "\x92" | sudo dd of='ProDOS16 Image' bs=256 seek=1 conv=notrunc 2> /dev/null
|
||||
echo -n -e "\x20\x7d\x14" | sudo dd of='ProDOS16 Image' bs=864 seek=1 conv=notrunc 2> /dev/null
|
||||
echo -n -e "\xad\x00\xc0\x29\xff\x00\xc9\xb8\x00\xd0\x06\xa9\x02\x00\x8d\x53\x14\xa9\x10\x0f\x60" | \
|
||||
sudo dd of='ProDOS16 Image' bs=1661 seek=1 conv=notrunc 2> /dev/null
|
||||
fi
|
||||
echo "A2SERVER: Boot Blocks have been installed."
|
||||
|
||||
# get a2server-tools if necessary
|
||||
if [[ ! -f /usr/local/bin/mkatinit ]] \
|
||||
|| [[ ! -f /usr/local/bin/afptype ]] \
|
||||
|| [[ ! -f /usr/local/bin/mkvolinfo ]] \
|
||||
|| [[ ! -f /usr/local/bin/afpsync ]]; then
|
||||
rm /tmp/2.tools &> /dev/null
|
||||
wget -q -O /tmp/2.tools appleii.ivanx.com/a2server/scripts/a2server-2-tools.txt
|
||||
chmod ugo+x /tmp/2.tools
|
||||
/tmp/2.tools
|
||||
rm /tmp/2.tools
|
||||
fi
|
||||
|
||||
# put BASIC.SYSTEM at root for ProDOS 8 startup
|
||||
cp -p /usr/local/etc/netatalk/a2boot/Basic.System $gsosDir/BASIC.SYSTEM
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
afptype -p SYS -q $gsosDir/BASIC.SYSTEM
|
||||
|
||||
# create tools for setting GS/OS or ProDOS 8 boot in battery RAM and rebooting. Props yet again to Geoff Body.
|
||||
if [[ ! -f $p8Dir/NETBOOT.P8 ]]; then
|
||||
echo
|
||||
echo "A2SERVER: Creating NETBOOT.P8..."
|
||||
touch $p8Dir/NETBOOT.P8
|
||||
echo -n -e "\x38\x20\x1f\xfe\x90\x01\x60\xfb\x08\xc2\x30\xf4\x02\x00\xf4\x62\x00\xa2\x03\x0b\x22\x00\x00\xe1\x78\xf4\x00\x00\xf4\x00\x00\xab\xab\x2b\x38\xfb\xce\xf4\x03\xa9\x0c\x8d\x68\xc0\x9c\x47\xc0\x9c\x41\xc0\xa9\x09\x8d\x39\xc0\xa9\xc0\x8d\x39\xc0\x5c\x62\xfa\x00" | \
|
||||
sudo dd of="$p8Dir/NETBOOT.P8" 2> /dev/null
|
||||
afpsync -v $p8Dir > /dev/null
|
||||
afptype -p SYS -q $p8Dir/NETBOOT.P8
|
||||
fi
|
||||
if [[ ! -f $gsosDir/NETBOOT.GSOS ]]; then
|
||||
echo
|
||||
echo "A2SERVER: Creating NETBOOT.GSOS..."
|
||||
# create tool for setting GSOS boot in battery RAM and rebooting. Props yet again to Geoff Body.
|
||||
touch $gsosDir/NETBOOT.GSOS
|
||||
echo -n -e "\x38\x20\x1f\xfe\x90\x01\x60\xfb\x08\xc2\x30\xf4\x01\x00\xf4\x62\x00\xa2\x03\x0b\x22\x00\x00\xe1\x78\xf4\x00\x00\xf4\x00\x00\xab\xab\x2b\x38\xfb\xce\xf4\x03\xa9\x0c\x8d\x68\xc0\x9c\x47\xc0\x9c\x41\xc0\xa9\x09\x8d\x39\xc0\xa9\xc0\x8d\x39\xc0\x5c\x62\xfa\x00" | \
|
||||
sudo dd of="$p8Dir/NETBOOT.GSOS" 2> /dev/null
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
afptype -p SYS -q $gsosDir/NETBOOT.GSOS
|
||||
fi
|
||||
|
||||
mkatinit -gs -d -f # GS/OS registered user and Guest starts up with SYSTEM/FINDER
|
||||
mkatinit -d -f guest # ProDOS 8 Guest starts up with BASIC.SYSTEM (no registered user)
|
||||
|
||||
if [[ -f "/srv/A2SERVER/A2FILES/SYSTEM/START.GS.OS" ]]; then
|
||||
echo "A2SERVER: GS/OS has already been downloaded and installed."
|
||||
gsosInstall=1
|
||||
else
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo "You can set up GS/OS 6.0.1 on your network drive, for network boot."
|
||||
echo -n "This may take a while. Download and install it now? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
gsosInstall=1
|
||||
|
||||
# get GS/OS disks from Internet Archive and put them in IMAGES
|
||||
# also dump contents into NET.INSTALL and modify scripts to work from there
|
||||
# echo
|
||||
# echo "Come back in a while. This takes a long time."
|
||||
echo
|
||||
echo "A2SERVER: Downloading GS/OS 6.0.1 installer disk images..."
|
||||
cd /tmp/netboot
|
||||
mkdir -p $imagesDir
|
||||
mkdir -p $netInstallDir
|
||||
activeDisk=0
|
||||
for diskname in Install System.Disk SystemTools1 SystemTools2 Fonts synthLAB; do
|
||||
outfile="$imagesDir/$(tr [:lower:] [:upper:] <<< $diskname)"
|
||||
if [ ! -f $outfile ]; then
|
||||
(( activeDisk++ ))
|
||||
echo "A2SERVER: Disk ${activeDisk} of 6: $diskname"
|
||||
wget -qO "Disk_${activeDisk}_of_7-$diskname.sea.bin" "http://archive.org/download/download.info.apple.com.2012.11/download.info.apple.com.2012.11.zip/download.info.apple.com%2FApple_Support_Area%2FApple_Software_Updates%2FEnglish-North_American%2FApple_II%2FApple_IIGS_System_6.0.1%2FDisk_${activeDisk}_of_7-$diskname.sea.bin"
|
||||
unar -k skip "Disk_${activeDisk}_of_7-$diskname.sea.bin" &> /dev/null
|
||||
truncate -s 819284 "Disk ${activeDisk} of 7-${diskname}.sea"
|
||||
dd if="Disk ${activeDisk} of 7-${diskname}.sea" of=${outfile} bs=84 skip=1 &> /dev/null
|
||||
cppo -s -ad $outfile $netInstallDir 2> /dev/null
|
||||
fi
|
||||
done
|
||||
rm *.sea* &> /dev/null
|
||||
sed -i "s/\([^\\]\r:\)/\1A2FILES:GSOS.INSTALLER:NET.INSTALL:/g" $netInstallDir/INSTALL/SCRIPTS/*
|
||||
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
|
||||
# install GS/OS
|
||||
# spec for GS/OS installer scripts: GS/OS Tech Note #64
|
||||
# http://www.1000bit.it/support/manuali/apple/technotes/iigs/tn.iigs.064.html
|
||||
processScript () {
|
||||
scriptEntries=$(cat $1 | tr '\r' '#' | tr '~' '\n' | sed 's/4#D/5/')
|
||||
IFS=$'\n'
|
||||
scriptEntries=($scriptEntries)
|
||||
pathPrefix="/A2FILES/GSOS.INSTALLER/NET.INSTALL"$(tr ':' '/' <<< ${scriptEntries[0]##S*\\\\#})
|
||||
entryCount=${#scriptEntries[@]}
|
||||
(( entryCount -= 2 ))
|
||||
entryIndex=3
|
||||
while (( entryIndex < entryCount )); do
|
||||
IFS='#'
|
||||
scriptEntry=(${scriptEntries[entryIndex]})
|
||||
# echo $entryIndex $entryCount ${scriptEntry[1]}
|
||||
action=${scriptEntry[1]:0:1}
|
||||
sourcePathMixed=$(tr ':' '/' <<< ${scriptEntry[5]})
|
||||
[[ ${sourcePathMixed:0:1} != '/' ]] && sourcePathMixed="${pathPrefix}/$sourcePathMixed"
|
||||
sourcePath=$(tr [:lower:] [:upper:] <<< $sourcePathMixed)
|
||||
targetPath=$gsosDir/$(tr ':' '/' <<< ${scriptEntry[6]} | tr [:lower:] [:upper:])
|
||||
# volumeName=$(cut -d/ -f 2 <<< $sourcePath)
|
||||
targetParent=${targetPath%/*}
|
||||
targetFile=${targetPath##*/}
|
||||
sourceParent=${sourcePath%/*}
|
||||
sourceFile=${sourcePath##*/}
|
||||
|
||||
if [[ $action == 1 || $action == 2 ]]; then
|
||||
mkdir -p $targetParent
|
||||
echo "copying: $sourcePathMixed"
|
||||
echo " to: $targetPath"
|
||||
echo
|
||||
[[ ! -d $targetParent ]] && mkdir -p $targetParent
|
||||
cp -p ${gsosDir%/*}$sourcePath $targetPath
|
||||
[[ ! -d $targetParent/.AppleDouble ]] && mkdir -p $targetParent/.AppleDouble
|
||||
cp -p ${gsosDir%/*}$sourceParent/.AppleDouble/$sourceFile $targetParent/.AppleDouble/$targetFile
|
||||
elif [[ $action == 3 || $action == 4 ]]; then
|
||||
if [[ -f "$targetPath" ]]; then
|
||||
echo "deleting $targetPath"
|
||||
rm "$targetPath"
|
||||
[[ -f $targetParent/.AppleDouble/$targetFile ]] && rm "$targetParent/.AppleDouble/$targetFile"
|
||||
fi
|
||||
fi
|
||||
(( entryIndex++ ))
|
||||
done
|
||||
unset IFS
|
||||
}
|
||||
|
||||
mkdir -p /tmp/netboot
|
||||
cd /tmp/netboot
|
||||
|
||||
echo "A2SERVER: Preparing GS/OS installer scripts..."
|
||||
# work through installer scripts
|
||||
processScript $netInstallDir/INSTALL/SCRIPTS/INSTAL.SYS.FILE
|
||||
processScript $netInstallDir/INSTALL/SCRIPTS/APPLESHARE
|
||||
processScript $netInstallDir/INSTALL/SCRIPTS/SERVER.SYS.FILE
|
||||
|
||||
# sync netatalk database
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo "Do you want to download and install utilities for working with"
|
||||
echo -n "disk images and archive files in GS/OS? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
# download image tools and put them in IMAGE.TOOLS
|
||||
echo "A2SERVER: Downloading GS/OS disk image utilities..."
|
||||
mkdir -p $imageToolsDir
|
||||
|
||||
# get Asimov2 (for GS/OS)
|
||||
echo -n "Asimov 2.0"
|
||||
if [[ -f $imageToolsDir/ASIMOV ]]; then
|
||||
echo " is already installed."
|
||||
else
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -q -nc http://www.ninjaforce.com/downloads/Asimov.shk
|
||||
nulib2 -x -s Asimov.shk > /dev/null
|
||||
cp -p Asimov/Asimov $imageToolsDir/ASIMOV
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
cat Asimov/Asimov_rsrc_ >> $imageToolsDir/.AppleDouble/ASIMOV
|
||||
afptype -p S16 -q $imageToolsDir/ASIMOV
|
||||
fi
|
||||
|
||||
echo -n "GS-ShrinkIt 1.1"
|
||||
# get GS-ShrinkIt
|
||||
if [[ -f $imageToolsDir/GSHK ]]; then
|
||||
echo " is already installed."
|
||||
else
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -qO gshk.sea http://web.archive.org/web/20131031160750/http://nulib.com/library/gshk11.sea
|
||||
#wget -qO gshk.sea http://www.nulib.com/library/gshk11.sea
|
||||
nulib2 -x -s gshk.sea > /dev/null
|
||||
cp -p GSHK $imageToolsDir/GSHK
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
cat GSHK_rsrc_ >> $imageToolsDir/.AppleDouble/GSHK
|
||||
afptype -p S16 -a DB07 -q $imageToolsDir/GSHK
|
||||
fi
|
||||
|
||||
echo -n "MountIt 1.4"
|
||||
# get MountIt (for GS/OS)
|
||||
if [[ -f $imageToolsDir/MOUNTIT.SHK ]]; then
|
||||
echo " is already installed."
|
||||
else
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -q -nc http://www.brutaldeluxe.fr/products/apple2gs/MOUNTIT.SHK
|
||||
cp -p MOUNTIT.SHK $imageToolsDir/MOUNTIT.SHK
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
afptype -p SHK -q $imageToolsDir/MOUNTIT.SHK
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo "Do you want to download and install utilities for working with"
|
||||
echo -n "disk images and archive files in ProDOS 8? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
echo "A2SERVER: Downloading ProDOS 8 disk image utilities..."
|
||||
|
||||
mkdir -p $diskToolsP8Dir
|
||||
|
||||
echo -n "ShrinkIt 3.4"
|
||||
# get ShrinkIt 3.4 (for ProDOS 8)
|
||||
if [[ -f $diskToolsP8Dir/SHRINKIT ]]; then
|
||||
echo " is already installed."
|
||||
else
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -qO shrinkit.sdk http://web.archive.org/web/20131031160750/http://www.nulib.com/library/shrinkit.sdk
|
||||
[[ ! -f shrinkit.sdk ]] && wget -qO shrinkit.sdk appleii.ivanx.com/a2server/files/shrinkit.sdk
|
||||
nulib2 -xs shrinkit.sdk > /dev/null
|
||||
cppo -s -ad SHRINKIT /SHRINKIT/SHRINKIT $diskToolsP8Dir 2> /dev/null
|
||||
afpsync -v $sharepath > /dev/null
|
||||
fi
|
||||
|
||||
echo -n "DSK2FILE 5.8"
|
||||
# get DSK2FILE (for ProDOS 8)
|
||||
if [[ -f $diskToolsP8Dir/DSK2FILE ]]; then
|
||||
echo " is already installed."
|
||||
else
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -q -O dsk2file.shk http://www.dwheeler.com/6502/oneelkruns/dsk2file.zip
|
||||
nulib2 -x -s dsk2file.shk > /dev/null
|
||||
cp -p DSK2FILE58 $diskToolsP8Dir/DSK2FILE
|
||||
afpsync -v $sharepath > /dev/null
|
||||
afptype -p SYS -q $diskToolsP8Dir/DSK2FILE
|
||||
fi
|
||||
|
||||
echo -n "Apple System Utilities 3.1"
|
||||
if [[ -f $diskToolsP8Dir/SYSUTIL ]]; then
|
||||
echo " is already installed."
|
||||
else
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -qO Apple_II_System_Disk_3.2.sea.bin http://archive.org/download/download.info.apple.com.2012.11/download.info.apple.com.2012.11.zip/download.info.apple.com%2FApple_Support_Area%2FApple_Software_Updates%2FEnglish-North_American%2FApple_II%2FApple_II_Supplemental%2FApple_II_System_Disk_3.2.sea.bin
|
||||
unar -k skip Apple_II_System_Disk_3.2.sea.bin &> /dev/null
|
||||
truncate -s 819284 'Apple II System Disk 3.2.sea'
|
||||
dd if='Apple II System Disk 3.2.sea' of=A2SYSDISK32.HDV bs=84 skip=1 2> /dev/null
|
||||
cppo -s -ad A2SYSDISK32.HDV /UTILITIES/SYSUTIL.SYSTEM $diskToolsP8Dir/SYSUTIL 2> /dev/null
|
||||
cppo -s -ad A2SYSDISK32.HDV /UTILITIES/UTIL.0 $diskToolsP8Dir 2> /dev/null
|
||||
cppo -s -ad A2SYSDISK32.HDV /UTILITIES/UTIL.1 $diskToolsP8Dir 2> /dev/null
|
||||
cppo -s -ad A2SYSDISK32.HDV /UTILITIES/UTIL.2 $diskToolsP8Dir 2> /dev/null
|
||||
afpsync -v $sharepath > /dev/null
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo "Do you want to download serial communications software for"
|
||||
echo -n "GS/OS and ProDOS 8? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
echo "A2SERVER: Downloading communications software..."
|
||||
|
||||
mkdir -p $commDir
|
||||
|
||||
echo -n "Spectrum"
|
||||
# get Spectrum
|
||||
if [[ -f $commDir/SPECTRUM/SPECTRUM.HDV ]]; then
|
||||
echo " is already installed."
|
||||
else
|
||||
mkdir -p $spectrumDir
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -qO- http://www.speccie.co.uk/speccie/software/spectrum.2mg | dd bs=64 skip=1 of=$spectrumDir/SPECTRUM.HDV 2> /dev/null
|
||||
wget -qO- http://www.speccie.co.uk/speccie/software/spectrum_extras.2mg | dd bs=64 skip=1 of=$spectrumDir/EXTRAS.HDV 2> /dev/null
|
||||
wget -qO- http://www.speccie.co.uk/speccie/software/spectrum_sounds.2mg | dd bs=64 skip=1 of=$spectrumDir/SOUNDS.HDV 2> /dev/null
|
||||
wget -qO- http://www.speccie.co.uk/speccie/software/spectrum_manuals.2mg | dd bs=64 skip=1 of=$spectrumDir/MANUALS.HDV 2> /dev/null
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
fi
|
||||
|
||||
echo -n "ProTERM and Z-Link"
|
||||
# get A2CLOUD disk and copy from there
|
||||
if [[ -f $commDir/PROTERM/PROTERM ]]; then
|
||||
echo " are already installed."
|
||||
else
|
||||
mkdir -p $protermDir
|
||||
mkdir -p $protermDir/.AppleDouble
|
||||
mkdir -p $zlinkDir
|
||||
mkdir -p $zlinkDir/.AppleDouble
|
||||
echo
|
||||
cd /tmp/netboot
|
||||
wget -qO A2CLOUD.HDV http://ivanx.com/a2cloud/files/A2CLOUD.HDV
|
||||
cppo -ad A2CLOUD.HDV . > /dev/null
|
||||
cd A2CLOUD
|
||||
mv *PT3* *PROTERM* $protermDir
|
||||
mv Z.LINK $zlinkDir
|
||||
cd .AppleDouble
|
||||
mv *PT3* *PROTERM* $protermDir/.AppleDouble
|
||||
mv Z.LINK $zlinkDir/.AppleDouble
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
fi
|
||||
|
||||
echo -n "ADTPro and VSDRIVE"
|
||||
if [[ -f $commDir/ADTPRO/ADTPRO ]]; then
|
||||
echo " are already installed."
|
||||
else
|
||||
mkdir -p $adtproDir
|
||||
mkdir -p $adtproDir/.AppleDouble
|
||||
echo
|
||||
cd /tmp/netboot/A2CLOUD
|
||||
mv *ADTPRO* *VEDRIVE* *VSDRIVE* $adtproDir
|
||||
cd .AppleDouble
|
||||
mv *ADTPRO* *VEDRIVE* *VSDRIVE* $adtproDir/.AppleDouble
|
||||
afpsync -v $gsosDir > /dev/null
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# clean up
|
||||
cd
|
||||
[[ -d /tmp/netboot ]] && rm -rf /tmp/netboot
|
||||
[[ -d ~/GNUstep ]] && rm -rf ~/GNUstep
|
||||
|
||||
# rock and roll!
|
||||
echo
|
||||
|
||||
echo
|
||||
if (( $gsosInstall )); then
|
||||
echo "GS/OS network boot (for registered user and Guest) and"
|
||||
fi
|
||||
echo "ProDOS 8 network boot (for Guest only) is now configured."
|
||||
echo "See http://appleii.ivanx.com/a2server for info using it."
|
||||
|
||||
fi
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo "Do you want to download the patch required for using"
|
||||
echo -n "a Farallon LocalTalk-to-Ethernet bridge with GS/OS? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
echo "A2SERVER: Downloading Farallon bridge patch..."
|
||||
wget -O /tmp/FARALLON.PO appleii.ivanx.com/a2server/files/FARALLON.B1.PO &> /dev/null
|
||||
if [[ -d $gsosDir/SYSTEM/SYSTEM.SETUP ]]; then
|
||||
cppo -s -ad /tmp/FARALLON.PO /ATALKPATCH/ATALKIRQ $gsosDir/SYSTEM/SYSTEM.SETUP &> /dev/null
|
||||
echo
|
||||
echo "A2SERVER: The Farallon bridge patch is installed."
|
||||
else
|
||||
cppo -s -ad /tmp/FARALLON.PO /ATALKPATCH/ATALKIRQ $gsosDir &> /dev/null
|
||||
echo
|
||||
echo "On your Apple IIgs, copy the file ATALKIRQ in /A2SHARED to the"
|
||||
echo "SYSTEM.SETUP folder of the SYSTEM folder of your GSOS startup disk,"
|
||||
echo "or, if you can't, download the patch from the A2SERVER web site."
|
||||
fi
|
||||
echo
|
||||
echo "Note: Farallon bridges can only be used in GS/OS (with this patch)"
|
||||
echo "and Apple IIe computers. Apple IIgs computers which network boot"
|
||||
echo "directly into ProDOS 8 will freeze after a few minutes."
|
||||
fi
|
||||
|
||||
fi
|
@ -1,95 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set up A2SERVER to support Samba (Windows File Sharing)
|
||||
# this script can also be used if new shares are introduced
|
||||
|
||||
[[ -f /tmp/a2server-autoAnswerYes ]] && autoAnswerYes=1 || autoAnswerYes=
|
||||
|
||||
if [[ ! $autoAnswerYes || -f /tmp/a2server-setupWindowsSharing ]]; then
|
||||
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo -n "Should Windows computers be able to connect to A2SERVER? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
echo "A2SERVER: Setting up Windows file sharing..."
|
||||
sudo true
|
||||
|
||||
if [[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]]; then
|
||||
[[ -f /etc/init/smbd.conf.off ]] && sudo mv /etc/init/smbd.conf.off /etc/init/smbd.conf
|
||||
[[ -f /etc/init/nmbd.conf.off ]] && sudo mv /etc/init/nmbd.conf.off /etc/init/nmbd.conf
|
||||
[[ ! -f /etc/init/smbd.conf || ! -f /etc/init/nmbd.conf ]] && installSamba=1
|
||||
else
|
||||
sudo update-rc.d samba defaults &> /dev/null
|
||||
[[ ! -f /etc/init.d/samba ]] && installSamba=1
|
||||
fi
|
||||
|
||||
if (( $installSamba )); then
|
||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||
# prepare for installing packages
|
||||
sudo apt-get -y update
|
||||
touch /tmp/a2server-packageReposUpdated
|
||||
fi
|
||||
|
||||
sudo apt-get -y install samba
|
||||
[[ -f /usr/bin/smbpasswd ]] || sudo apt-get -y install samba-common-bin
|
||||
sudo apt-get clean
|
||||
fi
|
||||
|
||||
if [[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]]; then
|
||||
sudo initctl start smbd &> /dev/null
|
||||
sudo initctl start nmbd &> /dev/null
|
||||
else
|
||||
sudo /etc/init.d/samba start &> /dev/null
|
||||
fi
|
||||
|
||||
workgroup=$(grep -o "^ workgroup = .*$" /etc/samba/smb.conf 2> /dev/null | cut -c 16-)
|
||||
[[ $workgroup ]] || workgroup="WORKGROUP"
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo "Enter workgroup name (or press return for '${workgroup}'): "
|
||||
read
|
||||
[[ $REPLY ]] && workgroup=$REPLY
|
||||
fi
|
||||
sudo sed -i 's/^ workgroup = .*$/ workgroup = '$workgroup'/' /etc/samba/smb.conf 2> /dev/null
|
||||
sudo sed -i 's/^# security = user/ security = user/' /etc/samba/smb.conf 2> /dev/null
|
||||
|
||||
grep ^/media /usr/local/etc/netatalk/AppleVolumes.default | cut -d" " -f2 \
|
||||
| while read sharename; do
|
||||
if [[ $(grep $sharename /etc/samba/smb.conf) ]]; then
|
||||
echo "A2SERVER: $sharename is already set up for Windows file sharing."
|
||||
else
|
||||
echo "[$sharename]" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||
echo " path = /srv/A2SERVER/$sharename" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||
echo " browsable = yes" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||
echo " guest ok = yes" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||
echo " read only = no" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||
echo " create mask = 0666" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||
echo " force user = $USER" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||
echo "A2SERVER: $sharename has been set up for Windows file sharing."
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "A2SERVER: Setting Windows file sharing password to 'apple2'."
|
||||
echo -e 'apple2\napple2' | sudo smbpasswd -s -a $USER
|
||||
|
||||
echo
|
||||
echo "A2SERVER: Windows file sharing is now running."
|
||||
else
|
||||
if [[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]]; then
|
||||
sudo initctl stop smbd &> /dev/null
|
||||
sudo initctl stop nmbd &> /dev/null
|
||||
[[ -f /etc/init/smbd.conf ]] && sudo mv /etc/init/smbd.conf /etc/init/smbd.conf.off
|
||||
[[ -f /etc/init/nmbd.conf ]] && sudo mv /etc/init/nmbd.conf /etc/init/nmbd.conf.off
|
||||
else
|
||||
sudo /etc/init.d/samba stop &> /dev/null
|
||||
sudo update-rc.d -f samba remove &> /dev/null
|
||||
fi
|
||||
echo "A2SERVER: Windows file sharing has been turned off."
|
||||
fi
|
||||
|
||||
echo
|
||||
fi
|
@ -1,105 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# --- Ubuntu Server console optimizaton (optional)
|
||||
|
||||
# This script helps when running on the Linux console within the VM.
|
||||
|
||||
echo
|
||||
|
||||
userPw=$(sudo grep "^$USER" /etc/shadow | cut -f 2 -d ':')
|
||||
[[ $userPw == "$(echo 'apple2' | perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "${userPw%"${userPw#\$*\$*\$}"}")" ]] && isApple2Pw=1 || isApple2Pw=
|
||||
[[ $userPw == "$(echo 'raspberry' | perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "${userPw%"${userPw#\$*\$*\$}"}")" ]] && isRaspberryPw=1 || isRaspberryPw=
|
||||
|
||||
password="your password"
|
||||
[[ $isApple2Pw ]] && password="'apple2'"
|
||||
[[ $isRaspberryPw ]] && password="'raspberry'"
|
||||
|
||||
isDebian=
|
||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "7." ) && ( $(uname -m) == "i686" ) ]] && isDebian=1
|
||||
|
||||
if [[ $isDebian ]]; then
|
||||
if { lspci 2> /dev/null | grep -q VirtualBox; }; then
|
||||
echo "A2SERVER: Disabling VirtualBox console screen blanking..."
|
||||
sudo sed -i 's/^BLANK_DPMS=off/BLANK_DPMS=on/' /etc/kbd/config
|
||||
sudo sed -i 's/^BLANK_TIME=[^0].$/BLANK_TIME=0/' /etc/kbd/config
|
||||
sudo /etc/init.d/kbd restart &> /dev/null
|
||||
sudo /etc/init.d/console-setup restart &> /dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# check that we're on Ubuntu
|
||||
if [[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]]; then
|
||||
|
||||
# don't do any of this if we're logged in via SSH
|
||||
if [[ $SSH_CLIENT || $REMOTEHOST ]]; then
|
||||
echo "A2SERVER: Logged in via SSH,not performing console optimization."
|
||||
echo "Run setup from the console if you want to optimize the console."
|
||||
else
|
||||
|
||||
# if we've already done this stuff, don't do it again
|
||||
if [[ ! -x /etc/update-motd.d/10-help-text ]]; then
|
||||
|
||||
echo "A2SERVER: Ubuntu console has already been optimized."
|
||||
else
|
||||
echo "Ubuntu console optimization for use in a virtual machine will:"
|
||||
echo "- show the default username/password on the login screen"
|
||||
echo "- remove the documentation URL and system statistics shown after login"
|
||||
echo "- ensure the screen clears before showing the login prompt"
|
||||
echo "- prevent the screen from dimming after 10 minutes (once logged in)"
|
||||
echo "- eliminate a harmless but annoying startup error about piix_smbus"
|
||||
echo "- fix an Ubuntu 10.04 issue with slow scrolling"
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Do you want to optimize the Ubuntu console? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
|
||||
echo "A2SERVER: Optimizing console..."
|
||||
|
||||
# remind the user how to log in (we're going for functionality here, not security)
|
||||
if [[ ! $(grep $USER\/$password /etc/issue) ]]; then
|
||||
sudo sed -i '/^Log in with.*$/d' /etc/issue
|
||||
echo "Log in with '$USER' / '$password'." | sudo tee -a /etc/issue > /dev/null
|
||||
echo | sudo tee -a /etc/issue > /dev/null
|
||||
fi
|
||||
|
||||
# If after logging in, you don't like the documentation URL and
|
||||
# system info (or an error about it) being displayed, type:
|
||||
sudo chmod -x /etc/update-motd.d/10-help-text
|
||||
sudo chmod -x /etc/update-motd.d/50-landscape-sysinfo
|
||||
|
||||
# If the screen doesn't clear for login after the boot messages, and
|
||||
# you'd like it to, type:
|
||||
sudo sed -i 's/X_DEFAULT=""/X_DEFAULT="quiet"/g' /etc/default/grub
|
||||
sudo update-grub
|
||||
|
||||
# If you see a piix4_smbus error on startup, it is harmless, but if you
|
||||
# want to eliminate it, type:
|
||||
echo -e '\nblacklist i2c_piix4' \
|
||||
| sudo tee -a /etc/modprobe.d/blacklist.conf > /dev/null
|
||||
sudo update-initramfs -u -k all
|
||||
|
||||
# If you want to prevent the Ubuntu screen from going blank after ten
|
||||
# minutes of inactivity (once you are logged in), type:
|
||||
echo -e \
|
||||
'\n[[ $SSH_CLIENT || $REMOTEHOST ]] || setterm -blank 0 -powersave off -powerdown 0' \
|
||||
| sudo tee -a /etc/profile > /dev/null
|
||||
setterm -blank 0 -powersave off -powerdown 0
|
||||
|
||||
# (note: These next lines addresses an issue only for Ubuntu 10.04.)
|
||||
# Type "ps aux" and press return. If you see slow text scrolling, type:
|
||||
if [[ "$(lsb_release -rs 2> /dev/null)" == "10.04" ]]; then
|
||||
echo -e '\nblacklist vga16fb' \
|
||||
| sudo tee -a /etc/modprobe.d/blacklist-framebuffer.conf > /dev/null
|
||||
if [[ ! $SSH_CLIENT ]]; then
|
||||
echo "Restarting now is recommended. To resume setup, log back"
|
||||
echo -n "in, press up-arrow, and press return. Restart now? "
|
||||
read; R=${REPLY:0:1}
|
||||
[[ $R != "y" ]] && [[ $R != "Y" ]] || sudo shutdown -r now
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
@ -1,86 +0,0 @@
|
||||
# A2SERVER aliases:
|
||||
|
||||
|
||||
alias a2server-help="more /usr/local/etc/a2server-help.txt"
|
||||
alias a2server-setup="wget -q -O /tmp/a2server-setup appleii.ivanx.com/a2server/setup/; source /tmp/a2server-setup"
|
||||
|
||||
alias a2server-version="cat /usr/local/etc/A2SERVER-version"
|
||||
alias a2server-update="wget -q -O /tmp/a2server-update appleii.ivanx.com/a2server/update/; source /tmp/a2server-update"
|
||||
|
||||
alias system-shutdown='sudo shutdown -h now'
|
||||
alias system-restart='sudo shutdown -r now'
|
||||
|
||||
|
||||
alias raspi-config='[[ -f /usr/bin/raspi-config ]] && sudo /usr/bin/raspi-config || echo "raspi-config not found. Are you using a Raspberry Pi with Raspbian?"'
|
||||
alias raspbian-update='wget -qO /tmp/raspbian-update ivanx.com/a2server/files/raspbian-update.txt; source /tmp/raspbian-update'
|
||||
alias rasppleii-update='raspbian-update a2cloud a2server'
|
||||
|
||||
alias welcome-message-edit='[[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]] && motd=/etc/issue || motd=/etc/motd; sudo nano $motd'
|
||||
|
||||
alias showip='ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1'
|
||||
alias showmac='ifconfig eth0 | grep "HWaddr" | cut -dH -f2 | cut -c7-23'
|
||||
alias showip-wifi='ifconfig wlan0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1'
|
||||
alias showmac-wifi='ifconfig wlan0 | grep "HWaddr" | cut -dH -f2 | cut -c7-23'
|
||||
alias ifreset='sudo rm /etc/udev/rules.d/70-persistent-net.rules; echo Interfaces removed. You should system-restart now.'
|
||||
|
||||
alias netatalk-stop="sudo /etc/init.d/netatalk stop; bonjour-off"
|
||||
alias netatalk-start="sudo /etc/init.d/netatalk start; bonjour-on"
|
||||
alias netatalk-restart="sudo /etc/init.d/netatalk restart; bonjour-on"
|
||||
alias netatalk-off='sudo /etc/init.d/netatalk stop; bonjour-off; sudo update-rc.d -f netatalk remove &> /dev/null'
|
||||
alias netatalk-on='sudo update-rc.d netatalk defaults &> /dev/null; bonjour-on; sudo /etc/init.d/netatalk restart'
|
||||
|
||||
alias bonjour-off="sudo mv /etc/avahi/services/afpd.service /etc/avahi/services/afpd.service_disabled &> /dev/null"
|
||||
alias bonjour-on="sudo mv /etc/avahi/services/afpd.service_disabled /etc/avahi/services/afpd.service &> /dev/null"
|
||||
|
||||
|
||||
alias netatalk-router-on='sudo sed -i '"'"'s/^eth0.*$/eth0 -router -phase 2 -net 1 -zone "A2SERVER"/'"'"' /usr/local/etc/netatalk/atalkd.conf; sudo sed -i '"'"'s/^wlan0.*$/wlan0 -router -phase 2 -net 1 -zone "A2SERVER"/'"'"' /usr/local/etc/netatalk/atalkd.conf; netatalk-restart'
|
||||
alias netatalk-router-off='sudo sed -i '"'"'s/^eth0.*$/eth0/'"'"' /usr/local/etc/netatalk/atalkd.conf; sudo sed -i '"'"'s/^wlan0.*$/wlan0/'"'"' /usr/local/etc/netatalk/atalkd.conf; netatalk-restart'
|
||||
|
||||
|
||||
alias netatalk-eth='sudo sed -i 's/^wlan0/eth0/' /usr/local/etc/netatalk/atalkd.conf; netatalk-restart'
|
||||
alias netatalk-wifi='sudo sed -i 's/^eth0/wlan0/' /usr/local/etc/netatalk/atalkd.conf; netatalk-restart'
|
||||
|
||||
|
||||
|
||||
alias appletalk-off='sudo sed -i "s/ATALKD_RUN=yes/ATALKD_RUN=no/" /etc/default/netatalk; sudo /etc/init.d/netatalk restart'
|
||||
alias appletalk-on='sudo sed -i "s/ATALKD_RUN=no/ATALKD_RUN=yes/" /etc/default/netatalk; sudo /etc/init.d/netatalk restart'
|
||||
|
||||
|
||||
NETATALK="/usr/local/etc/netatalk"
|
||||
A2FILES="/srv/A2SERVER/A2FILES"
|
||||
GSFILES="/srv/A2SERVER/GSFILES"
|
||||
|
||||
alias netboot-gsos="mkatinit -gs -d -f"
|
||||
alias netboot-gsos-guest="mkatinit -gs -d -f guest"
|
||||
alias netboot-p8="mkatinit -d -f"
|
||||
alias netboot-p8-guest="mkatinit -d -f guest"
|
||||
|
||||
|
||||
|
||||
|
||||
alias guest-off="sudo sed -i 's/uams_guest.so,//' /usr/local/etc/netatalk/afpd.conf; [[ -f /etc/samba/smb.conf ]] && sudo sed -i 's/^ guest ok = yes/ guest ok = no/' /etc/samba/smb.conf; sudo /etc/init.d/netatalk restart"
|
||||
alias guest-on="sudo sed -i 's/-uamlist uams_clrtxt.so/-uamlist uams_guest.so,uams_clrtxt.so/' /usr/local/etc/netatalk/afpd.conf; [[ -f /etc/samba/smb.conf ]] && sudo sed -i 's/^ guest ok = no/ guest ok = yes/' /etc/samba/smb.conf; sudo /etc/init.d/netatalk restart"
|
||||
|
||||
|
||||
|
||||
alias samba-off='[[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]] && { sudo initctl stop smbd; sudo initctl stop nmbd; [[ -f /etc/init/smbd.conf ]] && sudo mv /etc/init/smbd.conf /etc/init/smbd.conf.off; [[ -f /etc/init/nmbd.conf ]] && sudo mv /etc/init/nmbd.conf /etc/init/nmbd.conf.off; } || { sudo /etc/init.d/samba stop; sudo update-rc.d -f samba remove &> /dev/null; }'
|
||||
alias samba-on='[[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]] && { [[ -f /etc/init/smbd.conf.off ]] && sudo mv /etc/init/smbd.conf.off /etc/init/smbd.conf; [[ -f /etc/init/nmbd.conf.off ]] && sudo mv /etc/init/nmbd.conf.off /etc/init/nmbd.conf; sudo initctl start smbd; sudo initctl start nmbd; } || { sudo update-rc.d samba defaults &> /dev/null; sudo /etc/init.d/samba restart; }'
|
||||
alias samba-stop='[[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]] && { sudo initctl stop smbd; sudo initctl stop nmbd; } || { sudo /etc/init.d/samba stop; }'
|
||||
alias samba-start='[[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]] && { sudo initctl start smbd; sudo initctl start nmbd; } || { sudo /etc/init.d/samba start; }'
|
||||
alias samba-restart='[[ $(lsb_release -d 2> /dev/null | grep Ubuntu) ]] && { sudo initctl restart smbd; sudo initctl restart nmbd; } || { sudo /etc/init.d/samba restart; }'
|
||||
|
||||
alias gsfiles-share="sudo sed -i 's/^\/media\/A2SHARED\/GSFILES\ GSFILES options:prodos/#share1/' /usr/local/etc/netatalk/AppleVolumes.default"
|
||||
alias gsfiles-unshare="sudo sed -i 's/^#share1/\/media\/A2SHARED\/GSFILES\ GSFILES options:prodos/' /usr/local/etc/netatalk/AppleVolumes.default; [[ -d /srv/A2SERVER/GSFILES ]] || mkdir /srv/A2SERVER/GSFILES"
|
||||
alias a2files-share="sudo sed -i 's/^\/media\/A2SHARED\/A2FILES\ A2FILES options:prodos\ casefold:toupper/#share2/' /usr/local/etc/netatalk/AppleVolumes.default"
|
||||
alias a2files-unshare="sudo sed -i 's/^#share2/\/media\/A2SHARED\/A2FILES\ A2FILES options:prodos\ casefold:toupper/' /usr/local/etc/netatalk/AppleVolumes.default; [[ -d /srv/A2SERVER/A2FILES ]] || mkdir /srv/A2SERVER/A2FILES"
|
||||
|
||||
alias showalias="alias | cut -d= -f 1 | cut -d' ' -f2 | more"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
@ -1,86 +0,0 @@
|
||||
A2SERVER commands:
|
||||
(note: new commands may be added; use a2server-setup to refresh)
|
||||
|
||||
a2server-help: show this list of commands
|
||||
a2server-setup: set up network boot, Windows access, Farallon fix,
|
||||
refresh command list
|
||||
a2server-version: see installed version of A2SERVER
|
||||
a2server-update: check for update to A2SERVER
|
||||
|
||||
system-shutdown: shut down the server
|
||||
system-restart: shut down and restart the server
|
||||
|
||||
Raspberry Pi commands, if you're using one:
|
||||
raspi-config: utilize all space on RPi SD card & other options
|
||||
raspbian-update : update Raspbian operating system
|
||||
rasppleii-update : update Raspbian OS, A2CLOUD, A2SERVER, Apple II Pi
|
||||
|
||||
welcome-message-edit: change the welcome message
|
||||
|
||||
showip: show the current ethernet IP address of the server
|
||||
showmac: show the MAC (Ethernet hardware) address of the server
|
||||
showip-wifi: show the current wifi IP address of the server
|
||||
showmac-wifi: show the MAC (wifi hardware) address of the server
|
||||
ifreset: reset all network interfaces (requires restart)
|
||||
|
||||
netatalk-stop: stop the netatalk service until reboot
|
||||
netatalk-start: start the netatalk service
|
||||
netatalk-restart: restart the netatalk service
|
||||
netatalk-off: disable the netatalk service (even after reboot)
|
||||
netatalk-on: enable the netatalk service
|
||||
|
||||
bonjour-off: disable advertisement of shared folders to OS X
|
||||
bonjour-on : enable advertisement of shared folders to OS X
|
||||
(these are automatically set by the netatalk commands above)
|
||||
|
||||
netatalk-router-on: use netatalk in router mode (default)
|
||||
netatalk-router-off: use netatalk in node mode
|
||||
(use if there is an AppleTalk router such as a GatorBox present)
|
||||
|
||||
netatalk-eth: use wired ethernet interface for netatalk (default)
|
||||
netatalk-wifi: use wifi interface for netatalk
|
||||
note: if an interface isn't available, netatalk will be reset with
|
||||
router mode off; use "netatalk-router-on" to correct this if needed
|
||||
|
||||
appletalk-off: disable AppleTalk networking (even after reboot)
|
||||
appletalk-on : enable AppleTalk networking
|
||||
|
||||
environment variables:
|
||||
$NETATALK: directory containing netatalk configuration files
|
||||
$A2FILES : directory containing A2FILES shared volume
|
||||
$GSFILES : directory containing GSFILES shared volume
|
||||
|
||||
netboot-gsos: set the current user to netboot into GS/OS (default)
|
||||
netboot-gsos-guest: set guests to netboot into GS/OS
|
||||
netboot-p8: set the current user to netboot into ProDOS 8
|
||||
netboot-p8-guest: set guests to netboot into ProDOS 8 (default)
|
||||
note: when a IIgs is set to network boot into GS/OS, using the Network
|
||||
control panel or the NETBOOT.GSOS utility, guests will behave like
|
||||
registered users, and ignore the netboot setting of the guest user
|
||||
|
||||
guest-off: disallow guest access to A2SERVER
|
||||
guest-on: allow guest access to A2SERVER (default)
|
||||
note: by default, Guest access is the only way to network boot into
|
||||
ProDOS 8. For registered user boot into ProDOS 8, type "netboot-p8"
|
||||
|
||||
samba-off: disable Windows file sharing (even after reboot)
|
||||
samba-on: enable Windows file Sharing
|
||||
samba-stop: stop Windows file sharing until reboot
|
||||
samba-start: start Windows file sharing
|
||||
samba-restart: stop and restart Windows file sharing
|
||||
|
||||
gsfiles-share: disable the GSFILES shared volume
|
||||
gsfiles-unshare: enable the GSFILES shared volume
|
||||
a2files-share: disable the A2FILES shared volume
|
||||
a2files-unshare: enable the A2FILES shared volume
|
||||
|
||||
nulib2: create, extract, and work with NuFX (ShrinkIt) archive files
|
||||
unar: extract other archive files (multiformat)
|
||||
lsar: list contents of other archive files (multiformat)
|
||||
|
||||
afptype: set the ProDOS type/auxtype or Mac OS type/creator of a file
|
||||
afpsync: register files introduced outside of AFP with netatalk
|
||||
mkatinit: set up network boot configuration files
|
||||
cppo: catalog and copy files from ProDOS image file (slow, but works)
|
||||
(add -h to show help for the above four commands, e.g. "afptype -h")
|
||||
|
@ -1,114 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# afpsync: updates .AppleDouble components of files on shared volumes
|
||||
|
||||
# this must be used if any files are copied to the shared volume via
|
||||
# non-AFP methods (directly, via Samba, etc).
|
||||
|
||||
# usage:
|
||||
# afpsync [-v] [shared volume path]
|
||||
#
|
||||
# -v will silently create a .volinfo file if none exists.
|
||||
# If a path is specified, only that volume is synced; otherwise, all
|
||||
# all paths in /media which appear in
|
||||
# /usr/local/etc/netatalk/AppleVolumes.default are synced.
|
||||
|
||||
processPath () {
|
||||
if [[ ! -d $sharepath ]]; then
|
||||
echo "$sharepath does not exist."
|
||||
else
|
||||
volinfo="$sharepath/.AppleDesktop/.volinfo"
|
||||
if [[ ! -f $volinfo ]]; then
|
||||
if [[ ! $force ]]; then
|
||||
echo "Cannot update AppleDouble files for volume $sharepath,"
|
||||
echo "because its .volinfo file does not exist. To create it, log"
|
||||
echo "into the volume from an Apple II or Mac client computer,"
|
||||
echo "or use \"afpsync -v\"."
|
||||
else
|
||||
if (( $1 )); then
|
||||
mkvolinfo -f -c $sharepath
|
||||
else
|
||||
mkvolinfo -f $sharepath
|
||||
fi
|
||||
$0 $sharepath
|
||||
fi
|
||||
else
|
||||
IFS=''
|
||||
result=$(sudo dbd -r $sharepath | grep encoding)
|
||||
f=$(echo $result | wc -l)
|
||||
[[ $(echo $result | wc -w) == 0 ]] && f=0
|
||||
[[ f -eq 1 && $(echo $result | grep APPLEDESKTOP) && $(grep MTOULOWER $sharepath/.AppleDesktop/.volinfo) ]] && (( f-- ))
|
||||
if (( f == 0 )); then
|
||||
echo "AppleDouble files have been updated for volume $sharepath."
|
||||
else
|
||||
[[ ! $renameLower ]] && echo "Could not update all files on volume $sharepath."
|
||||
[[ ! $renameLower ]] && echo "Ensure filenames are all caps on volume $sharepath."
|
||||
if [[ $showerrors ]]; then
|
||||
echo $result \
|
||||
| while read LINE; do
|
||||
[[ ! $(echo $LINE | grep APPLEDESKTOP) ]] && echo $LINE
|
||||
done
|
||||
elif [[ $renameLower ]]; then
|
||||
echo $result \
|
||||
| while read LINE; do
|
||||
if [[ ! $(echo $LINE | grep APPLEDESKTOP) ]]; then
|
||||
filepath=$(echo $LINE | sed "s/^Bad\ encoding\ for\ '//" | sed s/\'//)
|
||||
filename=${filepath##*/}
|
||||
filedir=${filepath%/*}
|
||||
mv $filepath $filedir/${filename^^}
|
||||
echo "Renamed $filedir/${filename^^}."
|
||||
fi
|
||||
done
|
||||
$0 $sharepath
|
||||
else
|
||||
echo "Use afpsync -e to see error details."
|
||||
echo "Use afpsync -r to rename lowercase names to uppercase."
|
||||
fi
|
||||
fi
|
||||
unset IFS
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
while [[ $1 == "-r" || $1 == "-e" || $1 = "-v" ]]; do
|
||||
|
||||
if [[ $1 == "-v" ]]; then
|
||||
force=1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $1 == "-e" ]]; then
|
||||
showerrors=1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $1 == "-r" ]]; then
|
||||
renameLower=1
|
||||
shift
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if [[ ${1:0:1} == "-" ]]; then
|
||||
echo "Usage: afpsync [-e|-r] [-v] [shared volume path]"
|
||||
echo
|
||||
echo "-e: show error details"
|
||||
echo "-r: rename lowercase filenames to uppercase"
|
||||
echo "-v: create .volinfo file if none exists"
|
||||
echo "If no directory is specified, all found in"
|
||||
echo " /usr/local/etc/netatalk/AppleVolumes.default are processed."
|
||||
echo
|
||||
else
|
||||
sudo true
|
||||
if [[ $1 ]]; then
|
||||
sharepath=$(readlink -m $1)
|
||||
processPath
|
||||
else
|
||||
grep ^/media /usr/local/etc/netatalk/AppleVolumes.default | \
|
||||
while read line; do
|
||||
[[ $(echo $line | grep toupper) ]]; nocasefold=$?
|
||||
sharepath=$(echo $line | cut -d" " -f1)
|
||||
processPath nocasefold
|
||||
done
|
||||
fi
|
||||
fi
|
@ -1,498 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 2-25-11: tested on 10.6.5 and Ubuntu 10.10. Final.
|
||||
|
||||
# to do: allow hex offsets
|
||||
|
||||
# These bash functions perform single-byte dec-hex-character conversions
|
||||
# and file read/write operations, and hopefully work identically across
|
||||
# different platforms. Each can operate by itself without the presence
|
||||
# of the others. They have been tested on Mac OS X 10.6 and
|
||||
# Ubuntu Linux 10.10. Your mileage may vary.
|
||||
|
||||
# You provide parameters to the functions as arguments, or alternatively
|
||||
# standard in (for the functions which accept characters). Examples:
|
||||
# Write hex byte with value "F0" to offset 23 in file "myFile":
|
||||
# writecharHex myFile 23 F0
|
||||
# Write "ABCDE" to the beginning of file "myFile"
|
||||
# echo "ABCDE" | writechars myFile
|
||||
|
||||
# For functions which output something (all but the write operations),
|
||||
# you can call the functions with command substitution if you want to
|
||||
# assign the output to a variable rather than display it. Examples:
|
||||
# Convert decimal value 65 to its hexadecimal equivalent:
|
||||
# val=$(decToHex 65)
|
||||
# Get decimal value of the character/byte at offset 215 in "myFile":
|
||||
# val=$(readcharDec "myFile" 215)
|
||||
|
||||
# For functions which convert to or from a character, 0-127 will be
|
||||
# ASCII/UTF-8, while 128-255 will be system/locale/codepage dependent.
|
||||
# In this context, a character is effectively the same as a byte.
|
||||
|
||||
# The functions return a non-zero exit status for invalid or missing
|
||||
# arguments. If you don't need these checks, remove the lines
|
||||
# above the comment "args are valid" (or as otherwise noted).
|
||||
# The exit statuses are, generally:
|
||||
# 0 = no error
|
||||
# 8 = extraneous argument
|
||||
# 9 = standard input is invalid
|
||||
# 1x = missing required argument (e.g. 11 for missing argument 1)
|
||||
# 2x = argument is invalid (e.g. 22 for invalid argument 2)
|
||||
# any other exit status will originate from the final command in the
|
||||
# function (e.g. dd, printf)
|
||||
|
||||
# For the functions which output chars (readchars, decToChar, and
|
||||
# hexToChar), be aware that NUL (0) and trailing LF (10/0x0A) chars will
|
||||
# be stripped when assigned to a variable, and cannot appear in an
|
||||
# argument. To preserve them, pipe the output elsewhere, such as into
|
||||
# charToDec, charToHex, writechars, or a command. (readcharDec and
|
||||
# readcharHex handle these characters correctly.)
|
||||
|
||||
# questions/comments to ivan@ivanx.com
|
||||
|
||||
decToHex () {
|
||||
# converts single-byte decimal value to hexadecimal equivalent
|
||||
# arg: decimal value from 0-255
|
||||
# out: two-digit hex value from 00-FF
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ( $(printf %d "$1" 2> /dev/null) == $1 ) \
|
||||
&& ( $1 -ge 0 ) && ( $1 -le 255 ) ]] || return 21
|
||||
# args are valid
|
||||
printf %02X "$1"
|
||||
}
|
||||
|
||||
hexToDec () {
|
||||
# converts single-byte hexadecimal value to decimal equivalent
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: decimal value
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ${#1} -eq 2 ]] || return 21
|
||||
[[ $(printf %02X "0x$1" 2> /dev/null) == \
|
||||
$(echo -n "$1" | tr [a-z] [A-Z]) ]] || return 21
|
||||
# args are valid
|
||||
printf %d "0x$1"
|
||||
}
|
||||
|
||||
charToDec () {
|
||||
# converts single character to corresponding decimal value
|
||||
# stdin OR arg: one character
|
||||
# [arg overrides stdin; stdin is required for NUL (0) or LF (0x0A)]
|
||||
# out: decimal value from 0-255
|
||||
#exit: 8=extraneous arg, 9=invalid stdin,
|
||||
# 11=missing stdin/arg, 21=invalid arg
|
||||
[[ ( ! -t 0 ) && $1 ]] && { cat > /dev/null; return 8; }
|
||||
[[ ( -t 0 ) ]] && { [[ $2 ]] && return 8; [[ $1 ]] || return 11; }
|
||||
# arg/stdin is potentially valid (additional check below)
|
||||
charX="$1X"; [[ $1 ]] || charX="$(cat; echo -n 'X';)"
|
||||
[[ ${#charX} -le 2 ]] || return $(( $([[ $1 ]]; echo $?) ? 9 : 21 ))
|
||||
# above line verifies that arg/stdin is valid
|
||||
[[ ${#charX} -ne 2 ]] && { echo -n 0; return 0; }
|
||||
echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||
}
|
||||
|
||||
charToHex () {
|
||||
# converts single character to corresponding hexadecimal value
|
||||
# stdin OR arg: one character
|
||||
# [arg overrides stdin; stdin is required for NUL (0) or LF (0x0A)]
|
||||
# out: decimal value from 0-255
|
||||
#exit: 8=extraneous arg, 9=invalid stdin,
|
||||
# 11=missing stdin/arg, 21=invalid arg
|
||||
[[ ( ! -t 0 ) && $1 ]] && { cat > /dev/null; return 8; }
|
||||
[[ ( -t 0 ) ]] && { [[ $2 ]] && return 8; [[ $1 ]] || return 11; }
|
||||
# arg/stdin is potentially valid (additional check below)
|
||||
charX="$1X"; [[ $1 ]] || charX="$(cat; echo -n 'X';)"
|
||||
[[ ${#charX} -le 2 ]] || return $(( $([[ $1 ]]; echo $?) ? 9 : 21 ))
|
||||
# above line verifies that stdin/arg is valid
|
||||
[[ ${#charX} -ne 2 ]] && { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||
}
|
||||
|
||||
decToChar () {
|
||||
# converts single-byte decimal value to equivalent character
|
||||
# arg: decimal number from 0-255
|
||||
# out: one character
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ( $(printf %d "$1" 2> /dev/null ) == $1 ) \
|
||||
&& ( $1 -ge 0 ) && ( $1 -le 255 ) ]] || return 21
|
||||
# args are valid
|
||||
echo -n -e "\x$(printf %02X "$1")"
|
||||
}
|
||||
|
||||
hexToChar () {
|
||||
# converts single-byte hexadecimal value to corresponding character
|
||||
# arg: two-digit hexadecimal number from 00-FF
|
||||
# out: one character
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ${#1} -eq 2 ]] || return 21
|
||||
[[ $(printf %02X "0x$1" 2> /dev/null) == \
|
||||
$(echo -n "$1" | tr [a-z] [A-Z]) ]] || return 21
|
||||
# args are valid
|
||||
echo -n -e "\x$1"
|
||||
}
|
||||
|
||||
readchars () {
|
||||
# read one or more characters from a file
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# arg3: (optional) # of chars to read (default is until end of file)
|
||||
# out: sequence of characters
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11
|
||||
[[ $4 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
[[ $3 ]] && { [[ ( $(printf %d "$3" 2> /dev/null) == $3 ) \
|
||||
&& ( $3 -ge 0 ) ]] || return 23; }
|
||||
# args are valid
|
||||
dd if="$1" bs=1 skip=$(($2)) $([[ $3 ]] && echo -n "count=$3") \
|
||||
2> /dev/null
|
||||
}
|
||||
|
||||
readcharDec () {
|
||||
# read one character from file & convert to equivalent decimal value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
|
||||
echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||
}
|
||||
|
||||
readcharHex () {
|
||||
# read one character from file & convert to corresponding hex value
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 21=invalid arg1, 22=invalid arg2
|
||||
[[ $1 ]] || return 11
|
||||
[[ $3 ]] && return 8
|
||||
[[ -f $1 ]] || return 21
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||
# args are valid
|
||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||
count=1 2> /dev/null; echo -n X)"
|
||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||
}
|
||||
|
||||
### 2-15-11 above tested on OS X and Linux
|
||||
|
||||
writechars () {
|
||||
# write one or more characters (bytes) to file
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before writing)
|
||||
# arg3 OR stdin: sequence of characters
|
||||
# [stdin required if writing NUL (0) or trailing LF (0x0A) chars]
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 13=missing stdin/arg3, 22=invalid arg2
|
||||
[[ $1 ]] || { [[ -t 0 ]] || cat > /dev/null; return 11; }
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && \
|
||||
( $2 -ge 0 ) ]] || { [[ -t 0 ]] || cat > /dev/null; return 22; } }
|
||||
[[ ( ! -t 0 ) && $3 ]] && { cat > /dev/null; return 8; }
|
||||
[[ ( -t 0 ) ]] && { [[ $4 ]] && return 8; [[ $3 ]] || return 13; }
|
||||
# args are valid
|
||||
if [[ -t 0 ]]; then
|
||||
echo -n "$3" | \
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
else
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
writecharDec () {
|
||||
# write corresponding character of single-byte decimal value into file
|
||||
# arg1: filename
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: decimal number from 0-255
|
||||
# exit: 8=extraneous arg, 11=missing arg1, 12=missing arg2,
|
||||
# 13=missing arg3, 22=invalid arg2, 23=invalid arg3
|
||||
# out: nothing
|
||||
[[ $1 ]] || return 11; [[ $2 ]] || return 12; [[ $3 ]] || return 13
|
||||
[[ $4 ]] && return 8
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22
|
||||
[[ ( $(printf %d "$3" 2> /dev/null) == $3 ) \
|
||||
&& ( $3 -ge 0 ) && ( $3 -lt 255 ) ]] || return 23
|
||||
# args are valid
|
||||
echo -n -e "\x$(printf %02X "$3")" | \
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
}
|
||||
|
||||
writecharHex () {
|
||||
# write corresponding character of single-byte hex value into file
|
||||
# arg1: filename
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: two-digit hexadecimal number from 00-FF
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1, 12=missing arg2,
|
||||
# 13=missing arg3, 22=invalid arg2, 23=invalid arg3
|
||||
[[ $1 ]] || return 11; [[ $2 ]] || return 12; [[ $3 ]] || return 13
|
||||
[[ $4 ]] && return 8
|
||||
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
|
||||
&& ( $2 -ge 0 ) ]] || return 22
|
||||
[[ $(printf %02X "0x$3" 2> /dev/null) == \
|
||||
$(echo -n "$3" | tr [a-z] [A-Z]) ]] || return 23
|
||||
# args are valid
|
||||
echo -n -e "\x$3" | \
|
||||
dd of="$1" bs=1 seek=$2 conv=notrunc 2> /dev/null
|
||||
}
|
||||
|
||||
|
||||
# --- afptype is below this line
|
||||
|
||||
isHexByte () {
|
||||
[[ $(printf %02X "0x$1" 2> /dev/null) == \
|
||||
$(echo -n "$1" | tr [a-z] [A-Z]) ]] || return 1
|
||||
}
|
||||
|
||||
# support 00 and 0A as filetype chars?
|
||||
|
||||
debug=1
|
||||
ptypes="04:TXT 06:BIN B3:S16 E0:SHK F9:P16 FA:INT FC:BAS FF:SYS"
|
||||
|
||||
quit () {
|
||||
if [[ $2 && $debug ]]; then
|
||||
echo "$1" "$2"
|
||||
else
|
||||
echo -e "Error: $1"
|
||||
fi
|
||||
exit_usage
|
||||
}
|
||||
|
||||
exit_usage () {
|
||||
echo "Usage:"
|
||||
echo
|
||||
echo "show types: afptype filename"
|
||||
echo "set Mac OS: afptype [-t 'type'] [-c 'creator'] [-q] filename"
|
||||
echo "set ProDOS: afptype [-p type] [-a auxtype] [-q] filename"
|
||||
echo "Mac OS type or creator must be four characters; use \x plus"
|
||||
echo " two hex digits for untypeables (note: use '\xZZ' for 00)."
|
||||
echo "ProDOS type should be two hex digits, and auxtype should be four;"
|
||||
echo " type can alternatively be BAS, BIN, INT, P16, S16, SHK, SYS, TXT."
|
||||
echo "-q skips recheck of file (show types) after setting"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
lookupPdosType () {
|
||||
# looks up ProDOS hex type from code in list 'ptypes'
|
||||
# arg: three-character code
|
||||
# out: two-digit hex value
|
||||
#exit: 0=type found, 1=error, 2=type not found
|
||||
ptypes="04:TXT 06:BIN B3:S16 E0:SHK F9:P16 FA:INT FC:BAS FF:SYS"
|
||||
[[ $1 ]] || quit "lookupPdosType:" "no argument supplied ($1)"
|
||||
[[ ${#1} -eq 3 ]] || return 1
|
||||
arg=$(echo -n "$1" | tr [a-z] [A-Z])
|
||||
for ptype in $ptypes; do
|
||||
if [[ ${ptype:3:3} == $arg ]]
|
||||
then
|
||||
echo -n "${ptype:0:2}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "$1"
|
||||
return 1
|
||||
}
|
||||
|
||||
verifyTC () {
|
||||
[[ $1 ]] || return 1
|
||||
tcX="$(echo -e -n "$1"X)"
|
||||
[[ ${#tcX} -eq 5 ]] || return 1
|
||||
echo "$tcX"
|
||||
}
|
||||
|
||||
while [[ $1 && ( "${1:0:1}" == '-' ) ]]; do
|
||||
if [[ $1 == "-p" ]]; then
|
||||
[[ $p ]] && exit_usage
|
||||
shift
|
||||
p="$1"
|
||||
shift
|
||||
continue
|
||||
elif [[ $1 == "-a" ]]; then
|
||||
[[ $a ]] && exit_usage
|
||||
shift
|
||||
a="$1"
|
||||
shift
|
||||
continue
|
||||
elif [[ $1 == "-t" ]]; then
|
||||
[[ $t ]] && exit_usage
|
||||
shift
|
||||
t="$1"
|
||||
shift
|
||||
continue
|
||||
elif [[ $1 == "-c" ]]; then
|
||||
[[ $c ]] && exit_usage
|
||||
shift
|
||||
c="$1"
|
||||
shift
|
||||
continue
|
||||
elif [[ $1 == "-q" ]]; then
|
||||
[[ $q ]] && exit_usage
|
||||
q=1
|
||||
shift
|
||||
continue
|
||||
else
|
||||
exit_usage
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ( ( $p || $a ) && ( $t || $c ) ) || ( -z $1 ) ]]; then
|
||||
exit_usage
|
||||
fi
|
||||
|
||||
#filename="$1"
|
||||
#shift
|
||||
|
||||
for filename in $@; do
|
||||
|
||||
[[ ${#@} -gt 1 ]] && linestart="($filename) "
|
||||
|
||||
if [[ ! -f $filename ]]; then
|
||||
echo "${linestart}Not found."
|
||||
continue
|
||||
fi
|
||||
|
||||
adname="$(dirname "$filename")/.AppleDouble/$(basename "$filename")"
|
||||
[[ -f $adname ]] && filename=$adname
|
||||
ADversion=$(readcharDec "$filename" 5)
|
||||
if [[ ( ( $ADversion -ne 1 ) && ( $ADversion -ne 2 ) ) \
|
||||
|| ( "$(readchars "$filename" 1 3)" != "$(echo -e -n "\x05\x16\x07")" ) \
|
||||
|| ( $(readcharDec "$filename" 0) -ne 0 ) \
|
||||
|| ( $(readcharDec "$filename" 4) -ne 0 ) \
|
||||
|| ( $(readcharDec "$filename" 6) -ne 0 ) \
|
||||
|| ( $(readcharDec "$filename" 7) -ne 0 ) ]]; then
|
||||
echo "${linestart}Not an AppleDouble file."
|
||||
continue
|
||||
fi
|
||||
|
||||
entrycount=`readcharDec "$filename" 25`
|
||||
|
||||
entry=1
|
||||
offset=29
|
||||
|
||||
while [[ $(readcharDec "$filename" $offset) -ne 9 ]]; do
|
||||
(( entry = entry + 1 ))
|
||||
if (( entry > entrycount )); then
|
||||
echo "${linestart}Finder Info entry not found in AppleDouble file."
|
||||
break
|
||||
fi
|
||||
(( offset = (entry * 12 + 29) - 12 ))
|
||||
done
|
||||
(( entry > entrycount )) && continue
|
||||
|
||||
(( offset = offset + 3 ))
|
||||
(( tposHi = $(readcharDec "$filename" $offset) * 256 ))
|
||||
(( offset = offset + 1 ))
|
||||
(( tpos = $(readcharDec "$filename" $offset) + tposHi ))
|
||||
(( cpos = tpos + 4 ))
|
||||
(( ppos = tpos + 1 ))
|
||||
(( apos = tpos + 2 ))
|
||||
|
||||
if [[ $p || $a || $t || $c ]]; then # set
|
||||
if [[ $p || $a ]]; then
|
||||
if [[ $p ]]; then
|
||||
[[ ${#p} -eq 3 ]] && { p=$(lookupPdosType $p) || quit "Invalid ProDOS type name ($p)."; }
|
||||
isHexByte "$p" || quit "Invalid ProDOS file type ($p)."
|
||||
writecharHex "$filename" $ppos "$p"
|
||||
fi
|
||||
if [[ $a ]]; then
|
||||
isHexByte "${a:0:2}" && isHexByte "${a:2:2}" || quit "Invalid ProDOS aux type ($a)."
|
||||
writecharHex "$filename" $apos "${a:0:2}"
|
||||
(( apos=apos+1 ))
|
||||
writecharHex "$filename" $apos "${a:2:2}"
|
||||
fi
|
||||
writechars "$filename" $tpos "p"
|
||||
writechars "$filename" $cpos "pdos"
|
||||
elif [[ $t || $c ]]; then
|
||||
if [[ $t ]]; then
|
||||
type=$(verifyTC "$t") || quit "$(echo -n "Invalid Mac file type ($t)."; [[ $t == *x* ]] && echo -n " Try quotes."; echo)"
|
||||
writechars "$filename" $tpos "${type:0:4}"
|
||||
fi
|
||||
if [[ $c ]]; then
|
||||
creator=$(verifyTC "$c") || quit "$(echo -n "Invalid Mac file creator ($c)."; [[ $c == *x* ]] && echo -n " Try quotes."; echo)"
|
||||
writechars "$filename" $cpos "${creator:0:4}"
|
||||
fi
|
||||
fi
|
||||
[[ $q ]] || { echo -n "${linestart}File changed: "; "$0" "$filename"; }
|
||||
|
||||
else # show
|
||||
[[ $q ]] && quit "Can only use -q when changing type."
|
||||
|
||||
type="$(readchars "$filename" $tpos 4)"
|
||||
creator="$(readchars "$filename" $cpos 4)"
|
||||
|
||||
echo -n "$linestart"
|
||||
|
||||
if [[ $creator != "pdos" || ( ( $type != "TEXT" ) \
|
||||
&& ( $type != "PSYS" ) && ( ${type:0:1} != "p" ) ) ]]; then
|
||||
if [[ $creator || $type ]]; then
|
||||
echo "Mac file. Type:$type Creator:$creator"
|
||||
else
|
||||
echo "This file has no Mac or ProDOS file type information."
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ $type == "TEXT" ]]; then
|
||||
pdosType="\$04 [TXT]"
|
||||
pdosAuxType='$0000'
|
||||
elif [[ $type == "PSYS" ]]; then
|
||||
pdosType="\$FF [SYS]"
|
||||
pdosAuxType='$0000'
|
||||
else
|
||||
(( tpos=tpos+1 ))
|
||||
pdosType=$(readcharHex "$filename" $tpos)
|
||||
for ptype in $ptypes; do
|
||||
if [[ "${ptype:0:2}" == "$pdosType" ]]; then
|
||||
pdosType="$pdosType [${ptype:3:3}]"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
(( tpos=tpos+1 ))
|
||||
auxTypeHi=$(readcharHex "$filename" $tpos)
|
||||
(( tpos=tpos+1 ))
|
||||
auxTypeLo=$(readcharHex "$filename" $tpos)
|
||||
pdosAuxType=$auxTypeHi$auxTypeLo
|
||||
fi
|
||||
|
||||
echo "ProDOS file. Type:\$$pdosType AuxType:\$$pdosAuxType"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# 7-19-11
|
||||
# quick ProDOS testing/fixing on Linux, needs more
|
||||
# Mac Type testing not done yet, nor testing on a Mac
|
||||
|
||||
# test on lunix
|
||||
# test inside and outside of AD directory, and from other dirs (both cases)
|
||||
# finish conversion writebyte/readchar library
|
||||
# consider return 2 for missing parameters for subroutines
|
@ -1,882 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""cppo: Copy or catalog one or all files from a ProDOS raw disk image.
|
||||
|
||||
copy all files:
|
||||
cppo [-ad|-e] imagefile target_directory
|
||||
copy one file:
|
||||
cppo [-ad|-e] imagefile /FULL/PRODOS/FILE/PATH target_path
|
||||
catalog image:
|
||||
cppo -cat imagefile
|
||||
|
||||
-ad : Create AppleDouble header files and preserve resource forks.
|
||||
-e : Append ProDOS type and auxtype to filenames, and copy resource
|
||||
forks, for adding to ShrinkIt archives with Nulib2
|
||||
using its -e option.
|
||||
|
||||
Wildcard matching/globbing (*) is not supported.
|
||||
No verification or validation of the disk image is performed.
|
||||
|
||||
(Compatible with Python 2.6 and later, including 3.x.)
|
||||
"""
|
||||
|
||||
# cppo by Ivan X, ivan@ivanx.com, ivanx.com/appleii
|
||||
|
||||
# If anyone's looking at this, and feels it's not sufficiently Pythonic,
|
||||
# I know that. It's pretty much a line-for-line conversion of the original
|
||||
# Bash script. I did start a beautiful from-the-ground-up object-oriented
|
||||
# version, then realized it would be faster to translate it ugly and quick.
|
||||
|
||||
# imports for python 3 code compatibility
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
|
||||
# Intentially fails on pre-2.6 so user can see what's wrong
|
||||
b'ERROR: cppo requires Python 2.6 or later, including 3.x.'
|
||||
|
||||
class Globals(object):
|
||||
pass
|
||||
|
||||
g = Globals()
|
||||
|
||||
g.imageData = b''
|
||||
g.outFileData = bytearray(b'')
|
||||
g.adFileData = bytearray(b'')
|
||||
g.exFileData = bytearray(b'')
|
||||
|
||||
g.activeDirBlock = None
|
||||
g.activeFileName = None
|
||||
g.activeFileSize = None
|
||||
g.activeFileBytesCopied = 0
|
||||
g.resourceFork = 0
|
||||
|
||||
g.PDOSPATH = []
|
||||
g.PDOSPATH_INDEX = 0
|
||||
g.PDOSPATH_SEGMENT = None
|
||||
g.DIRPATH = ""
|
||||
|
||||
g.targetName = None
|
||||
g.targetDir = ""
|
||||
g.ADdir = None
|
||||
g.imageFile = None
|
||||
|
||||
g.AD = 0
|
||||
g.EX = 0
|
||||
g.DIR = 0
|
||||
g.silent = 0
|
||||
|
||||
# functions
|
||||
|
||||
def pdosDateToUnixDate(arg1):
|
||||
# input: ProDOS date/time bit sequence string in format:
|
||||
# "yyyyyyymmmmddddd000hhhhh00mmmmmm" (ustr)
|
||||
# output: seconds since Unix epoch (1-Jan-1970),
|
||||
# or current date/time if no ProDOS date
|
||||
year = (binToDec(slyce(arg1,0,7)) + 1900)
|
||||
if (year < 1940): year += 100
|
||||
month = binToDec(slyce(arg1,7,4))
|
||||
day = binToDec(slyce(arg1,11,5))
|
||||
hour = binToDec(slyce(arg1,19,5))
|
||||
minute = binToDec(slyce(arg1,26,6))
|
||||
# print(year, month, day, hour, minute)
|
||||
td = (datetime.datetime(year, month, day, hour, minute) -
|
||||
datetime.datetime(1970,1,1))
|
||||
unixDate_naive = (td.days*24*60*60 + td.seconds)
|
||||
td2 = (datetime.datetime.fromtimestamp(unixDate_naive) -
|
||||
datetime.datetime.utcfromtimestamp(unixDate_naive))
|
||||
utcoffset = (td2.days*24*60*60 + td2.seconds)
|
||||
# print(unixDate_naive - utcoffset)
|
||||
return (unixDate_naive - utcoffset) # local time zone with DST
|
||||
|
||||
def unixDateToADDate(arg1):
|
||||
# input: seconds since Unix epoch (1-Jan-1970 00:00:00 GMT)
|
||||
# output: seconds since Netatalk epoch (1-Jan-2000 00:00:00 GMT),
|
||||
# in hex-ustr (big endian)
|
||||
adDate = (arg1 - 946684800)
|
||||
if (adDate < 0 ):
|
||||
adDate += 4294967296 # to get negative hex number
|
||||
adDateHex = to_hex(adDate).zfill(8).upper()
|
||||
# print(arg1, adDate, adDateHex)
|
||||
return adDateHex
|
||||
|
||||
# cppo support routines:
|
||||
# arg1: directory block
|
||||
# arg2: file index (if applicable)
|
||||
# arg3: directory chunk # (if applicable)
|
||||
|
||||
#most of these not tested yet in Python
|
||||
# returns byte position in disk image file
|
||||
def getStartPos(arg1, arg2):
|
||||
return ( (arg1 * 512) +
|
||||
(39 * ((arg2 + (arg2 > 11)) % 13)) +
|
||||
(4 if (arg2 > 11) else 43) )
|
||||
|
||||
def getStorageType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
firstByte = readcharDec(g.imageData, start)
|
||||
return (firstByte//16)
|
||||
|
||||
def getFileName(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
firstByte = readcharDec(g.imageData, start)
|
||||
entryType = (firstByte//16)
|
||||
nameLength = (firstByte - entryType*16)
|
||||
return readchars(g.imageData, start+1, nameLength)
|
||||
|
||||
def getFileType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return readcharHex(g.imageData, start+16)
|
||||
|
||||
def getKeyPointer(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharDec(g.imageData, start+17) +
|
||||
readcharDec(g.imageData, start+18)*256)
|
||||
|
||||
def getFileLength(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharDec(g.imageData, start+21) +
|
||||
readcharDec(g.imageData, start+22)*256 +
|
||||
readcharDec(g.imageData, start+23)*65536)
|
||||
|
||||
def getAuxType(arg1, arg2):
|
||||
start = getStartPos(arg1, arg2)
|
||||
return (readcharHex(g.imageData, start+32) +
|
||||
readcharHex(g.imageData, start+31))
|
||||
|
||||
def getCreationDate(arg1, arg2):
|
||||
#outputs prodos creation date/time as Unix time
|
||||
# (seconds since Jan 1 1970 GMT)
|
||||
#or None if there is none
|
||||
start = getStartPos(arg1, arg2)
|
||||
pdosDate = (hexToBin(readcharHex(g.imageData, start+25)) +
|
||||
hexToBin(readcharHex(g.imageData, start+24)) +
|
||||
hexToBin(readcharHex(g.imageData, start+27)) +
|
||||
hexToBin(readcharHex(g.imageData, start+26)))
|
||||
try:
|
||||
rVal = pdosDateToUnixDate(pdosDate)
|
||||
except Exception:
|
||||
rVal = None
|
||||
return rVal
|
||||
|
||||
def getModifiedDate(arg1, arg2):
|
||||
#outputs prodos modified date/time as Unix time
|
||||
# (seconds since Jan 1 1970 GMT)
|
||||
#or None if there is none
|
||||
start = getStartPos(arg1, arg2)
|
||||
pdosDate = (hexToBin(readcharHex(g.imageData, start+34)) +
|
||||
hexToBin(readcharHex(g.imageData, start+33)) +
|
||||
hexToBin(readcharHex(g.imageData, start+36)) +
|
||||
hexToBin(readcharHex(g.imageData, start+35)))
|
||||
try:
|
||||
rVal = pdosDateToUnixDate(pdosDate)
|
||||
except Exception:
|
||||
rVal = None
|
||||
return rVal
|
||||
|
||||
def getVolumeName():
|
||||
return getWorkingDirName(2)
|
||||
|
||||
def getWorkingDirName(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
firstByte = readcharDec(g.imageData, start+4)
|
||||
entryType = (firstByte//16)
|
||||
nameLength = (firstByte - entryType*16)
|
||||
return readchars(g.imageData, start+5, nameLength)
|
||||
|
||||
def getDirEntryCount(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
return (readcharDec(g.imageData, start+37) +
|
||||
readcharDec(g.imageData, start+38)*256)
|
||||
|
||||
def getDirNextChunkPointer(arg1):
|
||||
start = ( arg1 * 512 )
|
||||
return (readcharDec(g.imageData, start+2) +
|
||||
readcharDec(g.imageData, start+3)*256)
|
||||
|
||||
# -- script begins in earnest here
|
||||
|
||||
def copyFile(arg1, arg2):
|
||||
g.outFileData = bytearray(b'')
|
||||
g.exFileData = bytearray(b'')
|
||||
g.activeFileBytesCopied = 0
|
||||
storageType = getStorageType(arg1, arg2)
|
||||
keyPointer = getKeyPointer(arg1, arg2)
|
||||
fileLen = getFileLength(arg1, arg2)
|
||||
if (storageType == 1): #seedling
|
||||
copyBlock(keyPointer, fileLen)
|
||||
elif (storageType == 2): #sapling
|
||||
processIndexBlock(keyPointer)
|
||||
elif (storageType == 3): #tree
|
||||
processMasterIndexBlock(keyPointer)
|
||||
elif (storageType == 5): #extended (forked)
|
||||
processForkedFile(keyPointer)
|
||||
|
||||
def copyBlock(arg1, arg2):
|
||||
#arg1: block to copy
|
||||
#arg2: bytes to write (should be 512,
|
||||
# unless final block with less than 512 bytes)
|
||||
#print(arg1 + " " + arg2 + " " + g.activeFileBytesCopied)
|
||||
if (arg1 == 0):
|
||||
outBytes = (b'\x00' * arg2)
|
||||
else:
|
||||
outBytes = slyce(g.imageData, arg1*512, arg2)
|
||||
if (g.resourceFork > 0):
|
||||
if g.AD:
|
||||
g.adFileData[g.activeFileBytesCopied+741:
|
||||
(g.activeFileBytesCopied+741 + arg2)] = outBytes
|
||||
if g.EX:
|
||||
g.exFileData[g.activeFileBytesCopied:
|
||||
(g.activeFileBytesCopied + arg2)] = outBytes
|
||||
else:
|
||||
g.outFileData[g.activeFileBytesCopied:
|
||||
(g.activeFileBytesCopied + arg2)] = outBytes
|
||||
g.activeFileBytesCopied += arg2
|
||||
|
||||
def processDir(arg1, arg2=None, arg3=None, arg4=None, arg5=None):
|
||||
# arg1: dirBlock
|
||||
# arg2/3/4/5: for non-key chunks: entryCount, entry#,
|
||||
# workingDirName, processedEntryCount
|
||||
|
||||
entryCount = None
|
||||
e = None
|
||||
pe = None
|
||||
workingDirName = None
|
||||
|
||||
if arg2:
|
||||
entryCount = arg2
|
||||
e = arg3
|
||||
workingDirName = arg4
|
||||
pe = arg5
|
||||
else:
|
||||
e = 0
|
||||
pe = 0
|
||||
entryCount = getDirEntryCount(arg1)
|
||||
workingDirName = getWorkingDirName(arg1).decode("L1")
|
||||
g.DIRPATH = (g.DIRPATH + "/" + workingDirName)
|
||||
if g.PDOSPATH_INDEX:
|
||||
if (g.PDOSPATH_INDEX == 1):
|
||||
if (("/" + g.PDOSPATH_SEGMENT) != g.DIRPATH):
|
||||
print("ProDOS volume name does not match disk image.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
else:
|
||||
print(g.DIRPATH)
|
||||
while (pe < entryCount):
|
||||
if (getStorageType(arg1, e) > 0):
|
||||
processEntry(arg1, e)
|
||||
pe += 1
|
||||
e += 1
|
||||
if not ((e + ( e>11 ) ) % 13):
|
||||
processDir(getDirNextChunkPointer(arg1),
|
||||
entryCount,
|
||||
e,
|
||||
workingDirName,
|
||||
pe)
|
||||
break
|
||||
|
||||
def processEntry(arg1, arg2):
|
||||
'''
|
||||
print(getFileName(arg1, arg2), getStorageType(arg1, arg2),
|
||||
getFileType(arg1, arg2), getKeyPointer(arg1, arg2),
|
||||
getFileLength(arg1, arg2), getAuxType(arg1, arg2),
|
||||
getCreationDate(arg1, arg2), getModifiedDate(arg1, arg2))
|
||||
'''
|
||||
g.activeFileName = getFileName(arg1 ,arg2).decode("L1")
|
||||
g.activeFileSize = getFileLength(arg1, arg2)
|
||||
|
||||
if ((not g.PDOSPATH_INDEX) or (g.activeFileName == g.PDOSPATH_SEGMENT)):
|
||||
|
||||
if (getStorageType(arg1, arg2) == 13): # if ProDOS directory
|
||||
if not g.PDOSPATH_INDEX:
|
||||
g.targetDir = (g.targetDir + "/" + g.activeFileName)
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not (g.DIR or os.path.isdir(g.targetDir)):
|
||||
makedirs(g.targetDir)
|
||||
if not (g.DIR or (not g.AD) or os.path.isdir(g.ADdir)):
|
||||
makedirs(g.ADdir)
|
||||
if g.PDOSPATH_SEGMENT:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
processDir(getKeyPointer(arg1, arg2))
|
||||
g.DIRPATH = g.DIRPATH.rsplit("/", 1)[0]
|
||||
if not g.PDOSPATH_INDEX:
|
||||
g.targetDir = g.targetDir.rsplit("/", 1)[0]
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
else: # if ProDOS file
|
||||
if not g.PDOSPATH_INDEX:
|
||||
print(" " + g.activeFileName)
|
||||
if g.DIR:
|
||||
return
|
||||
if not g.targetName:
|
||||
g.targetName = g.activeFileName
|
||||
if g.EX:
|
||||
eTargetName = (g.targetName + "#" +
|
||||
getFileType(arg1, arg2).lower() +
|
||||
getAuxType(arg1, arg2).lower())
|
||||
touch(g.targetDir + "/" + g.targetName)
|
||||
if g.AD: makeADfile()
|
||||
copyFile(arg1, arg2)
|
||||
saveFile((g.targetDir + "/" + g.targetName), g.outFileData)
|
||||
creationDate = getCreationDate(arg1, arg2)
|
||||
modifiedDate = getModifiedDate(arg1, arg2)
|
||||
if (creationDate is None and modifiedDate is not None):
|
||||
creationDate = modifiedDate
|
||||
elif (creationDate is not None and modifiedDate is None):
|
||||
modifiedDate = creationDate
|
||||
elif (creationDate is None and modifiedDate is None):
|
||||
creationDate = (datetime.datetime.today() -
|
||||
datetime.datetime(1970,1,1)).days*24*60*60
|
||||
modifiedDate = creationDate
|
||||
if g.AD: # AppleDouble
|
||||
# set dates
|
||||
ADfilePath = (g.ADdir + "/" + g.targetName)
|
||||
writecharsHex(g.adFileData,
|
||||
637,
|
||||
(unixDateToADDate(creationDate) +
|
||||
unixDateToADDate(modifiedDate)))
|
||||
writecharHex(g.adFileData, 645, "80")
|
||||
writecharHex(g.adFileData, 649, "80")
|
||||
#set type/creator
|
||||
writechars(g.adFileData, 653, b'p')
|
||||
writecharsHex(g.adFileData,
|
||||
654,
|
||||
(getFileType(arg1, arg2) +
|
||||
getAuxType(arg1, arg2)))
|
||||
writechars(g.adFileData, 657, b'pdos')
|
||||
saveFile(ADfilePath, g.adFileData)
|
||||
touch((g.targetDir + "/" + g.targetName), modifiedDate)
|
||||
if g.EX: # extended name
|
||||
os.rename((g.targetDir + "/" + g.targetName),
|
||||
(g.targetDir + "/" + eTargetName))
|
||||
if (len(g.exFileData) > 0):
|
||||
saveFile((g.targetDir + "/" + eTargetName + "r"),
|
||||
g.exFileData)
|
||||
touch((g.targetDir + "/" + eTargetName + "r"),
|
||||
modifiedDate)
|
||||
if g.PDOSPATH_SEGMENT:
|
||||
syncExit()
|
||||
g.targetName = None
|
||||
|
||||
#else:
|
||||
#print(g.activeFileName + " doesn't match " + g.PDOSPATH_SEGMENT)
|
||||
|
||||
def processForkedFile(arg1):
|
||||
# finder info except type/creator
|
||||
fInfoA_entryType = readcharDec(g.imageData, 9)
|
||||
fInfoB_entryType = readcharDec(g.imageData, 27)
|
||||
if (fInfoA_entryType == 1):
|
||||
writechars(g.imageData, 661, readchars(g.imageData, 18, 8))
|
||||
elif (fInfoA_entryType == 2):
|
||||
writechars(g.imageData, 669, readchars(g.imageData, 10, 16))
|
||||
if (fInfoB_entryType == 1):
|
||||
writechars(g.imageData, 661, readchars(g.imageData, 36, 8))
|
||||
elif (fInfoB_entryType == 2):
|
||||
writechars(g.imageData, 669, readchars(g.imageData, 28, 16))
|
||||
|
||||
for f in [0, 256]:
|
||||
g.resourceFork = f
|
||||
g.activeFileBytesCopied = 0
|
||||
forkStart = (arg1 * 512) # start of Forked File key block
|
||||
# print("--" + forkStart)
|
||||
forkStorageType = readcharDec(g.imageData, forkStart+f+0)
|
||||
forkKeyPointer = (readcharDec(g.imageData, forkStart+f+1) +
|
||||
readcharDec(g.imageData, forkStart+f+2)*256)
|
||||
forkFileLen = (readcharDec(g.imageData, forkStart+f+5) +
|
||||
readcharDec(g.imageData, forkStart+f+6)*256 +
|
||||
readcharDec(g.imageData, forkStart+f+7)*256*256)
|
||||
g.activeFileSize = forkFileLen
|
||||
if (g.resourceFork > 0):
|
||||
rsrcForkLenHex = (readcharHex(g.imageData, forkStart+f+7) +
|
||||
readcharHex(g.imageData, forkStart+f+6) +
|
||||
readcharHex(g.imageData, forkStart+f+5))
|
||||
# print(">>>" + rsrcForkLenHex)
|
||||
print(" [resource fork]")
|
||||
if g.AD:
|
||||
writecharsHex(g.adFileData, 35, rsrcForkLenHex)
|
||||
else:
|
||||
print(" [data fork]")
|
||||
if (forkStorageType == 1): #seedling
|
||||
copyBlock(forkKeyPointer, forkFileLen)
|
||||
elif (forkStorageType == 2): #sapling
|
||||
processIndexBlock(forkKeyPointer)
|
||||
elif (forkStorageType == 3): #tree
|
||||
processMasterIndexBlock(forkKeyPointer)
|
||||
# print()
|
||||
g.resourceFork = 0
|
||||
|
||||
def processMasterIndexBlock(arg1):
|
||||
processIndexBlock(arg1, True)
|
||||
|
||||
def processIndexBlock(arg1, arg2=False):
|
||||
#arg1: indexBlock
|
||||
#arg2: if True, it's a Master Index Block
|
||||
pos = 0
|
||||
bytesRemaining = g.activeFileSize
|
||||
while (g.activeFileBytesCopied < g.activeFileSize):
|
||||
targetBlock = (readcharDec(g.imageData, arg1*512+pos) +
|
||||
readcharDec(g.imageData, arg1*512+(pos+256))*256)
|
||||
if arg2:
|
||||
processIndexBlock(targetBlock)
|
||||
else:
|
||||
bytesRemaining = (g.activeFileSize - g.activeFileBytesCopied)
|
||||
bs = (bytesRemaining if (bytesRemaining < 512) else 512)
|
||||
copyBlock(targetBlock, bs)
|
||||
pos += 1
|
||||
if (pos > 255):
|
||||
break # go to next entry in Master Index Block (tree)
|
||||
|
||||
def makeADfile():
|
||||
if not g.AD: return
|
||||
touch(g.ADdir + "/" + g.targetName)
|
||||
g.adFileData = bytearray(b'\x00' * 741)
|
||||
# ADv2 header
|
||||
writecharsHex(g.adFileData, hexToDec("00"), "0005160700020000")
|
||||
# number of entries
|
||||
writecharsHex(g.adFileData, hexToDec("18"), "000D")
|
||||
# Resource Fork
|
||||
writecharsHex(g.adFileData, hexToDec("1A"), "00000002000002E500000000")
|
||||
# Real Name
|
||||
writecharsHex(g.adFileData, hexToDec("26"), "00000003000000B600000000")
|
||||
# Comment
|
||||
writecharsHex(g.adFileData, hexToDec("32"), "00000004000001B500000000")
|
||||
# Dates Info
|
||||
writecharsHex(g.adFileData, hexToDec("3E"), "000000080000027D00000010")
|
||||
# Finder Info
|
||||
writecharsHex(g.adFileData, hexToDec("4A"), "000000090000028D00000020")
|
||||
# ProDOS file info
|
||||
writecharsHex(g.adFileData, hexToDec("56"), "0000000B000002C100000008")
|
||||
# AFP short name
|
||||
writecharsHex(g.adFileData, hexToDec("62"), "0000000D000002B500000000")
|
||||
# AFP File Info
|
||||
writecharsHex(g.adFileData, hexToDec("6E"), "0000000E000002B100000004")
|
||||
# AFP Directory ID
|
||||
writecharsHex(g.adFileData, hexToDec("7A"), "0000000F000002AD00000004")
|
||||
# dbd (second time) will create DEV, INO, SYN, SV~
|
||||
|
||||
def syncExit():
|
||||
if (not g.silent and g.AD and os.path.isdir("/usr/local/etc/netatalk")):
|
||||
print("File(s) have been copied to the target directory. " +
|
||||
"If the directory")
|
||||
print("is shared by Netatalk, please type 'afpsync' now.")
|
||||
# saveFile(g.imageFile, g.imageData)
|
||||
sys.exit(0)
|
||||
|
||||
def usage():
|
||||
print(sys.modules[__name__].__doc__)
|
||||
sys.exit(1)
|
||||
|
||||
# --- ID bashbyter functions (adapted)
|
||||
|
||||
def decToHex(arg1):
|
||||
# converts single-byte decimal value to hexadecimal equivalent
|
||||
# arg: decimal value from 0-255
|
||||
# out: two-digit hex string from 00-FF
|
||||
#exit: 21=invalid arg
|
||||
if (arg1<0 or arg1>255): sys.exit(21)
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def hexToDec(arg1):
|
||||
# converts single-byte hexadecimal value to decimal equivalent
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: decimal value
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_dec(arg1)
|
||||
|
||||
def hexToBin(arg1):
|
||||
# converts single-byte hexadecimal value to binary string
|
||||
# arg: two-digit hex value from 00-FF
|
||||
# out: binary string value
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_bin(arg1).zfill(8)
|
||||
|
||||
def binToDec(arg1):
|
||||
# converts single-byte binary string (8 bits) value to decimal
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: decimal value
|
||||
return to_dec([arg1])
|
||||
|
||||
def binToHex(arg1):
|
||||
# converts single-byte binary string (8 bits) value to hex
|
||||
# warning: no error checking
|
||||
# arg: binary string up to 8 bits
|
||||
# out: hex value
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def charToDec(arg1):
|
||||
# converts single char (of type bytes) to corresponding decimal value
|
||||
# arg: one char (of type bytes)
|
||||
# out: decimal value from 0-255
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 1): return 21
|
||||
return to_dec(arg1)
|
||||
|
||||
def charToHex(arg1):
|
||||
# converts single char (of type bytes) to corresponding hex value
|
||||
# arg: one char (of type bytes)
|
||||
# out: hexadecimal value from 00-FF
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 1): return 21
|
||||
return to_hex(arg1).upper()
|
||||
|
||||
def decToChar(arg1):
|
||||
# converts single-byte decimal value to equivalent char (of type bytes)
|
||||
# arg: decimal number from 0-255
|
||||
# out: one character
|
||||
#exit: 21=invalid arg
|
||||
if (arg1<0 or arg1>255): sys.exit(21)
|
||||
return to_bytes(arg1)
|
||||
|
||||
def hexToChar(arg1):
|
||||
# converts single-byte hex value to corresponding char (of type bytes)
|
||||
# arg: two-digit hexadecimal number from 00-FF
|
||||
# out: one character
|
||||
#exit: 21=invalid arg
|
||||
if (len(arg1) != 2): return 21
|
||||
return to_bytes(arg1)
|
||||
|
||||
def readchars(arg1, arg2=0, arg3=0):
|
||||
# read one or more characters from a bytes variable
|
||||
# arg1: bytes or bytearray variable
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# arg3: (optional) # of chars to read (default is to end of bytes var)
|
||||
# out: sequence of characters (bytes or bytearray)
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if (arg3<0): sys.exit(23)
|
||||
if (arg3 == 0):
|
||||
arg3 = len(arg1)
|
||||
return slyce(arg1, arg2, arg3)
|
||||
|
||||
def readcharDec(arg1, arg2=0):
|
||||
# read one character from bytes var & convert to equivalent dec value
|
||||
# arg1: bytes var
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: decimal value from 0-255
|
||||
# exit: 21=invalid arg1, 22=invalid arg2
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
return to_dec(slyce(arg1, arg2, 1))
|
||||
|
||||
def readcharHex(arg1, arg2=0):
|
||||
# read one character from bytes var & convert to corresponding hex value
|
||||
# arg1: bytes var
|
||||
# arg2: (optional) offset (# of bytes to skip before reading)
|
||||
# out: two-digit hex value from 00-FF
|
||||
# exit: 21=invalid arg1, 22=invalid arg2
|
||||
if not (isinstance(arg1, bytes) or isinstance(arg1, bytearray)):
|
||||
sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
return to_hex(slyce(arg1, arg2, 1))
|
||||
|
||||
def writechars(arg1, arg2, arg3):
|
||||
# write one or more characters (bytes) to bytearray
|
||||
# arg1: bytearray variable
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: sequence of bytes (or bytearray)
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not (isinstance(arg3, bytes) or isinstance(arg3, bytearray)):
|
||||
sys.exit(23)
|
||||
arg1[arg2:arg2+len(arg3)] = arg3
|
||||
|
||||
def writecharDec(arg1, arg2, arg3):
|
||||
# write corresponding char of single-byte decimal value into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: decimal number from 0-255
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
# out: nothing
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isnumber(arg3): sys.exit(23)
|
||||
arg1[arg2:arg2+1] = to_bytes(arg3)
|
||||
|
||||
def writecharHex(arg1, arg2, arg3):
|
||||
# write corresponding character of single-byte hex value into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: two-digit hexadecimal number from 00-FF
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isinstance(arg3, type("".encode().decode())): sys.exit(23)
|
||||
arg1[arg2:arg2+1] = to_bytes(arg3)
|
||||
|
||||
def writecharsHex(arg1, arg2, arg3):
|
||||
# write corresponding characters of hex values into bytearray
|
||||
# arg1: bytearray
|
||||
# arg2: offset (# of bytes to skip before writing)
|
||||
# arg3: string of two-digit hexadecimal numbers from 00-FF
|
||||
# out: nothing
|
||||
# exit: 21=invalid arg1, 22=invalid arg2, 23=invalid arg3
|
||||
if not isinstance(arg1, bytearray): sys.exit(21)
|
||||
if (arg2<0): sys.exit(22)
|
||||
if not isinstance(arg3, type("".encode().decode())): sys.exit(23)
|
||||
arg1[arg2:arg2+len(to_bytes(arg3))] = to_bytes(arg3)
|
||||
|
||||
#---- IvanX general purpose functions ----#
|
||||
|
||||
def slyce(val, start_pos=0, length=1, reverse=False):
|
||||
"""returns slice of object (but not a slice object)
|
||||
allows specifying length, and 3.x "bytes" consistency"""
|
||||
the_slyce = val[start_pos:start_pos+length]
|
||||
return (the_slyce[::-1] if reverse else the_slyce)
|
||||
|
||||
def to_hex(val):
|
||||
"""convert bytes, decimal number, or [bin-ustr] to two-digit hex values
|
||||
unlike hex(), accepts bytes; has no leading 0x or trailing L"""
|
||||
from binascii import b2a_hex
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
val = int(val[0], 2)
|
||||
if isinstance(val, bytes): # bytes
|
||||
return b2a_hex(val).decode("L1")
|
||||
elif isnumber(val):
|
||||
# .encode().decode() always returns unicode in both P2 and P3
|
||||
return (hex(val)[2:].split("L")[0]).encode("L1").decode("L1")
|
||||
else:
|
||||
raise Exception("to_hex() requires bytes, int/long, or [bin-ustr]")
|
||||
|
||||
def hex_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce as hex-ustr"""
|
||||
return to_hex(slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def dec_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce converted to decimal int/long"""
|
||||
return to_dec(hex_slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def bin_slyce(val, start_pos=0, length=1, little_endian=False):
|
||||
"""returns bytes slyce converted to bin-ustr"""
|
||||
return to_bin(hex_slyce(val, start_pos, length, little_endian))
|
||||
|
||||
def to_dec(val):
|
||||
"""convert bytes, hex-ustr or [bin-ustr] to decimal int/long"""
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
return int(val[0], 2)
|
||||
elif isinstance(val, bytes): # bytes
|
||||
return int(to_hex(val), 16)
|
||||
elif isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return int(val, 16)
|
||||
else:
|
||||
raise Exception("to_dec() requires bytes, hex-ustr or [bin-ustr]")
|
||||
|
||||
def to_bin(val):
|
||||
"""convert bytes, hex-ustr, or int/long to bin-ustr"""
|
||||
if isinstance(val, bytes): # bytes
|
||||
return (bin(to_dec(to_hex(val))))[2:].encode("L1").decode("L1")
|
||||
elif isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return (bin(int(val, 16)))[2:].encode("L1").decode("L1")
|
||||
elif isnumber(val): # int/long
|
||||
return (bin(val))[2:].encode("L1").decode("L1")
|
||||
else:
|
||||
raise Exception("to_bin() requires bytes, hex-ustr, or int/long")
|
||||
|
||||
def to_bytes(val):
|
||||
"""converts hex-ustr, int/long, or [bin-ustr] to bytes"""
|
||||
from binascii import a2b_hex
|
||||
if isinstance(val, list): # [bin-ustr]
|
||||
val = to_hex(val[0])
|
||||
if isnumber(val): # int/long
|
||||
val = to_hex(val)
|
||||
if isinstance(val, type("".encode().decode())): # hex-ustr
|
||||
return a2b_hex(bytes(val.encode("L1"))) # works on both P2 and P3
|
||||
else:
|
||||
raise Exception(
|
||||
"to_bytes() requires hex-ustr, int/long, or [bin-ustr]")
|
||||
|
||||
def shift(items):
|
||||
"""Shift list items to left, losing the first item.
|
||||
|
||||
in : list
|
||||
out: list
|
||||
"""
|
||||
for i in range(0, (len(items)-1)):
|
||||
items[i] = items[i+1]
|
||||
del items[-1]
|
||||
return items
|
||||
|
||||
def s(string):
|
||||
"""Perform local variable substution, e.g. 'total: {num} items'"""
|
||||
# http://stackoverflow.com/questions/2960772/
|
||||
# putting-a-variable-inside-a-string-python
|
||||
# http://stackoverflow.com/questions/6618795/
|
||||
# get-locals-from-calling-namespace-in-python
|
||||
import inspect
|
||||
frame = inspect.currentframe()
|
||||
try:
|
||||
rVal = string.format(**frame.f_back.f_locals)
|
||||
finally:
|
||||
del frame
|
||||
return rVal
|
||||
|
||||
def get_object_names(cls, include_subclasses=True):
|
||||
object_names = []
|
||||
for (this_object_name, this_object_id) in list(globals().items()):
|
||||
if include_subclasses:
|
||||
if isinstance(this_object_id, cls):
|
||||
object_names.append(this_object_name)
|
||||
else:
|
||||
if type(this_object_id) is cls:
|
||||
object_names.append(this_object_name)
|
||||
return object_names
|
||||
|
||||
def touch(filePath, modTime=None):
|
||||
# http://stackoverflow.com/questions/1158076/implement-touch-using-python
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "ab"):
|
||||
os.utime(filePath, (None if (modTime is None) else (modTime, modTime)))
|
||||
|
||||
def mkdir(dirPath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if dirPath[-1] == ".": dirPath += "-"
|
||||
dirPath = dirPath.replace("./", ".-/")
|
||||
try:
|
||||
os.mkdir(dirPath)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
def makedirs(dirPath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if dirPath[-1] == ".": dirPath += "-"
|
||||
dirPath = dirPath.replace("./", ".-/")
|
||||
try:
|
||||
os.makedirs(dirPath)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
def loadFile(filePath):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "rb") as imageHandle:
|
||||
return imageHandle.read()
|
||||
|
||||
def saveFile(filePath, fileData):
|
||||
import os
|
||||
if (os.name == "nt"):
|
||||
if filePath[-1] == ".": filePath += "-"
|
||||
filePath = filePath.replace("./", ".-/")
|
||||
with open(filePath, "wb") as imageHandle:
|
||||
imageHandle.write(fileData)
|
||||
|
||||
def isnumber(number):
|
||||
try: # make sure it's not a string
|
||||
len(number)
|
||||
return False
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
int(number)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
#---- end IvanX general purpose functions ----#
|
||||
|
||||
|
||||
# --- start
|
||||
|
||||
args = sys.argv
|
||||
if (len(args) == 1):
|
||||
usage()
|
||||
|
||||
if (args[1] == "-s"):
|
||||
g.silent=1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-ad"):
|
||||
g.AD = 1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-e"):
|
||||
if g.AD: usage()
|
||||
g.EX = 1
|
||||
args = args[1:] #shift
|
||||
|
||||
if (args[1] == "-cat"):
|
||||
g.DIR = 1
|
||||
args = args[1:]
|
||||
|
||||
if not ((g.DIR and len(args) >= 2) or (len(args) >= 3)):
|
||||
usage()
|
||||
if ((len(args) == 4) and
|
||||
(slyce(args[2],0,1) != "/") and
|
||||
(slyce(args[2],0,1) != ":")):
|
||||
usage()
|
||||
|
||||
g.imageFile = args[1]
|
||||
if not os.path.isfile(g.imageFile):
|
||||
print("Source " + g.imageFile + " was not found.")
|
||||
sys.exit(2)
|
||||
g.imageData = loadFile(g.imageFile)
|
||||
|
||||
if (len(args) == 4):
|
||||
g.PDOSPATH = args[2].upper()
|
||||
targetPath = args[3]
|
||||
if os.path.isdir(targetPath):
|
||||
g.targetDir = targetPath
|
||||
else:
|
||||
g.targetDir = targetPath.rsplit("/", 1)[0]
|
||||
g.targetName = targetPath.rsplit("/", 1)[1]
|
||||
if not os.path.isdir(g.targetDir):
|
||||
print("Target directory not found.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if not g.DIR:
|
||||
if not os.path.isdir(args[2]):
|
||||
print("Target directory not found.")
|
||||
sys.exit(2)
|
||||
|
||||
g.activeDirBlock = 0
|
||||
g.activeFileName = ""
|
||||
g.activeFileSize = 0
|
||||
g.activeFileBytesCopied = 0
|
||||
g.resourceFork = 0
|
||||
g.PDOSPATH_INDEX = 0
|
||||
|
||||
if (len(args) == 4):
|
||||
g.PDOSPATH = g.PDOSPATH.replace(':', '/').split('/')
|
||||
if not g.PDOSPATH[0]:
|
||||
g.PDOSPATH_INDEX += 1
|
||||
g.PDOSPATH_SEGMENT = g.PDOSPATH[g.PDOSPATH_INDEX]
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not ((not g.AD) or os.path.isdir(g.ADdir)):
|
||||
mkdir(g.ADdir)
|
||||
processDir(2)
|
||||
print("ProDOS file not found within image file.")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if not g.DIR:
|
||||
# print(args[0], args[1], args[2])
|
||||
g.targetDir = (args[2] + "/" + getVolumeName().decode("L1"))
|
||||
g.ADdir = (g.targetDir + "/.AppleDouble")
|
||||
if not os.path.isdir(g.targetDir):
|
||||
makedirs(g.targetDir)
|
||||
if not ((not g.AD) or os.path.isdir(g.ADdir)):
|
||||
makedirs(g.ADdir)
|
||||
processDir(2)
|
||||
if not g.DIR:
|
||||
syncExit()
|
||||
|
@ -1,286 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# mkatinit by Ivan Drucker, http://appleii.ivanx.com
|
||||
# not licensed; please modify and redistribute as you like
|
||||
# 1.0b4 1-30-11
|
||||
|
||||
# 1.1d1 -- uses bashByter. NOT TESTED.
|
||||
|
||||
# This script creates the ATINIT file required for netbooting Apple IIe and
|
||||
# IIGS clients from a netatalk server. ATINIT is put in the in the
|
||||
# (sharename)/USERS hierarchy, or the current directory if it can't.
|
||||
# The user can specify the ProDOS startup system program and default prefix.
|
||||
# If an argument is supplied, it is used as the username and the prompt is
|
||||
# skipped.
|
||||
|
||||
# The ATINIT file is not as complete as the ones generated by AppleShare 3.0,
|
||||
# and features such as default printer are not used.
|
||||
|
||||
# to do
|
||||
# possibly require confirmation if AFPD_GUEST is not set correctly
|
||||
# or offer to change it
|
||||
|
||||
# from ID-bashByter library
|
||||
decToChar () {
|
||||
# converts single-byte decimal value to equivalent character
|
||||
# arg: decimal number from 0-255
|
||||
# out: one character
|
||||
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
|
||||
[[ $1 ]] || return 11
|
||||
[[ $2 ]] && return 8
|
||||
[[ ( $(printf %d "$1" 2> /dev/null ) == $1 ) \
|
||||
&& ( $1 -ge 0 ) && ( $1 -le 255 ) ]] || return 21
|
||||
# args are valid
|
||||
echo -n -e "\x$(printf %02X "$1")"
|
||||
}
|
||||
|
||||
writechars () {
|
||||
# write one or more characters (bytes) to file
|
||||
# arg1: filename
|
||||
# arg2: (optional) offset (# of bytes to skip before writing)
|
||||
# arg3 OR stdin: sequence of characters
|
||||
# [stdin required if writing NUL (0) or trailing LF (0x0A) chars]
|
||||
# out: nothing
|
||||
# exit: 8=extraneous arg, 11=missing arg1,
|
||||
# 13=missing stdin/arg3, 22=invalid arg2
|
||||
[[ $1 ]] || { [[ -t 0 ]] || cat > /dev/null; return 11; }
|
||||
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && \
|
||||
( $2 -ge 0 ) ]] || { [[ -t 0 ]] || cat > /dev/null; return 22; } }
|
||||
[[ ( ! -t 0 ) && $3 ]] && { cat > /dev/null; return 8; }
|
||||
[[ ( -t 0 ) ]] && { [[ $4 ]] && return 8; [[ $3 ]] || return 13; }
|
||||
# args are valid
|
||||
if [[ -t 0 ]]; then
|
||||
echo -n "$3" | \
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
else
|
||||
dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
#---- mkatinit starts here
|
||||
IFS=''
|
||||
|
||||
#defaults
|
||||
sharepath=$(grep options:prodos /usr/local/etc/netatalk/AppleVolumes.default | tail -1 | cut -d" " -f1)
|
||||
prefix=/$(grep options:prodos /usr/local/etc/netatalk/AppleVolumes.default | tail -1 | cut -d" " -f2)
|
||||
gsprefix=$prefix
|
||||
startprog="$prefix/BASIC.SYSTEM"
|
||||
gsstartprog="$prefix/SYSTEM/FINDER"
|
||||
filename="ATINIT"
|
||||
user=$(whoami)
|
||||
|
||||
echo
|
||||
|
||||
usersfolder=1
|
||||
while [ -n "$1" ] && [ "${1:0:1}" = '-' ]; do
|
||||
flag="$1"
|
||||
if [ $flag = "-gs" ]; then
|
||||
gs=1
|
||||
shift
|
||||
continue
|
||||
elif [ $flag = "-d" ]; then
|
||||
noprompt=1
|
||||
shift
|
||||
continue
|
||||
elif [ $flag = "-f" ]; then
|
||||
overwrite=1
|
||||
shift
|
||||
continue
|
||||
elif [ $flag = "-g" ]; then
|
||||
alsoguest=1
|
||||
shift
|
||||
continue
|
||||
elif [ $flag = "-c" ]; then
|
||||
usersfolder=0
|
||||
shift
|
||||
continue
|
||||
else
|
||||
badflag=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $usersfolder -eq 0 ] && [ -n "$alsoguest" ]; then
|
||||
badflag=1
|
||||
fi
|
||||
|
||||
if [ $badflag ]; then
|
||||
echo "usage: mkatinit [-gs] [-d] [-f] [-g | -c] [<username>|guest]"
|
||||
echo
|
||||
echo "<username> should be the name of a netatalk user, or 'guest'"
|
||||
echo "-gs sets the default ProDOS netboot system startup program and"
|
||||
echo " prefix for GS/OS (if omitted, ProDOS 8 defaults are used)"
|
||||
echo "-d use the default start program and prefix, without prompting"
|
||||
echo "-f overwrite existing ATINIT file if present, without warning"
|
||||
echo "-g create an ATINIT file for Guest as well as the specified user"
|
||||
echo "-c write ATNIT to current directory instead of USERS hierarchy"
|
||||
echo
|
||||
exit
|
||||
fi
|
||||
|
||||
arg="$1"
|
||||
|
||||
[[ -z $arg ]] && arg=$user
|
||||
|
||||
while : ; do
|
||||
|
||||
if [ ${#arg} -gt 32 ]; then
|
||||
echo "User name is too long. Exiting with no action."
|
||||
exit
|
||||
elif [ -n "$arg" ]; then
|
||||
if [ `echo $arg | tr '[:upper:]' '[:lower:]'` = "guest" ]; then
|
||||
username='<Any User>'
|
||||
alsoguest=
|
||||
if [[ ! $(grep -F -s $(ls -1 /home) /etc/default/netatalk) ]]; then
|
||||
echo 'Warning: The AFPD_GUEST setting in /etc/default/netatalk is not assigned to a'
|
||||
echo 'user with a folder in /home. Guest users may be able to boot over the network'
|
||||
echo 'into ProDOS 8 for read-only access, but will not be able to boot into GS/OS.'
|
||||
if [ $gs ]; then
|
||||
echo ' Using ProDOS 8 defaults.'
|
||||
gs=
|
||||
else
|
||||
echo
|
||||
fi
|
||||
echo
|
||||
fi
|
||||
else
|
||||
username="$arg"
|
||||
if [[ ! $(ls -1 /home | grep -F -s $username) ]]; then
|
||||
echo "Warning: This username ($username) does not have a folder in /home. This user may"
|
||||
echo "not be able to boot over the network into ProDOS 8 or GS/OS."
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
if [ $gs ]; then
|
||||
startprog="$gsstartprog"
|
||||
prefix="$gsprefix"
|
||||
fi
|
||||
fi
|
||||
|
||||
# make username all caps
|
||||
username=`echo $username | tr '[:lower:]' '[:upper:]'`
|
||||
|
||||
# prompt for folders
|
||||
if [ ! $doalsoguest ] && [ ! $noprompt ]; then
|
||||
while : ; do
|
||||
echo "Enter the ProDOS path to the startup system program."
|
||||
echo "default (CR to accept): $startprog"
|
||||
read
|
||||
if [ ${#REPLY} -gt 64 ]; then
|
||||
continue
|
||||
elif [ -n "$REPLY" ]; then
|
||||
startprog="`echo $REPLY | tr '[:lower:]' '[:upper:]'`"
|
||||
echo
|
||||
fi
|
||||
break
|
||||
done
|
||||
|
||||
while : ; do
|
||||
echo "Enter the initial ProDOS prefix:"
|
||||
echo "default (CR to accept): $prefix"
|
||||
read
|
||||
if [ ${#REPLY} -gt 64 ]; then
|
||||
continue
|
||||
elif [ -n "$REPLY" ]; then
|
||||
prefix="`echo $REPLY | tr '[:lower:]' '[:upper:]'`"
|
||||
echo
|
||||
fi
|
||||
break
|
||||
done
|
||||
fi
|
||||
|
||||
# create folders if needed
|
||||
filepath="$PWD/$filename"
|
||||
|
||||
while [ $usersfolder -eq 1 ]; do
|
||||
# create folders for ATINIT
|
||||
while [ ! -d "$sharepath" ]; do
|
||||
echo "Shared volume '$sharepath' not found. Edit mkatinit to change the default."
|
||||
echo "Enter the local path to the netatalk shared volume used for netboot:"
|
||||
read sharepath
|
||||
done
|
||||
|
||||
if [ ! -d "$sharepath/USERS" ]; then
|
||||
mkdir "$sharepath/USERS"
|
||||
if [ $? -ne 0 ]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
if [ ! -d "$sharepath/USERS/$username" ]; then
|
||||
mkdir "$sharepath/USERS/$username"
|
||||
if [ $? -ne 0 ]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
if [ ! -d "$sharepath/USERS/$username/SETUP" ]; then
|
||||
mkdir "$sharepath/USERS/$username/SETUP"
|
||||
if [ $? -ne 0 ]; then
|
||||
break
|
||||
fi
|
||||
else
|
||||
if [ ! -w "$sharepath/USERS/$username/SETUP" ]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
# we have a valid USERS folder target for ATINIT
|
||||
filepath="$sharepath/USERS/$username/SETUP/$filename"
|
||||
usersfolder=2
|
||||
done
|
||||
|
||||
if [ $usersfolder -eq 1 ]; then
|
||||
echo "Could not write to shared volume. Creating ATINIT in current directory."
|
||||
if [ -n "$alsoguest" ]; then
|
||||
echo "ATINIT for Guest user will not be created."
|
||||
fi
|
||||
echo
|
||||
alsoguest=
|
||||
fi
|
||||
|
||||
if [ ! $doalsoguest ]; then
|
||||
echo "netboot start program: $startprog"
|
||||
echo "netboot start prefix : $prefix"
|
||||
echo
|
||||
fi
|
||||
|
||||
#remove ATINIT if present
|
||||
if [ ! $overwrite ] && [ -f "$filepath" ]; then
|
||||
echo -n "$filepath already exists. Overwrite? "
|
||||
while read -s -n 1 > /dev/null 2>&1; do
|
||||
if [ -z "$REPLY" ]; then
|
||||
continue
|
||||
elif [ "$REPLY" = "Y" ] || [ "$REPLY" = "y" ]; then
|
||||
echo
|
||||
break
|
||||
elif [ "$REPLY" = "N" ] || [ "$REPLY" = "n" ]; then
|
||||
echo
|
||||
echo "Exiting with no action."
|
||||
exit
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
#write the file. start with zeroes
|
||||
dd if=/dev/zero of="$filepath" bs=1 count=276 2> /dev/null
|
||||
#put in startprog, prefix, username (first byte of each field is length)
|
||||
# ( echo -n "${#startprog}" | awk '{printf("%c",$0);}'; echo -n "$startprog"; ) | dd of="$filepath" bs=1 seek=7 conv=notrunc 2> /dev/null
|
||||
# ( echo -n "${#prefix}" | awk '{printf("%c",$0);}'; echo -n "$prefix"; ) | dd of="$filepath" bs=1 seek=78 conv=notrunc 2> /dev/null
|
||||
# ( echo -n "${#username}" | awk '{printf("%c",$0);}'; echo -n "$username"; ) | dd of="$filepath" bs=1 seek=143 conv=notrunc 2> /dev/null
|
||||
( decToChar "${#startprog}"; echo -n "$startprog"; ) | writechars "$filepath" 7
|
||||
( decToChar "${#prefix}"; echo -n "$prefix"; ) | writechars "$filepath" 78
|
||||
( decToChar "${#username}"; echo -n "$username"; ) | writechars "$filepath" 143
|
||||
|
||||
echo "Created $filepath"
|
||||
if [ ! $alsoguest ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
if [ $usersfolder -eq 2 ]; then
|
||||
usersfolder=1
|
||||
fi
|
||||
doalsoguest=1
|
||||
arg='guest'
|
||||
done
|
||||
|
||||
echo
|
||||
|
@ -1,82 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# mkvolinfo -- creates a (share)/.AppleDesktop/.volinfo file
|
||||
|
||||
makeVolInfoFile () {
|
||||
[[ -d $sharepath/.AppleDesktop ]] || mkdir $sharepath/.AppleDesktop
|
||||
touch $volinfo
|
||||
echo 'MAC_CHARSET:MAC_ROMAN' >> $volinfo
|
||||
echo 'VOL_CHARSET:UTF8' >> $volinfo
|
||||
echo 'ADOUBLE_VER:v2' >> $volinfo
|
||||
echo 'CNIDBACKEND:dbd' >> $volinfo
|
||||
echo 'CNIDDBDHOST:localhost' >> $volinfo
|
||||
echo 'CNIDDBDPORT:4700' >> $volinfo
|
||||
echo "CNID_DBPATH:$sharepath" >> $volinfo
|
||||
echo 'VOLUME_OPTS:PRODOS CACHEID' >> $volinfo
|
||||
if (( $mixedcase )); then
|
||||
echo 'VOLCASEFOLD:' >> $volinfo
|
||||
else
|
||||
echo 'VOLCASEFOLD:MTOULOWER UTOMUPPER' >> $volinfo
|
||||
fi
|
||||
echo 'EXTATTRTYPE:AFPVOL_EA_AD' >> $volinfo
|
||||
echo ".volinfo for $sharepath has been created."
|
||||
}
|
||||
|
||||
while [[ $1 == "-f" || $1 == "-c" ]]; do
|
||||
if [[ $1 == "-f" ]]; then
|
||||
force=1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [[ $1 == "-c" ]]; then
|
||||
mixedcase=1
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${1:0:1} == "-" ]]; then
|
||||
|
||||
echo "usage: mkvolinfo [-f] [-c] [shared volume path]"
|
||||
echo
|
||||
echo "-c will create the .volinfo file to specify no uppercase filename conversion"
|
||||
echo "-f will create the .volinfo file without prompting, if none exists"
|
||||
echo "If a path is specified, that is what is used, otherwise the last entry"
|
||||
echo "in /usr/local/etc/netatalk/AppleVolumes.default is used."
|
||||
|
||||
else
|
||||
sudo true
|
||||
if [[ $1 ]]; then
|
||||
sharepath=$(readlink -m $1)
|
||||
else
|
||||
sharepath=$(grep ^/media /usr/local/etc/netatalk/AppleVolumes.default | tail -1 | cut -d" " -f1)
|
||||
fi
|
||||
|
||||
volinfo=$sharepath/.AppleDesktop/.volinfo
|
||||
|
||||
if [[ ! -d $sharepath ]]; then
|
||||
echo "$sharepath does not exist."
|
||||
else
|
||||
if [[ -f $volinfo ]]; then
|
||||
echo "$volinfo already exists."
|
||||
else
|
||||
if [[ $force ]]; then
|
||||
makeVolInfoFile
|
||||
else
|
||||
echo "The .volinfo file is automatically generated when you first"
|
||||
echo "log in from an AFP (Apple II or Mac) client machine."
|
||||
echo "If you can't do this, you can create a .volinfo file now"
|
||||
echo "based on assumed defaults; proceed with caution if you have"
|
||||
echo "customized your AppleVolumes files."
|
||||
echo
|
||||
echo "If the path shown below is incorrect, you can specify"
|
||||
echo "the path to your shared volume as an argument to mkvolinfo."
|
||||
echo
|
||||
echo -n "Make .volinfo for shared volume $sharepath now? "
|
||||
read
|
||||
if [[ ${REPLY:0:1} == "y" ]] || [[ ${REPLY:0:1} == "Y" ]]; then
|
||||
makeVolInfoFile
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
@ -1,285 +0,0 @@
|
||||
# A2SERVER master setup script, last update 15-Feb-2015
|
||||
# it downloads and executes several scripts related to the setup of
|
||||
# netatalk configured for Apple II use on Debian, Raspbian, or Ubuntu.
|
||||
# more info is at http://appleii.ivanx.com/a2server
|
||||
|
||||
# to download and execute, type:
|
||||
# wget appleii.ivanx.com/a2server/setup; source setup
|
||||
|
||||
a2serverVersion="124"
|
||||
|
||||
isRpi=
|
||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1
|
||||
|
||||
isDebian=
|
||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "7." ) && ( $(uname -m) == "i686" ) ]] && isDebian=1
|
||||
|
||||
if [[ -f /usr/local/etc/A2SERVER-version ]]; then
|
||||
echo "A2SERVER version available: $a2serverVersion"
|
||||
echo "A2SERVER version installed: $(cat /usr/local/etc/A2SERVER-version)"
|
||||
fi
|
||||
|
||||
skipRepoUpdate=
|
||||
autoAnswerYes=
|
||||
setupNetBoot=
|
||||
setupWindowsSharing=
|
||||
updateRasppleII=
|
||||
while [[ $1 ]]; do
|
||||
if [[ $1 == "-r" ]]; then
|
||||
shift
|
||||
skipRepoUpdate="-r"
|
||||
touch /tmp/a2server-packageReposUpdated
|
||||
elif [[ $1 == "-y" ]]; then
|
||||
shift
|
||||
autoAnswerYes="-y"
|
||||
touch /tmp/a2server-autoAnswerYes
|
||||
elif [[ $1 == "-b" ]]; then
|
||||
shift
|
||||
setupNetBoot="-b"
|
||||
touch /tmp/a2server-setupNetBoot
|
||||
elif [[ $1 == "-w" ]]; then
|
||||
shift
|
||||
setupWindowsSharing="-w"
|
||||
touch /tmp/a2server-setupWindowsSharing
|
||||
elif [[ $1 == "-os" || $1 == "os" ]]; then
|
||||
# elif [[ ${1,,} == "rasppleii" || ${1,,} == "raspple" || ${1,,} == "rasappleii" || ${1,,} == "rasapple" || ${1,,} == "raspple2" || ${1,,} == "rasapple2" ]]; then
|
||||
shift
|
||||
updateRasppleII=1
|
||||
elif [[ $1 == "-v" ]]; then
|
||||
shift
|
||||
if [[ ! -f /usr/local/etc/A2SERVER-version ]]; then
|
||||
echo "A2SERVER version available: $a2serverVersion"
|
||||
echo "A2SERVER version installed: none"
|
||||
fi
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
elif [[ $1 ]]; then
|
||||
echo "options:"
|
||||
echo "-v: display installed and available versions, then exit"
|
||||
echo "-y: auto-answer yes to all prompts"
|
||||
echo "-r: don't update package repositories"
|
||||
echo "-b: auto-setup network boot (use with -y)"
|
||||
echo "-w: auto-setup Windows file sharing (use with -y)"
|
||||
if [[ $isRpi ]]; then
|
||||
echo "-os: update Raspbian OS, A2CLOUD, A2SERVER, and Apple II Pi"
|
||||
fi
|
||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $updateRasppleII ]]; then
|
||||
echo "A2SERVER: Updating Raspple II (takes up to an hour)..."
|
||||
wget -qO /tmp/raspbian-update ivanx.com/a2server/files/raspbian-update.txt
|
||||
source /tmp/raspbian-update a2cloud a2server $autoAnswerYes $skipRepoUpdate
|
||||
[[ $0 == "-bash" ]] && return 0 || exit 0
|
||||
fi
|
||||
|
||||
if { [[ -f /usr/local/etc/A2SERVER-version ]] && (( $(cat /usr/local/etc/A2SERVER-version) < 110 )); }; then
|
||||
echo
|
||||
echo "WARNING: The current A2SERVER installer scripts haven't been tested for"
|
||||
echo "updating the earlier version of A2SERVER that you have. A fresh install"
|
||||
echo "is suggested. Continuing is not recommended and could make A2SERVER"
|
||||
echo "no longer work properly, or cause data to be lost."
|
||||
fi
|
||||
|
||||
a2server_update=0
|
||||
doSetup=1
|
||||
|
||||
unsupportedOS=1
|
||||
if [[ $isRpi ]]; then #supported Raspbian? (16-Feb-15, 20-Jun-14, 09-Jan-14, etc)
|
||||
fwhash=$(zcat /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz | grep -m 1 'as of' | awk '{print $NF}')
|
||||
[[ ($fwhash == "8aca5762") || ($fwhash == "462f3e3f476f7b6") || ($fwhash == "c32bc633039cd9") || ($fwhash == "9d34d0475f9") || ($fwhash == "d4f5315cfac4e") || ($fwhash == "6f4a90c8cb8817f") || ($fwhash == "5dd9b4962e") || ($fwhash == "17c8799375") ]] && unsupportedOS=0
|
||||
elif [[ "$(lsb_release -rs 2> /dev/null)" == "12.04" ]]; then #Ubuntu 12.04?
|
||||
unsupportedOS=0
|
||||
elif [[ "$(lsb_release -rs 2> /dev/null)" == "7.3" || "$(lsb_release -rs 2> /dev/null)" == "7.6" || "$(lsb_release -rs 2> /dev/null)" == "7.8" ]]; then # tested Debian?
|
||||
unsupportedOS=0
|
||||
fi
|
||||
|
||||
if (( unsupportedOS )); then
|
||||
echo
|
||||
echo "WARNING: A2SERVER and its installer scripts have not been tested on this"
|
||||
echo "operating system version. Continuing is probably fine, but might not be."
|
||||
echo "Worst case could make your operating system no longer work properly,"
|
||||
echo "or cause data to be lost."
|
||||
echo "More information is at http://appleii.ivanx.com/a2server."
|
||||
fi
|
||||
|
||||
doSetup=1
|
||||
if [[ ! -f /usr/local/etc/a2server-help.txt ]] || (( $a2server_update )); then
|
||||
echo
|
||||
echo "Setting up A2SERVER will take up to 60 minutes, during which"
|
||||
echo "you'll see a bunch of stuff spit out across the screen."
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Ready to set up A2SERVER? "
|
||||
read
|
||||
[[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]]; doSetup=$(( 1 - $? ))
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( $doSetup )); then
|
||||
|
||||
echo
|
||||
echo "a2server-setup modifies files and performs actions as the root user."
|
||||
echo "For details, visit http://appleii.ivanx.com/a2server."
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Continue? "
|
||||
read
|
||||
[[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]]; doSetup=$(( 1 - $? ))
|
||||
fi
|
||||
|
||||
if (( $doSetup )); then
|
||||
|
||||
userPw=$(sudo grep "^$USER" /etc/shadow | cut -f 2 -d ':')
|
||||
[[ $userPw == "$(echo 'apple2' | perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "${userPw%"${userPw#\$*\$*\$}"}")" ]] && isApple2Pw=1 || isApple2Pw=
|
||||
[[ $userPw == "$(echo 'raspberry' | perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "${userPw%"${userPw#\$*\$*\$}"}")" ]] && isRaspberryPw=1 || isRaspberryPw=
|
||||
|
||||
password="your password"
|
||||
[[ $isApple2Pw ]] && password="'apple2'"
|
||||
[[ $isRaspberryPw ]] && password="'raspberry'"
|
||||
|
||||
|
||||
[[ $isRpi ]] && a2server="your Raspberry Pi" || a2server="A2SERVER"
|
||||
if [[ ! $isApple2Pw && ! -f /usr/local/etc/A2SERVER-version ]]; then
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo
|
||||
echo "To ensure that all client computers are able to connect to"
|
||||
echo "${a2server} using the same password, you are recommended"
|
||||
echo "to change your user password to 'apple2'."
|
||||
echo
|
||||
echo -n "Do you want to change the password for user '$USER' to 'apple2' now? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
echo "A2SERVER: changing password for user '$USER' to 'apple2'..."
|
||||
echo "$USER:apple2" | sudo chpasswd
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "During this installation, enter ${password} if prompted for passwords."
|
||||
echo
|
||||
|
||||
sudo true
|
||||
|
||||
echo
|
||||
echo "A2SERVER: Downloading scripts..."
|
||||
|
||||
wget -q -O /tmp/1.storage appleii.ivanx.com/a2server/scripts/a2server-1-storage.txt
|
||||
chmod ugo+x /tmp/1.storage
|
||||
|
||||
wget -q -O /tmp/2.tools appleii.ivanx.com/a2server/scripts/a2server-2-tools.txt
|
||||
chmod ugo+x /tmp/2.tools
|
||||
|
||||
wget -q -O /tmp/3.sharing appleii.ivanx.com/a2server/scripts/a2server-3-sharing.txt
|
||||
chmod ugo+x /tmp/3.sharing
|
||||
|
||||
wget -q -O /tmp/5.netboot appleii.ivanx.com/a2server/scripts/a2server-5-netboot.txt
|
||||
chmod ugo+x /tmp/5.netboot
|
||||
|
||||
wget -q -O /tmp/6.samba appleii.ivanx.com/a2server/scripts/a2server-6-samba.txt
|
||||
chmod ugo+x /tmp/6.samba
|
||||
|
||||
wget -q -O /tmp/7.console appleii.ivanx.com/a2server/scripts/a2server-7-console.txt
|
||||
chmod ugo+x /tmp/7.console
|
||||
|
||||
echo "A2SERVER: Scripts have been downloaded. Installing..."
|
||||
|
||||
/tmp/1.storage
|
||||
rm /tmp/1.storage
|
||||
/tmp/2.tools
|
||||
rm /tmp/2.tools
|
||||
/tmp/3.sharing
|
||||
rm /tmp/3.sharing
|
||||
/tmp/5.netboot
|
||||
rm /tmp/5.netboot
|
||||
/tmp/6.samba
|
||||
rm /tmp/6.samba
|
||||
/tmp/7.console
|
||||
rm /tmp/7.console
|
||||
rm /tmp/a2server-packageReposUpdated &> /dev/null
|
||||
|
||||
if [[ ! -f /usr/local/etc/A2SERVER-version ]] \
|
||||
|| (( $(cat /usr/local/etc/A2SERVER-version) < "$a2serverVersion" )); then
|
||||
echo "$a2serverVersion" | sudo tee /usr/local/etc/A2SERVER-version &> /dev/null
|
||||
fi
|
||||
|
||||
source /usr/local/etc/a2server-aliases
|
||||
|
||||
# get Kernel release (e.g. 3.6.11+) and version (e.g. #557)
|
||||
kernelRelease=$(uname -r)
|
||||
kernelMajorRelease=$(cut -d '.' -f 1 <<< $kernelRelease)
|
||||
kernelMinorRelease=$(cut -d '.' -f 2 <<< $kernelRelease | sed 's/\(^[0-9]*\)[^0-9].*$/\1/')
|
||||
|
||||
# all done, see if AppleTalk is available and notify either way
|
||||
if [[ $(ps aux | grep [a]talkd) ]]; then
|
||||
echo "You now have a fully functional file server for Apple II clients."
|
||||
echo "On an Apple IIe, it should be accessible via \"Log In\" on the"
|
||||
echo "Workstation Card software. For IIgs users, it should be accessible"
|
||||
echo "via the AppleShare control panel."
|
||||
echo
|
||||
echo
|
||||
echo "A2SERVER setup is complete! Go connect from your Apple II!"
|
||||
echo
|
||||
elif [[ -f /tmp/rpiUpdate ]]; then
|
||||
echo "A2SERVER is now configured, but Apple II clients will not be able"
|
||||
echo "to connect until you restart your Raspberry Pi."
|
||||
echo
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo -n "Restart now? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
sudo shutdown -r now
|
||||
echo
|
||||
echo "A2SERVER: Preparing to restart..."
|
||||
while :; do sleep 60; done
|
||||
fi
|
||||
rm /tmp/rpiUpdate
|
||||
echo
|
||||
elif [[ $kernelMajorRelease -eq 3 && $kernelMinorRelease -ge 12 ]]; then
|
||||
echo "A2SERVER is now configured, but Apple II clients cannot connect"
|
||||
echo "because of a kernel-crashing bug in Linux kernel 3.12 through 3.15."
|
||||
echo "You have kernel version $kernelMajorRelease.$kernelMinorRelease."
|
||||
echo "A2SERVER has disabled AppleTalk networking to prevent crashes."
|
||||
echo "Please use kernel 3.11 or earlier, or kernel 3.16 or later."
|
||||
echo
|
||||
else
|
||||
echo "A2SERVER is now configured, but Apple II clients cannot connect because"
|
||||
echo "AppleTalk networking is unavailable. Please make sure that"
|
||||
echo "your Linux distribution has a loadable AppleTalk kernel module or"
|
||||
echo "has AppleTalk built into the kernel, and restart your server."
|
||||
echo "Or, if you previously disabled AppleTalk in A2SERVER, re-enable it"
|
||||
echo "by typing 'appletalk-on'."
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ -f /tmp/singleUser ]]; then
|
||||
if [[ ! $autoAnswerYes ]]; then
|
||||
echo "Your Raspberry Pi was started in single-user mode in order to"
|
||||
echo -n "fix a problem. You should restart to operate normally. Restart now? "
|
||||
read
|
||||
fi
|
||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||
sudo shutdown -r now
|
||||
echo
|
||||
echo "A2SERVER: Preparing to restart..."
|
||||
while :; do sleep 60; done
|
||||
fi
|
||||
echo
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Type 'system-shutdown' to turn off A2SERVER."
|
||||
echo "Type 'a2server-setup' to configure network boot."
|
||||
echo "Type 'a2server-help' for a list of other commands."
|
||||
fi
|
||||
fi
|
||||
|
||||
unset a2server_update 2> /dev/null
|
||||
unset doSetup 2> /dev/null
|
||||
rm /tmp/a2server-autoAnswerYes 2> /dev/null
|
||||
rm /tmp/a2server-packageReposUpdated 2> /dev/null
|
||||
rm /tmp/a2server-setupNetBoot 2> /dev/null
|
||||
rm /tmp/a2server-setupWindowsSharing 2> /dev/null
|
||||
rm setup &> /dev/null
|
@ -1,37 +0,0 @@
|
||||
currentVersion=124
|
||||
|
||||
if [[ -f /usr/local/etc/A2SERVER-version ]]; then
|
||||
installedVersion=$(cat /usr/local/etc/A2SERVER-version)
|
||||
else
|
||||
installedVersion=100
|
||||
fi
|
||||
|
||||
autoAnswerYes=
|
||||
for arg in $@; do
|
||||
if [[ $arg == "-y" ]]; then
|
||||
autoAnswerYes=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Update history:"
|
||||
wget -qO- appleii.ivanx.com/a2server/update/versionhistory.txt
|
||||
echo
|
||||
echo "installed version: ${installedVersion:0:1}.${installedVersion:1:1}.${installedVersion:2:1}"
|
||||
echo "current version: ${currentVersion:0:1}.${currentVersion:1:1}.${currentVersion:2:1}"
|
||||
echo
|
||||
if [[ $autoAnswerYes ]]; then
|
||||
REPLY="y"
|
||||
else
|
||||
echo -n "Do you want to update (or reinstall) A2SERVER? "
|
||||
read
|
||||
fi
|
||||
if [[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]]; then
|
||||
sudo rm /usr/local/etc/A2SERVER-version &> /dev/null
|
||||
# sudo rm /usr/local/etc/netatalk/a2boot/* &> /dev/null
|
||||
wget -q -O /tmp/setup appleii.ivanx.com/a2server/setup; source /tmp/setup "$@"
|
||||
fi
|
||||
|
||||
unset currentVersion 2> /dev/null
|
||||
unset installedVersion 2> /dev/null
|
@ -1,51 +0,0 @@
|
||||
1.0.0: Jan 2012: initial release
|
||||
|
||||
1.0.1: Jan 2012: fixes Netatalk date-stamp bug (thanks to Steven Hirsch)
|
||||
|
||||
1.0.2: Jan 2013: Netatalk 2.2.4; OS X 10.7+ login fixed; netboot fixes;
|
||||
Raspbian "Wheezy" support; Ubuntu 12.04 LTS support
|
||||
|
||||
1.1.0: Apr 2013: Full GS/OS install; eliminated GS.SYSTEM volume;
|
||||
Raspberry Pi enhancements; lots of improvements to installer;
|
||||
more utilities installed for Apple II; improved cppo
|
||||
NOTE: fresh install required, can't update earlier version
|
||||
|
||||
1.1.1: Jun 2013: Wi-Fi support; updates/additions to commands in a2server-help;
|
||||
bug fixes and improvements to install script; appletalk kernel
|
||||
module for Raspbian (instead of replacement kernel); RPi
|
||||
console (onboard serial) set to 19,200 bps during boot
|
||||
|
||||
1.1.2: Oct 2013: resolves issue of no AppleTalk in Raspbian 2013-09-10 and
|
||||
later; faster command-line installation on Raspberry Pi
|
||||
(nulib2 and unar binaries are downloaded rather than compiled)
|
||||
|
||||
1.1.3: Jan 2014: shares ADTPro disks folder as ADTDISKS; added environment
|
||||
variables for shared folders; can resolve by name
|
||||
"a2server.local" if network client has Bonjour/zeroconf;
|
||||
server presents itself as Shared computer to Macs on network;
|
||||
VM based on Debian 7
|
||||
|
||||
1.1.4: Jan 2014: fixes bug with network boot if ADTPro disks folder is shared
|
||||
|
||||
1.1.5: Jul 2014: a2server-setup fixes Raspbian 20-Jul-14 AppleTalk kernel panic
|
||||
|
||||
1.2.0: Aug 2014: a2server-setup and Netatalk startup script addresses AppleTalk
|
||||
kernel panic on any Linux kernel 3.12-3.15; Netatalk starts
|
||||
in background, preventing startup delay; a2server-setup always
|
||||
configures Netatalk startup script and can download a new one
|
||||
if missing; a2server-setup on Raspbian or Debian 7 x86 is
|
||||
faster because it downloads binaries rather than compiling
|
||||
from source; unbit/unexec/usq unarchivers added; additional
|
||||
virtual machine which has both A2SERVER and A2CLOUD installed
|
||||
|
||||
1.2.1: Jan 2015: minor fixes; support for LED blink on Raspbian 2015-01-31
|
||||
|
||||
1.2.2: Mar 2015: installer improvements: now has command line options,
|
||||
including unattended install; installer sets passwords
|
||||
automatically to 'apple2'; status messages are now prefixed by
|
||||
A2SERVER:; can update Raspple II (Raspbian OS,
|
||||
NOOBS install manager, A2SERVER, and A2CLOUD); minor fixes.
|
||||
|
||||
1.2.3: May 2015: changed Apple software links to Internet Archive
|
||||
|
||||
1.2.4: Jul 2015: offer to download A2CLOUD disk contents onto A2FILES volume
|
Loading…
x
Reference in New Issue
Block a user