mirror of
https://github.com/RasppleII/a2server.git
synced 2025-09-11 22:24:38 +00:00
Compare commits
91 Commits
1.2.7
...
current-te
Author | SHA1 | Date | |
---|---|---|---|
|
4fb47b06ed | ||
|
a615ed1808 | ||
|
5e0feab69c | ||
|
a3a7a9479d | ||
|
34836dcbb4 | ||
|
7b7917d417 | ||
|
938db3c46b | ||
|
4d1b5db5e3 | ||
|
7d1a06a916 | ||
|
f9b120002a | ||
|
49d50e49ac | ||
|
dfa1e26c80 | ||
|
d86e3bfa88 | ||
|
cd20570999 | ||
|
cd8271cd56 | ||
|
750b9998df | ||
|
9ba5258fe0 | ||
|
50875f5c3f | ||
|
ca4e3b76e6 | ||
|
3a82176d0a | ||
|
061c3c1897 | ||
|
dea2ea2ce2 | ||
|
bb5f42462e | ||
|
59d293ec84 | ||
|
9dfbe0e9f3 | ||
|
ca12a4a9e9 | ||
|
94b6dcaa26 | ||
|
da204bd05b | ||
|
fbc1ce5ba2 | ||
|
b7528026de | ||
|
60f88e4e8a | ||
|
13343a5c2a | ||
|
95fb701098 | ||
|
3a0e123c0a | ||
|
5c47545772 | ||
|
c5460eb292 | ||
|
653218535f | ||
|
a0ded5a7cf | ||
|
3cc2beabcf | ||
|
4ca810bd26 | ||
|
f8d7a916e2 | ||
|
80c4818d47 | ||
|
b846df61da | ||
|
ec0bf3b9d5 | ||
|
631ad8a2e2 | ||
|
4ad9e10c77 | ||
|
9760380115 | ||
|
5660347bc8 | ||
|
6f835905af | ||
|
9bd8b0d3f0 | ||
|
9b87db8eb4 | ||
|
71274cb18f | ||
|
502e638964 | ||
|
85cbf4d741 | ||
|
c5c14759d1 | ||
|
6e9ddb5e47 | ||
|
180dcc5634 | ||
|
7163390b19 | ||
|
e0a78c5756 | ||
|
8327a5eb8d | ||
|
4a0d574f8a | ||
|
e58fd1bbb1 | ||
|
02442b16e5 | ||
|
00adf2673d | ||
|
fc7aaf4d53 | ||
|
0ca7ef94b8 | ||
|
1403fde73d | ||
|
7e12bbd696 | ||
|
1af347ae8f | ||
|
22020603f6 | ||
|
5fab6a21af | ||
|
6b45259759 | ||
|
4692537443 | ||
|
4e4bd8dbbd | ||
|
d2775f4d27 | ||
|
8f6fae4bb4 | ||
|
53404e7784 | ||
|
01d3ce1775 | ||
|
14f5ef66be | ||
|
04ad897c97 | ||
|
06bc59ece7 | ||
|
c2bb79860a | ||
|
343bde59fa | ||
|
024f579850 | ||
|
0fffaf93cb | ||
|
0bd95253fe | ||
|
b5496b55aa | ||
|
9f397b1f9f | ||
|
435857e3bb | ||
|
b0bb0e7b99 | ||
|
bb9e458a98 |
13
LICENSE.md
Normal file
13
LICENSE.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
License for A2SERVER
|
||||||
|
====================
|
||||||
|
|
||||||
|
A2SERVER
|
||||||
|
|
||||||
|
Copyright (C) 2013-2015 Ivan Drucker <ivan@ivanx.com>
|
||||||
|
|
||||||
|
The A2SERVER scripts themselves are written primarily by Ivan Drucker and
|
||||||
|
released under the WTFPL version 2, which you may download from its web page
|
||||||
|
at <http://www.wtfpl.net/txt/copying/>. This is essentially a public domain
|
||||||
|
release, which doesn't extend to the other programs used by A2SERVER such as
|
||||||
|
netatalk or the various Linux tools it installs. These have their own license
|
||||||
|
terms and Copyrights.
|
98
README.md
98
README.md
@@ -1,5 +1,6 @@
|
|||||||
# A2SERVER
|
# A2SERVER
|
||||||
AppleTalk server for Apple // computers developed by Ivan Drucker
|
AppleTalk server for Apple // computers developed by Ivan Drucker, with
|
||||||
|
substantial rework and by T. Joseph Carter
|
||||||
|
|
||||||
Documentation here is sparse for the moment; see [Ivan's site]() for
|
Documentation here is sparse for the moment; see [Ivan's site]() for
|
||||||
information about A2SERVER and how it all works. There's a lot there and it's
|
information about A2SERVER and how it all works. There's a lot there and it's
|
||||||
@@ -13,24 +14,91 @@ relatively modern piece of it. As such they should be preserved as they are.
|
|||||||
|
|
||||||
## Developer note
|
## Developer note
|
||||||
|
|
||||||
To use the scripts on a server other than Ivan's, you'll want to export
|
To use the scripts with a specific GitHub tag:
|
||||||
the shell variable A2SERVER_SCRIPT_URL to the base URL of this repository
|
~~~ bash
|
||||||
on your server. The base-URL should be slash-terminated. You can then run
|
export A2SERVER_SCRIPT_URL=https://raw.githubusercontent.com/RasppleII/a2server/TAG_GOES_HERE/
|
||||||
the following snippet:
|
export A2SERVER_BINARY_URL=${A2SERVER_SCRIPT_URL}files
|
||||||
|
wget -O setup ${A2SERVER_SCRIPT_URL}setup/index.txt; source setup
|
||||||
|
~~~
|
||||||
|
|
||||||
```bash
|
Or, to use the scripts on your own server, including your local machine:
|
||||||
wget -O a2server-setup ${A2SERVER_SCRIPT_URL}setup/index.txt; source a2server-setup
|
|
||||||
```
|
|
||||||
|
|
||||||
A simple method installing from a local folder is to change to that sudirectory
|
~~~ bash
|
||||||
and run the following. Then export A2SERVER_SCRIPT_URL to "http://localhost:8000/"
|
export A2SERVER_SCRIPT_URL=http://yoururl.com/
|
||||||
|
~~~
|
||||||
|
|
||||||
```bash
|
To prevent needing to recompile various packages from source code during
|
||||||
|
installation, a number of precompiled binary files are downloaded for Raspbian,
|
||||||
|
Debian-x86, and Debian-amd64. If you wish to host these on your own server:
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
export A2SERVER_BINARY_URL=http://yoururl.com/files/
|
||||||
|
~~~
|
||||||
|
|
||||||
|
You do not need to use a subdirectory called "files", or the same server, but
|
||||||
|
that's the normal arrangement. The precompiled packages are available here:
|
||||||
|
`http://ivanx.com/a2server/files/dist/a2serverbinaries.tar.gz`
|
||||||
|
|
||||||
|
Several Apple II third-party binaries are downloaded during installation, as
|
||||||
|
well as third-party source code if precompiled binaries are unavailable or
|
||||||
|
you don't wish to use them. If you want these external dependencies locally
|
||||||
|
during development, they need to go into a folder called "external" in
|
||||||
|
the binaries URL, and that needs to contain folders called "appleii" and
|
||||||
|
"source". To download all of these external packages, download and run the
|
||||||
|
shell script at
|
||||||
|
`http://ivanx.com/a2server/files/dist/getexternal.sh`.
|
||||||
|
|
||||||
|
Once you have those:
|
||||||
|
|
||||||
|
~~~ bash
|
||||||
|
export A2SERVER_NO_EXTERNAL=1
|
||||||
|
~~~
|
||||||
|
|
||||||
|
You may want to put the above exports into `~/.bashrc` or `~/.bash_profile`.
|
||||||
|
|
||||||
|
If you want to host scripts locally installed on your own machine or another
|
||||||
|
computer on your LAN, type the following, and export "http://localhost:8000/"
|
||||||
|
or "http://lan.ip.address:8000/" for the above URL's.
|
||||||
|
|
||||||
|
~~~
|
||||||
python -m SimpleHTTPServer
|
python -m SimpleHTTPServer
|
||||||
```
|
~~~
|
||||||
|
|
||||||
|
Once you're set, you can then run the following snippet to install A2SERVER:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
wget -O setup ${A2SERVER_SCRIPT_URL}setup/index.txt; source setup
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
Offline install:
|
||||||
|
|
||||||
|
Using locally hosted binaries and external dependencies, it's possible to
|
||||||
|
install completely offline if dependent packages have been installed.
|
||||||
|
|
||||||
|
If precompiled binaries are available, on Wheezy:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
sudo apt-get -y install unzip libgnustep-base1.22 libdb5.1 libgcrypt11 libssl1.0.0 attr fuse libglib2.0-0 libattr1 libfuse2
|
||||||
|
~~~
|
||||||
|
|
||||||
|
If precompiled binaries are available, on Jessie:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
sudo apt-get -y install unzip unar libdb5.3 libgcrypt20 libssl1.0.0 attr fuse libglib2.0-0 libattr1 libfuse2
|
||||||
|
~~~
|
||||||
|
|
||||||
|
If precompiled binaries are not available, on Wheezy:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
sudo apt-get -y install unzip build-essential zlib1g-dev libgnustep-base-dev libz-dev libbz2-dev libssl-dev libicu-dev libdb5.1-dev libgcrypt11-dev libglib2.0-dev libattr1-dev libfuse-dev
|
||||||
|
~~~
|
||||||
|
|
||||||
|
If precompiled binaries are not available, on Jessie:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
sudo apt-get -y install unzip unar build-essential zlib1g-dev unzip libssl-dev libdb5.3-dev libgcrypt11-dev libglib2.0-dev libattr1-dev libfuse-dev
|
||||||
|
~~~
|
||||||
|
|
||||||
You should probably export A2SERVER_SCRIPT_URL in your .bashrc or whatever
|
|
||||||
file configures your development environment. Also be advised that as of
|
|
||||||
version 1.24 of A2SERVER, you must use the snippet above.
|
|
||||||
|
|
||||||
[Ivan's site]: http://appleii.ivanx.com/a2server/
|
[Ivan's site]: http://appleii.ivanx.com/a2server/
|
||||||
|
@@ -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 /media/A2SHARED.
|
|
||||||
|
|
||||||
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 /media/A2SHARED. 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 /media/A2SHARED 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,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 /media/A2SHARED ]]; then
|
|
||||||
|
|
||||||
echo "A2SERVER: Shared disk is already prepared for use."
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
echo "A2SERVER: Preparing the shared files disk..."
|
|
||||||
|
|
||||||
sudo mkdir /media/A2SHARED
|
|
||||||
|
|
||||||
sudo chown $USER:$USER /media/A2SHARED
|
|
||||||
|
|
||||||
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 /media/A2SHARED/GSFILES ]] || mkdir -p /media/A2SHARED/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 /media/A2SHARED/A2FILES ]] || mkdir -p /media/A2SHARED/A2FILES
|
|
||||||
if [[ ! -d /media/A2SHARED/A2FILES/.AppleDesktop ]]; then
|
|
||||||
cd /media/A2SHARED/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 /media/A2SHARED/ADTDISKS ]]; then
|
|
||||||
ln -s /usr/local/adtpro/disks /media/A2SHARED/ADTDISKS
|
|
||||||
fi
|
|
||||||
if [[ ! $(grep ADTDISKS /usr/local/etc/netatalk/AppleVolumes.default) ]]; then
|
|
||||||
sudo sed -i 's@^# End of File@/media/A2SHARED/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="/media/A2SHARED/A2FILES"
|
|
||||||
imagesDir=$gsosDir/GSOS.INSTALLER/IMAGES
|
|
||||||
imageToolsDir=$gsosDir/GSOS.INSTALLER/IMAGE.TOOLS
|
|
||||||
netInstallDir=$gsosDir/GSOS.INSTALLER/NET.INSTALL
|
|
||||||
|
|
||||||
p8Dir="/media/A2SHARED/A2FILES"
|
|
||||||
diskToolsP8Dir=$p8Dir/DISK.TOOLS.P8
|
|
||||||
|
|
||||||
commDir="/media/A2SHARED/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 "/media/A2SHARED/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 = /media/A2SHARED/$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="/media/A2SHARED/A2FILES"
|
|
||||||
GSFILES="/media/A2SHARED/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 /media/A2SHARED/GSFILES ]] || mkdir /media/A2SHARED/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 /media/A2SHARED/A2FILES ]] || mkdir /media/A2SHARED/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
|
|
@@ -1,541 +0,0 @@
|
|||||||
#! /usr/bin/env python
|
|
||||||
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=python:
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
|
|
||||||
import os, sys, subprocess
|
|
||||||
import tempfile
|
|
||||||
import hashlib
|
|
||||||
import shutil
|
|
||||||
import xml.etree.cElementTree as ET
|
|
||||||
|
|
||||||
quiet = False
|
|
||||||
verbose = True
|
|
||||||
|
|
||||||
disk7_sources = {
|
|
||||||
"file" : "Disk_7_of_7-Apple_II_Setup.sea.bin",
|
|
||||||
"digest" : "43fbc296ab66da84aadc275b80fd51ec4f7fe986",
|
|
||||||
"type" : "sea.bin",
|
|
||||||
"sources" : [
|
|
||||||
( "Apple", "http://download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/English-North_American/Apple_II/Apple_IIGS_System_6.0.1/Disk_7_of_7-Apple_II_Setup.sea.bin" ),
|
|
||||||
( "archive.org", "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" )
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
a2boot_files = [
|
|
||||||
{
|
|
||||||
"unix" : "Apple ::e Boot Blocks",
|
|
||||||
"hfsutils" : "Apple_--e_Boot_Blocks.bin",
|
|
||||||
"netatalk" : "Apple :2f:2fe Boot Blocks",
|
|
||||||
"digest" : "cada362ac2eca3ffa506e9b4e76650ba031e0035",
|
|
||||||
"patches" : (
|
|
||||||
[
|
|
||||||
"Cleartext password login bug",
|
|
||||||
(0x4d43, b"\xA8\xA2\x01\xBD\x80\x38\x99\xA0\x38\xC8\xE8\xE0\x09\x90\xF4"),
|
|
||||||
|
|
||||||
"ProDOS 8 patch: year table, splash date (6.0.3)",
|
|
||||||
(0x004f, b"\xb0\xb2\xad\xc1\xf5\xe7\xad\xb1\xb5"),
|
|
||||||
(0x1b9f, b"\x12\x11\x0b\x10\x0f\x0e\x0d"),
|
|
||||||
],
|
|
||||||
"8cff6ef453533423b34b5b4fefd642441e2ee374",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"unix" : "Basic.System",
|
|
||||||
"hfsutils" : "Basic.System.bin",
|
|
||||||
"netatalk" : "Basic.System",
|
|
||||||
"digest" : "4d53424f1451cd2e874cf792dbdc8cc6735dcd36",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"unix" : "ProDOS16 Boot Blocks",
|
|
||||||
"hfsutils" : "ProDOS16_Boot_Blocks.bin",
|
|
||||||
"netatalk" : "ProDOS16 Boot Blocks",
|
|
||||||
"digest" : "fab829e82e6662ed6aab119ad18e16ded7d43cda",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"unix" : "ProDOS16 Image",
|
|
||||||
"hfsutils" : "ProDOS16_Image.bin",
|
|
||||||
"netatalk" : "ProDOS16 Image",
|
|
||||||
"digest" : "db4608067b9e7877f45eb557971c4d8c45b46be5",
|
|
||||||
"patches" : (
|
|
||||||
[
|
|
||||||
"Cleartext password login bug",
|
|
||||||
(0x5837, b"\xA8\xA2\x01\xBD\x80\x10\x99\xA0\x10\xC8\xE8\xE0\x09\x90\xF4"),
|
|
||||||
|
|
||||||
"Enable pressing \"8\" during GS/OS netboot to load ProDOS 8",
|
|
||||||
(0x0100, b"\x92"),
|
|
||||||
(0x0360, b"\x20\x7d\x14"),
|
|
||||||
(0x067d, b"\xad\x00\xc0\x29\xff\x00\xc9\xb8\x00\xd0\x06\xa9\x02\x00\x8d\x53\x14\xa9\x10\x0f\x60"),
|
|
||||||
|
|
||||||
"ProDOS 8 patch: year table, splash date (6.0.3)",
|
|
||||||
(0x0c26, b"\xb0\xb2\xad\xc1\xf5\xe7\xad\xb1\xb5"),
|
|
||||||
(0x1b76, b"\x12\x11\x0b\x10\x0f\x0e\x0d"),
|
|
||||||
],
|
|
||||||
"1f0477030b7e9c809b0a2282896ca66033e7ca9f",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"unix" : "p8",
|
|
||||||
"hfsutils" : "p8.bin",
|
|
||||||
"netatalk" : "p8",
|
|
||||||
# 36c288a5272cf01e0a64eed16786258959118e0e P8 (02-Apr-93, a2setup)
|
|
||||||
# c99f69c8dbfe79f02c715162fb409aedf52d378a P8 (06-May-93, 6.0.1)
|
|
||||||
# Only splash date differs.
|
|
||||||
"digest" : "36c288a5272cf01e0a64eed16786258959118e0e",
|
|
||||||
"patches" : (
|
|
||||||
[
|
|
||||||
# May as well patch the splash as well. *shrug*
|
|
||||||
"ProDOS 8 patch: year table, splash date (6.0.3)",
|
|
||||||
(0x0026, b"\xb0\xb2\xad\xc1\xf5\xe7\xad\xb1\xb5"),
|
|
||||||
(0x0f76, b"\x12\x11\x0b\x10\x0f\x0e\x0d"),
|
|
||||||
],
|
|
||||||
"ad1e6c8f653df428d13cb8ae5ce4f8425a52016b",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
# True for Python 3.0 and later
|
|
||||||
PY3 = sys.version_info >= (3, 0)
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
stdin_input = input
|
|
||||||
import urllib.request as urlrequest
|
|
||||||
else:
|
|
||||||
stdin_input = raw_input
|
|
||||||
import urllib2 as urlrequest
|
|
||||||
|
|
||||||
|
|
||||||
def sha1sum_file (filename, blocksize=65536):
|
|
||||||
f = open(filename, "rb")
|
|
||||||
digest = hashlib.sha1()
|
|
||||||
buf = f.read(blocksize)
|
|
||||||
while len(buf) > 0:
|
|
||||||
digest.update(buf)
|
|
||||||
buf = f.read(blocksize)
|
|
||||||
f.close()
|
|
||||||
return digest.hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
def download_from_sources(fileinfo, output_dir):
|
|
||||||
output_path = os.path.join(output_dir, fileinfo["file"])
|
|
||||||
if not quiet:
|
|
||||||
print("Downloading %s" % (fileinfo["file"]))
|
|
||||||
for (source, url) in fileinfo["sources"]:
|
|
||||||
if not quiet:
|
|
||||||
print(" From %s..." % (source), end="")
|
|
||||||
|
|
||||||
try:
|
|
||||||
html = urlrequest.urlopen(url)
|
|
||||||
data = html.read()
|
|
||||||
f = open(output_path, "wb")
|
|
||||||
f.write(data)
|
|
||||||
f.close()
|
|
||||||
except:
|
|
||||||
if not quiet:
|
|
||||||
print(" download failed.")
|
|
||||||
if 'f' in locals():
|
|
||||||
if not f.isclosed():
|
|
||||||
f.close()
|
|
||||||
continue
|
|
||||||
|
|
||||||
digest = sha1sum_file(output_path)
|
|
||||||
if digest == fileinfo["digest"]:
|
|
||||||
if not quiet:
|
|
||||||
print(" successfully downloaded.")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
if not quiet:
|
|
||||||
print(" failed (digest mismatch).")
|
|
||||||
if verbose:
|
|
||||||
print(" Expected: %s\n Received: %s"
|
|
||||||
% (fileinfo["digest"], digest))
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
# Apple's GS/OS 6.0.1 images are stored in MacBinary-wrapped
|
|
||||||
# self-extracting disk image files. The Unarchiver's unar is able
|
|
||||||
# to unwrap the MacBinary wrapper for us, but we have to extract the
|
|
||||||
# disk image oursselves. Fortunately, it's uncompressed.
|
|
||||||
def extract_800k_sea_bin(archive_name, image_name, archive_dir):
|
|
||||||
if not quiet:
|
|
||||||
print("Extracting %s..." % (archive_name), end="")
|
|
||||||
|
|
||||||
archive_path = os.path.join(archive_dir, archive_name)
|
|
||||||
image_path = os.path.join(archive_dir, image_name)
|
|
||||||
|
|
||||||
if not os.path.isfile(archive_path):
|
|
||||||
if not quiet:
|
|
||||||
print(" not found.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Extract the original filename from the file
|
|
||||||
# MacBinary II header is 128 bytes. The first byte is NUL, followed by a
|
|
||||||
# Pascal string of length 63 (so 64 bytes total) containing the encoded
|
|
||||||
# filename.
|
|
||||||
#
|
|
||||||
# Source: http://files.stairways.com/other/macbinaryii-standard-info.txt
|
|
||||||
# FIXME: We should eventually implement a full MacBinary reader.
|
|
||||||
|
|
||||||
try:
|
|
||||||
f = open(archive_path, "rb")
|
|
||||||
sea_name = f.read(65)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if len(sea_name) < 65:
|
|
||||||
if not quiet:
|
|
||||||
print(" file too short.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
sea_name = sea_name[2:2 + sea_name[1]].decode("mac_roman")
|
|
||||||
else:
|
|
||||||
sea_name = sea_name[2:2 + ord(sea_name[1])]
|
|
||||||
except:
|
|
||||||
if not quiet:
|
|
||||||
print(" error: cannot read expanded name")
|
|
||||||
if 'f' in locals():
|
|
||||||
if not f.isclosed():
|
|
||||||
f.close()
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
cmdline = ["unar", "-q", "-o", archive_dir, "-k", "skip", archive_path]
|
|
||||||
ret = subprocess.call(cmdline)
|
|
||||||
if ret != 0:
|
|
||||||
if not quiet:
|
|
||||||
print(" error: unar returned error %i" % (ret))
|
|
||||||
return False
|
|
||||||
except OSError as e:
|
|
||||||
if not quiet:
|
|
||||||
print(" error: running unar: %s" % (e))
|
|
||||||
return False
|
|
||||||
|
|
||||||
sea_path = os.path.join(archive_dir, sea_name)
|
|
||||||
if not os.path.isfile(sea_path):
|
|
||||||
if not quiet:
|
|
||||||
print(" error: \"%s\" was not extracted." % (sea_name))
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
# The image starts 84 bytes in, and is exactly 819200 bytes long
|
|
||||||
with open(sea_path, "rb") as src, open(image_path, "wb") as dst:
|
|
||||||
src.seek(84)
|
|
||||||
dst.write(src.read(819200))
|
|
||||||
if dst.tell() != 819200:
|
|
||||||
raise IOError()
|
|
||||||
extracted = True
|
|
||||||
except:
|
|
||||||
if not quiet:
|
|
||||||
print(" error: \"%s\" is not an 800k floppy image"
|
|
||||||
% (sea_name))
|
|
||||||
extracted = False
|
|
||||||
finally:
|
|
||||||
if not quiet:
|
|
||||||
print(" done.")
|
|
||||||
os.unlink(sea_path)
|
|
||||||
os.unlink(archive_path)
|
|
||||||
|
|
||||||
return extracted
|
|
||||||
|
|
||||||
|
|
||||||
def plist_keyvalue(plist_dict, key):
|
|
||||||
if plist_dict.tag != "dict":
|
|
||||||
raise ValueError("not a plist dict")
|
|
||||||
found = False
|
|
||||||
for elem in plist_dict:
|
|
||||||
if found:
|
|
||||||
return elem
|
|
||||||
if elem.tag == "key" and elem.text == key:
|
|
||||||
found = True
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_mountpoint(xmlstr):
|
|
||||||
plistroot = ET.fromstring(xmlstr)
|
|
||||||
if plistroot.tag != "plist":
|
|
||||||
raise ValueError("xmlstr is not an XML-format plist")
|
|
||||||
if plistroot[0].tag == "dict":
|
|
||||||
sys_entities = plist_keyvalue(plistroot[0], "system-entities")
|
|
||||||
if sys_entities.tag != "array":
|
|
||||||
raise ValueError("expected dict to contain an array")
|
|
||||||
for child in sys_entities:
|
|
||||||
if child.tag == "dict":
|
|
||||||
mountpoint = plist_keyvalue(child, "mount-point")
|
|
||||||
return mountpoint.text
|
|
||||||
else:
|
|
||||||
raise ValueError("system-entities should be an array of dict objects")
|
|
||||||
else:
|
|
||||||
raise ValueError("Root element is not a dict")
|
|
||||||
|
|
||||||
a2setup_platform = None
|
|
||||||
|
|
||||||
def a2setup_set_platform():
|
|
||||||
global a2setup_platform
|
|
||||||
|
|
||||||
a2setup_platform = os.uname()[0]
|
|
||||||
if a2setup_platform not in ["Linux", "Darwin"]:
|
|
||||||
a2setup_platform = "hfsutils"
|
|
||||||
elif a2setup_platform == "Linux":
|
|
||||||
use_sudo = False
|
|
||||||
if os.geteuid() != 0:
|
|
||||||
reply = stdin_input("""
|
|
||||||
You must have either root access or the hfsutils package to
|
|
||||||
access the disk image containing Apple // boot blocks. Do
|
|
||||||
you want to mount the image using the sudo command? [y] """)
|
|
||||||
if reply.startswith("y") or reply.startswith("Y") or reply == "":
|
|
||||||
use_sudo = True
|
|
||||||
print("""
|
|
||||||
Okay, if asked for a password, type your user password. It
|
|
||||||
will not be echoed when you type.""")
|
|
||||||
else:
|
|
||||||
a2setup_platform = "hfsutils"
|
|
||||||
|
|
||||||
|
|
||||||
def a2setup_mount(image_path):
|
|
||||||
mountpoint = None
|
|
||||||
if a2setup_platform == "Linux":
|
|
||||||
mountpoint = tempfile.mkdtemp(prefix = "tmp-hfsmount.")
|
|
||||||
mount_cmd = ["mount", "-t", "hfs", "-o", "ro,loop", image_path, mountpoint]
|
|
||||||
if use_sudo:
|
|
||||||
mount_cmd = ["sudo"] + mount_cmd
|
|
||||||
subprocess.call(mount_cmd)
|
|
||||||
elif a2setup_platform == "Darwin":
|
|
||||||
xmlstr = subprocess.check_output(["hdiutil", "attach", "-plist",
|
|
||||||
image_path])
|
|
||||||
mountpoint = find_mountpoint(xmlstr)
|
|
||||||
elif a2setup_platform == "hfsutils":
|
|
||||||
mountpoint = tempfile.mkdtemp(prefix = "tmp-hfsmount.")
|
|
||||||
sys_folder = os.path.join(mountpoint, "System Folder")
|
|
||||||
os.mkdir(sys_folder)
|
|
||||||
devnull = open(os.devnull, "wb")
|
|
||||||
subprocess.call(["hmount", image_path], stdout=devnull)
|
|
||||||
devnull.close()
|
|
||||||
subprocess.call(["hcopy", "Apple II Setup:System Folder:*", sys_folder])
|
|
||||||
subprocess.call(["humount", "Apple II Setup"])
|
|
||||||
|
|
||||||
return mountpoint
|
|
||||||
|
|
||||||
|
|
||||||
def a2setup_copyfile(bootfile, mountpoint, dest_dir, dest_fmt):
|
|
||||||
src_dir = os.path.join(mountpoint, "System Folder")
|
|
||||||
if a2setup_platform == "Linux" or a2setup_platform == "Darwin":
|
|
||||||
src_path = os.path.join(src_dir, bootfile["unix"])
|
|
||||||
elif a2setup_platform == "hfsutils":
|
|
||||||
src_path = os.path.join(src_dir, bootfile["hfsutils"])
|
|
||||||
dest_path = os.path.join(dest_dir, bootfile[dest_fmt])
|
|
||||||
try:
|
|
||||||
shutil.copyfile(src_path, dest_path)
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def a2setup_umount(mountpoint):
|
|
||||||
if a2setup_platform == "Linux":
|
|
||||||
umount_cmd = ["umount", mountpoint]
|
|
||||||
if use_sudo:
|
|
||||||
umount_cmd = ["sudo"] + umount_cmd
|
|
||||||
subprocess.call(umount_cmd)
|
|
||||||
os.rmdir(mountpoint)
|
|
||||||
elif a2setup_platform == "Darwin":
|
|
||||||
devnull = open(os.devnull, "wb")
|
|
||||||
subprocess.call(["hdiutil", "eject", mountpoint], stdout=devnull)
|
|
||||||
devnull.close()
|
|
||||||
elif a2setup_platform == "hfsutils":
|
|
||||||
sys_folder = os.path.join(mountpoint, "System Folder")
|
|
||||||
for f in os.listdir(sys_folder):
|
|
||||||
os.unlink(os.path.join(sys_folder, f))
|
|
||||||
os.rmdir(sys_folder)
|
|
||||||
os.rmdir(mountpoint)
|
|
||||||
|
|
||||||
|
|
||||||
def apply_patches(bootfile, dest_dir, dest_fmt):
|
|
||||||
if "patches" in bootfile:
|
|
||||||
(patches, digest) = bootfile["patches"]
|
|
||||||
patch_path = os.path.join(dest_dir, bootfile[dest_fmt])
|
|
||||||
dest_digest = sha1sum_file(patch_path)
|
|
||||||
if dest_digest == digest:
|
|
||||||
if not quiet:
|
|
||||||
print(" \"%s\" is already patched." % (bootfile[dest_fmt]))
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
if verbose:
|
|
||||||
print(" Patching %s..." % (bootfile[dest_fmt]))
|
|
||||||
elif not quiet:
|
|
||||||
print(" Patching %s..." % (bootfile[dest_fmt]), end="")
|
|
||||||
f = open(patch_path, "r+b")
|
|
||||||
for patch in patches:
|
|
||||||
if isinstance(patch, str):
|
|
||||||
if verbose:
|
|
||||||
print(" %s" % (patch))
|
|
||||||
else:
|
|
||||||
(offset, data) = patch
|
|
||||||
f.seek(offset)
|
|
||||||
f.write(data)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
# Verify...
|
|
||||||
dest_digest = sha1sum_file(patch_path)
|
|
||||||
if dest_digest == digest:
|
|
||||||
print(" patched.")
|
|
||||||
else:
|
|
||||||
print(" patch failed.\n Expected: %s\n Received: %s"
|
|
||||||
% (bootfile["patches"][1], dest_digest))
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def install_bootblocks(dest_dir, dest_fmt):
|
|
||||||
if dest_fmt not in ["unix", "netatalk"]:
|
|
||||||
raise ValueError("Only basic UNIX and netatalk formats are supported for now")
|
|
||||||
|
|
||||||
if not quiet:
|
|
||||||
print("Installing Apple // boot blocks...")
|
|
||||||
|
|
||||||
if not os.path.isdir(dest_dir):
|
|
||||||
os.makedirs(dest_dir, mode=0o0755)
|
|
||||||
|
|
||||||
work_dir = tempfile.mkdtemp(prefix = "tmp-a2sv-bootblocks.")
|
|
||||||
a2setup_name = "A2SETUP.img"
|
|
||||||
if verbose:
|
|
||||||
print(" dest_fmt : %s\n dest_dir : %s\n work_dir : %s\n"
|
|
||||||
% (dest_fmt, dest_dir, work_dir))
|
|
||||||
|
|
||||||
a2setup_set_platform()
|
|
||||||
|
|
||||||
a2boot_needed = False
|
|
||||||
a2setup_extracted = False
|
|
||||||
a2boot_installed = False
|
|
||||||
|
|
||||||
for bootfile in a2boot_files:
|
|
||||||
dest_path = os.path.join(dest_dir, bootfile[dest_fmt])
|
|
||||||
if not os.path.isfile(dest_path):
|
|
||||||
a2boot_needed = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
dest_digest = sha1sum_file(dest_path)
|
|
||||||
if dest_digest != bootfile["digest"]:
|
|
||||||
if "patches" not in bootfile or dest_digest != bootfile["patches"][1]:
|
|
||||||
a2boot_needed = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not a2boot_needed:
|
|
||||||
if not quiet:
|
|
||||||
print("Files already copied.")
|
|
||||||
a2boot_installed = True
|
|
||||||
else:
|
|
||||||
if download_from_sources(disk7_sources, work_dir):
|
|
||||||
if disk7_sources["type"] == "sea.bin":
|
|
||||||
a2setup_extracted = extract_800k_sea_bin(disk7_sources["file"],
|
|
||||||
a2setup_name, work_dir)
|
|
||||||
else:
|
|
||||||
# Placeholder for 6.0.4+ files packed some other way
|
|
||||||
pass
|
|
||||||
|
|
||||||
if a2setup_extracted:
|
|
||||||
a2setup_path = os.path.join(work_dir, a2setup_name)
|
|
||||||
mountpoint = a2setup_mount(a2setup_path)
|
|
||||||
src_dir = os.path.join(mountpoint, "System Folder")
|
|
||||||
|
|
||||||
if not quiet:
|
|
||||||
print("Copying files...", end="")
|
|
||||||
a2boot_installed = True
|
|
||||||
for bootfile in a2boot_files:
|
|
||||||
if not a2setup_copyfile(bootfile, mountpoint, dest_dir, dest_fmt):
|
|
||||||
a2boot_installed = False
|
|
||||||
|
|
||||||
if not quiet:
|
|
||||||
if a2boot_installed:
|
|
||||||
print(" success.")
|
|
||||||
else:
|
|
||||||
print(" error copying files")
|
|
||||||
|
|
||||||
a2setup_umount(mountpoint)
|
|
||||||
os.unlink(a2setup_path)
|
|
||||||
|
|
||||||
os.rmdir(work_dir)
|
|
||||||
|
|
||||||
if not a2boot_installed and not quiet:
|
|
||||||
print("Installation failed.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
for bootfile in a2boot_files:
|
|
||||||
apply_patches(bootfile, dest_dir, dest_fmt)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def do_install():
|
|
||||||
netboot_tmp = tempfile.mkdtemp(suffix = ".a2server-netboot")
|
|
||||||
print("You'll want to go and delete this directory:")
|
|
||||||
print(netboot_tmp)
|
|
||||||
os.chdir(netboot_tmp)
|
|
||||||
|
|
||||||
# If we need boot files:
|
|
||||||
# Download a disk image
|
|
||||||
# If it is one we need to unpack (.sea.bin):
|
|
||||||
# unar it
|
|
||||||
# extract the embedded image
|
|
||||||
# If we need to apply boot block patches:
|
|
||||||
# fix cleartext password bug in //e boot block
|
|
||||||
# fix cleartext password bug in IIgs boot block
|
|
||||||
# patch IIgs boot block to allow booting ProDOS 8
|
|
||||||
# If we don't have A2SERVER tools:
|
|
||||||
# Download the installer script
|
|
||||||
# Run the installer script
|
|
||||||
# Copy Basic.System to A2FILES for ProDOS 8
|
|
||||||
# If NETBOOT.P8 (battery ram set to boot into ProDOS 8) doesn't exist:
|
|
||||||
# Create it
|
|
||||||
# If NETBOOT.GSOS (battery ram set to boot into GSOS) doesn't exist:
|
|
||||||
# Create it
|
|
||||||
# Set GS/OS to boot SYSTEM/FINDER (registered user or guest)
|
|
||||||
# Set ProDOS 8 to boot BASIC.SYSTEM (guest)
|
|
||||||
# If SYSTEM/START.GS.OS doesn't exist in A2FILES:
|
|
||||||
# Ask if user wants to install GS/OS 6.0.1
|
|
||||||
# If they answer yes:
|
|
||||||
# create imagesDir
|
|
||||||
# create netInstallDir
|
|
||||||
# For each disk:
|
|
||||||
# Download the disk
|
|
||||||
# If it is one we need to unpack (.sea.bin):
|
|
||||||
# extract_800k_sea_bin it
|
|
||||||
# unpack the disk to netInstallDir
|
|
||||||
|
|
||||||
|
|
||||||
# XXX Re-enable this
|
|
||||||
#os.rmdir(netboot_tmp)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# bail out on automated netboot setup unless -b is also specified
|
|
||||||
# FIXME: This logic belongs in a2server-setup, not here
|
|
||||||
autoAnswerYes = os.path.isfile("/tmp/a2server-autoAnswerYes")
|
|
||||||
if autoAnswerYes and not os.path.isfile("/tmp/a2server-setupNetBoot"):
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# We need root to do this. If we don't have it, just rerun the command with
|
|
||||||
# sudo and be done with it.
|
|
||||||
#
|
|
||||||
# FIXME: Should we be doing this? A generic installer should not assume it's
|
|
||||||
# writing to a root-owned dir, nor care. Probably the reason to do it this way
|
|
||||||
# is as a proof of concept that it can be done this way in the main
|
|
||||||
# a2server-setup script, which of course means we don't actually need to change
|
|
||||||
# the password for the user.
|
|
||||||
#
|
|
||||||
# XXX Disabling this for development
|
|
||||||
"""
|
|
||||||
if os.geteuid() != 0:
|
|
||||||
args = sys.argv
|
|
||||||
args.insert(0, "sudo")
|
|
||||||
# At the very least, we should print the command line we"re running here
|
|
||||||
print ("Rerunning with sudo...")
|
|
||||||
ret = subprocess.call(args)
|
|
||||||
sys.exit(ret)
|
|
||||||
"""
|
|
||||||
|
|
||||||
install_bootblocks(os.path.join(os.getcwd(), "a2boot"), "netatalk")
|
|
||||||
#reply = stdin_input("""\nDo you want to set up A2SERVER to be able to boot Apple II\ncomputers over the network? [y] """)
|
|
||||||
#if reply.startswith("y") or reply.startswith("Y") or reply == "":
|
|
||||||
# do_install()
|
|
1749
files/A2FILES-list.txt
Normal file
1749
files/A2FILES-list.txt
Normal file
File diff suppressed because it is too large
Load Diff
65
files/dist/getexternal.sh
vendored
Executable file
65
files/dist/getexternal.sh
vendored
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
||||||
|
|
||||||
|
if ! hash wget; then
|
||||||
|
echo "wget is not installed. On a Mac, install it with MacPorts or Homebrew."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Downloading items..."
|
||||||
|
|
||||||
|
mkdir -p files/external/source
|
||||||
|
wget -O files/external/source/ciopfs-0.4.tar.gz http://www.brain-dump.org/projects/ciopfs/ciopfs-0.4.tar.gz
|
||||||
|
wget -O files/external/source/macipgw.zip https://github.com/zero2sixd/macipgw/archive/2a5f6a7521a627e46b18468d44f4306fb0a7b7ab.zip
|
||||||
|
wget -O files/external/source/netatalk-2.2.4.tar.gz http://downloads.sourceforge.net/project/netatalk/netatalk/2.2.4/netatalk-2.2.4.tar.gz
|
||||||
|
wget -O files/external/source/nulib2-3.1.0a2.zip https://github.com/fadden/nulib2/archive/20fe7efb4d37fedf807416c16d74d51d893ea48a.zip
|
||||||
|
wget -O files/external/source/unar-1.8.1.zip https://github.com/incbee/Unarchiver/archive/unar-1.8.1.zip
|
||||||
|
|
||||||
|
mkdir -p files/external/appleii
|
||||||
|
wget --max-redirect 0 -O files/external/appleii/Apple_II_System_Disk_3.2.sea.bin http://download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/English-North_American/Apple_II/Apple_II_Supplemental/Apple_II_System_Disk_3.2.sea.bin
|
||||||
|
wget -O files/external/appleii/Asimov.shk http://www.ninjaforce.com/downloads/Asimov.shk
|
||||||
|
wget -O files/external/appleii/MOUNTIT.SHK http://www.brutaldeluxe.fr/products/apple2gs/MOUNTIT.SHK
|
||||||
|
wget -O files/external/appleii/Marinetti3.0b8.po http://www.a2retrosystems.com/downloads/Marinetti3.0b8.po
|
||||||
|
wget -O files/external/appleii/PPPX.1.3d4.SHK http://www.apple2.org/marinetti/PPPX.1.3d4.SHK
|
||||||
|
wget -O files/external/appleii/dsk2file.shk http://www.dwheeler.com/6502/oneelkruns/dsk2file.zip
|
||||||
|
wget -O files/external/appleii/gshk11.sea http://www.nulib.com/library/gshk11.sea
|
||||||
|
wget -O files/external/appleii/shrinkit.sdk http://www.nulib.com/library/shrinkit.sdk
|
||||||
|
wget -O files/external/appleii/spectrum_gold_2mg.zip http://speccie.uk/speccie/downloads/spectrum_gold_2mg.zip
|
||||||
|
wget -O files/external/appleii/uthernet2ll.bxy http://speccie.uk/speccie/downloads/uthernet2ll.bxy
|
||||||
|
wget -O files/external/appleii/uthernetll.bxy http://speccie.uk/speccie/downloads/uthernetll.bxy
|
||||||
|
|
||||||
|
unset safeUrl samUrl snapUrl
|
||||||
|
safeUrl=$(wget -qO- http://speccie.uk/software/safe2/ | grep -i 'safe2.*bxy' | tr '<>' '\n' | grep href | cut -d '=' -f 2 | tr -d '"')
|
||||||
|
samUrl=$(wget -qO- http://speccie.uk/software/sam2/ | grep -i 'sam2.*bxy' | tr '<>' '\n' | grep href | cut -d '=' -f 2 | tr -d '"')
|
||||||
|
snapUrl=$(wget -qO- http://speccie.uk/software/snap/ | grep -i 'snap.*bxy' | tr '<>' '\n' | grep href | cut -d '=' -f 2 | tr -d '"')
|
||||||
|
wget -O files/external/appleii/safe2.bxy "$safeUrl"
|
||||||
|
wget -O files/external/appleii/sam2.bxy "$samUrl"
|
||||||
|
wget -O files/external/appleii/snap.bxy "$snapUrl"
|
||||||
|
|
||||||
|
for gsosInstall in {1..3}; do
|
||||||
|
activeDisk=0
|
||||||
|
mkdir -p files/external/appleii/gsos60${gsosInstall}
|
||||||
|
|
||||||
|
diskNames=( Install System.Disk SystemTools1 SystemTools2 Fonts synthLAB )
|
||||||
|
if (( $gsosInstall == 1 )); then
|
||||||
|
gsosURL="http://download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/English-North_American/Apple_II/Apple_IIGS_System_6.0.1/"
|
||||||
|
wget --max-redirect 0 -O files/external/appleii/gsos601/Disk_7_of_7-Apple_II_Setup.sea.bin http://download.info.apple.com/Apple_Support_Area/Apple_Software_Updates/English-North_American/Apple_II/Apple_IIGS_System_6.0.1/Disk_7_of_7-Apple_II_Setup.sea.bin
|
||||||
|
elif (( $gsosInstall == 2 )); then
|
||||||
|
gsosURL="http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Software/Operating%20Systems/Apple%20IIGS%20System/Disk%20Images/"
|
||||||
|
diskNames=( Install System.Disk SystemTools1 SystemTools2 SystemTools3 Fonts1 Fonts2 synthLAB )
|
||||||
|
diskWebNames=( Install System%20disk System%20tools%201 System%20tools%202 System%20tools%203 Fonts%201 Fonts%202 Synthlab )
|
||||||
|
elif (( $gsosInstall == 3 )); then
|
||||||
|
gsosURL="ftp://ftp.apple.asimov.net/pub/apple_II/images/gs/os/gsos/Apple_IIGS_System_6.0.3/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for diskname in ${diskNames[@]}; do
|
||||||
|
outfile="files/external/appleii/gsos60${gsosInstall}/$diskname.po"
|
||||||
|
(( activeDisk++ ))
|
||||||
|
if (( $gsosInstall == 1 )); then
|
||||||
|
wget --max-redirect 0 -O files/external/appleii/gsos601/"Disk_${activeDisk}_of_7-${diskname}.sea.bin" "${gsosURL}Disk_${activeDisk}_of_7-${diskname}.sea.bin"
|
||||||
|
elif (( $gsosInstall == 2 )); then
|
||||||
|
wget -O $outfile "$gsosURL/IIGS%20System%206.0.2%20-%20Disk%20${activeDisk}%20${diskWebNames[$activeDisk-1]}.po"
|
||||||
|
elif (( $gsosInstall == 3 )); then
|
||||||
|
wget -O $outfile "$gsosURL/$diskname.po"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
152
files/netatalk-init.d-clean.txt
Executable file
152
files/netatalk-init.d-clean.txt
Executable file
@@ -0,0 +1,152 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: netatalk
|
||||||
|
# Required-Start: $remote_fs $syslog
|
||||||
|
# Should-Start: avahi-daemon
|
||||||
|
# Required-Stop: $remote_fs $syslog
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 1
|
||||||
|
### END INIT INFO
|
||||||
|
#
|
||||||
|
# netatalk Netatalk 2.2.4 initscript
|
||||||
|
# Author: Thomas Kaiser <Thomas.Kaiser@phg-online.de>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||||
|
DESC="Netatalk"
|
||||||
|
NAME=netatalk
|
||||||
|
SCRIPTNAME=/etc/init.d/$NAME
|
||||||
|
|
||||||
|
# Guard to prevent execution if netatalk was removed.
|
||||||
|
test -x /usr/local/sbin/afpd || exit 0
|
||||||
|
|
||||||
|
# Set defaults. Please change these options in /etc/default/netatalk
|
||||||
|
ATALK_NAME=`/bin/hostname --short`
|
||||||
|
ATALK_UNIX_CHARSET='LOCALE'
|
||||||
|
ATALK_MAC_CHARSET='MAC_ROMAN'
|
||||||
|
|
||||||
|
CNID_METAD_RUN=yes
|
||||||
|
AFPD_RUN=yes
|
||||||
|
AFPD_MAX_CLIENTS=50
|
||||||
|
AFPD_UAMLIST="-U uams_dhx2.so"
|
||||||
|
AFPD_GUEST=nobody
|
||||||
|
CNID_CONFIG="-l log_note"
|
||||||
|
|
||||||
|
ATALKD_RUN=no
|
||||||
|
PAPD_RUN=no
|
||||||
|
TIMELORD_RUN=no
|
||||||
|
#A2BOOT_RUN=no
|
||||||
|
ATALK_ZONE=
|
||||||
|
ATALK_BGROUND=no
|
||||||
|
|
||||||
|
# old /etc/default/netatalk expected hostname in $HOSTNAME by default
|
||||||
|
HOSTNAME=`/bin/hostname`
|
||||||
|
|
||||||
|
# Read in netatalk configuration.
|
||||||
|
if [ -f /etc/default/netatalk ]; then
|
||||||
|
. /etc/default/netatalk
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start Netatalk servers.
|
||||||
|
atalk_startup() {
|
||||||
|
if [ x"$ATALKD_RUN" = x"yes" ]; then
|
||||||
|
|
||||||
|
# Try to load the AppleTalk kernel module if it was intended.
|
||||||
|
if grep -q '^appletalk$' /etc/modules; then
|
||||||
|
/sbin/modprobe appletalk || echo "[could not load appletalk module]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start atalkd server.
|
||||||
|
/usr/local/sbin/atalkd
|
||||||
|
|
||||||
|
# register workstation
|
||||||
|
/usr/local/bin/nbprgstr -p 4 "$ATALK_NAME:Workstation$ATALK_ZONE"
|
||||||
|
/usr/local/bin/nbprgstr -p 4 "$ATALK_NAME:netatalk$ATALK_ZONE"
|
||||||
|
|
||||||
|
echo -n " atalkd"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# prepare startup of file services
|
||||||
|
if [ "x$CNID_METAD_RUN" = "xyes" -a -x /usr/local/sbin/cnid_metad ] ; then
|
||||||
|
echo -n " cnid_metad"
|
||||||
|
/usr/local/sbin/cnid_metad $CNID_CONFIG
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$AFPD_RUN" = x"yes" ]; then
|
||||||
|
/usr/local/sbin/afpd $AFPD_UAMLIST -g $AFPD_GUEST -c $AFPD_MAX_CLIENTS \
|
||||||
|
-n "$ATALK_NAME$ATALK_ZONE"
|
||||||
|
echo -n " afpd"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$ATALKD_RUN" = "xyes" ]; then
|
||||||
|
if [ "x$PAPD_RUN" = "xyes" ]; then
|
||||||
|
/usr/local/sbin/papd
|
||||||
|
echo -n " papd"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$TIMELORD_RUN" = x"yes" ]; then
|
||||||
|
/usr/local/sbin/timelord
|
||||||
|
echo -n " timelord"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
if [ "x$ATALK_BGROUND" = "xyes" -a "x$ATALKD_RUN" = "xyes" ]; then
|
||||||
|
echo "Starting Netatalk services in the background."
|
||||||
|
atalk_startup >/dev/null &
|
||||||
|
else
|
||||||
|
echo -n "Starting Netatalk services (this will take a while): "
|
||||||
|
atalk_startup
|
||||||
|
echo "."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
echo -n "Stopping Netatalk Daemons:"
|
||||||
|
echo -n " afpd"
|
||||||
|
start-stop-daemon --stop --quiet --oknodo --exec /usr/local/sbin/afpd
|
||||||
|
|
||||||
|
echo -n " cnid_metad"
|
||||||
|
start-stop-daemon --stop --quiet --oknodo --exec /usr/local/sbin/cnid_metad
|
||||||
|
|
||||||
|
if test -x /usr/local/sbin/papd; then
|
||||||
|
echo -n " papd"
|
||||||
|
start-stop-daemon --stop --quiet --oknodo --exec /usr/local/sbin/papd
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -x /usr/local/sbin/timelord; then
|
||||||
|
echo -n " timelord"
|
||||||
|
start-stop-daemon --stop --quiet --oknodo --exec /usr/local/sbin/timelord
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -x /usr/local/sbin/atalkd; then
|
||||||
|
echo -n " atalkd"
|
||||||
|
start-stop-daemon --stop --quiet --oknodo --exec /usr/local/sbin/atalkd
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "."
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
$0 force-reload
|
||||||
|
;;
|
||||||
|
|
||||||
|
force-reload)
|
||||||
|
echo -n "Restarting Netatalk Daemons (this will take a while)"
|
||||||
|
$0 stop
|
||||||
|
echo -n "."
|
||||||
|
sleep 2
|
||||||
|
echo -n "."
|
||||||
|
if $0 start; then
|
||||||
|
echo "done."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|restart|force-reload}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
@@ -78,7 +78,7 @@ if [[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]]; then
|
|||||||
if [[ $(sha1sum /tmp/sd/lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko | cut -f 1 -d ' ') != "ecb239fc084c36de93f6926e7749b80f6024f269" ]]; 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..."
|
echo "Removing defective AppleTalk module from kernel $kernelRelease..."
|
||||||
sudo rm -rf /tmp/sd/lib/modules/$kernelRelease/kernel/net/appletalk 2> /dev/null
|
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
|
wget -qO /tmp/appletalk.ko.gz ${A2SERVER_SCRIPT_URL}files/appletalk-$kernelRelease.ko.gz
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
# if we found a prebuilt one on a2server site, so install it
|
# if we found a prebuilt one on a2server site, so install it
|
||||||
gunzip -f /tmp/appletalk.ko.gz
|
gunzip -f /tmp/appletalk.ko.gz
|
@@ -3,18 +3,29 @@
|
|||||||
|
|
||||||
# --- Setting up the share volume
|
# --- Setting up the share volume
|
||||||
|
|
||||||
|
# 1.3.0: move /media/A2SHARED (pre-1.3.0) to /srv/A2SERVER
|
||||||
|
if [[ -d /media/A2SHARED ]]; then
|
||||||
|
echo "A2SERVER: Moving /media/A2SHARED to /srv/A2SERVER..."
|
||||||
|
sudo /etc/init.d/netatalk stop &> /dev/null
|
||||||
|
sudo /etc/init.d/samba stop &> /dev/null
|
||||||
|
[[ ! -d /srv ]] && sudo mkdir -p /srv
|
||||||
|
sudo mv /media/A2SHARED /srv/A2SERVER
|
||||||
|
sudo sed -i 's|/media/A2SHARED|/srv/A2SERVER|g' /usr/local/etc/netatalk/AppleVolumes.default
|
||||||
|
[[ -f /etc/samba/smbd.conf ]] && sudo sed -i 's|/media/A2SHARED|/srv/A2SERVER|g' /etc/samba/smbd.conf
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
# skip if we're already set up
|
# skip if we're already set up
|
||||||
if [[ -d /media/A2SHARED ]]; then
|
if [[ -d /srv/A2SERVER ]]; then
|
||||||
|
|
||||||
echo "A2SERVER: Shared disk is already prepared for use."
|
echo "A2SERVER: Shared volume is already prepared for use."
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
echo "A2SERVER: Preparing the shared files disk..."
|
echo "A2SERVER: Preparing the shared files volume..."
|
||||||
|
|
||||||
sudo mkdir /media/A2SHARED
|
sudo mkdir -p /srv/A2SERVER
|
||||||
|
|
||||||
sudo chown $USER:$USER /media/A2SHARED
|
sudo chown $USER:$USER /srv/A2SERVER
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
@@ -7,32 +7,65 @@
|
|||||||
# Ensure URL we'll use ends in a /
|
# Ensure URL we'll use ends in a /
|
||||||
case "$A2SERVER_SCRIPT_URL" in
|
case "$A2SERVER_SCRIPT_URL" in
|
||||||
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
||||||
*) scriptURL="${A2SERVER_SCRIPT_URL:-http://appleii.ivanx.com/a2server}/" ;;
|
*) scriptURL="${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current}/" ;;
|
||||||
esac
|
esac
|
||||||
|
case "$A2SERVER_BINARY_URL" in
|
||||||
|
*/) binaryURL="$A2SERVER_BINARY_URL" ;;
|
||||||
|
*) binaryURL="${A2SERVER_BINARY_URL:-http://ivanx.com/a2server/files}/" ;;
|
||||||
|
esac
|
||||||
|
useExternalURL=1
|
||||||
|
[[ $A2SERVER_NO_EXTERNAL ]] && useExternalURL=
|
||||||
|
|
||||||
|
debianVersion=$(cat /etc/debian_version 2> /dev/null)
|
||||||
isRpi=
|
isRpi=
|
||||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1
|
arch=
|
||||||
|
if [[ -f /usr/bin/raspi-config ]]; then
|
||||||
|
isRpi=1
|
||||||
|
arch='rpi'
|
||||||
|
elif lsb_release -a 2> /dev/null | grep -q 'Distributor ID:.Debian' && [[ $(cut -d . -f 1 <<< $debianVersion) -ge "7" ]]; then
|
||||||
|
uname_m="$(uname -m)"
|
||||||
|
if [[ $uname_m == "i686" ]]; then
|
||||||
|
arch='debian_x86'
|
||||||
|
elif [[ $uname_m == "x86_64" ]]; then
|
||||||
|
arch='debian_x64'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
isDebian=
|
debianName=
|
||||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1 < /etc/debian_version) -ge "7" ) && ( $(uname -m) == "i686" ) ]] && isDebian=1
|
if [[ $debianVersion ]]; then
|
||||||
|
debianMajor=$(cut -d . -f 1 <<< $debianVersion)
|
||||||
isJessie=
|
if [[ $debianMajor == "9" ]]; then
|
||||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "8." ) ]] && isJessie=1
|
debianName="stretch"
|
||||||
|
elif [[ $debianMajor == "8" ]]; then
|
||||||
|
debianName="jessie"
|
||||||
|
elif [[ $debianMajor == "7" ]]; then
|
||||||
|
debianName="wheezy"
|
||||||
|
else
|
||||||
|
debianName="unknown"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo "A2SERVER: Installing A2SERVER tools..."
|
echo "A2SERVER: Installing A2SERVER tools..."
|
||||||
|
|
||||||
if ! command -v nulib2 > /dev/null; then
|
# delete older nulib2 which doesn't correctly handle zero-length forks in GSHK-created archives
|
||||||
|
if hash nulib2 &> /dev/null; then
|
||||||
|
nulib2version=$(nulib2 | sed -n 2p | sed 's|^.*v\([0-9]\)\.\([0-9]\)\.\([0-9]\).*$|\1\2\3|' 2> /dev/null)
|
||||||
|
if (( $nulib2version < 310 )); then
|
||||||
|
sudo apt-get -y purge nulib2 &> /dev/null
|
||||||
|
sudo rm $(command -v nulib2) &> /dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! hash nulib2 &> /dev/null; then
|
||||||
|
|
||||||
echo "A2SERVER: Installing nulib2..."
|
echo "A2SERVER: Installing nulib2..."
|
||||||
|
|
||||||
cd /tmp
|
cd /tmp
|
||||||
if [[ $isRpi ]]; then
|
if [[ $arch && ! -f /tmp/a2server-compileAlways ]]; then
|
||||||
wget -qO- "http://appleii.ivanx.com/a2server/files/nulib2-rpi.tgz" | sudo tar Pzx
|
{ wget -qO- "${binaryURL}precompiled/nulib2-3.1.0a2-${arch}.tgz" | sudo tar Pzx; } &> /dev/null
|
||||||
elif [[ $isDebian ]]; then
|
|
||||||
wget -qO- "http://appleii.ivanx.com/a2server/files/nulib2-debian7_x86.tgz" | sudo tar Pzx
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! command -v nulib2 > /dev/null; then
|
if ! hash nulib2 &> /dev/null; then
|
||||||
|
|
||||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||||
# prepare for installing packages
|
# prepare for installing packages
|
||||||
@@ -40,25 +73,35 @@ if ! command -v nulib2 > /dev/null; then
|
|||||||
touch /tmp/a2server-packageReposUpdated
|
touch /tmp/a2server-packageReposUpdated
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo apt-get -y install build-essential
|
# Dependencies: build-dep for nulib
|
||||||
sudo apt-get -y install zlib1g-dev
|
sudo apt-get -y install build-essential zlib1g-dev
|
||||||
sudo apt-get -y clean
|
sudo apt-get -y clean
|
||||||
|
|
||||||
cd /tmp
|
cd /tmp
|
||||||
rm -rf /tmp/nulib &> /dev/null
|
rm -rf /tmp/nulib2 &> /dev/null
|
||||||
mkdir /tmp/nulib
|
mkdir /tmp/nulib2
|
||||||
cd /tmp/nulib
|
cd /tmp/nulib2
|
||||||
wget -q -O nulib.tgz http://web.archive.org/web/20131031160750/http://www.nulib.com/downloads/nulibdist.tar.gz
|
if [[ $useExternalURL ]]; then
|
||||||
tar zxf nulib.tgz
|
wget -q -O nulib2-3.1.0a2.zip "https://github.com/fadden/nulib2/archive/20fe7efb4d37fedf807416c16d74d51d893ea48a.zip"
|
||||||
cd nufxlib*
|
unzip nulib2-3.1.0a2.zip 2> /dev/null
|
||||||
|
rm nulib2-3.1.0a2.zip &> /dev/null
|
||||||
|
fi
|
||||||
|
if [ ! -d nulib2* ]; then
|
||||||
|
wget -q -O nulib2-3.1.0a2.zip "${binaryURL}external/source/nulib2-3.1.0a2.zip"
|
||||||
|
unzip nulib2-3.1.0a2.zip 2> /dev/null
|
||||||
|
rm nulib2-3.1.0a2.zip &> /dev/null
|
||||||
|
fi
|
||||||
|
cd nulib2*
|
||||||
|
cd nufxlib
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
cd ../nulib2*
|
cd ../nulib2
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
cd
|
cd
|
||||||
rm -rf /tmp/nulib
|
rm -rf /tmp/nulib2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -68,7 +111,7 @@ fi
|
|||||||
# download and install The Unarchiver, for expanding Apple disk images
|
# download and install The Unarchiver, for expanding Apple disk images
|
||||||
# http://wakaba.c3.cx/s/apps/unarchiver.html
|
# http://wakaba.c3.cx/s/apps/unarchiver.html
|
||||||
|
|
||||||
if ! command -v unar > /dev/null; then
|
if ! hash unar &> /dev/null; then
|
||||||
|
|
||||||
echo "A2SERVER: Installing The Unarchiver..."
|
echo "A2SERVER: Installing The Unarchiver..."
|
||||||
|
|
||||||
@@ -78,34 +121,39 @@ if ! command -v unar > /dev/null; then
|
|||||||
touch /tmp/a2server-packageReposUpdated
|
touch /tmp/a2server-packageReposUpdated
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $isJessie ]]; then
|
# jessie and later: Just use the unar package
|
||||||
sudo apt-get install -y unar
|
if [[ $debianMajor -ge 8 ]]; then
|
||||||
|
sudo apt-get -y install unar
|
||||||
sudo apt-get clean
|
sudo apt-get clean
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! command -v unar > /dev/null; then
|
if ! hash unar &> /dev/null; then
|
||||||
if [[ $isRpi || $isDebian ]]; then
|
if [[ $arch && ! -f /tmp/a2server-compileAlways ]]; then
|
||||||
|
# Dependencies: for unar
|
||||||
sudo apt-get -y install libgnustep-base1.22
|
sudo apt-get -y install libgnustep-base1.22
|
||||||
sudo apt-get clean
|
sudo apt-get clean
|
||||||
if [[ $isRpi ]]; then
|
{ wget -qO- "${binaryURL}precompiled/unar-${arch}_${debianName}.tgz" | sudo tar Pzx; } &> /dev/null
|
||||||
wget -qO- "http://appleii.ivanx.com/a2server/files/unar-rpi_wheezy.tgz" | sudo tar Pzx
|
|
||||||
elif [[ $isDebian ]]; then
|
|
||||||
wget -qO- "http://appleii.ivanx.com/a2server/files/unar-debian7_x86.tgz" | sudo tar Pzx
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If all else fails, compile from source.
|
# If all else fails, compile from source.
|
||||||
if ! command -v unar >/dev/null; then
|
if ! hash unar &> /dev/null; then
|
||||||
sudo apt-get -y install build-essential
|
|
||||||
sudo apt-get -y install libgnustep-base-dev libz-dev libbz2-dev
|
# Dependencies: build-deps for unar
|
||||||
sudo apt-get -y install libssl-dev libicu-dev unzip
|
sudo apt-get -y install build-essential libgnustep-base-dev libz-dev libbz2-dev libssl-dev libicu-dev unzip
|
||||||
sudo apt-get clean
|
sudo apt-get clean
|
||||||
|
|
||||||
rm -rf /tmp/unar &> /dev/null
|
rm -rf /tmp/unar &> /dev/null
|
||||||
mkdir /tmp/unar
|
mkdir /tmp/unar
|
||||||
cd /tmp/unar
|
cd /tmp/unar
|
||||||
wget -qO unar1.7_src.zip http://theunarchiver.googlecode.com/files/unar1.7_src.zip
|
if [[ $useExternalURL ]]; then
|
||||||
unzip -o unar1.7_src.zip
|
wget -O unar-1.8.1.zip https://github.com/incbee/Unarchiver/archive/unar-1.8.1.zip
|
||||||
cd The\ Unarchiver/XADMaster
|
unzip -o unar-1.8.1.zip &> /dev/null
|
||||||
|
fi
|
||||||
|
if [ ! -d *Unarchiver*/XADMaster ]; then # need single bracket for glob
|
||||||
|
wget -O unar-1.8.1.zip ${binaryURL}external/source/unar-1.8.1.zip
|
||||||
|
unzip -o unar-1.8.1.zip &> /dev/null
|
||||||
|
fi
|
||||||
|
cd *Unarchiver*/XADMaster
|
||||||
make -f Makefile.linux
|
make -f Makefile.linux
|
||||||
sudo mv lsar unar /usr/local/bin
|
sudo mv lsar unar /usr/local/bin
|
||||||
cd ../Extra
|
cd ../Extra
|
||||||
@@ -119,9 +167,17 @@ else
|
|||||||
echo "A2SERVER: The Unarchiver has already been installed."
|
echo "A2SERVER: The Unarchiver has already been installed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! command -v unzip >/dev/null; then
|
if ! hash unzip &> /dev/null; then
|
||||||
echo "A2SERVER: Installing unzip..."
|
echo "A2SERVER: Installing unzip..."
|
||||||
sudo apt-get -y install unzip
|
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||||
|
# prepare for installing packages
|
||||||
|
sudo apt-get -y update
|
||||||
|
touch /tmp/a2server-packageReposUpdated
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dependencies: unzip
|
||||||
|
sudo apt-get -y install unzip
|
||||||
|
sudo apt-get clean
|
||||||
else
|
else
|
||||||
echo "A2SERVER: unzip has already been installed."
|
echo "A2SERVER: unzip has already been installed."
|
||||||
fi
|
fi
|
||||||
@@ -138,15 +194,20 @@ sudo wget -q -O /usr/local/bin/cppo "${scriptURL}scripts/tools/cppo.txt"
|
|||||||
sudo chmod ugo+x /usr/local/bin/cppo
|
sudo chmod ugo+x /usr/local/bin/cppo
|
||||||
sudo wget -q -O /usr/local/etc/a2server-help.txt "${scriptURL}scripts/tools/a2server-help.txt"
|
sudo wget -q -O /usr/local/etc/a2server-help.txt "${scriptURL}scripts/tools/a2server-help.txt"
|
||||||
sudo wget -q -O /usr/local/etc/a2server-aliases "${scriptURL}scripts/tools/a2server-aliases.txt"
|
sudo wget -q -O /usr/local/etc/a2server-aliases "${scriptURL}scripts/tools/a2server-aliases.txt"
|
||||||
|
sudo wget -q -O /usr/local/etc/a2serverrc "${scriptURL}scripts/tools/a2serverrc.txt"
|
||||||
|
|
||||||
grep a2server-aliases /etc/bash.bashrc > /dev/null || \
|
# 1.3.0: a2serverrc is now called from /etc/bash.bashrc,
|
||||||
echo "source /usr/local/etc/a2server-aliases" | sudo tee -a /etc/bash.bashrc > /dev/null
|
# which in turn calls a2server-aliases
|
||||||
|
grep 'a2server-aliases' /etc/bash.bashrc > /dev/null && \
|
||||||
|
sudo sed -i 's/a2server-aliases/a2serverrc/' /etc/bash.bashrc
|
||||||
|
grep 'a2serverrc' /etc/bash.bashrc > /dev/null || \
|
||||||
|
echo "source /usr/local/etc/a2serverrc" | sudo tee -a /etc/bash.bashrc > /dev/null
|
||||||
|
|
||||||
motd="/etc/motd"
|
motd="/etc/motd"
|
||||||
if [[ ! $(grep A2SERVER $motd) ]]; then
|
if [[ ! $(grep A2SERVER $motd) ]]; then
|
||||||
echo | sudo tee -a $motd > /dev/null
|
echo | sudo tee -a $motd > /dev/null
|
||||||
echo "Type 'system-shutdown' to turn off A2SERVER." | 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-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 "Type 'a2server-help' for a list of other commands." | sudo tee -a $motd > /dev/null
|
||||||
echo | sudo tee -a $motd > /dev/null
|
echo | sudo tee -a $motd > /dev/null
|
||||||
fi
|
fi
|
||||||
|
@@ -16,21 +16,57 @@
|
|||||||
|
|
||||||
# Ensure URL we'll use ends in a /
|
# Ensure URL we'll use ends in a /
|
||||||
case "$A2SERVER_SCRIPT_URL" in
|
case "$A2SERVER_SCRIPT_URL" in
|
||||||
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
||||||
*) scriptURL="${A2SERVER_SCRIPT_URL:-http://appleii.ivanx.com/a2server}/" ;;
|
*) scriptURL="${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current}/" ;;
|
||||||
esac
|
esac
|
||||||
|
case "$A2SERVER_BINARY_URL" in
|
||||||
|
*/) binaryURL="$A2SERVER_BINARY_URL" ;;
|
||||||
|
*) binaryURL="${A2SERVER_BINARY_URL:-http://ivanx.com/a2server/files}/" ;;
|
||||||
|
esac
|
||||||
|
useExternalURL=1
|
||||||
|
[[ $A2SERVER_NO_EXTERNAL ]] && useExternalURL=
|
||||||
|
|
||||||
|
debianVersion=$(cat /etc/debian_version 2> /dev/null)
|
||||||
isRpi=
|
isRpi=
|
||||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1
|
arch=
|
||||||
|
if [[ -f /usr/bin/raspi-config ]]; then
|
||||||
|
isRpi=1
|
||||||
|
arch='rpi'
|
||||||
|
elif lsb_release -a 2> /dev/null | grep -q 'Distributor ID:.Debian' && [[ $(cut -d . -f 1 <<< $debianVersion) -ge "7" ]]; then
|
||||||
|
uname_m="$(uname -m)"
|
||||||
|
if [[ $uname_m == "i686" ]]; then
|
||||||
|
arch='debian_x86'
|
||||||
|
elif [[ $uname_m == "x86_64" ]]; then
|
||||||
|
arch='debian_x64'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
isDebian_x86=
|
debianName=
|
||||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1 < /etc/debian_version) -ge 7 ) && ( $(uname -m) == "i686" ) ]] && isDebian_x86=1
|
if [[ $debianVersion ]]; then
|
||||||
|
debianMajor=$(cut -d . -f 1 <<< $debianVersion)
|
||||||
|
if [[ $debianMajor == "10" ]]; then
|
||||||
|
debianName="buster"
|
||||||
|
elif [[ $debianMajor == "9" ]]; then
|
||||||
|
debianName="stretch"
|
||||||
|
elif [[ $debianMajor == "8" ]]; then
|
||||||
|
debianName="jessie"
|
||||||
|
elif [[ $debianMajor == "7" ]]; then
|
||||||
|
debianName="wheezy"
|
||||||
|
else
|
||||||
|
debianName="unknown"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
isJessie=
|
# enable SSH (disabled by default in Raspbian from late 2016 onward)
|
||||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "8." ) ]] && isJessie=1
|
if [[ $isRpi && $debianMajor -ge 8 ]] && ! ps aux | grep -q '[s]shd'; then
|
||||||
|
echo "A2SERVER: Enabling ssh access..."
|
||||||
|
sudo systemctl enable ssh &> /dev/null && sudo systemctl start ssh &> /dev/null
|
||||||
|
else
|
||||||
|
echo "A2SERVER: ssh access is already enabled."
|
||||||
|
fi
|
||||||
|
|
||||||
# skip this if already done
|
# skip this if already done
|
||||||
if [[ -f /usr/local/etc/A2SERVER-version ]] && (( $(cat /usr/local/etc/A2SERVER-version) >= 101 )); then
|
if [[ -f /usr/local/etc/A2SERVER-version ]] && (( $(head -c 3 /usr/local/etc/A2SERVER-version) >= 101 )); then
|
||||||
|
|
||||||
echo "A2SERVER: Netatalk is already installed."
|
echo "A2SERVER: Netatalk is already installed."
|
||||||
|
|
||||||
@@ -38,8 +74,11 @@ else
|
|||||||
|
|
||||||
echo "A2SERVER: Installing Netatalk (this will take a while)..."
|
echo "A2SERVER: Installing Netatalk (this will take a while)..."
|
||||||
|
|
||||||
# stop Netatalk if running (during upgrade)
|
# stop Netatalk and samba if running (during upgrade)
|
||||||
[[ $(ps --no-headers -C afpd) ]] && sudo /etc/init.d/netatalk stop
|
if [[ $(ps --no-headers -C afpd) ]]; then
|
||||||
|
sudo /etc/init.d/netatalk stop &> /dev/null
|
||||||
|
sudo /etc/init.d/samba stop &> /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||||
# prepare for installing packages
|
# prepare for installing packages
|
||||||
@@ -47,61 +86,68 @@ else
|
|||||||
touch /tmp/a2server-packageReposUpdated
|
touch /tmp/a2server-packageReposUpdated
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# not being used as of 1.2.9, but it's available if full URL to .deb package is supplied
|
||||||
getOldPackage () {
|
getOldPackage () {
|
||||||
for url in $@; do
|
for url in $@; do
|
||||||
pkgFile=${url##*/}
|
pkgFile=${url##*/}
|
||||||
pkgName=${pkgFile%%_*}
|
pkgName=${pkgFile%%_*}
|
||||||
if ! dpkg -l $pkgName 2> /dev/null | grep -q '^ii'; then
|
if ! dpkg -l $pkgName 2> /dev/null | grep -q '^ii'; then
|
||||||
wget -qO /tmp/${url##*/} "$url"
|
if [[ $useExternalURL ]]; then
|
||||||
sudo dpkg -i /tmp/${url##*/}
|
wget -qO "/tmp/${url##*/}" "$url"
|
||||||
|
fi
|
||||||
|
if [[ $? -ne 0 || ! -f "/tmp/${url##*/}" ]]; then
|
||||||
|
wget -qO "/tmp/${url##*/}" "${binaryURL}external/deb/${url##*/}"
|
||||||
|
fi
|
||||||
|
sudo dpkg -i "/tmp/${url##*/}"
|
||||||
sudo apt-get clean
|
sudo apt-get clean
|
||||||
rm /tmp/${url##*/}
|
rm "/tmp/${url##*/}"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
compileFromSource=1
|
compileFromSource=1
|
||||||
urls=
|
urls=
|
||||||
while [[ $isRpi || $isDebian_x86 ]]; do
|
while [[ $arch ]]; do
|
||||||
# Install runtime libraries needed by Netatalk
|
# Install runtime libraries needed by Netatalk
|
||||||
if [[ $isJessie ]]; then
|
if [[ $(apt-cache search '^libdb5.1$') ]]; then # Wheezy
|
||||||
if [[ $isRpi ]]; then
|
# Dependencies: netatalk 2.2.4
|
||||||
getOldPackage "http://mirrordirector.raspbian.org/raspbian/pool/main/d/db/libdb5.1_5.1.29-5_armhf.deb"
|
|
||||||
elif [[ $isDebian_x86 ]]; then
|
|
||||||
getOldPackage "http://ftp.debian.org/debian/pool/main/d/db/libdb5.1_5.1.29-5_i386.deb"
|
|
||||||
fi
|
|
||||||
elif [[ $(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
|
sudo apt-get -y install libdb5.1
|
||||||
|
elif [[ $(apt-cache search '^libdb5.3$') ]]; then # Jessie or Stretch
|
||||||
|
# Dependencies: netatalk 2.2.4
|
||||||
|
sudo apt-get -y install libdb5.3
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
if [[ $(apt-cache search '^libssl1.0.0$') ]]; then
|
if [[ $(apt-cache search '^libssl1.0.0$') ]]; then # Wheezy or Jessie
|
||||||
|
# Dependencies: netatalk 2.2.4
|
||||||
sudo apt-get -y install libssl1.0.0
|
sudo apt-get -y install libssl1.0.0
|
||||||
elif [[ $(apt-cache search '^libssl0.9.8$') ]]; then
|
elif [[ $(apt-cache search '^libssl1.0.2$') ]]; then # Stretch
|
||||||
sudo apt-get -y install libssl0.9.8
|
# Dependencies: netatalk 2.2.4
|
||||||
|
sudo apt-get -y install libssl1.0.2
|
||||||
|
elif [[ $(apt-cache search '^libssl1.1$') ]]; then # Buster
|
||||||
|
# Dependencies: netatalk 2.2.4
|
||||||
|
echo "deb http://deb.debian.org/debian/ oldstable main" | sudo tee -a /etc/apt/sources.list > /dev/null
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install libssl1.0.2
|
||||||
|
sudo sed -i '$d' /etc/apt/sources.list
|
||||||
|
sudo apt-get -y update
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $isJessie ]]; then
|
if [[ $(apt-cache search '^libgcrypt11$') ]]; then # Wheezy
|
||||||
if [[ $isRpi ]]; then
|
# Dependencies: netatalk 2.2.4
|
||||||
getOldPackage "http://mirrordirector.raspbian.org/raspbian/pool/main/libg/libgcrypt11/libgcrypt11_1.5.0-5+deb7u3_armhf.deb"
|
|
||||||
elif [[ $isDebian_x86 ]]; then
|
|
||||||
getOldPackage "http://ftp.debian.org/debian/pool/main/libg/libgcrypt11/libgcrypt11_1.5.0-5+deb7u3_i386.deb"
|
|
||||||
fi
|
|
||||||
elif [[ $(apt-cache search '^libgcrypt11$') ]]; then
|
|
||||||
sudo apt-get -y install libgcrypt11
|
sudo apt-get -y install libgcrypt11
|
||||||
|
elif [[ $(apt-cache search '^libgcrypt20$') ]]; then # Jessie, Stretch, Buster
|
||||||
|
# Dependencies: netatalk 2.2.4
|
||||||
|
sudo apt-get -y install libgcrypt20
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# install Netatalk
|
# install Netatalk
|
||||||
if [[ $isRpi ]]; then
|
if [[ $arch && ! -f /tmp/a2server-compileAlways ]]; then
|
||||||
{ wget -qO- /tmp/netatalk.tgz "http://appleii.ivanx.com/a2server/files/netatalk224-rpi_wheezy.tgz" | sudo tar Pzx; } 2> /dev/null
|
{ wget -qO- "${binaryURL}precompiled/netatalk226-${arch}_${debianName}.tgz" | sudo tar Pzx; } &> /dev/null
|
||||||
elif [[ $isDebian_x86 ]]; then
|
|
||||||
{ wget -qO- /tmp/netatalk.tgz "http://appleii.ivanx.com/a2server/files/netatalk224-debian7_x86.tgz" | sudo tar Pzx; } 2> /dev/null
|
|
||||||
fi
|
fi
|
||||||
sudo mandb &> /dev/null
|
sudo mandb &> /dev/null
|
||||||
|
|
||||||
@@ -111,36 +157,60 @@ else
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ $compileFromSource ]]; then
|
if [[ $compileFromSource ]]; then
|
||||||
# Install development libraries needed by Netatalk
|
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
sudo apt-get -y install build-essential
|
sudo apt-get -y install build-essential
|
||||||
sudo apt-get -y install libssl-dev
|
|
||||||
if [[ $isJessie ]]; then
|
if [[ $(dpkg -l | grep libssl-dev | tr -s ' ' | cut -d ' ' -f 3 | cut -c 1-3) == "1.1" ]]; then
|
||||||
if [[ $isRpi ]]; then
|
echo "A2SERVER: WARNING: libssl-dev 1.1 is already installed; removing."
|
||||||
getOldPackage "http://mirrordirector.raspbian.org/raspbian/pool/main/d/db/libdb5.1-dev_5.1.29-5_armhf.deb"
|
sudo apt-get -y purge libssl-dev
|
||||||
elif [[ $isDebian_x86 ]]; then
|
sudo apt -y autoremove
|
||||||
getOldPackage "http://ftp.us.debian.org/debian/pool/main/d/db/libdb5.1-dev_5.1.29-5_i386.deb"
|
fi
|
||||||
|
|
||||||
|
if [[ $(apt-cache search '^libssl1.0-dev$') ]]; then # Stretch
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
|
sudo apt-get -y install libssl1.0-dev
|
||||||
|
else # Jessie or Wheezy (libssl-dev 1.0.x) or Buster (absent)
|
||||||
|
if [[ $(apt-cache madison libssl-dev | grep '^libssl' | head -1 | cut -d '|' -f 2 | tr -d ' ' | cut -c 1-3) == "1.1" ]]; then # Buster, so pull from Stretch
|
||||||
|
echo "deb http://deb.debian.org/debian/ oldstable main" | sudo tee -a /etc/apt/sources.list > /dev/null
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install libssl1.0.dev
|
||||||
|
sudo sed -i '$d' /etc/apt/sources.list
|
||||||
|
sudo apt-get -y update
|
||||||
|
else # Jessie or Wheezy
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
|
sudo apt-get -y install libssl-dev
|
||||||
fi
|
fi
|
||||||
elif [[ $(apt-cache search '^libdb4.8-dev$') ]]; then
|
fi
|
||||||
sudo apt-get -y install libdb4.8-dev
|
|
||||||
elif [[ $(apt-cache search '^libdb5.1-dev$') ]]; then
|
if [[ $(apt-cache search '^libdb5.1-dev$') ]]; then # Wheezy
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
sudo apt-get -y install libdb5.1-dev
|
sudo apt-get -y install libdb5.1-dev
|
||||||
|
elif [[ $(apt-cache search '^libdb5.3-dev$') ]]; then # Jessie, Stretch, Buster
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
|
sudo apt-get -y install libdb5.3-dev
|
||||||
else
|
else
|
||||||
echo "A2SERVER: WARNING: unknown version of libdb-dev is being installed"
|
echo "A2SERVER: WARNING: unknown version of libdb-dev is being installed."
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
sudo apt-get -y install libdb-dev
|
sudo apt-get -y install libdb-dev
|
||||||
fi
|
fi
|
||||||
if [[ $isJessie ]]; then
|
|
||||||
sudo apt-get -y install libgpg-error-dev
|
if [[ $(apt-cache search '^libgcrypt11-dev$') ]]; then # Stretch, Jessie or Wheezy
|
||||||
if [[ $isRpi ]]; then
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
getOldPackage "http://mirrordirector.raspbian.org/raspbian/pool/main/libg/libgcrypt11/libgcrypt11-dev_1.5.0-5+deb7u3_armhf.deb"
|
|
||||||
elif [[ $isDebian_x86 ]]; then
|
|
||||||
getOldPackage "http://ftp.debian.org/debian/pool/main/libg/libgcrypt11/libgcrypt11-dev_1.5.0-5+deb7u3_i386.deb"
|
|
||||||
fi
|
|
||||||
elif [[ $(apt-cache search '^libgcrypt11-dev$') ]]; then
|
|
||||||
sudo apt-get -y install libgcrypt11-dev
|
sudo apt-get -y install libgcrypt11-dev
|
||||||
|
elif [[ $(apt-cache search '^libgcrypt20-dev$') ]]; then # Buster
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
|
echo "deb http://deb.debian.org/debian/ oldstable main" | sudo tee -a /etc/apt/sources.list > /dev/null
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install libgcrypt11-dev
|
||||||
|
sudo sed -i '$d' /etc/apt/sources.list
|
||||||
|
sudo apt-get -y update
|
||||||
else
|
else
|
||||||
echo "A2SERVER: WARNING: unknown version of libgcrypt-dev is being installed"
|
echo "A2SERVER: WARNING: unknown version of libgcrypt-dev is being installed."
|
||||||
|
# Dependencies: build-deps for netatalk 2.2.4
|
||||||
sudo apt-get -y install $(apt-cache search '^libgcrypt.*dev$' | sort -r | head -1 | cut -d ' ' -f 1)
|
sudo apt-get -y install $(apt-cache search '^libgcrypt.*dev$' | sort -r | head -1 | cut -d ' ' -f 1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo apt-get clean
|
sudo apt-get clean
|
||||||
|
|
||||||
# get Netatalk
|
# get Netatalk
|
||||||
@@ -148,8 +218,14 @@ else
|
|||||||
mkdir /tmp/netatalk
|
mkdir /tmp/netatalk
|
||||||
cd /tmp/netatalk
|
cd /tmp/netatalk
|
||||||
|
|
||||||
wget -q "http://downloads.sourceforge.net/project/netatalk/netatalk/2.2.4/netatalk-2.2.4.tar.gz"
|
if [[ $useExternalURL ]]; then
|
||||||
tar zxf netatalk-2.2.4.tar.gz
|
wget -qO netatalk-2.2.4.tar.gz "http://downloads.sourceforge.net/project/netatalk/netatalk/2.2.4/netatalk-2.2.4.tar.gz"
|
||||||
|
tar zxf netatalk-2.2.4.tar.gz &> /dev/null
|
||||||
|
fi
|
||||||
|
if [[ ! -d netatalk-2.2.4 ]]; then
|
||||||
|
wget -O netatalk-2.2.4.tar.gz "${binaryURL}external/source/netatalk-2.2.4.tar.gz"
|
||||||
|
tar zxf netatalk-2.2.4.tar.gz &> /dev/null
|
||||||
|
fi
|
||||||
cd netatalk-2.2.4
|
cd netatalk-2.2.4
|
||||||
|
|
||||||
# Patch the source so file dates are preserved during a GS/OS folder copy,
|
# Patch the source so file dates are preserved during a GS/OS folder copy,
|
||||||
@@ -158,10 +234,10 @@ else
|
|||||||
# props to Steven Hirsch for these
|
# 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 ':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
|
sed -i 's/rtmp->rt_iface == iface/rtmp->rt_iface != iface/g' etc/atalkd/main.c
|
||||||
|
|
||||||
# prepare to build Netatalk
|
# prepare to build Netatalk
|
||||||
./configure --enable-debian --enable-ddp --enable-a2boot
|
./configure --enable-debian --enable-ddp --enable-a2boot
|
||||||
|
|
||||||
# uninstall Netatalk if already installed
|
# uninstall Netatalk if already installed
|
||||||
[[ -f /usr/local/sbin/afpd ]] && sudo make uninstall
|
[[ -f /usr/local/sbin/afpd ]] && sudo make uninstall
|
||||||
|
|
||||||
@@ -172,7 +248,41 @@ else
|
|||||||
# to remove the Netatalk source code (optional), type:
|
# to remove the Netatalk source code (optional), type:
|
||||||
cd
|
cd
|
||||||
rm -rf /tmp/netatalk
|
rm -rf /tmp/netatalk
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Install MacIPgw
|
||||||
|
if ! hash macipgw &> /dev/null; then
|
||||||
|
echo "A2SERVER: Installing TCP over AppleTalk (MacIP)..."
|
||||||
|
|
||||||
|
if [[ $arch && ! -f /tmp/a2server-compileAlways ]]; then
|
||||||
|
{ wget -qO- "${binaryURL}precompiled/macipgw-${arch}.tgz" | sudo tar Pzx; } 2> /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! hash macipgw &> /dev/null; then
|
||||||
|
wd="$PWD"
|
||||||
|
sudo apt-get -y install build-essential
|
||||||
|
rm -rf /tmp/macipgw &> /dev/null
|
||||||
|
mkdir /tmp/macipgw
|
||||||
|
cd /tmp/macipgw
|
||||||
|
if [[ $useExternalURL ]]; then
|
||||||
|
wget -qO macipgw.zip "https://github.com/zero2sixd/macipgw/archive/2a5f6a7521a627e46b18468d44f4306fb0a7b7ab.zip"
|
||||||
|
unzip macipgw.zip 2> /dev/null
|
||||||
|
rm macipgw.zip &> /dev/null
|
||||||
|
fi
|
||||||
|
if [ ! -d macipgw* ]; then
|
||||||
|
wget -qO macipgw.zip "${binaryURL}external/source/macipgw.zip"
|
||||||
|
unzip macipgw.zip 2> /dev/null
|
||||||
|
rm macipgw.zip &> /dev/null
|
||||||
|
fi
|
||||||
|
cd macipgw*
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
cd "$wd"
|
||||||
|
rm -rf /tmp/macipgw
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "A2SERVER: TCP over AppleTalk (MacIP) has already been installed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Configuring Netatalk
|
# --- Configuring Netatalk
|
||||||
@@ -182,7 +292,7 @@ echo "A2SERVER: Configuring Netatalk..."
|
|||||||
# if missing Netatalk startup file, download a fresh one
|
# if missing Netatalk startup file, download a fresh one
|
||||||
if [ ! -f /etc/init.d/netatalk ]; then
|
if [ ! -f /etc/init.d/netatalk ]; then
|
||||||
echo "A2SERVER: Downloading new Netatalk startup script..."
|
echo "A2SERVER: Downloading new Netatalk startup script..."
|
||||||
sudo wget -qO /etc/init.d/netatalk http://appleii.ivanx.com/a2server/files/netatalk-init.d-clean.txt
|
sudo wget -qO /etc/init.d/netatalk ${binaryURL}netatalk-init.d-clean.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# make the Netatalk startup script work correctly
|
# make the Netatalk startup script work correctly
|
||||||
@@ -192,7 +302,16 @@ sudo sed -i 's/bin\/sh/bin\/bash/' /etc/init.d/netatalk
|
|||||||
sudo sed -i 's/#ATALKD_RUN=no/ATALKD_RUN=yes/' /etc/default/netatalk
|
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
|
sudo sed -i 's/#ATALK_BGROUND=no/ATALK_BGROUND=yes/' /etc/default/netatalk
|
||||||
if [[ ! $(grep 'kernelRelease' /etc/init.d/netatalk) ]]; then
|
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
|
sudo sed -i 's@\(\tif \[ x\"$ATALKD_RUN\)@\n\t# check for valid AppleTalk kernel module\n\t[[ $ATALKD_RUN == "yes" ]] \&\& { kernelRelease=$(uname -r); kernelMajor=$(cut -d "." -f 1 <<< $kernelRelease); kernelMinor=$(cut -d "." -f 2 <<< $kernelRelease | sed '"'"'s/\\(^[0-9]*\\)[^0-9].*$/\\1/'"'"'); kernelPatch=$(cut -d "." -f 3- <<< $kernelRelease | sed '"'"'s/\\(^[0-9]*\\)[^0-9].*$/\\1/'"'"'); [[ ( $kernelMajor -eq 3 \&\& $kernelMinor -ge 12 \&\& $kernelMinor -le 15 ) \&\& ( ! ( -f /usr/bin/raspi-config \&\& $kernelMinor -eq 12 \&\& $kernelPatch -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
|
||||||
|
sudo sed -i 's/Starting Netatalk services (this will take a while): /Starting Netatalk services"\n\t\t\t[[ $ATALKD_RUN == "yes" ]] \&\& echo -n " (this will take 45 seconds)"\n\t\t\techo -n ":/' /etc/init.d/netatalk
|
||||||
|
sudo sed -i 's/Starting Netatalk services in the background./Netatalk services will be available in 45 seconds./' /etc/init.d/netatalk
|
||||||
|
sudo sed -i 's/-n "Restarting Netatalk Daemons (this will take a while)"/"Restarting Netatalk Daemons."/' /etc/init.d/netatalk
|
||||||
|
|
||||||
|
# enable MacIPgw support after launching atalkd
|
||||||
|
if ! grep -q -i 'macipgw' /etc/init.d/netatalk; then
|
||||||
|
sudo sed -i ':a;N;$!ba;s@\(echo -n " atalkd"\)\(.*# prepare\)@\1\n\n\t\t# start MacIPgw (TCP over AppleTalk) service\n\t\tps aux | grep -q "[m]acipgw" \&\& sudo killall macipgw 2> /dev/null || :\n\t\tatalkd_interface=$(grep "^[^ #]" /etc/netatalk/atalkd.conf | tail -1 | cut -d " " -f 1)\n\t\tsysctl -w net.ipv4.ip_forward=1 > /dev/null\n\t\tmacipgw -n 8.8.8.8 192.168.151.0 255.255.255.0\n\t\t/sbin/iptables -t nat -A POSTROUTING -o ${atalkd_interface} -j MASQUERADE\n\t\t/sbin/iptables -A FORWARD -i ${atalkd_interface} -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT\n\t\t/sbin/iptables -A FORWARD -i tun1 -o ${atalkd_interface} -j ACCEPT\n\n\t\techo -n " macipgw"\n\2@' /etc/init.d/netatalk
|
||||||
|
sudo sed -i 's@\(start-stop-daemon --stop --quiet --oknodo --exec /usr/local/sbin/atalkd.*$\)@\1\n echo -n " macipgw"\n sudo killall macipgw 2> /dev/null@' /etc/init.d/netatalk
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# enable network boot support in netatalk
|
# enable network boot support in netatalk
|
||||||
@@ -231,12 +350,12 @@ sudo sed -i 's/^~/#share1\n\n#share2/' \
|
|||||||
sudo sed -i 's/^:DEFAULT/#:DEFAULT/' \
|
sudo sed -i 's/^:DEFAULT/#:DEFAULT/' \
|
||||||
/usr/local/etc/netatalk/AppleVolumes.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
|
# if [[ ! $(grep ^eth0 /usr/local/etc/netatalk/atalkd.conf) && ! $(grep ^wlan0 /usr/local/etc/netatalk/atalkd.conf) ]]; then
|
||||||
|
if [[ $(tac /usr/local/etc/netatalk/atalkd.conf | sed '/./,$!d' | head -1 | cut -c 1) == "#" ]]; then
|
||||||
# enable netatalk on the default network interface
|
# enable netatalk on the default network interface
|
||||||
# needs -router and -zone to prevent GS/OS AppleShare CDEV crash when used
|
# needs -router and -zone to prevent GS/OS AppleShare CDEV crash when used
|
||||||
# with Dayna or Asante bridges
|
# with Dayna or Asante bridges
|
||||||
echo -e 'eth0 -router -phase 2 -net 1 -zone "A2SERVER"' \
|
echo -e 'eth0 -router -phase 2 -net 1 -zone "A2SERVER"' | sudo tee -a /usr/local/etc/netatalk/atalkd.conf > /dev/null
|
||||||
| sudo tee -a /usr/local/etc/netatalk/atalkd.conf > /dev/null
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Raspberry Pi
|
# Raspberry Pi
|
||||||
@@ -255,8 +374,8 @@ fi
|
|||||||
# /usr/local/etc/netatalk/AppleVolumes.default
|
# /usr/local/etc/netatalk/AppleVolumes.default
|
||||||
|
|
||||||
# 1.3.0: if GSFILES is being shared, make directory if not there
|
# 1.3.0: if GSFILES is being shared, make directory if not there
|
||||||
if grep -q '^/media/A2SHARED/GSFILES' /usr/local/etc/netatalk/AppleVolumes.default; then
|
if grep -q '^/srv/A2SERVER/GSFILES' /usr/local/etc/netatalk/AppleVolumes.default; then
|
||||||
[[ -d /media/A2SHARED/GSFILES ]] || mkdir -p /media/A2SHARED/GSFILES;
|
[[ -d /srv/A2SERVER/GSFILES ]] || mkdir -p /srv/A2SERVER/GSFILES;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# prior to 1.3.0:
|
# prior to 1.3.0:
|
||||||
@@ -268,19 +387,22 @@ fi
|
|||||||
# see if shared already uses ciopfs (case-insensitive file system), and convert if not
|
# see if shared already uses ciopfs (case-insensitive file system), and convert if not
|
||||||
# restore known GS/OS file paths to mixed case
|
# restore known GS/OS file paths to mixed case
|
||||||
# set up ciopfs (case insensitive file system) for share
|
# set up ciopfs (case insensitive file system) for share
|
||||||
if [[ -d /media/A2SHARED/A2FILES && ! -d /media/A2SHARED/.a2files ]]; then
|
if [[ -d /srv/A2SERVER/A2FILES && ! -d /srv/A2SERVER/.a2files ]]; then
|
||||||
echo "A2SERVER: Converting A2FILES to support mixed case..."
|
echo "A2SERVER: Converting A2FILES to support mixed case..."
|
||||||
sudo /etc/init.d/netatalk stop &> /dev/null
|
sudo /etc/init.d/netatalk stop &> /dev/null
|
||||||
if ! command -v getfattr &> /dev/null; then
|
sudo /etc/init.d/samba stop &> /dev/null
|
||||||
|
if ! hash getfattr &> /dev/null; then
|
||||||
|
# Dependency: for ciopfs conversion (setfattr)
|
||||||
sudo apt-get -y install attr &> /dev/null
|
sudo apt-get -y install attr &> /dev/null
|
||||||
sudo apt-get clean
|
sudo apt-get clean
|
||||||
fi
|
fi
|
||||||
rm /media/A2SHARED/A2FILES/.APPLEDESKTOP 2> /dev/null
|
rm /srv/A2SERVER/A2FILES/.APPLEDESKTOP 2> /dev/null
|
||||||
mkdir -p /tmp/netboot
|
mkdir -p /tmp/netboot
|
||||||
a2FilesList="$(wget -qO- http://ivanx.com/a2server/files/A2FILES-list.txt)"
|
wget -qO /tmp/A2FILES-list.txt ${binaryURL}A2FILES-list.txt
|
||||||
find /media/A2SHARED/A2FILES -name '*' | tail -n +2 | tac | while read -d $'\n' thisFile; do
|
find /srv/A2SERVER/A2FILES -name '*' | tail -n +2 | tac > /tmp/filelist.txt
|
||||||
|
while read thisFile; do
|
||||||
mixedCase="${thisFile##*/}"
|
mixedCase="${thisFile##*/}"
|
||||||
gsosPath=$(grep -i "^${thisFile}$" <<< "$a2FilesList")
|
gsosPath=$(grep -i -m 1 "^${thisFile}$" /tmp/A2FILES-list.txt)
|
||||||
[[ $gsosPath ]] && mixedCase="${gsosPath##*/}"
|
[[ $gsosPath ]] && mixedCase="${gsosPath##*/}"
|
||||||
sudo setfattr -n "user.filename" -v "$mixedCase" "$thisFile"
|
sudo setfattr -n "user.filename" -v "$mixedCase" "$thisFile"
|
||||||
if [[ ${thisFile##*/} != $mixedCase ]]; then
|
if [[ ${thisFile##*/} != $mixedCase ]]; then
|
||||||
@@ -288,24 +410,26 @@ if [[ -d /media/A2SHARED/A2FILES && ! -d /media/A2SHARED/.a2files ]]; then
|
|||||||
else
|
else
|
||||||
echo -e " processing $thisFile\n"
|
echo -e " processing $thisFile\n"
|
||||||
fi
|
fi
|
||||||
sudo mv "$thisFile" "${thisFile%/*}"/"$(tr [:upper:] [:lower:] <<< $mixedCase)" 2> /dev/null
|
sudo mv "$thisFile" "${thisFile%/*}/${mixedCase,,}" 2> /dev/null
|
||||||
done
|
done < /tmp/filelist.txt
|
||||||
mv /media/A2SHARED/A2FILES /media/A2SHARED/.a2files
|
mv /srv/A2SERVER/A2FILES /srv/A2SERVER/.a2files
|
||||||
mkdir /media/A2SHARED/A2FILES
|
mkdir /srv/A2SERVER/A2FILES
|
||||||
sudo sed -i 's/casefold:toupper //' /usr/local/etc/netatalk/AppleVolumes.default
|
sudo sed -i 's/casefold:toupper //' /usr/local/etc/netatalk/AppleVolumes.default 2> /dev/null
|
||||||
sudo sed -i 's/^VOLCASEFOLD:.*/VOLCASEFOLD:/' /media/A2SHARED/.a2files/.appledesktop/.volinfo
|
sudo sed -i 's/^VOLCASEFOLD:.*/VOLCASEFOLD:/' /srv/A2SERVER/.a2files/.appledesktop/.volinfo 2> /dev/null
|
||||||
|
sudo sed -i 's|/media/A2SHARED/A2FILES|/srv/A2SERVER/A2FILES|' /srv/A2SERVER/.a2files/.appledesktop/.volinfo 2> /dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 1.3.0: remove GSFILES if empty
|
# 1.3.0: remove GSFILES if empty
|
||||||
if grep -q '^/media/A2SHARED/GSFILES' /usr/local/etc/netatalk/AppleVolumes.default; then
|
if grep -q '^/srv/A2SERVER/GSFILES' /usr/local/etc/netatalk/AppleVolumes.default; then
|
||||||
gsFilesContents=
|
gsFilesContents=
|
||||||
if [[ -d /media/A2SHARED/GSFILES ]]; then
|
if [[ -d /srv/A2SERVER/GSFILES ]]; then
|
||||||
gsFilesContents="$(find /media/A2SHARED/GSFILES -not -path '*/\.*' | grep -v '^/media/A2SHARED/GSFILES$' | grep -v '^/media/A2SHARED/GSFILES/Network Trash Folder$' | grep -v '^/media/A2SHARED/GSFILES/Temporary Items$')"
|
gsFilesContents="$(find /srv/A2SERVER/GSFILES -not -path '*/\.*' | grep -v '^/srv/A2SERVER/GSFILES$' | grep -v '^/srv/A2SERVER/GSFILES/Network Trash Folder$' | grep -v '^/srv/A2SERVER/GSFILES/Temporary Items$')"
|
||||||
if [[ ! $gsFilesContents ]]; then
|
if [[ ! $gsFilesContents ]]; then
|
||||||
echo "A2SERVER: Removing empty GSFILES shared volume..."
|
echo "A2SERVER: Removing empty GSFILES shared volume..."
|
||||||
sudo /etc/init.d/netatalk stop &> /dev/null
|
sudo /etc/init.d/netatalk stop &> /dev/null
|
||||||
sudo sed -i 's|^/media/A2SHARED/GSFILES.*$|#share1|' /usr/local/etc/netatalk/AppleVolumes.default
|
sudo /etc/init.d/samba stop &> /dev/null
|
||||||
sudo rm -r /media/A2SHARED/GSFILES
|
sudo sed -i 's|^/srv/A2SERVER/GSFILES.*$|#share1|' /usr/local/etc/netatalk/AppleVolumes.default
|
||||||
|
sudo rm -r /srv/A2SERVER/GSFILES
|
||||||
else
|
else
|
||||||
echo "A2SERVER: GSFILES shared volume has files, leaving as is."
|
echo "A2SERVER: GSFILES shared volume has files, leaving as is."
|
||||||
fi
|
fi
|
||||||
@@ -314,20 +438,20 @@ fi
|
|||||||
|
|
||||||
# set up A2FILES case-insensitive share (for ProDOS 8 files, and GS/OS system)
|
# set up A2FILES case-insensitive share (for ProDOS 8 files, and GS/OS system)
|
||||||
sudo sed -i \
|
sudo sed -i \
|
||||||
's/^#share2/\/media\/A2SHARED\/A2FILES\ A2FILES options:prodos\ ea:ad/' \
|
's/^#share2/\/srv\/A2SERVER\/A2FILES\ A2FILES options:prodos\ ea:ad/' \
|
||||||
/usr/local/etc/netatalk/AppleVolumes.default
|
/usr/local/etc/netatalk/AppleVolumes.default
|
||||||
[[ -d /media/A2SHARED/A2FILES ]] || mkdir -p /media/A2SHARED/A2FILES
|
[[ -d /srv/A2SERVER/A2FILES ]] || mkdir -p /srv/A2SERVER/A2FILES
|
||||||
[[ -d /media/A2SHARED/.a2files ]] || mkdir -p /media/A2SHARED/.a2files
|
[[ -d /srv/A2SERVER/.a2files ]] || mkdir -p /srv/A2SERVER/.a2files
|
||||||
|
|
||||||
# set up ciopfs
|
# set up ciopfs
|
||||||
if ! command -v ciopfs > /dev/null; then
|
if ! hash ciopfs &> /dev/null; then
|
||||||
echo "A2SERVER: Installing ciopfs (case insensitive file system)..."
|
echo "A2SERVER: Installing ciopfs (case insensitive file system)..."
|
||||||
cd /tmp
|
cd /tmp
|
||||||
|
|
||||||
|
# Dependency: For ciopfs
|
||||||
sudo apt-get -y install fuse libglib2.0-0 libattr1 libfuse2
|
sudo apt-get -y install fuse libglib2.0-0 libattr1 libfuse2
|
||||||
if [[ $isRpi ]]; then
|
if [[ $arch && ! -f /tmp/a2server-compileAlways ]]; then
|
||||||
wget -qO- "http://appleii.ivanx.com/a2server/files/ciopfs-rpi.tgz" | sudo tar Pzx
|
{ wget -qO- "${binaryURL}precompiled/ciopfs-${arch}.tgz" | sudo tar Pzx; } &> /dev/null
|
||||||
elif [[ $isDebian_x86 ]]; then
|
|
||||||
wget -qO- "http://appleii.ivanx.com/a2server/files/ciopfs-debian7_x86.tgz" | sudo tar Pzx
|
|
||||||
fi
|
fi
|
||||||
if [[ -f /etc/fuse.conf ]] && sudo grep -q user_allow_other /etc/fuse.conf; then
|
if [[ -f /etc/fuse.conf ]] && sudo grep -q user_allow_other /etc/fuse.conf; then
|
||||||
sudo sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
|
sudo sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
|
||||||
@@ -335,21 +459,34 @@ if ! command -v ciopfs > /dev/null; then
|
|||||||
echo "user_allow_other" | sudo tee /etc/fuse.conf > /dev/null
|
echo "user_allow_other" | sudo tee /etc/fuse.conf > /dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! command -v ciopfs > /dev/null; then
|
if ! hash ciopfs &> /dev/null; then
|
||||||
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||||
# prepare for installing packages
|
# prepare for installing packages
|
||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
touch /tmp/a2server-packageReposUpdated
|
touch /tmp/a2server-packageReposUpdated
|
||||||
fi
|
fi
|
||||||
sudo apt-get -y install build-essential
|
|
||||||
sudo apt-get -y install libfuse-dev libglib2.0-dev libattr1-dev
|
# Dependency: build-dep for ciopfs
|
||||||
|
sudo apt-get -y install build-essential libfuse-dev libglib2.0-dev libattr1-dev
|
||||||
sudo apt-get -y clean
|
sudo apt-get -y clean
|
||||||
|
|
||||||
cd /tmp
|
cd /tmp
|
||||||
rm -rf /tmp/ciopfs &> /dev/null
|
rm -rf /tmp/ciopfs &> /dev/null
|
||||||
mkdir /tmp/ciopfs
|
mkdir /tmp/ciopfs
|
||||||
cd /tmp/ciopfs
|
cd /tmp/ciopfs
|
||||||
wget -q -O ciopfs-0.4.tar.gz http://www.brain-dump.org/projects/ciopfs/ciopfs-0.4.tar.gz
|
if [[ $useExternalURL ]]; then
|
||||||
tar zxf ciopfs-0.4.tar.gz
|
wget -q -O ciopfs-0.4.tar.gz http://www.brain-dump.org/projects/ciopfs/ciopfs-0.4.tar.gz
|
||||||
|
if (( $? != 0 )); then
|
||||||
|
wget -q -O ciopfs-0.4.tar.gz http://web.archive.org/web/20160911102924/http://www.brain-dump.org/projects/ciopfs/ciopfs-0.4.tar.gz
|
||||||
|
fi
|
||||||
|
tar zxf ciopfs-0.4.tar.gz &> /dev/null
|
||||||
|
rm ciopfs-0.4.tar.gz &> /dev/null
|
||||||
|
fi
|
||||||
|
if [ ! -f ciopfs*/ciopfs.c ]; then # single brackets required for glob
|
||||||
|
wget -q -O ciopfs-0.4.tar.gz ${binaryURL}external/source/ciopfs-0.4.tar.gz
|
||||||
|
tar zxf ciopfs-0.4.tar.gz &> /dev/null
|
||||||
|
rm ciopfs-0.4.tar.gz &> ?dev/null
|
||||||
|
fi
|
||||||
cd ciopfs*
|
cd ciopfs*
|
||||||
make
|
make
|
||||||
sudo mv ciopfs /usr/local/bin
|
sudo mv ciopfs /usr/local/bin
|
||||||
@@ -357,34 +494,36 @@ if ! command -v ciopfs > /dev/null; then
|
|||||||
rm -rf /tmp/ciopfs
|
rm -rf /tmp/ciopfs
|
||||||
fi
|
fi
|
||||||
if ! grep -q '^ciopfs' /etc/fstab; then
|
if ! grep -q '^ciopfs' /etc/fstab; then
|
||||||
echo "ciopfs#/media/A2SHARED/.a2files /media/A2SHARED/A2FILES fuse allow_other 0 0" | sudo tee -a /etc/fstab > /dev/null
|
echo "ciopfs#/srv/A2SERVER/.a2files /srv/A2SERVER/A2FILES fuse allow_other 0 0" | sudo tee -a /etc/fstab > /dev/null
|
||||||
fi
|
fi
|
||||||
if ! mount | grep '^ciopfs.*A2FILES'; then
|
if ! mount | grep '^ciopfs.*A2FILES'; then
|
||||||
sudo ciopfs /media/A2SHARED/.a2files /media/A2SHARED/A2FILES -o allow_other
|
sudo ciopfs /srv/A2SERVER/.a2files /srv/A2SERVER/A2FILES -o allow_other
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "A2SERVER: ciopfs (case insensitive file system) has already been installed."
|
echo "A2SERVER: ciopfs (case insensitive file system) has already been installed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -d /media/A2SHARED/A2FILES/.AppleDesktop ]]; then
|
if [[ ! -d /srv/A2SERVER/A2FILES/.AppleDesktop ]]; then
|
||||||
cd /media/A2SHARED/A2FILES
|
cd /srv/A2SERVER/A2FILES
|
||||||
mkdir .AppleDesktop
|
mkdir .AppleDesktop
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# set up ADTDISKS share (ADTPro disk image folder, if A2CLOUD is installed)
|
# 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)
|
# 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 /usr/local/adtpro/disks ]]; then # A2CLOUD/ADTPro installed
|
||||||
if [[ ! -d /media/A2SHARED/ADTDISKS ]]; then
|
if [[ ! -d /srv/A2SERVER/ADTDISKS ]]; then
|
||||||
ln -s /usr/local/adtpro/disks /media/A2SHARED/ADTDISKS
|
ln -s /usr/local/adtpro/disks /srv/A2SERVER/ADTDISKS
|
||||||
fi
|
fi
|
||||||
if [[ ! $(grep ADTDISKS /usr/local/etc/netatalk/AppleVolumes.default) ]]; then
|
if [[ ! $(grep ADTDISKS /usr/local/etc/netatalk/AppleVolumes.default) ]]; then
|
||||||
sudo sed -i 's@^# End of File@/media/A2SHARED/ADTDISKS ADTDISKS ea:ad\n\n# End of File@' /usr/local/etc/netatalk/AppleVolumes.default
|
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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# to make Netatalk start up when the server boots:
|
# to make Netatalk start up when the server boots:
|
||||||
sudo update-rc.d netatalk defaults &> /dev/null
|
sudo update-rc.d netatalk defaults &> /dev/null
|
||||||
|
|
||||||
|
# prepare shared volumes for use
|
||||||
|
afpsync -v < /dev/null
|
||||||
|
|
||||||
# --- Setting up users
|
# --- Setting up users
|
||||||
|
|
||||||
@@ -398,17 +537,14 @@ if [[ -f /usr/local/etc/netatalk/afppasswd ]]; then
|
|||||||
else
|
else
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "A2SERVER: Setting up AFP password 'apple2' for Apple II and Mac clients."
|
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 "A2SERVER: Enter 'apple2' or another password of up to eight characters."
|
||||||
echo
|
echo
|
||||||
# set registered user login using RandNum authentication
|
# set registered user login using RandNum authentication
|
||||||
sudo afppasswd -c
|
sudo afppasswd -c
|
||||||
sudo sed -i "s/^\(${USER}\).*$/\1:6170706C65320000:****************:********/" /usr/local/etc/netatalk/afppasswd
|
sudo sed -i "s/^\(${USER}\).*$/\1: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 -c only needs to ever be done once. You can repeat
|
||||||
# the afppasswd -a to make Netatalk logins for other Linux users.)
|
# the afppasswd -a to make Netatalk randnum logins for other Linux users.)
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -416,24 +552,25 @@ fi
|
|||||||
|
|
||||||
# get Kernel release (e.g. 3.6.11+) and version (e.g. #557)
|
# get Kernel release (e.g. 3.6.11+) and version (e.g. #557)
|
||||||
kernelRelease=$(uname -r)
|
kernelRelease=$(uname -r)
|
||||||
kernelMajorRelease=$(cut -d '.' -f 1 <<< $kernelRelease)
|
kernelMajor=$(cut -d '.' -f 1 <<< $kernelRelease)
|
||||||
kernelMinorRelease=$(cut -d '.' -f 2 <<< $kernelRelease | sed 's/\(^[0-9]*\)[^0-9].*$/\1/')
|
kernelMinor=$(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/')
|
kernelPatch=$(cut -d '.' -f 3- <<< $kernelRelease | sed 's/\(^[0-9]*\)[^0-9].*$/\1/')
|
||||||
|
kernelMajorMinor=$(cut -d '.' -f 1-2 <<< $kernelRelease)
|
||||||
|
|
||||||
# if on kernel 3.12 through 3.15, check if we need to delete AppleTalk module to prevent kernel panics
|
# 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 [[ $kernelMajor -eq 3 && $kernelMinor -ge 12 && $kernelMinor -le 15 ]]; then
|
||||||
# if not RPi, or RPi without ivanx-fixed AppleTalk module, delete the module
|
# if not RPi, or RPi without ivanx-fixed AppleTalk module, delete the module
|
||||||
if [[ ! ( $isRpi && $kernelMinorRelease -eq 12 && $kernelPatchRelease -ge 25 ) ]]; then
|
if [[ ! ( $isRpi && $kernelMinor -eq 12 && $kernelPatch -ge 25 ) ]]; then
|
||||||
if [[ -f /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko ]]; 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
|
if [[ $(sha1sum /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko | cut -f 1 -d ' ') != "ecb239fc084c36de93f6926e7749b80f6024f269" ]]; then
|
||||||
# stop Netatalk
|
# stop Netatalk
|
||||||
sudo /etc/init.d/netatalk stop &> /dev/null
|
sudo /etc/init.d/netatalk stop &> /dev/null
|
||||||
echo "A2SERVER: Deleting defective AppleTalk kernel module."
|
echo "A2SERVER: Deleting defective AppleTalk kernel module..."
|
||||||
sudo rmmod appletalk 2> /dev/null
|
sudo rmmod appletalk 2> /dev/null
|
||||||
sudo rm -r /lib/modules/$kernelRelease/kernel/net/appletalk
|
sudo rm -r /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||||
# disable single-user mode on Pi (other Linux can use Recovery boot)
|
# disable single-user mode on Pi (other Linux can use Recovery boot)
|
||||||
if [[ $isRpi && $(grep ' single' /boot/cmdline.txt 2> /dev/null) ]]; then
|
if [[ $isRpi && $(grep ' single' /boot/cmdline.txt 2> /dev/null) ]]; then
|
||||||
echo "A2SERVER: Disabling single-user mode for next boot."
|
echo "A2SERVER: Disabling single-user mode for next boot..."
|
||||||
sudo sed -i 's/ single//' /boot/cmdline.txt
|
sudo sed -i 's/ single//' /boot/cmdline.txt
|
||||||
touch /tmp/singleUser # so note to restart can display following install
|
touch /tmp/singleUser # so note to restart can display following install
|
||||||
fi
|
fi
|
||||||
@@ -442,6 +579,102 @@ if [[ $kernelMajorRelease -eq 3 && $kernelMinorRelease -ge 12 && $kernelMinorRel
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# if IPDDP module exists (e.g. Debian, but not Raspbian),
|
||||||
|
# AppleTalk kernel module has been compiled to support it and can't work with MacIP
|
||||||
|
if [[ -f "/lib/modules/$kernelRelease/kernel/drivers/net/appletalk/ipddp.ko" ]]; then
|
||||||
|
sudo /etc/init.d/netatalk stop &> /dev/null
|
||||||
|
sudo rmmod ipddp 2> /dev/null
|
||||||
|
sudo rmmod appletalk 2> /dev/null
|
||||||
|
echo "A2SERVER: Replacing AppleTalk kernel module (IPDDP disabled) for MacIP use..."
|
||||||
|
|
||||||
|
sudo mv /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko /tmp 2> /dev/null
|
||||||
|
|
||||||
|
if [[ ! $compileFromSource && ${arch%_*} == "debian" ]]; then
|
||||||
|
echo "A2SERVER: Fetching AppleTalk kernel module for Debian..."
|
||||||
|
wget -qO /tmp/appletalk.tgz ${binaryURL}precompiled/appletalk-$kernelRelease-${arch}.tgz
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
# if we found a prebuilt one on a2server site, install it and load it
|
||||||
|
sudo tar Pxf /tmp/appletalk.tgz &> /dev/null
|
||||||
|
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 &> /dev/null
|
||||||
|
else
|
||||||
|
echo "A2SERVER: failed to load AppleTalk kernel module"
|
||||||
|
# if we didn't load it successfully, remove it
|
||||||
|
sudo rm /lib/modules/$kernelRelease/kernel/net/appletalk/appletalk.ko 2> /dev/null
|
||||||
|
fi
|
||||||
|
else # download failed, so premade kernel not found, remove empty file
|
||||||
|
rm /tmp/appletalk.tgz 2>/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! lsmod | grep -q appletalk; then
|
||||||
|
# we don't have a prebuilt AppleTalk module, try to build from source
|
||||||
|
if [[ ! -f /tmp/a2server-packageReposUpdated ]]; then
|
||||||
|
# prepare for installing packages
|
||||||
|
sudo apt-get -y update
|
||||||
|
touch /tmp/a2server-packageReposUpdated
|
||||||
|
fi
|
||||||
|
|
||||||
|
# kernel module compile adapted from from: http://askubuntu.com/a/338403/288003
|
||||||
|
for i in 1; do
|
||||||
|
echo "A2SERVER: Building AppleTalk kernel module..."
|
||||||
|
[[ -f /boot/config-$kernelRelease ]] || break
|
||||||
|
sudo apt-get -y install linux-headers-$kernelRelease linux-source-$kernelMajorMinor || break
|
||||||
|
sudo apt-get -y install build-essential
|
||||||
|
sudo apt-get -y install libelf-dev # required as of kernel 4.14.12, apparently
|
||||||
|
cd /usr/src
|
||||||
|
kernelSrc=$(find linux-source-${kernelMajorMinor}*)
|
||||||
|
if [[ ${kernelSrc##*.} == "xz" ]]; then
|
||||||
|
{ xzcat $kernelSrc | sudo tar x; } &> /dev/null
|
||||||
|
elif [[ ${kernelSrc##*.} == "bz2" ]]; then
|
||||||
|
sudo tar jxf $kernelSrc &> /dev/null
|
||||||
|
elif [[ ${kernelSrc##*.} == "gz" || ${kernelSrc##*.} == "tgz" ]]; then
|
||||||
|
sudo tar zxf $kernelSrc &> /dev/null
|
||||||
|
fi
|
||||||
|
cd linux-source-$kernelMajorMinor
|
||||||
|
sudo make mrproper
|
||||||
|
sudo cp ../linux-headers-$kernelRelease/Module.symvers .
|
||||||
|
yes '' | sudo make oldconfig
|
||||||
|
sudo sed -i 's:^.*IPDDP.*$:# CONFIG_IPDDP is not set:gI' .config # disable IPDDP in kernel config
|
||||||
|
sudo sed -i '$!N; /^\(# CONFIG_IPDDP is not set\)\n\1$/!P; D' .config # delete repeated entries
|
||||||
|
sudo make prepare
|
||||||
|
sudo make modules_prepare
|
||||||
|
sudo make SUBDIRS=scripts/mod
|
||||||
|
sudo make SUBDIRS=net/appletalk modules
|
||||||
|
sudo cp net/appletalk/appletalk.ko /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||||
|
sudo depmod
|
||||||
|
sudo modprobe appletalk
|
||||||
|
sudo rm -r /lib/modules/$kernelRelease/kernel/drivers/net/appletalk/ipddp.ko
|
||||||
|
sudo rmdir /lib/modules/$kernelRelease/kernel/drivers/net/appletalk 2> /dev/null
|
||||||
|
|
||||||
|
# clean up
|
||||||
|
cd
|
||||||
|
sudo rm /usr/src/$kernelSrc
|
||||||
|
sudo rm -r /usr/src/linux-source-$kernelMajorMinor
|
||||||
|
sudo apt-get -y purge linux-source-$kernelMajorMinor
|
||||||
|
sudo apt -y autoremove
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $(lsmod | grep appletalk) ]]; then
|
||||||
|
# if it loaded, make permanent and restart netatalk
|
||||||
|
sudo rm /lib/modules/$kernelRelease/kernel/drivers/net/appletalk/ipddp.ko 2> /dev/null
|
||||||
|
sudo sed -i 's:^.*IPDDP.*$:# CONFIG_IPDDP is not set:gI' /boot/config-$kernelRelease
|
||||||
|
sudo sed -i '$!N; /^\(# CONFIG_IPDDP is not set\)\n\1$/!P; D' /boot/config-$kernelRelease
|
||||||
|
sudo sed -i "s/ATALKD_RUN=no/ATALKD_RUN=yes/" /etc/default/netatalk; sudo /etc/init.d/netatalk restart &> /dev/null
|
||||||
|
else
|
||||||
|
# if we didn't load it successfully, put back the one that was there
|
||||||
|
echo "A2SERVER: Unable to replace AppleTalk module, replacing original."
|
||||||
|
sudo mv /tmp/appletalk.ko /lib/modules/$kernelRelease/kernel/net/appletalk 2> /dev/null
|
||||||
|
sudo depmod
|
||||||
|
touch /tmp/noMacIP # to notify at end of install
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# --- Start Netatalk (if not running)
|
# --- Start Netatalk (if not running)
|
||||||
|
|
||||||
bground=
|
bground=
|
||||||
@@ -474,11 +707,11 @@ if [[ ( ! $(ps aux | grep [a]talkd) ) && ( $isRpi ) ]]; then
|
|||||||
|
|
||||||
# if no AppleTalk module, try to download it from a2server site
|
# 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
|
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..."
|
echo "A2SERVER: Installing AppleTalk kernel module for Raspbian..."
|
||||||
wget -qO /tmp/appletalk.ko.gz http://appleii.ivanx.com/a2server/files/appletalk-$kernelRelease.ko.gz
|
wget -qO /tmp/appletalk.ko.gz ${binaryURL}appletalk-$kernelRelease-rpi.ko.gz
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
# if we found a prebuilt one on a2server site, install it and load it
|
# if we found a prebuilt one on a2server site, install it and load it
|
||||||
gunzip -f /tmp/appletalk.ko.gz
|
gunzip -f /tmp/appletalk.ko.gz &> /dev/null
|
||||||
sudo mkdir -p /lib/modules/$kernelRelease/kernel/net/appletalk
|
sudo mkdir -p /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||||
sudo mv /tmp/appletalk.ko /lib/modules/$kernelRelease/kernel/net/appletalk
|
sudo mv /tmp/appletalk.ko /lib/modules/$kernelRelease/kernel/net/appletalk
|
||||||
sudo depmod
|
sudo depmod
|
||||||
@@ -539,7 +772,10 @@ if [[ ! $(dpkg -l avahi-daemon 2> /dev/null | grep ^ii) || ! $(dpkg -l libnss-md
|
|||||||
sudo apt-get -y update
|
sudo apt-get -y update
|
||||||
touch /tmp/a2server-packageReposUpdated
|
touch /tmp/a2server-packageReposUpdated
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Dependency: Bonjour for netatalk
|
||||||
sudo apt-get -y install avahi-daemon libnss-mdns &> /dev/null
|
sudo apt-get -y install avahi-daemon libnss-mdns &> /dev/null
|
||||||
|
|
||||||
fi
|
fi
|
||||||
sudo sed -i 's/^\(hosts.*\)$/\1 mdns/' /etc/nsswitch.conf
|
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
|
if [[ ! -f /etc/avahi/services/afpd.service && ! -f /etc/avahi/services/afpd.service_disabled ]]; then
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -28,8 +28,10 @@ if [[ ! $autoAnswerYes || -f /tmp/a2server-setupWindowsSharing ]]; then
|
|||||||
touch /tmp/a2server-packageReposUpdated
|
touch /tmp/a2server-packageReposUpdated
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Dependency: samba for Windows/modern Macs
|
||||||
|
# FIXME: Figure out when smbpasswd moved and adjust this as necessary
|
||||||
sudo apt-get -y install samba
|
sudo apt-get -y install samba
|
||||||
command -v smbpasswd >/dev/null || sudo apt-get -y install samba-common-bin
|
hash smbpasswd &> /dev/null || sudo apt-get -y install samba-common-bin
|
||||||
sudo apt-get clean
|
sudo apt-get clean
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -46,13 +48,19 @@ if [[ ! $autoAnswerYes || -f /tmp/a2server-setupWindowsSharing ]]; then
|
|||||||
sudo sed -i 's/^ workgroup = .*$/ workgroup = '$workgroup'/' /etc/samba/smb.conf 2> /dev/null
|
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
|
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 \
|
# remove GSFILES if no longer serving it
|
||||||
|
if ! grep ^/srv/A2SERVER/GSFILES /usr/local/etc/netatalk/AppleVolumes.default; then
|
||||||
|
sudo sed -i ':a;N;$!ba;s#\n\[GSFILES\].*\[#\n[#' /etc/samba/smb.conf
|
||||||
|
sudo sed -i ':a;N;$!ba;s#\n\[GSFILES\].*$#\n#' /etc/samba/smb.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
grep ^/srv/A2SERVER /usr/local/etc/netatalk/AppleVolumes.default | cut -d" " -f2 \
|
||||||
| while read sharename; do
|
| while read sharename; do
|
||||||
if [[ $(grep $sharename /etc/samba/smb.conf) ]]; then
|
if [[ $(grep $sharename /etc/samba/smb.conf) ]]; then
|
||||||
echo "A2SERVER: $sharename is already set up for Windows file sharing."
|
echo "A2SERVER: $sharename is already set up for Windows file sharing."
|
||||||
else
|
else
|
||||||
echo "[$sharename]" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
echo "[$sharename]" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||||
echo " path = /media/A2SHARED/$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 " 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 " 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 " read only = no" | sudo tee -a /etc/samba/smb.conf > /dev/null
|
||||||
|
@@ -14,7 +14,7 @@ password="your password"
|
|||||||
[[ $isRaspberryPw ]] && password="'raspberry'"
|
[[ $isRaspberryPw ]] && password="'raspberry'"
|
||||||
|
|
||||||
isDebian=
|
isDebian=
|
||||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "7." ) && ( $(uname -m) == "i686" ) ]] && isDebian=1
|
b_release -a 2> /dev/null | grep -q 'Distributor ID:.Debian' && [[ ( -f /etc/debian_version ) && ( $(cut -d . -f 1 < /etc/debian_version) -ge "7" ) ]] && isDebian=1
|
||||||
|
|
||||||
if [[ $isDebian ]]; then
|
if [[ $isDebian ]]; then
|
||||||
if { lspci 2> /dev/null | grep -q VirtualBox; }; then
|
if { lspci 2> /dev/null | grep -q VirtualBox; }; then
|
||||||
|
180
scripts/clock.patch.py
Executable file
180
scripts/clock.patch.py
Executable file
@@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
'''CLOCK.PATCH by Greg Branche implemented in Python 2/3 for A2SERVER
|
||||||
|
|
||||||
|
This is a line-for-line conversion of an edited version of CLOCK.PATCH
|
||||||
|
from the System Tools 2 disk in GS/OS 6.0.1. It's not good Python,
|
||||||
|
but I thought it would be an interesting exercise. In general
|
||||||
|
I have tried replicate each line as closely to BASIC as possible.
|
||||||
|
|
||||||
|
Because BASIC substrings are 1-based and python's are 0-based, various
|
||||||
|
indexes are minus one of their BASIC equivalents.
|
||||||
|
|
||||||
|
The one change is that you can optionally pass the day and date by
|
||||||
|
command line argument (e.g "Wed 3/13/15"). I also improved error
|
||||||
|
checking. These are in the BASIC lines that don't end in 0.
|
||||||
|
|
||||||
|
Rather than modifying PRODOS, this outputs a string of comma-separated
|
||||||
|
year values for a calling script (the a2server-setup installer),
|
||||||
|
followed by a space and a dd-Mmm-yy date string.
|
||||||
|
'''
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# other imports
|
||||||
|
import sys
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
# substitute raw_input for input in Python2
|
||||||
|
try: input = raw_input
|
||||||
|
except NameError: pass
|
||||||
|
|
||||||
|
dow_str = None
|
||||||
|
day = None
|
||||||
|
if len(sys.argv) > 2:
|
||||||
|
dow_str = sys.argv[1] # day of week passed on command line
|
||||||
|
day = sys.argv[2] # date passed on command line
|
||||||
|
|
||||||
|
# 60000 REM # of days in each month
|
||||||
|
data = [31,28,31,30,31,30,31,31,30,31,30] # 60010 DATA 31,28,31,30,31,30,31,31,30,31,30
|
||||||
|
# 60020 REM Names of days of week
|
||||||
|
data += [ # 60030 DATA SUN,MON,TUE,WED,THU,FRI,SAT
|
||||||
|
"SUN","MON","TUE","WED","THU","FRI","SAT"]
|
||||||
|
data = iter(data)
|
||||||
|
# 110 REM cu() = cumulative # of days in year
|
||||||
|
cu = [0] * 13 # 120 DIM CU(12)
|
||||||
|
# 130 REM fill array with # of days in year
|
||||||
|
cu[1] = 0 # 140 CU(1) = 0: REM January
|
||||||
|
for i in range(2,13): # 150 FOR I = 2 TO 12
|
||||||
|
x = next(data) # 160 READ X
|
||||||
|
cu[i] = cu[i-1] + x # 170 CU(I) = CU(I - 1) + X
|
||||||
|
# 180 NEXT I
|
||||||
|
|
||||||
|
# 200 REM DN$() = Names for days of week
|
||||||
|
dn = [""] * 8 # 210 DIM DN$(7)
|
||||||
|
# 220 REM fill array with names of days of week
|
||||||
|
for i in range(1,8): # 230 FOR I = 1 TO 7
|
||||||
|
dn[i] = next(data) # 240 READ DN$(I)
|
||||||
|
# 250 NEXT I
|
||||||
|
|
||||||
|
# 270 REM yt() is the year table values
|
||||||
|
yt = [0] * 8 # 280 DIM YT(7)
|
||||||
|
|
||||||
|
def mod7(x): # 340 DEF FN MOD7(X) = INT (((X / 7) - INT (X / 7)) * 7 + .5)
|
||||||
|
return int(((x / 7) - int(x / 7)) * 7 + .5)
|
||||||
|
|
||||||
|
def find_slash_pos(day): # 799 REM Finds position of / within date string
|
||||||
|
x = -1 # 800 X = 0: REM On exit, contains position of /, or 0 if none found
|
||||||
|
for i in range(0,3): # 810 FOR I = 1 TO 3
|
||||||
|
if day[i:i+1] == "/": x = i; break # 820 IF MID$ (DAY$,I,1) = "/" THEN X = I:I = 3
|
||||||
|
# 830 NEXT I
|
||||||
|
return x # 840 RETURN
|
||||||
|
|
||||||
|
while True: # 999 REM get the user's input and convert
|
||||||
|
if not day:
|
||||||
|
print( # 1010 PRINT "Please enter today's date (mm/dd/yy)"
|
||||||
|
"Please enter today's date (mm/dd/yy)")
|
||||||
|
day = input("-> ") # 1020 INPUT "-> ";DAY$
|
||||||
|
x = find_slash_pos(day) # 1030 GOSUB 800: REM find slash separator
|
||||||
|
input_ok = False
|
||||||
|
while not input_ok:
|
||||||
|
if not (x != -1): # 1040 IF X < > 0 THEN 1080
|
||||||
|
print( # 1050 PRINT "Invalid date entered. Please try again."; CHR$ (7)
|
||||||
|
"Invalid date entered. Please try again.\x07")
|
||||||
|
break # 1060 GOTO 1010
|
||||||
|
# 1070 REM Convert month value to numeric variable
|
||||||
|
mo = int(day[0:0+x]) # 1080 MO = VAL ( MID$ (DAY$,1,X - 1))
|
||||||
|
day = day[x+1:] # 1090 DAY$ = MID$ (DAY$,X + 1)
|
||||||
|
if mo < 1 or mo > 12: x = -1; continue # 1100 IF MO < 1 OR MO > 12 THEN 1050: REM Range check the month value
|
||||||
|
x = find_slash_pos(day) # 1110 GOSUB 800: REM Parse out the current day
|
||||||
|
if x == -1: continue # 1120 IF X = 0 THEN 1050
|
||||||
|
# 1130 REM Convert day string into numeric value
|
||||||
|
da = int(day[0:0+x]) # 1140 DA = VAL ( MID$ (DAY$,1,X - 1))
|
||||||
|
day = day[x+1:] # 1150 DAY$ = MID$ (DAY$,X + 1)
|
||||||
|
if da < 1 or da > 31: x = -1; continue # 1160 IF DA < 1 OR DA > 31 THEN 1050: REM Range check the day value
|
||||||
|
if mo == 2 and da > 29: # 1161 IF MO = 2 AND DA > 29 THEN 1050
|
||||||
|
x = -1; continue
|
||||||
|
if (mo == 4 or # 1162 IF (MO = 4 OR MO = 6 OR MO = 9 OR MO = 11) AND DA > 30 THEN 1050
|
||||||
|
mo == 6 or
|
||||||
|
mo == 9 or
|
||||||
|
mo == 11) and da > 30: x = -1; continue
|
||||||
|
# 1170 REM Convert year string into numeric value
|
||||||
|
yr = int(day) # 1180 YR = VAL (DAY$)
|
||||||
|
if yr < 0 or yr > 99: x = -1; continue # 1190 IF YR < 0 OR YR > 99 THEN 1050: REM Only allow 0-99
|
||||||
|
if yr > 39: yr = yr + 1900 # 1200 IF YR > 39 THEN YR = YR + 1900: REM 40-99 must be 1940-1999
|
||||||
|
if yr < 40: yr = yr + 2000 # 1210 IF YR < 40 THEN YR = YR + 2000: REM 0-39 must be 2000-2039
|
||||||
|
if ((yr / 4) != int(yr / 4) and # 1211 IF ((YR / 4) < > INT(YR / 4)) AND MO = 2 AND DA > 28 THEN 1050
|
||||||
|
mo == 2 and
|
||||||
|
da > 28): x = -1; continue
|
||||||
|
input_ok = True
|
||||||
|
if x != -1: break
|
||||||
|
else: dow_str = ""; day = ""
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if not dow_str:
|
||||||
|
print(
|
||||||
|
"Please enter the day of the week") # 1230 PRINT "Please enter the day of the week"
|
||||||
|
dow_str = input("(e.g. Wed) -> ") # 1240 INPUT "(e.g. Wed) -> ";DOW$
|
||||||
|
input_ok = False
|
||||||
|
while not input_ok:
|
||||||
|
if not (len(dow_str) >= 3): # 1250 IF LEN (DOW$) > = 3 THEN 1270: REM Must be at least 3 characters
|
||||||
|
print( # 1260 PRINT "Invalid day of week. Please try again."; CHR$ (7): GOTO 1230
|
||||||
|
"Invalid day of week. Please try again.\x07")
|
||||||
|
break
|
||||||
|
if len(dow_str) > 3: # 1270 IF LEN (DOW$) > 3 THEN DOW$ = LEFT$ (DOW$,3)
|
||||||
|
dow_str = dow_str[0:0+3]
|
||||||
|
# 1280 REM Shift any lower case letters to upper case
|
||||||
|
b = "" # 1290 B$ = ""
|
||||||
|
for i in range(0,3): # 1300 FOR I = 1 TO 3
|
||||||
|
a = dow_str[i:i+1] # 1310 A$ = MID$ (DOW$,I,1)
|
||||||
|
if ( # 1320 IF ASC (A$) > = ASC ("a") AND ASC (A$) < = ASC ("z") THEN A$ = CHR$ ( ASC (A$) - ( ASC ("a") - ASC ("A")))
|
||||||
|
ord(a) >= ord("a") and ord(a) <= ord("z")): a = chr(ord(a) - (ord("a") - ord("A")))
|
||||||
|
b = b + a # 1330 B$ = B$ + A$
|
||||||
|
# 1340 NEXT I
|
||||||
|
dow_str = b # 1350 DOW$ = B$
|
||||||
|
# 1360 REM Now convert day-of-week string to numeric value
|
||||||
|
dow_num = 0 # 1370 DOW = 0
|
||||||
|
for i in range (1,8): # 1380 FOR I = 1 TO 7
|
||||||
|
if dow_str == dn[i]: # 1390 IF DOW$ = DN$(I) THEN DOW = I:I = 7
|
||||||
|
dow_num = i; i = 7
|
||||||
|
# 1400 NEXT I
|
||||||
|
if dow_num == 0: dow_str = ""; continue # 1410 IF DOW = 0 THEN 1260
|
||||||
|
input_ok = True
|
||||||
|
if len(dow_str) >= 3: break
|
||||||
|
else: dow_str = ""; day = ""
|
||||||
|
# 1430 REM Calculate the number of days so far this year
|
||||||
|
dys = da + cu[mo] # 1440 DYS = DA + CU(MO)
|
||||||
|
oyr = yr
|
||||||
|
# 1450 REM Must account for extra day in leap year
|
||||||
|
if ((yr / 4) == int(yr / 4)) and (mo > 2): # 1460 IF (YR / 4) = INT (YR / 4) AND MO > 2 THEN DYS = DYS + 1
|
||||||
|
dys = dys + 1
|
||||||
|
|
||||||
|
# 1480 REM Now calculate the index to use to fill in the table
|
||||||
|
idx = dow_num - mod7(dys) + 1 # 1490 IDX = DOW - FN MOD7(DYS) + 1
|
||||||
|
idx = abs(idx - 10) # 1500 IDX = ABS (IDX - 10)
|
||||||
|
if idx > 7: idx = idx - 7 # 1510 IF IDX > 7 THEN IDX = IDX - 7
|
||||||
|
|
||||||
|
# 1530 REM Now we can fill in the year table
|
||||||
|
for i in range(1,8): # 1540 FOR I = 1 TO 7
|
||||||
|
if '_i' in vars() and i < (_i + 1): continue # python: simulate change of i within loop
|
||||||
|
x = yr - 1900 # 1550 X = YR - 1900
|
||||||
|
if x >= 100: x = x - 100 # 1560 IF X > = 100 THEN X = X - 100
|
||||||
|
yt[idx] = x # 1570 YT(IDX) = X: REM store the year into table
|
||||||
|
idx = idx - 1 # 1580 IDX = IDX - 1
|
||||||
|
if idx < 1: idx = 7 # 1590 IF IDX < 1 THEN IDX = 7
|
||||||
|
if not ((yr / 4) != int(yr / 4)): # 1600 IF (YR / 4) < > INT (YR / 4) THEN 1660: REM not a leap year
|
||||||
|
i = i + 1; _i = i # 1610 I = I + 1: REM update index
|
||||||
|
if i > 7: continue # 1620 IF I > 7 THEN 1670: REM if entire array done, exit
|
||||||
|
yt[idx] = x # 1630 YT(IDX) = X: REM duplicate entry for leap year
|
||||||
|
idx = idx - 1 # 1640 IDX = IDX - 1
|
||||||
|
if idx < 1: idx = 7 # 1650 IF IDX < 1 THEN IDX = 7
|
||||||
|
yr = yr + 1 # 1660 YR = YR + 1
|
||||||
|
# 1670 NEXT I
|
||||||
|
|
||||||
|
print(",".join([str(x) for x in yt[1:]]) + " " +
|
||||||
|
str(da).encode("L1").decode("L1").zfill(2) + "-" +
|
||||||
|
datetime.date(1900, mo, 1).strftime('%b') + "-" +
|
||||||
|
str(oyr).encode("L1").decode("L1")[2:])
|
233
scripts/raspbian-update.txt
Normal file
233
scripts/raspbian-update.txt
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# raspbian-update
|
||||||
|
# updates Raspbian to latest version, including NOOBS if installed
|
||||||
|
|
||||||
|
[[ -f /usr/bin/raspi-config ]] && isRpi=1 || isRpi=
|
||||||
|
|
||||||
|
if [[ ! $isRpi ]]; then
|
||||||
|
echo "This ain't a Raspberry Pi."
|
||||||
|
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
skipRepoUpdate=
|
||||||
|
autoYes=
|
||||||
|
updateA2Cloud=
|
||||||
|
updateA2Server=
|
||||||
|
while [[ $1 ]]; do
|
||||||
|
if [[ $1 == "-r" ]]; then
|
||||||
|
shift
|
||||||
|
skipRepoUpdate="-r"
|
||||||
|
elif [[ $1 == "-y" ]]; then
|
||||||
|
shift
|
||||||
|
autoYes="-y"
|
||||||
|
elif [[ $1 == "-n" ]]; then
|
||||||
|
shift
|
||||||
|
noobsOnly="-n"
|
||||||
|
elif [[ $1 == "a2cloud" ]]; then
|
||||||
|
shift
|
||||||
|
updateA2Cloud=1
|
||||||
|
elif [[ $1 == "a2server" ]]; then
|
||||||
|
shift
|
||||||
|
updateA2Server=1
|
||||||
|
elif [[ $1 ]]; then
|
||||||
|
echo "options:"
|
||||||
|
echo "-y: auto-answer yes to all prompts and don't prompt for restart"
|
||||||
|
echo "-r: don't update package repositories"
|
||||||
|
echo "-n: update NOOBS only; don't update Raspbian"
|
||||||
|
echo "a2cloud : update A2CLOUD when complete"
|
||||||
|
echo "a2server: update A2SERVER when complete"
|
||||||
|
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
noobs=
|
||||||
|
readarray -t partitions < <(sudo fdisk -l | grep '^/dev')
|
||||||
|
if [[ \
|
||||||
|
${partitions[0]:0:14} == "/dev/mmcblk0p1" && ${partitions[0]:57:2} == " e" &&
|
||||||
|
${partitions[1]:0:14} == "/dev/mmcblk0p2" && ${partitions[1]:57:2} == "85" &&
|
||||||
|
${partitions[2]:0:14} == "/dev/mmcblk0p3" && ${partitions[2]:57:2} == "83" &&
|
||||||
|
${partitions[3]:0:14} == "/dev/mmcblk0p5" && ${partitions[3]:57:2} == " c" &&
|
||||||
|
${partitions[4]:0:14} == "/dev/mmcblk0p6" && ${partitions[4]:57:2} == "83" ]]; then
|
||||||
|
noobs=" and the NOOBS install manager"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! $autoYes ]]; then
|
||||||
|
echo
|
||||||
|
echo "You are about to update your SD card to the latest version of the"
|
||||||
|
echo "Raspbian operating system${noobs}."
|
||||||
|
echo
|
||||||
|
echo "This may take an hour or more, and will require restarting when complete."
|
||||||
|
echo "You might want a backup before continuing in case it doesn't go as planned."
|
||||||
|
echo
|
||||||
|
echo -n "Update Raspbian? "
|
||||||
|
read
|
||||||
|
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||||
|
[[ $0 == "-bash" ]] && return 2 || exit 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
origDir="$PWD"
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
if [[ ! $skipRepoUpdate ]]; then
|
||||||
|
echo "Updating package repositories..."
|
||||||
|
sudo apt-get -y update > /dev/null
|
||||||
|
else
|
||||||
|
echo "Not updating package repositories..."
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! $noobsOnly ]]; then
|
||||||
|
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||||
|
freeSpace=$(df / | tail -1 | awk '{ print $4 }')
|
||||||
|
if (( $freeSpace < 400000 )); then
|
||||||
|
if dpkg -l | grep -q wolfram-engine; then
|
||||||
|
if [[ ! $autoYes ]]; then
|
||||||
|
echo "In order to create enough space on your SD card to upgrade,"
|
||||||
|
echo "the Wolfram Language and Mathematica software packages must be removed."
|
||||||
|
echo "If you don't know what these are, this won't affect you at all."
|
||||||
|
echo
|
||||||
|
echo -n "Remove Wolfram software? "
|
||||||
|
read
|
||||||
|
if [[ ${REPLY:0:1} != "Y" && ${REPLY:0:1} != "y" ]]; then
|
||||||
|
[[ $0 == "-bash" ]] && return 2 || exit 2
|
||||||
|
fi
|
||||||
|
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||||
|
sudo apt-get -y purge wolfram-engine
|
||||||
|
else
|
||||||
|
echo "Removing Wolfram software due to space constraints..."
|
||||||
|
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||||
|
sudo apt-get -y purge wolfram-engine
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "You don't have enough free space on your SD card to upgrade."
|
||||||
|
echo "Sorry, man. Delete some stuff or get a bigger card."
|
||||||
|
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||||
|
dpkg -l | grep -q a2pi && sudo apt-get -y --force-yes install a2pi
|
||||||
|
dpkg -l | grep -q apple2user && sudo apt-get -y --force-yes install apple2user gsport
|
||||||
|
if dpkg -l | grep -q wolfram-engine; then
|
||||||
|
sudo rm /opt/Wolfram/WolframEngine/10.0/SystemFiles/Java/Linux-ARM 2> /dev/null
|
||||||
|
if [[ $freeSpace -lt 750000 && $(apt-get -s install wolfram-engine | grep upgraded) ]]; then
|
||||||
|
sudo apt-get -y purge wolfram-engine
|
||||||
|
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||||
|
fi
|
||||||
|
sudo apt-get -y install wolfram-engine
|
||||||
|
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||||
|
fi
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" upgrade
|
||||||
|
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
|
||||||
|
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||||
|
sudo apt-get -y install raspberrypi-ui-mods
|
||||||
|
{ cd /tmp; sudo apt-get -y autoremove; sudo apt-get -y autoclean; sudo apt-get -y clean; } > /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $noobs ]]; then
|
||||||
|
echo "Updating NOOBS..."
|
||||||
|
|
||||||
|
# update Partition 3
|
||||||
|
mkdir -p /tmp/p3
|
||||||
|
sudo mount /dev/mmcblk0p3 /tmp/p3
|
||||||
|
sudo rm -rf /tmp/p3/os/* 2> /dev/null
|
||||||
|
if grep -q 'Raspple II' /tmp/p3/installed_os.json; then
|
||||||
|
echo "Downloading Raspple II lite..."
|
||||||
|
noobsUrl="ivanx.com/rasppleii/files/RasppleII_lite.zip"
|
||||||
|
noobsOSurl="ivanx.com/rasppleii/noobs-os"
|
||||||
|
distDir="Raspple_II"
|
||||||
|
sudo mkdir -p /tmp/p3/os/$distDir
|
||||||
|
sudo sed -i 's:/Raspbian:/Raspple_II:' /tmp/p3/installed_os.json
|
||||||
|
sudo wget -qO /tmp/p3/icon.png $noobsOSurl/Raspple_II.png
|
||||||
|
{ wget -qO- $noobsOSurl/slidesAB.tar | sudo tar -C /tmp/p3/os/$distDir -x; } &> /dev/null
|
||||||
|
else
|
||||||
|
echo "Downloading NOOBS lite..."
|
||||||
|
noobsRoot="downloads.raspberrypi.org/NOOBS_lite/images/"
|
||||||
|
noobsDir=$(wget -qO- $noobsRoot | grep '^<tr><td' | tail -1 | grep -P -o 'href=".*?"' | cut -c 6- | tr -d '"')
|
||||||
|
noobsUrl=$noobsRoot$noobsDir$(wget -qO- $noobsRoot$noobsDir | grep -P -o 'href=".*.zip"' | cut -c 6- | tr -d '"')
|
||||||
|
noobsOSurl="downloads.raspberrypi.org/raspbian"
|
||||||
|
distDir="Raspbian"
|
||||||
|
sudo mkdir -p /tmp/p3/os/$distDir
|
||||||
|
sudo wget -qO /tmp/p3/icon.png $noobsOSurl/Raspbian.png
|
||||||
|
{ wget -qO- $noobsOSurl/marketing.tar | sudo tar -C /tmp/p3/os/$distDir -x; } &> /dev/null
|
||||||
|
fi
|
||||||
|
sudo rm -rf /tmp/p3/cache 2> /dev/null
|
||||||
|
releaseDate=$(wget -qO- $noobsOSurl/os.json | grep 'release_date' | cut -f 4 -d '"')
|
||||||
|
sudo sed -i 's/"release_date".*$/"release_date" : "'$releaseDate'"/' /tmp/p3/installed_os.json
|
||||||
|
sudo sed -i 's/keyboard_layout=gb/keyboard_layout=us/' /tmp/p3/noobs.conf
|
||||||
|
sudo sed -i 's:/mnt/:/settings/:' /tmp/p3/installed_os.json
|
||||||
|
sudo sed -i 's@"icon".*,@"icon" : "/settings/os/'$distDir'/icon.png",@' /tmp/p3/installed_os.json
|
||||||
|
sudo cp /tmp/p3/icon.png /tmp/p3/os/$distDir
|
||||||
|
sudo wget -qO /tmp/p3/os/$distDir/os.json $noobsOSurl/os.json
|
||||||
|
sudo wget -qO /tmp/p3/os/$distDir/partition_setup.sh $noobsOSurl/partition_setup.sh
|
||||||
|
sudo wget -qO /tmp/p3/os/$distDir/partitions.json $noobsOSurl/partitions.json
|
||||||
|
sudo umount /tmp/p3
|
||||||
|
rmdir /tmp/p3
|
||||||
|
|
||||||
|
# update Partition 1
|
||||||
|
mkdir -p /tmp/p1
|
||||||
|
sudo mount /dev/mmcblk0p1 /tmp/p1
|
||||||
|
wget -qO /tmp/noobs_lite.zip $noobsUrl
|
||||||
|
sudo rm -rf /tmp/p1/*
|
||||||
|
sudo unzip -d /tmp/p1 /tmp/noobs_lite.zip
|
||||||
|
sudo sed -i 's/^runinstaller //' /tmp/p1/recovery.cmdline
|
||||||
|
sudo sed -i 's/silentinstall//' /tmp/p1/recovery.cmdline
|
||||||
|
grep -q 'keyboard=us' /tmp/p1/recovery.cmdline || sudo sed -i '1 s/^\(.*\)$/\1 keyboard=us/' /tmp/p1/recovery.cmdline
|
||||||
|
grep -q 'disablesafemode' /tmp/p1/recovery.cmdline || sudo sed -i '1 s/^\(.*\)$/\1 disablesafemode/' /tmp/p1/recovery.cmdline
|
||||||
|
sudo umount /tmp/p1
|
||||||
|
rmdir /tmp/p1
|
||||||
|
|
||||||
|
sudo sed -i 's/\(Raspple II release.*[^u]$\)/\1u/' /etc/issue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "*** Raspbian update completed. ***"
|
||||||
|
echo
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
if [[ $updateA2Cloud ]]; then
|
||||||
|
wget -qO /tmp/a2cloud-setup ivanx.com/a2cloud/setup/
|
||||||
|
source /tmp/a2cloud-setup -y -r noSetGroups
|
||||||
|
if acmd -g /usr/share/gsport/disks/GSport\ Internet\ Starter\ Kit.2mg SYSTEM/FONTS/SIS.4.10 &> /dev/null; then
|
||||||
|
wget -qO /tmp/ua2.txt ivanx.com/rasppleii/files/a/ua2.txt
|
||||||
|
source /tmp/ua2.txt
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "*** A2CLOUD update completed. ***"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
if [[ $updateA2Server ]]; then
|
||||||
|
wget -q -O /tmp/a2server-setup ivanx.com/a2server/setup/
|
||||||
|
if ps aux | grep -q [s]mbd; then
|
||||||
|
source /tmp/a2server-setup -y -r -w
|
||||||
|
else
|
||||||
|
source /tmp/a2server-setup -y -r
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
echo "*** A2SERVER update completed. ***"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$origDir"
|
||||||
|
|
||||||
|
if [[ ! $autoYes ]]; then
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "Your system has been updated and needs to reboot to use its new software."
|
||||||
|
echo
|
||||||
|
echo -n "Reboot now (recommended)? "
|
||||||
|
read
|
||||||
|
if [[ ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
||||||
|
sudo shutdown -r now
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "*** raspbian-update completed. ***"
|
||||||
|
sudo shutdown -r now
|
||||||
|
fi
|
@@ -2,17 +2,17 @@
|
|||||||
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
||||||
|
|
||||||
alias a2server-help="more /usr/local/etc/a2server-help.txt"
|
alias a2server-help="more /usr/local/etc/a2server-help.txt"
|
||||||
alias a2server-setup="wget -q -O /tmp/a2server-setup ${A2SERVER_SCRIPT_URL:-http://appleii.ivanx.com/a2server}$([[ "$A2SERVER_SCRIPT_URL" == */ ]] || echo -n "/")setup/ || { echo \"Can't download A2SERVER setup scripts. Do you has internet?\"; false; } && source /tmp/a2server-setup"
|
alias a2server-setup='wget -q -O /tmp/a2server-setup ${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current/}setup/index.txt || { echo "Can'"'"'t download A2SERVER setup scripts. Do you has internet?"; false; } && source /tmp/a2server-setup'
|
||||||
|
|
||||||
alias a2server-version="cat /usr/local/etc/A2SERVER-version"
|
alias a2server-version="cat /usr/local/etc/A2SERVER-version"
|
||||||
alias a2server-update="wget -q -O /tmp/a2server-update ${A2SERVER_SCRIPT_URL:-http://appleii.ivanx.com/a2server}$([[ "$A2SERVER_SCRIPT_URL" == */ ]] || echo -n "/")update/ || { echo \"Can't download A2SERVER setup scripts. Do you has internet?\"; false; } && source /tmp/a2server-update"
|
alias a2server-update='wget -q -O /tmp/a2server-update ${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current/}update/index.txt || { echo "Can'"'"'t download A2SERVER setup scripts. Do you has internet?"; false; } && source /tmp/a2server-update'
|
||||||
|
|
||||||
alias system-shutdown='sudo shutdown -h now'
|
alias system-shutdown='sudo shutdown -h now'
|
||||||
alias system-restart='sudo shutdown -r 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 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 raspbian-update='wget -qO /tmp/raspbian-update ${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current/}scripts/raspbian-update.txt || { echo "Can'"'"'t download A2SERVER setup scripts. Do you has internet?"; false; } && source /tmp/raspbian-update'
|
||||||
alias rasppleii-update='raspbian-update a2cloud a2server'
|
alias rasppleii-update='raspbian-update a2cloud a2server'
|
||||||
|
|
||||||
alias welcome-message-edit='sudo nano /etc/motd'
|
alias welcome-message-edit='sudo nano /etc/motd'
|
||||||
@@ -24,8 +24,8 @@ 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 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-stop="sudo /etc/init.d/netatalk stop; bonjour-off"
|
||||||
alias netatalk-start="sudo /etc/init.d/netatalk start; bonjour-on"
|
alias netatalk-start="sudo /etc/init.d/netatalk start; bonjour-on; grep -q 'ATALKD_RUN=yes' /etc/default/netatalk"
|
||||||
alias netatalk-restart="sudo /etc/init.d/netatalk restart; bonjour-on"
|
alias netatalk-restart="sudo /etc/init.d/netatalk restart; bonjour-on; grep -q 'ATALKD_RUN=yes' /etc/default/netatalk"
|
||||||
alias netatalk-off='sudo /etc/init.d/netatalk stop; bonjour-off; sudo update-rc.d -f netatalk remove &> /dev/null'
|
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 netatalk-on='sudo update-rc.d netatalk defaults &> /dev/null; bonjour-on; sudo /etc/init.d/netatalk restart'
|
||||||
|
|
||||||
@@ -33,8 +33,8 @@ alias bonjour-off="sudo mv /etc/avahi/services/afpd.service /etc/avahi/services/
|
|||||||
alias bonjour-on="sudo mv /etc/avahi/services/afpd.service_disabled /etc/avahi/services/afpd.service &> /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-on='sudo sed -i '"'"'s/^\([^# ]*\)\( .*\)$/\1 -router\2 -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-router-off='sudo sed -i '"'"'s/^\([^#].*\) -router\(.*\) -zone [^ ]*\(.*\)$/\1\2\3/'"'"' /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-eth='sudo sed -i 's/^wlan0/eth0/' /usr/local/etc/netatalk/atalkd.conf; netatalk-restart'
|
||||||
@@ -47,8 +47,8 @@ alias appletalk-on='sudo sed -i "s/ATALKD_RUN=no/ATALKD_RUN=yes/" /etc/default/n
|
|||||||
|
|
||||||
|
|
||||||
NETATALK="/usr/local/etc/netatalk"
|
NETATALK="/usr/local/etc/netatalk"
|
||||||
A2FILES="/media/A2SHARED/A2FILES"
|
A2FILES="/srv/A2SERVER/A2FILES"
|
||||||
GSFILES="/media/A2SHARED/GSFILES"
|
GSFILES="/srv/A2SERVER/GSFILES"
|
||||||
|
|
||||||
alias netboot-gsos="mkatinit -gs -d -f"
|
alias netboot-gsos="mkatinit -gs -d -f"
|
||||||
alias netboot-gsos-guest="mkatinit -gs -d -f guest"
|
alias netboot-gsos-guest="mkatinit -gs -d -f guest"
|
||||||
@@ -69,8 +69,8 @@ alias samba-stop='sudo /etc/init.d/samba stop'
|
|||||||
alias samba-start='sudo /etc/init.d/samba start'
|
alias samba-start='sudo /etc/init.d/samba start'
|
||||||
alias samba-restart='sudo /etc/init.d/samba restart'
|
alias samba-restart='sudo /etc/init.d/samba restart'
|
||||||
|
|
||||||
alias a2files-share="sudo sed -i 's/^#share2/\/media\/A2SHARED\/A2FILES\ A2FILES options:prodos ea:ad/' /usr/local/etc/netatalk/AppleVolumes.default; [[ -d /media/A2SHARED/A2FILES ]] || mkdir /media/A2SHARED/A2FILES"
|
alias a2files-share="sudo sed -i 's/^#share2/\/srv\/A2SERVER\/A2FILES\ A2FILES options:prodos ea:ad/' /usr/local/etc/netatalk/AppleVolumes.default; [[ -d /srv/A2SERVER/A2FILES ]] || mkdir /srv/A2SERVER/A2FILES"
|
||||||
alias a2files-unshare="sudo sed -i 's/^\/media\/A2SHARED\/A2FILES.*$/#share2/' /usr/local/etc/netatalk/AppleVolumes.default"
|
alias a2files-unshare="sudo sed -i 's/^\/srv\/A2SERVER\/A2FILES.*$/#share2/' /usr/local/etc/netatalk/AppleVolumes.default"
|
||||||
|
|
||||||
alias showalias="alias | cut -d= -f 1 | cut -d' ' -f2 | more"
|
alias showalias="alias | cut -d= -f 1 | cut -d' ' -f2 | more"
|
||||||
|
|
||||||
|
6
scripts/tools/a2serverrc.txt
Executable file
6
scripts/tools/a2serverrc.txt
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
||||||
|
|
||||||
|
export A2SERVER_SCRIPT_URL="${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current/}"
|
||||||
|
export A2SERVER_BINARY_URL="${A2SERVER_BINARY_URL:-http://ivanx.com/a2server/files/}"
|
||||||
|
source /usr/local/etc/a2server-aliases
|
@@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# -v will silently create a .volinfo file if none exists.
|
# -v will silently create a .volinfo file if none exists.
|
||||||
# If a path is specified, only that volume is synced; otherwise, all
|
# If a path is specified, only that volume is synced; otherwise, all
|
||||||
# all paths in /media which appear in
|
# all paths in /srv/A2SERVER which appear in
|
||||||
# /usr/local/etc/netatalk/AppleVolumes.default are synced.
|
# /usr/local/etc/netatalk/AppleVolumes.default are synced.
|
||||||
|
|
||||||
processPath () {
|
processPath () {
|
||||||
@@ -43,7 +43,6 @@ processPath () {
|
|||||||
echo "AppleDouble files have been updated for volume $sharepath."
|
echo "AppleDouble files have been updated for volume $sharepath."
|
||||||
else
|
else
|
||||||
[[ ! $renameLower ]] && echo "Could not update all files on volume $sharepath."
|
[[ ! $renameLower ]] && echo "Could not update all files on volume $sharepath."
|
||||||
[[ ! $renameLower ]] && echo "Ensure filenames are all caps on volume $sharepath."
|
|
||||||
if [[ $showerrors ]]; then
|
if [[ $showerrors ]]; then
|
||||||
echo $result \
|
echo $result \
|
||||||
| while read LINE; do
|
| while read LINE; do
|
||||||
@@ -63,7 +62,6 @@ processPath () {
|
|||||||
$0 $sharepath
|
$0 $sharepath
|
||||||
else
|
else
|
||||||
echo "Use afpsync -e to see error details."
|
echo "Use afpsync -e to see error details."
|
||||||
echo "Use afpsync -r to rename lowercase names to uppercase."
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
unset IFS
|
unset IFS
|
||||||
@@ -108,7 +106,7 @@ else
|
|||||||
# (as opposed to defaulting to casefold:toupper previously)
|
# (as opposed to defaulting to casefold:toupper previously)
|
||||||
processPath 1
|
processPath 1
|
||||||
else
|
else
|
||||||
grep ^/media /usr/local/etc/netatalk/AppleVolumes.default | \
|
grep ^/srv/A2SERVER /usr/local/etc/netatalk/AppleVolumes.default | \
|
||||||
while read line; do
|
while read line; do
|
||||||
[[ $(echo $line | grep toupper) ]]; nocasefold=$?
|
[[ $(echo $line | grep toupper) ]]; nocasefold=$?
|
||||||
sharepath=$(echo $line | cut -d" " -f1)
|
sharepath=$(echo $line | cut -d" " -f1)
|
||||||
|
@@ -158,7 +158,7 @@ readchars () {
|
|||||||
&& ( $3 -ge 0 ) ]] || return 23; }
|
&& ( $3 -ge 0 ) ]] || return 23; }
|
||||||
# args are valid
|
# args are valid
|
||||||
dd if="$1" bs=1 skip=$(($2)) $([[ $3 ]] && echo -n "count=$3") \
|
dd if="$1" bs=1 skip=$(($2)) $([[ $3 ]] && echo -n "count=$3") \
|
||||||
2> /dev/null
|
2> /dev/null | tr -d ' \0'
|
||||||
}
|
}
|
||||||
|
|
||||||
readcharDec () {
|
readcharDec () {
|
||||||
@@ -175,7 +175,7 @@ readcharDec () {
|
|||||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||||
# args are valid
|
# args are valid
|
||||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||||
count=1 2> /dev/null; echo -n X)"
|
count=1 2> /dev/null | tr -d '\0'; echo -n X)"
|
||||||
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
|
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
|
||||||
echo -n "${charX:0:1}" | od -t u1 | \
|
echo -n "${charX:0:1}" | od -t u1 | \
|
||||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
|
||||||
@@ -195,7 +195,7 @@ readcharHex () {
|
|||||||
&& ( $2 -ge 0 ) ]] || return 22; }
|
&& ( $2 -ge 0 ) ]] || return 22; }
|
||||||
# args are valid
|
# args are valid
|
||||||
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
charX="$(dd if="$1" bs=1 skip=$(($2)) \
|
||||||
count=1 2> /dev/null; echo -n X)"
|
count=1 2> /dev/null | tr -d '\0'; echo -n X)"
|
||||||
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
|
||||||
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
|
||||||
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -49,7 +49,7 @@ else
|
|||||||
if [[ $1 ]]; then
|
if [[ $1 ]]; then
|
||||||
sharepath=$(readlink -m $1)
|
sharepath=$(readlink -m $1)
|
||||||
else
|
else
|
||||||
sharepath=$(grep ^/media /usr/local/etc/netatalk/AppleVolumes.default | tail -1 | cut -d" " -f1)
|
sharepath=$(grep ^/srv/A2SERVER /usr/local/etc/netatalk/AppleVolumes.default | tail -1 | cut -d" " -f1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
volinfo=$sharepath/.AppleDesktop/.volinfo
|
volinfo=$sharepath/.AppleDesktop/.volinfo
|
||||||
|
1
scripts/tools/netatalk-maketar.txt
Normal file
1
scripts/tools/netatalk-maketar.txt
Normal file
File diff suppressed because one or more lines are too long
206
setup/index.txt
206
setup/index.txt
@@ -1,44 +1,61 @@
|
|||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
||||||
|
|
||||||
# A2SERVER master setup script, last update 17-Nov-15
|
# A2SERVER master setup script, last update 15-Jul-20
|
||||||
# it downloads and executes several scripts related to the setup of
|
# it downloads and executes several scripts related to the setup of
|
||||||
# netatalk configured for Apple II use on Debian or Raspbian.
|
# netatalk configured for Apple II use on Debian or Raspbian.
|
||||||
# more info is at http://appleii.ivanx.com/a2server
|
# more info is at http://ivanx.com/a2server
|
||||||
|
|
||||||
# to download and execute, type:
|
# to download and execute, type:
|
||||||
# wget appleii.ivanx.com/a2server/setup; source setup
|
# wget ivanx.com/a2server/setup; source setup
|
||||||
|
|
||||||
a2serverVersion="127"
|
a2serverVersion="153"
|
||||||
|
|
||||||
# Ensure URL we'll use ends in a /
|
# Ensure URL we'll use ends in a /
|
||||||
case "$A2SERVER_SCRIPT_URL" in
|
case "$A2SERVER_SCRIPT_URL" in
|
||||||
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
||||||
*) scriptURL="${A2SERVER_SCRIPT_URL:-http://appleii.ivanx.com/a2server}/" ;;
|
*) scriptURL="${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current}/" ;;
|
||||||
esac
|
esac
|
||||||
|
case "$A2SERVER_BINARY_URL" in
|
||||||
|
*/) binaryURL="$A2SERVER_BINARY_URL" ;;
|
||||||
|
*) binaryURL="${A2SERVER_BINARY_URL:-http://ivanx.com/a2server/files}/" ;;
|
||||||
|
esac
|
||||||
|
useExternalURL=1
|
||||||
|
[[ $A2SERVER_NO_EXTERNAL ]] && useExternalURL=
|
||||||
|
|
||||||
isRpi=
|
isRpi=
|
||||||
[[ -f /usr/bin/raspi-config ]] && isRpi=1
|
[[ -f /usr/bin/raspi-config ]] && isRpi=1
|
||||||
|
|
||||||
isDebian=
|
isDebian=
|
||||||
[[ ( -f /etc/debian_version ) && ( $(cut -c 1-2 < /etc/debian_version) == "7." ) && ( $(uname -m) == "i686" ) ]] && isDebian=1
|
lsb_release -a 2> /dev/null | grep -q 'Distributor ID:.Debian' && [[ ( -f /etc/debian_version ) && ( $(cut -d . -f 1 < /etc/debian_version) -ge "7" ) ]] && isDebian=1
|
||||||
|
|
||||||
if [[ -f /usr/local/etc/A2SERVER-version ]]; then
|
installedVersion=
|
||||||
echo "A2SERVER version available: $a2serverVersion"
|
if [ -f /usr/local/etc/A2SERVER-version ]; then
|
||||||
echo "A2SERVER version installed: $(cat /usr/local/etc/A2SERVER-version)"
|
installedVersion="$(cat /usr/local/etc/A2SERVER-version)"
|
||||||
fi
|
fi
|
||||||
|
echo "A2SERVER version available: $a2serverVersion"
|
||||||
|
echo "A2SERVER version installed: ${installedVersion:=None}"
|
||||||
|
|
||||||
|
echo
|
||||||
|
[[ $scriptURL != *"ivanx.com"* && $scriptURL != *"raw.githubusercontent.com/RasppleII/a2server"* ]] && echo "Using script URL: $scriptURL"
|
||||||
|
[[ $binaryURL != *"ivanx.com"* ]] && echo "Using binary URL: $binaryURL"
|
||||||
|
[[ ! $useExternalURL ]] && echo -e "Not using external URLs. Downloads must be available from:\n ${binaryURL}external/appleii/\n ${binaryURL}external/source/\n (See the A2SERVER developer page for more information.)"
|
||||||
|
|
||||||
skipRepoUpdate=
|
skipRepoUpdate=
|
||||||
autoAnswerYes=
|
autoAnswerYes=
|
||||||
|
installAll=
|
||||||
setupNetBoot=
|
setupNetBoot=
|
||||||
setupWindowsSharing=
|
setupWindowsSharing=
|
||||||
updateRasppleII=
|
compileAlways=
|
||||||
rm /tmp/a2server-* 2> /dev/null
|
rm /tmp/a2server-* 2> /dev/null
|
||||||
while [[ $1 ]]; do
|
while [[ $1 ]]; do
|
||||||
if [[ $1 == "-r" ]]; then
|
if [[ $1 == "-r" ]]; then
|
||||||
shift
|
shift
|
||||||
skipRepoUpdate="-r"
|
skipRepoUpdate="-r"
|
||||||
touch /tmp/a2server-packageReposUpdated
|
touch /tmp/a2server-packageReposUpdated
|
||||||
|
elif [[ $1 == "-i" ]]; then
|
||||||
|
shift
|
||||||
|
installAll="-i"
|
||||||
elif [[ $1 == "-y" ]]; then
|
elif [[ $1 == "-y" ]]; then
|
||||||
shift
|
shift
|
||||||
autoAnswerYes="-y"
|
autoAnswerYes="-y"
|
||||||
@@ -51,39 +68,28 @@ while [[ $1 ]]; do
|
|||||||
shift
|
shift
|
||||||
setupWindowsSharing="-w"
|
setupWindowsSharing="-w"
|
||||||
touch /tmp/a2server-setupWindowsSharing
|
touch /tmp/a2server-setupWindowsSharing
|
||||||
elif [[ $1 == "-os" || $1 == "os" ]]; then
|
elif [[ $1 == "-c" ]]; then
|
||||||
# elif [[ ${1,,} == "rasppleii" || ${1,,} == "raspple" || ${1,,} == "rasappleii" || ${1,,} == "rasapple" || ${1,,} == "raspple2" || ${1,,} == "rasapple2" ]]; then
|
|
||||||
shift
|
shift
|
||||||
updateRasppleII=1
|
compileAlways="-c"
|
||||||
|
touch /tmp/a2server-compileAlways
|
||||||
elif [[ $1 == "-v" ]]; then
|
elif [[ $1 == "-v" ]]; then
|
||||||
shift
|
shift
|
||||||
if [[ ! -f /usr/local/etc/A2SERVER-version ]]; then
|
# Version was already printed
|
||||||
echo "A2SERVER version available: $a2serverVersion"
|
|
||||||
echo "A2SERVER version installed: none"
|
|
||||||
fi
|
|
||||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||||
elif [[ $1 ]]; then
|
elif [[ $1 ]]; then
|
||||||
echo "options:"
|
echo "options:"
|
||||||
echo "-v: display installed and available versions, then exit"
|
echo "-v: display installed and available versions, then exit"
|
||||||
|
echo "-i: reinstall A2SERVER software (but not Apple II software)"
|
||||||
echo "-y: auto-answer yes to all prompts"
|
echo "-y: auto-answer yes to all prompts"
|
||||||
echo "-r: don't update package repositories"
|
echo "-r: don't update package repositories"
|
||||||
echo "-b: auto-setup network boot (use with -y)"
|
echo "-b: auto-setup network boot (use with -y)"
|
||||||
echo "-w: auto-setup Windows file sharing (use with -y)"
|
echo "-w: auto-setup Windows file sharing (use with -y)"
|
||||||
if [[ $isRpi ]]; then
|
echo "-c: compile non-package items, rather than downloading binaries"
|
||||||
echo "-os: update Raspbian OS, A2CLOUD, A2SERVER, and Apple II Pi"
|
|
||||||
fi
|
|
||||||
[[ $0 == "-bash" ]] && return 1 || exit 1
|
[[ $0 == "-bash" ]] && return 1 || exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ $updateRasppleII ]]; then
|
if { [[ -f /usr/local/etc/A2SERVER-version ]] && (( $(head -c 3 /usr/local/etc/A2SERVER-version) < 110 )); }; then
|
||||||
echo "A2SERVER: Updating Raspple II (takes up to an hour)..."
|
|
||||||
wget -qO /tmp/raspbian-update "http://appleii.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
|
||||||
echo "WARNING: The current A2SERVER installer scripts haven't been tested for"
|
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 "updating the earlier version of A2SERVER that you have. A fresh install"
|
||||||
@@ -94,29 +100,49 @@ fi
|
|||||||
a2server_update=0
|
a2server_update=0
|
||||||
doSetup=1
|
doSetup=1
|
||||||
|
|
||||||
|
if { [[ -f /usr/local/etc/A2SERVER-version ]] && (( $(head -c 3 /usr/local/etc/A2SERVER-version) < 152 )); }; then
|
||||||
|
a2server_update=1
|
||||||
|
fi
|
||||||
|
|
||||||
unsupportedOS=1
|
unsupportedOS=1
|
||||||
if [[ $isRpi ]]; then #supported Raspbian? (16-Feb-15, 20-Jun-14, 09-Jan-14, etc)
|
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=$(zcat /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz | grep -m 1 'as of' | awk '{print $NF}')
|
||||||
fwsupported="-8aca5762- -462f3e3f476f7b6- -c32bc633039cd9- -9d34d0475f9-
|
fwsupported="-8aca5762- -462f3e3f476f7b6- -c32bc633039cd9- -9d34d0475f9-
|
||||||
-d4f5315cfac4e- -6f4a90c8cb8817f- -5dd9b4962e- -17c8799375-
|
-d4f5315cfac4e- -6f4a90c8cb8817f- -5dd9b4962e- -17c8799375-
|
||||||
-960832a6c2590635216c296b6ee0bebf67b21d50-"
|
-960832a6c2590635216c296b6ee0bebf67b21d50-
|
||||||
[[ "$fwsupported" == *-$fwhash-* ]] && unsupportedOS=0
|
-2a329e0c7d8ea19c085bac5633aa4fccee0f21be-
|
||||||
[[ ($fwhash == "8aca5762") || ($fwhash == "462f3e3f476f7b6") || ($fwhash == "c32bc633039cd9") || ($fwhash == "9d34d0475f9") || ($fwhash == "d4f5315cfac4e") || ($fwhash == "6f4a90c8cb8817f") || ($fwhash == "5dd9b4962e") || ($fwhash == "17c8799375") ]] && unsupportedOS=0
|
-b2420fc150ae4616f5d9ec24bdaedc630586a529-"
|
||||||
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?
|
[[ "$fwsupported" == *-$fwhash-* ]] && unsupportedOS=
|
||||||
unsupportedOS=0
|
# [[ ($fwhash == "8aca5762") || ($fwhash == "462f3e3f476f7b6") || ($fwhash == "c32bc633039cd9") || ($fwhash == "9d34d0475f9") || ($fwhash == "d4f5315cfac4e") || ($fwhash == "6f4a90c8cb8817f") || ($fwhash == "5dd9b4962e") || ($fwhash == "17c8799375") ]] && unsupportedOS=
|
||||||
|
elif [[ $isDebian ]]; then # supported Debian?
|
||||||
|
debianVersion=$(cat /etc/debian_version)
|
||||||
|
debianSupported="-10.4- -9.2- -8.2- -7.9- -7.8- -7.6- -7.3-"
|
||||||
|
[[ $debianSupported == *-$debianVersion-* ]] && unsupportedOS=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (( unsupportedOS )); then
|
if [[ $unsupportedOS && $isRpi ]]; then
|
||||||
echo
|
echo
|
||||||
echo "WARNING: A2SERVER and its installer scripts have not been tested on this"
|
echo "A2SERVER and its installer scripts have been tested on Raspbian Buster,"
|
||||||
echo "operating system version. Continuing is probably fine, but might not be."
|
echo "Stretch, Jessie, and Wheezy, though not this specific firmware version"
|
||||||
echo "Worst case could make your operating system no longer work properly,"
|
echo "(${fwhash:0:7}). Just FYI."
|
||||||
echo "or cause data to be lost."
|
unsupportedOS=
|
||||||
echo "More information is at http://appleii.ivanx.com/a2server."
|
elif [[ $unsupportedOS && $isDebian ]]; then
|
||||||
|
echo
|
||||||
|
echo "A2SERVER and its installer scripts have been tested on Debian 7/8/9/10,"
|
||||||
|
echo "though not this specific point release ($debianVersion). Just FYI."
|
||||||
|
unsupportedOS=
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $unsupportedOS ]]; then
|
||||||
|
echo
|
||||||
|
echo "WARNING: A2SERVER and its installer scripts have only been tested on"
|
||||||
|
echo "Debian and Raspbian. Continuing is probably fine, but might not be."
|
||||||
|
echo "Theoretical worst case would be your operating system no longer works"
|
||||||
|
echo "properly or data is lost, so consider backing up first."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
doSetup=1
|
doSetup=1
|
||||||
if [[ ! -f /usr/local/etc/a2server-help.txt ]] || (( $a2server_update )); then
|
if [[ $installAll || ! -f /usr/local/etc/a2server-help.txt ]] || (( $a2server_update )); then
|
||||||
echo
|
echo
|
||||||
echo "Setting up A2SERVER will take up to 60 minutes, during which"
|
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 "you'll see a bunch of stuff spit out across the screen."
|
||||||
@@ -132,7 +158,7 @@ if (( $doSetup )); then
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "a2server-setup modifies files and performs actions as the root user."
|
echo "a2server-setup modifies files and performs actions as the root user."
|
||||||
echo "For details, visit http://appleii.ivanx.com/a2server."
|
echo "For details, visit http://ivanx.com/a2server."
|
||||||
echo
|
echo
|
||||||
if [[ ! $autoAnswerYes ]]; then
|
if [[ ! $autoAnswerYes ]]; then
|
||||||
echo -n "Continue? "
|
echo -n "Continue? "
|
||||||
@@ -142,34 +168,38 @@ if (( $doSetup )); then
|
|||||||
|
|
||||||
if (( $doSetup )); then
|
if (( $doSetup )); then
|
||||||
|
|
||||||
userPw=$(sudo grep "^$USER" /etc/shadow | cut -f 2 -d ':')
|
checkPw=1
|
||||||
[[ $userPw == "$(echo 'apple2' | perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "${userPw%"${userPw#\$*\$*\$}"}")" ]] && isApple2Pw=1 || isApple2Pw=
|
while [[ $checkPw ]] ; do
|
||||||
[[ $userPw == "$(echo 'raspberry' | perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "${userPw%"${userPw#\$*\$*\$}"}")" ]] && isRaspberryPw=1 || isRaspberryPw=
|
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=
|
||||||
password="your password"
|
[[ $userPw == "$(echo 'raspberry' | perl -e '$_ = <STDIN>; chomp; print crypt($_, $ARGV[0])' "${userPw%"${userPw#\$*\$*\$}"}")" ]] && isRaspberryPw=1 || isRaspberryPw=
|
||||||
[[ $isApple2Pw ]] && password="'apple2'"
|
|
||||||
[[ $isRaspberryPw ]] && password="'raspberry'"
|
password="your password"
|
||||||
|
[[ $isApple2Pw ]] && password="apple2"
|
||||||
|
[[ $isRaspberryPw ]] && password="raspberry"
|
||||||
[[ $isRpi ]] && a2server="your Raspberry Pi" || a2server="A2SERVER"
|
checkPw=
|
||||||
if [[ ! $isApple2Pw && ! -f /usr/local/etc/A2SERVER-version ]]; then
|
|
||||||
if [[ ! $autoAnswerYes ]]; then
|
[[ $isRpi ]] && a2server="your Raspberry Pi" || a2server="A2SERVER"
|
||||||
echo
|
if [[ ! $isApple2Pw && ! -f /usr/local/etc/A2SERVER-version ]]; then
|
||||||
echo "To ensure that all client computers are able to connect to"
|
if [[ ! $autoAnswerYes ]]; then
|
||||||
echo "${a2server} using the same password, you are recommended"
|
echo
|
||||||
echo "to change your user password to 'apple2'."
|
echo "To ensure that all client computers are able to connect to"
|
||||||
echo
|
echo "${a2server} using the same password, you probably want"
|
||||||
echo -n "Do you want to change the password for user '$USER' to 'apple2' now? "
|
echo "to change your user password to 'apple2'."
|
||||||
read
|
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
|
||||||
|
checkPw=1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if [[ $autoAnswerYes || ${REPLY:0:1} == "Y" || ${REPLY:0:1} == "y" ]]; then
|
done
|
||||||
echo "A2SERVER: changing password for user '$USER' to 'apple2'..."
|
|
||||||
echo "$USER:apple2" | sudo chpasswd
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "During this installation, enter ${password} if prompted for passwords."
|
echo "During this installation, enter '${password}' if prompted for passwords."
|
||||||
echo
|
echo
|
||||||
|
|
||||||
sudo true
|
sudo true
|
||||||
@@ -197,6 +227,16 @@ if (( $doSetup )); then
|
|||||||
|
|
||||||
echo "A2SERVER: Scripts have been downloaded. Installing..."
|
echo "A2SERVER: Scripts have been downloaded. Installing..."
|
||||||
|
|
||||||
|
if [[ $installAll ]]; then
|
||||||
|
sudo rm /usr/local/etc/A2SERVER-version 2> /dev/null
|
||||||
|
sudo rm /usr/local/bin/nulib2 2> /dev/null
|
||||||
|
sudo rm /usr/local/bin/unar 2> /dev/null
|
||||||
|
sudo rm /usr/local/sbin/macipgw 2> /dev/null
|
||||||
|
sudo rm /usr/local/bin/ciopfs 2> /dev/null
|
||||||
|
sudo rm /usr/local/etc/netatalk/afppasswd 2> /dev/null
|
||||||
|
sudo rm /usr/local/etc/netatalk/a2boot/p8 /usr/local/etc/netatalk/a2boot/ProDOS16\ Image 2> /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
/tmp/1.storage
|
/tmp/1.storage
|
||||||
rm /tmp/1.storage
|
rm /tmp/1.storage
|
||||||
/tmp/2.tools
|
/tmp/2.tools
|
||||||
@@ -212,11 +252,11 @@ if (( $doSetup )); then
|
|||||||
rm /tmp/a2server-packageReposUpdated &> /dev/null
|
rm /tmp/a2server-packageReposUpdated &> /dev/null
|
||||||
|
|
||||||
if [[ ! -f /usr/local/etc/A2SERVER-version ]] \
|
if [[ ! -f /usr/local/etc/A2SERVER-version ]] \
|
||||||
|| (( $(cat /usr/local/etc/A2SERVER-version) < "$a2serverVersion" )); then
|
|| (( $(head -c 3 /usr/local/etc/A2SERVER-version) < ${a2serverVersion:0:3} )); then
|
||||||
echo "$a2serverVersion" | sudo tee /usr/local/etc/A2SERVER-version &> /dev/null
|
echo "$a2serverVersion" | sudo tee /usr/local/etc/A2SERVER-version &> /dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
source /usr/local/etc/a2server-aliases
|
source /usr/local/etc/a2serverrc
|
||||||
|
|
||||||
# get Kernel release (e.g. 3.6.11+) and version (e.g. #557)
|
# get Kernel release (e.g. 3.6.11+) and version (e.g. #557)
|
||||||
kernelRelease=$(uname -r)
|
kernelRelease=$(uname -r)
|
||||||
@@ -230,7 +270,20 @@ if (( $doSetup )); then
|
|||||||
echo "On an Apple IIe, it should be accessible via \"Log In\" on the"
|
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 "Workstation Card software. For IIgs users, it should be accessible"
|
||||||
echo "via the AppleShare control panel."
|
echo "via the AppleShare control panel."
|
||||||
echo
|
if [[ -f /srv/A2SERVER/A2FILES/System/Start.GS.OS ]]; then
|
||||||
|
echo
|
||||||
|
echo "You can network boot GS/OS."
|
||||||
|
echo "On a ROM 01 IIgs, set slot 1 (printer port), or slot 2 (modem port)"
|
||||||
|
echo "to Your Card, and slot 7 to AppleTalk, and Startup Slot to 7 or Scan."
|
||||||
|
echo "On a ROM 3 IIgs, set slot 1 or 2, and Startup Slot, to AppleTalk."
|
||||||
|
fi
|
||||||
|
if [[ -f /srv/A2SERVER/A2FILES/BASIC.System ]]; then
|
||||||
|
echo
|
||||||
|
echo "You can network boot ProDOS 8. On an Apple IIe, put your Workstation Card"
|
||||||
|
echo "in a slot above your disk controller card, or type PR#X with open-apple"
|
||||||
|
echo "held down, with X being the slot of your Workstation Card."
|
||||||
|
echo 'On a IIgs, press "8" during the initial procession of periods.'
|
||||||
|
fi
|
||||||
echo
|
echo
|
||||||
echo "A2SERVER setup is complete! Go connect from your Apple II!"
|
echo "A2SERVER setup is complete! Go connect from your Apple II!"
|
||||||
echo
|
echo
|
||||||
@@ -266,9 +319,18 @@ if (( $doSetup )); then
|
|||||||
echo "by typing 'appletalk-on'."
|
echo "by typing 'appletalk-on'."
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -f /tmp/noMacIP ]]; then
|
||||||
|
echo
|
||||||
|
echo "MacIP connections may be unavailable. If you know how, try"
|
||||||
|
echo "recompiling the AppleTalk kernel module with IPDDP options disabled."
|
||||||
|
echo
|
||||||
|
rm /tmp/noMacIP
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -f /tmp/singleUser ]]; then
|
if [[ -f /tmp/singleUser ]]; then
|
||||||
if [[ ! $autoAnswerYes ]]; then
|
if [[ ! $autoAnswerYes ]]; then
|
||||||
|
echo
|
||||||
echo "Your Raspberry Pi was started in single-user mode in order to"
|
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? "
|
echo -n "fix a problem. You should restart to operate normally. Restart now? "
|
||||||
read
|
read
|
||||||
@@ -279,6 +341,7 @@ if (( $doSetup )); then
|
|||||||
echo "A2SERVER: Preparing to restart..."
|
echo "A2SERVER: Preparing to restart..."
|
||||||
while :; do sleep 60; done
|
while :; do sleep 60; done
|
||||||
fi
|
fi
|
||||||
|
rm /tmp/singleUser
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -291,8 +354,5 @@ fi
|
|||||||
|
|
||||||
unset a2server_update 2> /dev/null
|
unset a2server_update 2> /dev/null
|
||||||
unset doSetup 2> /dev/null
|
unset doSetup 2> /dev/null
|
||||||
rm /tmp/a2server-autoAnswerYes 2> /dev/null
|
rm /tmp/a2server-* 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
|
rm setup &> /dev/null
|
||||||
|
120
update/devhistory.txt
Normal file
120
update/devhistory.txt
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
1.2.4+:Oct 2015: support for using A2SERVER scripts from a location other than
|
||||||
|
[unannounced] ivanx.com/a2server for development purposes
|
||||||
|
|
||||||
|
1.2.5: Nov 2015: netboot install option for GS/OS 6.0.2/3
|
||||||
|
netboot always downloads GS/OS disk images even if present
|
||||||
|
provides error if a2setup doesn't have internet
|
||||||
|
remove persisting a2server-setup options after aborted install
|
||||||
|
fixed installer bug that omits first and last script elements
|
||||||
|
download images from Apple, with Internet Archive as a backup
|
||||||
|
install HFS.FST during netboot install
|
||||||
|
|
||||||
|
1.2.5+:Nov 2015: Merged Ivan's 1.2.5 release, removed support for Ubuntu for
|
||||||
|
[unannounced] now (see RasppleII/a2server#11), patched ProDOS 8 in boot
|
||||||
|
files for current year table, install unar from a package if
|
||||||
|
it exists.
|
||||||
|
|
||||||
|
1.2.6: Nov 2015: full, ready to use install of Spectrum; install unzip
|
||||||
|
[unannounced]
|
||||||
|
|
||||||
|
1.2.6+:Nov 2015: merged Ivan's 1.2.6 (into github master branch)
|
||||||
|
[unannounced]
|
||||||
|
|
||||||
|
1.2.7: Dec 2015: preliminary Jessie support; case insensitive file system for
|
||||||
|
[unannounced] A2FILES; removes GSFILES if empty; DOS3.3.FST and TEACH are
|
||||||
|
installed with netboot installation; minor bug fixes and
|
||||||
|
tweaks; Ubuntu support removed; branches unified
|
||||||
|
|
||||||
|
1.2.8: Dec 2015: can specify alternate host for binaries and external files;
|
||||||
|
[unannounced] 64-bit Debian precompiled binaries; move /media/A2SHARED/*
|
||||||
|
to /srv/A2SERVER; internet access (MacIP support);
|
||||||
|
|
||||||
|
1.2.9: Jan 2016: cppo supports ShrinkIt, DOS 3.3, DSK, 2MG; MountIt fully
|
||||||
|
[unannounced] installed; nulib2 fixes handling empty forks (thanks Andy);
|
||||||
|
-c installer option compiles all software (no binaries)
|
||||||
|
|
||||||
|
1.3.0: Jan 2016: Marinetti 3.0b8 installed, with preconfigured MacIP
|
||||||
|
[unannounced]
|
||||||
|
|
||||||
|
1.3.1: Jan 2016: patch Prodos 8 Thunderclock year table based on current date
|
||||||
|
[unannounced]
|
||||||
|
|
||||||
|
1.3.2: Jan 2016: install SAFE2, SAM2, and SNAP, configured for Apple II sites;
|
||||||
|
[unannounced] -i installer option reinstalls A2SERVER
|
||||||
|
|
||||||
|
1.5.0: Jan 2016: defaults to GitHub for location of installer scripts
|
||||||
|
[unannounced]
|
||||||
|
|
||||||
|
1.5.1: May 2016: changed URLs from rawgit.com to raw.githubusercontent.com
|
||||||
|
to resolve https problems during install; OS X temp dir
|
||||||
|
path corrected; added getexternal.sh to repo;
|
||||||
|
cppo changes; minor text changes (JTC); better Debian
|
||||||
|
version checking (JTC)
|
||||||
|
[unannounced]
|
||||||
|
|
||||||
|
1.5.1r2: Oct 2017: set internal version to 1.5.1; expanded version history
|
||||||
|
[unannounced]
|
||||||
|
|
||||||
|
1.5.2: Nov 2017: support for Stretch; suppress null byte read warnings in
|
||||||
|
Bash 4.4; enable SSH server on Raspberry Pi if disabled;
|
||||||
|
use Internet Archive backup URL's for external downloads if
|
||||||
|
possible; compile AppleTalk kernel if -c flag is
|
||||||
|
specified (rather than downloading); better cleanup after
|
||||||
|
AppleTalk kernel compile; notification if AppleTalk kernel
|
||||||
|
module doesn't load; fixed download links for comm software;
|
||||||
|
bug fixes when compiling macipgw and ciopfs;
|
||||||
|
os option (Raspbian update) removed from a2server-setup
|
||||||
|
|
||||||
|
1.5.3a1: July 2020: initial support for Debian/Raspbian Buster
|
@@ -1,7 +1,13 @@
|
|||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
# vim: set tabstop=4 shiftwidth=4 expandtab filetype=sh:
|
||||||
|
|
||||||
currentVersion=127
|
# Ensure URL we'll use ends in a /
|
||||||
|
case "$A2SERVER_SCRIPT_URL" in
|
||||||
|
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
||||||
|
*) scriptURL="${A2SERVER_SCRIPT_URL:-https://raw.githubusercontent.com/RasppleII/a2server/current}/" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
currentVersion=$(wget -qO- "${scriptURL}setup/index.txt" | grep '^a2serverVersion' | cut -d '"' -f 2)
|
||||||
|
|
||||||
if [[ -f /usr/local/etc/A2SERVER-version ]]; then
|
if [[ -f /usr/local/etc/A2SERVER-version ]]; then
|
||||||
installedVersion=$(cat /usr/local/etc/A2SERVER-version)
|
installedVersion=$(cat /usr/local/etc/A2SERVER-version)
|
||||||
@@ -9,12 +15,6 @@ else
|
|||||||
installedVersion=100
|
installedVersion=100
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure URL we'll use ends in a /
|
|
||||||
case "$A2SERVER_SCRIPT_URL" in
|
|
||||||
*/) scriptURL="$A2SERVER_SCRIPT_URL" ;;
|
|
||||||
*) scriptURL="${A2SERVER_SCRIPT_URL:-http://appleii.ivanx.com/a2server}/" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
autoAnswerYes=
|
autoAnswerYes=
|
||||||
for arg in $@; do
|
for arg in $@; do
|
||||||
if [[ $arg == "-y" ]]; then
|
if [[ $arg == "-y" ]]; then
|
||||||
@@ -37,9 +37,8 @@ else
|
|||||||
read
|
read
|
||||||
fi
|
fi
|
||||||
if [[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]]; then
|
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
|
# sudo rm /usr/local/etc/netatalk/a2boot/* &> /dev/null
|
||||||
wget -q -O /tmp/setup "${scriptURL}setup"; source /tmp/setup "$@"
|
wget -q -O /tmp/setup "${scriptURL}setup/index.txt"; source /tmp/setup -i "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
unset currentVersion 2> /dev/null
|
unset currentVersion 2> /dev/null
|
||||||
|
@@ -48,34 +48,41 @@
|
|||||||
|
|
||||||
1.2.3: May 2015: changed Apple software links to Internet Archive
|
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
|
1.2.4: Jul 2015: install option for ProTERM, Z.Link, ADTPro, Spectrum images
|
||||||
|
|
||||||
1.2.4+:Oct 2015: support for using A2SERVER scripts from a location other than
|
1.2.5: Nov 2015: netboot install option for GS/OS 6.0.2/3; install HFS.FST
|
||||||
appleii.ivanx.com/a2server for development purposes
|
during netboot install
|
||||||
[not released]
|
|
||||||
|
|
||||||
1.2.5: Nov 2015: netboot install option for GS/OS 6.0.2/3
|
1.2.6: Nov 2015: full, ready to use install of Spectrum
|
||||||
netboot always downloads GS/OS disk images even if present
|
[unannounced; released briefly, then withdrawn]
|
||||||
provides error if a2setup doesn't have internet
|
|
||||||
remove persisting a2server-setup options after aborted install
|
|
||||||
fixed installer bug that omits first and last script elements
|
|
||||||
download images from Apple, with Internet Archive as a backup
|
|
||||||
install HFS.FST during netboot install
|
|
||||||
|
|
||||||
1.2.5+:Nov 2015: Merged Ivan's 1.2.5 release, removed support for Ubuntu for
|
1.5.0: Jan 2016: mixed case filenames for A2FILES; remove GSFILES if empty;
|
||||||
now (see RasppleII/a2server#11), patched ProDOS 8 in boot
|
install Marinetti 3.0b8 with internet access via MacIP;
|
||||||
files for current year table, install unar from a package if
|
fully install Spectrum, SAFE2, SAM2, SNAP, MountIt; install
|
||||||
it exists.
|
DOS3.3 and TEACH; remove Ubuntu support; move/media/A2SHARED/*
|
||||||
[not released]
|
to /srv/A2SERVER; faster install (precompiled binaries) on
|
||||||
|
64-bit Debian; cppo supports ShrinkIt, DOS 3.3, DSK, 2MG,mixed
|
||||||
|
case filenames; nulib2 handles empty forks (thanks Andy);
|
||||||
|
new installer options; patch P8 Thunderclock driver year table
|
||||||
|
for current date; install from any host URL for development;
|
||||||
|
source code at GitHub (thanks Joseph)
|
||||||
|
|
||||||
1.2.6: Nov 2015: full, ready to use install of Spectrum; install unzip
|
1.5.1: Jan 2016: fixed GitHub URLs to prevent https errors during installation
|
||||||
[released briefly, then withdrawn]
|
(thanks to http://blogs.yahoo.co.jp/ushi_cow/57459736.html);
|
||||||
|
bug fixes and minor text changes
|
||||||
|
|
||||||
1.2.6+:Nov 2015: merged Ivan's 1.2.6
|
1.5.1r2: Oct 2017: corrected version number
|
||||||
[not released]
|
|
||||||
|
1.5.2: Nov 2017: support for Debian/Raspbian Stretch; fixes minor bugs during
|
||||||
|
install; enable SSH server if disabled on Raspberry Pi; fixes
|
||||||
|
changed download links for GS/OS communication software
|
||||||
|
|
||||||
|
1.5.3a2: July 2020: initial support for Debian/Raspbian Buster
|
||||||
|
|
||||||
1.2.7: Dec 2015: codebase unified; preliminary Jessie support; case insensitive
|
Big thanks to: Anthony Martino, Henry Courbis, Joseph Carter, Jason King,
|
||||||
file system for A2FILES; removes GSFILES if empty; DOS3.3.FST
|
Andy McFadden, Steven Hirsch, Geoff Body, Peter Wong, Tony Diaz, David Schmidt,
|
||||||
and TEACH are installed with netboot installation; minor bug
|
David Schmenk, Ewen Wannop, Andrew Roughan, Antoine Vignau, Martin Haye,
|
||||||
fixes and tweaks
|
Ken Gagne, Peter Neubauer, James Littlejohn, Ninjaforce; the creators of
|
||||||
[not released]
|
Netatalk, The Unarchiver, ciopfs, macipgw; and the entire Apple II community.
|
||||||
|
Redistribution of Spectrum, SAFE2, SAM2, SNAP by permission of Ewen Wannop.
|
||||||
|
Thanks for using A2SERVER!
|
||||||
|
Reference in New Issue
Block a user