Combine Dependencies; Other Improvements
-Removed CPU intensive python based telnet server option -Removed Micropython -Renamed AT Telnet Daemon socat-at bridge -Moved TTL related files not part of the www/cgi-bin directory to /simplefirewall -Improved Simplefirewall menu, added ability to change TTL -Combined uninstall and install functions for simpleadmin and dependencies into single functions
This commit is contained in:
@@ -1,29 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Define paths
|
||||
USRDATA_DIR="/usrdata"
|
||||
MICROPYTHON_DIR="/usrdata/micropython"
|
||||
AT_TELNET_DIR="/usrdata/at-telnet"
|
||||
AT_TELNET_SYSD_DIR="/usrdata/at-telnet/systemd_units"
|
||||
AT_TELNET_SMD7_SYSD_DIR="/usrdata/at-telnet/smd7_systemd_units"
|
||||
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
|
||||
# Define toolkit paths
|
||||
GITTREE="development"
|
||||
TMP_DIR="/tmp"
|
||||
GITHUB_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/main.zip"
|
||||
GITHUB_SIMPADMIN_FULL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminfull.zip"
|
||||
GITHUB_SIMPADMIN_NOCMD_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminnoatcmds.zip"
|
||||
GITHUB_SIMPADMIN_TTL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminttlonly.zip"
|
||||
GITHUB_SIMPADMIN_TEST_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadmintest.zip"
|
||||
TAILSCALE_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
USRDATA_DIR="/usrdata"
|
||||
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
|
||||
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
|
||||
SOCAT_AT_SMD7_SYSD_DIR="/usrdata/socat-at-bridge/smd7_systemd_units"
|
||||
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
|
||||
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
|
||||
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
|
||||
SIMPLE_FIREWALL_SERVICE="/lib/systemd/system/simplefirewall.service"
|
||||
|
||||
GITHUB_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/$GITTREE.zip"
|
||||
GITHUB_SIMPADMIN_FULL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminfullatcmds.zip"
|
||||
GITHUB_SIMPADMIN_TTL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminttlonly.zip"
|
||||
GITHUB_SIMPADMIN_TEST_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadmintest.zip"
|
||||
TAILSCALE_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
# AT Command Script Variables and Functions
|
||||
DEVICE_FILE="/dev/smd7"
|
||||
TIMEOUT=4 # Set a timeout for the response
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Basic AT commands without socat bridge for fast responce commands only
|
||||
start_listening() {
|
||||
cat "$DEVICE_FILE" > /tmp/device_readout &
|
||||
CAT_PID=$!
|
||||
@@ -93,195 +101,40 @@ send_at_commands() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Check if AT Telnet Daemon is installed
|
||||
is_at_telnet_installed() {
|
||||
[ -d "$MICROPYTHON_DIR" ] && return 0 || return 1
|
||||
[ -d "$AT_TELNET_DIR" ] && return 0 || return 1
|
||||
}
|
||||
|
||||
# Function to check if Simple Firewall is installed
|
||||
is_simple_firewall_installed() {
|
||||
if [ -d "$SIMPLE_FIREWALL_DIR" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if Simple Admin is installed
|
||||
is_simple_admin_installed() {
|
||||
[ -d "$SIMPLE_ADMIN_DIR" ] && return 0 || return 1
|
||||
}
|
||||
|
||||
# Function to install/update Simple Firewall
|
||||
install_update_simple_firewall() {
|
||||
echo "Installing/Updating Simple Firewall..."
|
||||
mount -o remount,rw /
|
||||
mkdir -p "$SIMPLE_FIREWALL_DIR"
|
||||
mkdir -p "$SIMPLE_FIREWALL_SYSTEMD_DIR"
|
||||
wget -O "$SIMPLE_FIREWALL_SCRIPT" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/simplefirewall/simplefirewall.sh
|
||||
chmod +x "$SIMPLE_FIREWALL_SCRIPT"
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/simplefirewall/systemd/simplefirewall.service
|
||||
cp -f "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" "$SIMPLE_FIREWALL_SERVICE"
|
||||
ln -sf "$SIMPLE_FIREWALL_SERVICE" "/lib/systemd/system/multi-user.target.wants/"
|
||||
systemctl daemon-reload
|
||||
systemctl restart simplefirewall
|
||||
mount -o remount,ro /
|
||||
echo "Simple Firewall installation/update complete."
|
||||
}
|
||||
|
||||
# Function to uninstall Simple Firewall
|
||||
uninstall_simple_firewall() {
|
||||
echo "Uninstalling Simple Firewall..."
|
||||
mount -o remount,rw /
|
||||
systemctl stop simplefirewall
|
||||
rm -f "/lib/systemd/system/multi-user.target.wants/simplefirewall.service"
|
||||
rm -f "$SIMPLE_FIREWALL_SERVICE"
|
||||
rm -rf "$SIMPLE_FIREWALL_DIR"
|
||||
systemctl daemon-reload
|
||||
mount -o remount,ro /
|
||||
echo "Simple Firewall uninstalled."
|
||||
}
|
||||
|
||||
# Function to configure Simple Firewall
|
||||
configure_simple_firewall() {
|
||||
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
|
||||
echo "Simple Firewall script not found."
|
||||
return
|
||||
fi
|
||||
|
||||
# Extract current ports configuration
|
||||
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
|
||||
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
|
||||
echo "$ports" | awk '{print NR") "$0}'
|
||||
|
||||
while true; do
|
||||
echo "Enter a port number to add/remove, or type 'done' to finish:"
|
||||
read port
|
||||
if [ "$port" = "done" ]; then
|
||||
break
|
||||
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
|
||||
echo "Invalid input: Please enter a numeric value."
|
||||
elif echo "$ports" | grep -q "^$port\$"; then
|
||||
# Remove port
|
||||
ports=$(echo "$ports" | grep -v "^$port\$")
|
||||
echo "Port $port removed."
|
||||
else
|
||||
# Add port
|
||||
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
|
||||
echo "Port $port added."
|
||||
fi
|
||||
done
|
||||
|
||||
# Prepare updated ports line
|
||||
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
|
||||
|
||||
# Update the script with new ports
|
||||
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
|
||||
systemctl restart simplefirewall
|
||||
echo "Firewall configuration updated."
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# Function for Simplefirewall Submenu
|
||||
simplefirewall_menu() {
|
||||
while true; do
|
||||
echo "Simple Firewall Management"
|
||||
echo "1) Install/Update/Uninstall Simple Firewall"
|
||||
echo "2) Configure Simple Firewall"
|
||||
echo "3) Exit"
|
||||
read -p "Enter your choice: " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
if is_simple_firewall_installed; then
|
||||
echo "Simple Firewall is already installed."
|
||||
echo "1) Update Simple Firewall"
|
||||
echo "2) Uninstall Simple Firewall"
|
||||
read -p "Enter your choice: " update_uninstall_choice
|
||||
case $update_uninstall_choice in
|
||||
1) install_update_simple_firewall;;
|
||||
2) uninstall_simple_firewall;;
|
||||
*) echo "Invalid option";;
|
||||
esac
|
||||
else
|
||||
install_update_simple_firewall
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
configure_simple_firewall
|
||||
;;
|
||||
3)
|
||||
echo "Exiting..."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# Function to install/update AT Telnet Daemon
|
||||
install_update_at_telnet() {
|
||||
# Function to install/update AT Socat Bridge
|
||||
install_update_at_socat() {
|
||||
remount_rw
|
||||
mkdir $MICROPYTHON_DIR
|
||||
mkdir $AT_TELNET_DIR
|
||||
cd $MICROPYTHON_DIR
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/errno.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/fcntl.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/ffilib.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/logging.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/micropython
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/os_compat.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/serial.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/stat.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/time.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/traceback.mpy
|
||||
cd $AT_TELNET_DIR
|
||||
mkdir $AT_TELNET_SYSD_DIR
|
||||
mkdir $AT_TELNET_SMD7_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/modem-multiclient.py
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/picocom
|
||||
mkdir "$SOCAT_AT_DIR"
|
||||
cd "$SOCAT_AT_DIR"
|
||||
mkdir $SOCAT_AT_SYSD_DIR
|
||||
mkdir $SOCAT_AT_SMD7_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/socat-armel-static
|
||||
cd $AT_TELNET_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/socat-smd11.service
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/at-telnet-daemon.service
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/socat-smd11-from-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/socat-smd11-to-ttyIN.service
|
||||
cd $AT_TELNET_SMD7_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/at-telnet-daemon.service
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/socat-smd7-from-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/socat-smd7-to-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/socat-smd7.service
|
||||
|
||||
# Set execute permissions
|
||||
chmod +x $MICROPYTHON_DIR/micropython
|
||||
chmod +x $AT_TELNET_DIR/modem-multiclient.py
|
||||
chmod +x $AT_TELNET_DIR/socat-armel-static
|
||||
chmod +x $AT_TELNET_DIR/picocom
|
||||
chmod +x "$SOCAT_AT_DIR"/socat-armel-static
|
||||
|
||||
# User prompt for selecting device
|
||||
echo "Which device should AT over Telnet use?"
|
||||
echo "Which device should Simpleadmin use?"
|
||||
echo "This will create virtual tty ports (serial ports) that will use either smd11 or smd7"
|
||||
echo "1) Use smd11 (default)"
|
||||
echo "2) Use smd7 (use this if another application is using smd11)"
|
||||
echo "2) Use smd7 (use this if another application is using smd11 already)"
|
||||
read -p "Enter your choice (1 or 2): " device_choice
|
||||
|
||||
# Stop and disable existing services before installing new ones
|
||||
echo -e "\033[0;32mThese errors are OK, script tries to remove all first in case you are updating\033[0m"
|
||||
systemctl stop at-telnet-daemon
|
||||
systemctl disable at-telnet-daemon
|
||||
systemctl stop socat-smd11
|
||||
@@ -298,7 +151,8 @@ install_update_at_telnet() {
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN.service
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN.service
|
||||
systemctl daemon-reload
|
||||
|
||||
echo -e "\033[0;32mThese errors are OK, script tries to remove all first in case you are updating\033[0m"
|
||||
|
||||
# Depending on the choice, copy the respective systemd unit files
|
||||
case $device_choice in
|
||||
2)
|
||||
@@ -311,6 +165,7 @@ install_update_at_telnet() {
|
||||
sleep 2s
|
||||
systemctl start socat-smd7-to-ttyIN
|
||||
systemctl start socat-smd7-from-ttyIN
|
||||
cd /
|
||||
;;
|
||||
1)
|
||||
cp -f $AT_TELNET_SYSD_DIR/*.service /lib/systemd/system
|
||||
@@ -322,195 +177,203 @@ install_update_at_telnet() {
|
||||
sleep 2s
|
||||
systemctl start socat-smd11-to-ttyIN
|
||||
systemctl start socat-smd11-from-ttyIN
|
||||
cd /
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
# User prompt for enabling Telnet server
|
||||
echo "-Telnet server is not required for simpleadmin"
|
||||
echo "-Simpleadmin uses the tty port created in the previous step"
|
||||
echo "-If enabled a telnet server will listen on the gateway address on port 5000"
|
||||
echo "-It isn't password protceted though so it is recommended to only enable if you need it"
|
||||
echo "Enable Telnet server?"
|
||||
echo "1) Yes"
|
||||
echo "2) No"
|
||||
read -p "Enter your choice (1 or 2): " telnet_choice
|
||||
|
||||
# Link or remove systemd files based on user choice
|
||||
if [ "$telnet_choice" = "1" ]; then
|
||||
ln -sf /lib/systemd/system/at-telnet-daemon.service /lib/systemd/system/multi-user.target.wants/
|
||||
|
||||
# Start Services
|
||||
systemctl start at-telnet-daemon
|
||||
remount_ro
|
||||
else
|
||||
remount_ro
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# Function to remove AT Telnet Daemon
|
||||
remove_at_telnet() {
|
||||
remount_rw
|
||||
# Stop and disable all possible services related to AT Telnet Daemon
|
||||
systemctl stop at-telnet-daemon
|
||||
systemctl disable at-telnet-daemon
|
||||
systemctl stop socat-smd11
|
||||
systemctl stop socat-smd11-to-ttyIN
|
||||
systemctl stop socat-smd11-from-ttyIN
|
||||
systemctl stop socat-smd7
|
||||
systemctl stop socat-smd7-to-ttyIN
|
||||
systemctl stop socat-smd7-from-ttyIN
|
||||
|
||||
# Remove all systemd service files for both smd11 and smd7 configurations
|
||||
rm /lib/systemd/system/at-telnet-daemon.service
|
||||
rm /lib/systemd/system/socat-smd11.service
|
||||
rm /lib/systemd/system/socat-smd11-to-ttyIN.service
|
||||
rm /lib/systemd/system/socat-smd11-from-ttyIN.service
|
||||
rm /lib/systemd/system/socat-smd7.service
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN.service
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN.service
|
||||
|
||||
# Reload systemd to apply changes
|
||||
# Function to install Simple Firewall
|
||||
install_simple_firewall() {
|
||||
systemctl stop simplefirewall
|
||||
systemctl stop ttl-overide
|
||||
echo -e "\033[0;32mInstalling/Updating Simple Firewall...\033[0m"
|
||||
mount -o remount,rw /
|
||||
mkdir -p "$SIMPLE_FIREWALL_DIR"
|
||||
mkdir -p "$SIMPLE_FIREWALL_SYSTEMD_DIR"
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/simplefirewall.sh" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/simplefirewall.sh
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttl-overide" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttl-overide
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttlvalue" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttlvalue
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/ttl-overide"
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/simplefirewall.service
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/ttl-overide.service" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/ttl-overide.service
|
||||
cp -f $SIMPLE_FIREWALL_SYSTEMD_DIR/* /lib/systemd/system
|
||||
ln -sf "/lib/systemd/system/simplefirewall.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
ln -sf "/lib/systemd/system/ttl-overide.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
systemctl daemon-reload
|
||||
|
||||
# Prompt user before removing micropython
|
||||
echo "Do you want to remove MicroPython?"
|
||||
echo "1) Yes"
|
||||
echo "2) No"
|
||||
read -p "Enter your choice: " choice
|
||||
|
||||
case $choice in
|
||||
1 )
|
||||
rm -rf $MICROPYTHON_DIR
|
||||
echo "MicroPython directory removed."
|
||||
;;
|
||||
2 )
|
||||
echo "MicroPython directory not removed."
|
||||
;;
|
||||
* )
|
||||
echo "Invalid choice. MicroPython directory not removed."
|
||||
;;
|
||||
esac
|
||||
|
||||
# Remove the AT Telnet Daemon directory
|
||||
rm -rf $AT_TELNET_DIR
|
||||
systemctl start simplefirewall
|
||||
systemctl start ttl-overide
|
||||
remount_ro
|
||||
echo "AT Telnet Daemon removed successfully."
|
||||
echo -e "\033[0;32mSimple Firewall installation/update complete.\033[0m"
|
||||
}
|
||||
|
||||
configure_simple_firewall() {
|
||||
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
|
||||
echo "Simple Firewall script not found."
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Configuring Simple Firewall:"
|
||||
echo "1) Configure incoming port block"
|
||||
echo "2) Configure TTL"
|
||||
read -p "Enter your choice (1-2): " menu_choice
|
||||
|
||||
case $menu_choice in
|
||||
1)
|
||||
# Original ports configuration code with exit option
|
||||
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
|
||||
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
|
||||
echo "Current configured ports:"
|
||||
echo "$ports" | awk '{print NR") "$0}'
|
||||
|
||||
while true; do
|
||||
echo "Enter a port number to add/remove, or type 'done' or 'exit' to finish:"
|
||||
read port
|
||||
if [ "$port" = "done" ] || [ "$port" = "exit" ]; then
|
||||
if [ "$port" = "exit" ]; then
|
||||
echo "Exiting without making changes..."
|
||||
return
|
||||
fi
|
||||
break
|
||||
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
|
||||
echo "Invalid input: Please enter a numeric value."
|
||||
elif echo "$ports" | grep -q "^$port\$"; then
|
||||
ports=$(echo "$ports" | grep -v "^$port\$")
|
||||
echo "Port $port removed."
|
||||
else
|
||||
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
|
||||
echo "Port $port added."
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$port" != "exit" ]; then
|
||||
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
|
||||
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
# TTL configuration code
|
||||
ttl_value=$(cat /usrdata/simplefirewall/ttlvalue)
|
||||
if [ "$ttl_value" -eq 0 ]; then
|
||||
echo "TTL is not set."
|
||||
else
|
||||
echo "TTL value is set to $ttl_value."
|
||||
fi
|
||||
|
||||
echo "Type 'exit' to cancel."
|
||||
read -p "What do you want the TTL value to be: " new_ttl_value
|
||||
if [ "$new_ttl_value" = "exit" ]; then
|
||||
echo "Exiting TTL configuration..."
|
||||
return
|
||||
elif ! echo "$new_ttl_value" | grep -qE '^[0-9]+$'; then
|
||||
echo "Invalid input: Please enter a numeric value."
|
||||
return
|
||||
else
|
||||
echo "$new_ttl_value" > /usrdata/simplefirewall/ttlvalue
|
||||
echo "TTL value updated to $new_ttl_value."
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice. Please select either 1 or 2."
|
||||
;;
|
||||
esac
|
||||
|
||||
systemctl restart simplefirewall
|
||||
echo "Firewall configuration updated."
|
||||
}
|
||||
|
||||
# Function to install/update Simple Admin
|
||||
install_update_simple_admin() {
|
||||
install_simple_admin() {
|
||||
while true; do
|
||||
echo "Make sure to Install AT Telnet Daemon first. You don't need to Enable the Telnet Server if you don't need it"
|
||||
echo "What version of Simple Admin do you want to install? This will start a webserver on port 8080"
|
||||
echo "What version of Simple Admin do you want to install? This will start a webserver on port 8080"
|
||||
echo "1) Full Install"
|
||||
echo "2) No AT Commands, List only (for use with firmware that already has a web UI)"
|
||||
echo "2) No AT Commands, List only "
|
||||
echo "3) TTL Only"
|
||||
echo "4) Install Test Build (work in progress/not ready yet)"
|
||||
echo "4) Install Test Build (work in progress/not ready yet)"
|
||||
echo "5) Return to Main Menu"
|
||||
echo "Select your choice: "
|
||||
read choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
install_update_at_socat
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_FULL_URL -O simpleadminfull.zip
|
||||
unzip -o simpleadminfull.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadminfull/simpleadmin/ $USRDATA_DIR
|
||||
|
||||
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
|
||||
|
||||
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
|
||||
|
||||
systemctl start simpleadmin_generate_status
|
||||
systemctl start simpleadmin_httpd
|
||||
systemctl start ttl-override
|
||||
remount_ro
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminfull.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminfull/
|
||||
break
|
||||
;;
|
||||
2)
|
||||
install_update_at_socat
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_NOCMD_URL -O simpleadminnoatcmds.zip
|
||||
unzip -o simpleadminnoatcmds.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadminnoatcmds/simpleadmin/ $USRDATA_DIR
|
||||
|
||||
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
|
||||
|
||||
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
|
||||
|
||||
systemctl start simpleadmin_generate_status
|
||||
systemctl start simpleadmin_httpd
|
||||
systemctl start ttl-override
|
||||
remount_ro
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminnoatcmds.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminnoatcmds/
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminnoatcmds.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminnoatcmds/
|
||||
break
|
||||
;;
|
||||
3)
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_TTL_URL -O simpleadminttlonly.zip
|
||||
unzip -o simpleadminttlonly.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadminttlonly/simpleadmin/ $USRDATA_DIR
|
||||
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
|
||||
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
|
||||
|
||||
systemctl start simpleadmin_httpd
|
||||
systemctl start ttl-override
|
||||
remount_ro
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminttlonly.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminttlonly/
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminttlonly.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminttlonly/
|
||||
break
|
||||
;;
|
||||
4)
|
||||
remount_rw
|
||||
install_update_at_socat
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_TEST_URL -O simpleadmintest.zip
|
||||
wget $GITHUB_SIMPADMIN_FULL_URL -O simpleadmintest.zip
|
||||
unzip -o simpleadmintest.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadmintest/simpleadmin/ $USRDATA_DIR
|
||||
|
||||
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
|
||||
|
||||
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
|
||||
|
||||
systemctl start simpleadmin_generate_status
|
||||
systemctl start simpleadmin_httpd
|
||||
systemctl start ttl-override
|
||||
remount_ro
|
||||
break
|
||||
;;
|
||||
@@ -525,23 +388,70 @@ install_update_simple_admin() {
|
||||
done
|
||||
}
|
||||
|
||||
# Function to Uninstall Simpleadmin and dependencies
|
||||
uninstall_simpleadmin_components() {
|
||||
echo "Starting the uninstallation process for Simpleadmin components."
|
||||
echo "Note: Uninstalling certain components may affect the functionality of others."
|
||||
|
||||
# Uninstall Simple Firewall
|
||||
echo "Do you want to uninstall Simplefirewall?"
|
||||
echo "If you do, the TTL part of simpleadmin will no longer work."
|
||||
echo "1) Yes"
|
||||
echo "2) No"
|
||||
read -p "Enter your choice (1 or 2): " choice_simplefirewall
|
||||
if [ "$choice_simplefirewall" -eq 1 ]; then
|
||||
echo "Uninstalling Simplefirewall..."
|
||||
systemctl stop simplefirewall
|
||||
systemctl stop ttl-overide
|
||||
rm -f /lib/systemd/system/simplefirewall.service
|
||||
rm -f /lib/systemd/system/ttl-overide.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$SIMPLE_FIREWALL_DIR"
|
||||
echo "Simplefirewall uninstalled."
|
||||
fi
|
||||
|
||||
# Function to remove Simple Admin
|
||||
remove_simple_admin() {
|
||||
remount_rw
|
||||
systemctl stop simpleadmin_generate_status
|
||||
systemctl stop ttl-override
|
||||
systemctl stop simpleadmin_httpd
|
||||
systemctl disable simpleadmin_httpd
|
||||
systemctl disable ttl-override
|
||||
systemctl disable simpleadmin_httpd
|
||||
rm -rf $SIMPLE_ADMIN_DIR
|
||||
rm /lib/systemd/system/simpleadmin_httpd.service
|
||||
rm /lib/systemd/system/simpleadmin_generate_status.service
|
||||
rm /lib/systemd/system/ttl-override.service
|
||||
systemctl daemon-reload
|
||||
remount_ro
|
||||
# Uninstall socat-at-bridge
|
||||
echo "Do you want to uninstall socat-at-bridge?"
|
||||
echo "If you do, AT commands and the stat page will no longer work."
|
||||
echo "1) Yes"
|
||||
echo "2) No"
|
||||
read -p "Enter your choice (1 or 2): " choice_socat_at_bridge
|
||||
if [ "$choice_socat_at_bridge" -eq 1 ]; then
|
||||
echo "Uninstalling socat-at-bridge..."
|
||||
systemctl stop socat-smd11
|
||||
systemctl stop socat-smd11-to-ttyIN
|
||||
systemctl stop socat-smd11-from-ttyIN
|
||||
systemctl stop socat-smd7
|
||||
systemctl stop socat-smd7-to-ttyIN
|
||||
systemctl stop socat-smd7-from-ttyIN
|
||||
rm -f /lib/systemd/system/socat-smd11.service
|
||||
rm -f /lib/systemd/system/socat-smd11-to-ttyIN.service
|
||||
rm -f /lib/systemd/system/socat-smd11-from-ttyIN.service
|
||||
rm -f /lib/systemd/system/socat-smd7.service
|
||||
rm -f /lib/systemd/system/socat-smd7-to-ttyIN.service
|
||||
rm -f /lib/systemd/system/socat-smd7-from-ttyIN.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$SOCAT_AT_DIR"
|
||||
echo "socat-at-bridge uninstalled."
|
||||
fi
|
||||
|
||||
# Uninstall the rest of Simpleadmin
|
||||
echo "Do you want to uninstall the rest of Simpleadmin?"
|
||||
echo "1) Yes"
|
||||
echo "2) No"
|
||||
read -p "Enter your choice (1 or 2): " choice_simpleadmin
|
||||
if [ "$choice_simpleadmin" -eq 1 ]; then
|
||||
echo "Uninstalling the rest of Simpleadmin..."
|
||||
systemctl stop simpleadmin_httpd
|
||||
systemctl stop simpleadmin_generate_status
|
||||
rm -f /lib/systemd/system/simpleadmin_httpd.service
|
||||
rm -f /lib/systemd/system/simpleadmin_generate_status.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$SIMPLE_ADMIN_DIR"
|
||||
echo "The rest of Simpleadmin uninstalled."
|
||||
fi
|
||||
|
||||
echo "Uninstallation process completed."
|
||||
}
|
||||
|
||||
# Function for Tailscale Submenu
|
||||
@@ -572,41 +482,12 @@ install_update_remove_tailscale() {
|
||||
|
||||
case $tailscale_update_remove_choice in
|
||||
1)
|
||||
echo "Updating Tailscale..."
|
||||
remount_rw
|
||||
$TAILSCALE_DIR/tailscale down
|
||||
$TAILSCALE_DIR/tailscale logout
|
||||
systemctl stop tailscaled
|
||||
# Follow the installation steps with force overwrite
|
||||
echo "Downloading the latest Tailscale binaries..."
|
||||
wget -O $TAILSCALE_DIR/tailscaled https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscaled
|
||||
wget -O $TAILSCALE_DIR/tailscale https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscale
|
||||
|
||||
echo "Setting permissions for the new binaries..."
|
||||
chmod +x $TAILSCALE_DIR/tailscaled
|
||||
chmod +x $TAILSCALE_DIR/tailscale
|
||||
|
||||
echo "Downloading the latest systemd files..."
|
||||
wget -O $TAILSCALE_SYSD_DIR/tailscaled.service https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.service
|
||||
wget -O $TAILSCALE_SYSD_DIR/tailscaled.defaults https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.defaults
|
||||
|
||||
echo "Copying the new systemd units..."
|
||||
cp -f $TAILSCALE_SYSD_DIR/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
|
||||
echo "Restarting Tailscaled service..."
|
||||
systemctl restart tailscaled
|
||||
|
||||
echo "Tailscale updated successfully."
|
||||
|
||||
remount_ro
|
||||
echo "Tailscale updated successfully."
|
||||
echo "You will need to reconnect and Log back in"
|
||||
read -p "Press Enter to continue..."
|
||||
echo "Updating Tailscale..."
|
||||
/usrdata/tailscale/tailscale update
|
||||
;;
|
||||
2)
|
||||
echo "Removing Tailscale..."
|
||||
remount_rw
|
||||
remount_rw
|
||||
$TAILSCALE_DIR/tailscale down
|
||||
$TAILSCALE_DIR/tailscale logout
|
||||
systemctl stop tailscaled
|
||||
@@ -623,82 +504,81 @@ install_update_remove_tailscale() {
|
||||
else
|
||||
echo "Installing Tailscale..."
|
||||
remount_rw
|
||||
echo "Creating /usrdata/tailscale/"
|
||||
mkdir $TAILSCALE_DIR
|
||||
mkdir $TAILSCALE_SYSD_DIR
|
||||
echo "Creating /usrdata/tailscale/"
|
||||
mkdir $TAILSCALE_DIR
|
||||
mkdir $TAILSCALE_SYSD_DIR
|
||||
cd $TAILSCALE_DIR
|
||||
echo "Downloading binary: /usrdata/tailscale/tailscaled"
|
||||
echo "Downloading binary: /usrdata/tailscale/tailscaled"
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscaled
|
||||
echo "Downloading binary: /usrdata/tailscale/tailscale"
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscale
|
||||
echo "Downloading binary: /usrdata/tailscale/tailscale"
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscale
|
||||
echo "Downloading systemd files..."
|
||||
cd $TAILSCALE_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.service
|
||||
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.defaults
|
||||
sleep 2s
|
||||
echo "Setting Permissions..."
|
||||
sleep 2s
|
||||
echo "Setting Permissions..."
|
||||
chmod +x /usrdata/tailscale/tailscaled
|
||||
chmod +x /usrdata/tailscale/tailscale
|
||||
echo "Copy systemd units..."
|
||||
echo "Copy systemd units..."
|
||||
cp -f /usrdata/tailscale/systemd/* /lib/systemd/system
|
||||
ln -sf /lib/systemd/system/tailscaled.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/tailscaled.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl daemon-reload
|
||||
echo "Starting Tailscaled..."
|
||||
echo "Starting Tailscaled..."
|
||||
systemctl start tailscaled
|
||||
cd /
|
||||
cd /
|
||||
remount_ro
|
||||
echo "Tailscale installed successfully."
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Function to Configure Tailscale
|
||||
configure_tailscale() {
|
||||
while true; do
|
||||
echo "Configure Tailscale"
|
||||
echo "1) Enable Tailscale Web UI at http://192.168.225.1:8088 (Gateway on port 8088)"
|
||||
echo "Configure Tailscale"
|
||||
echo "1) Enable Tailscale Web UI at http://192.168.225.1:8088 (Gateway on port 8088)"
|
||||
echo "2) Disable Tailscale Web UI"
|
||||
echo "3) Connect to Tailnet"
|
||||
echo "4) Connect to Tailnet with SSH ON"
|
||||
echo "5) Connect to Tailnet with SSH OFF (reset flag)"
|
||||
echo "4) Connect to Tailnet with SSH ON"
|
||||
echo "5) Reconnect to Tailnet with SSH OFF"
|
||||
echo "6) Disconnect from Tailnet (reconnects at reboot)"
|
||||
echo "7) Logout from tailscale account"
|
||||
echo "7) Logout from tailscale account"
|
||||
echo "8) Return to Tailscale Menu"
|
||||
read -p "Enter your choice: " config_choice
|
||||
|
||||
case $config_choice in
|
||||
1)
|
||||
1)
|
||||
remount_rw
|
||||
cd /lib/systemd/system/
|
||||
wget -O tailscale-webui.service https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscale-webui.service
|
||||
wget -O tailscale-webui-trigger.service https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscale-webui-trigger.service
|
||||
ln -sf /lib/systemd/system/tailscale-webui-trigger.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl daemon-reload
|
||||
echo "Tailscale Web UI Enabled"
|
||||
ln -sf /lib/systemd/system/tailscale-webui-trigger.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl daemon-reload
|
||||
echo "Tailscale Web UI Enabled"
|
||||
echo "Starting Web UI..."
|
||||
systemctl start tailscale-webui
|
||||
echo "Web UI started!"
|
||||
remount_ro
|
||||
systemctl start tailscale-webui
|
||||
echo "Web UI started!"
|
||||
remount_ro
|
||||
;;
|
||||
2)
|
||||
remount_rw
|
||||
systemctl stop tailscale-webui
|
||||
systemctl disable tailscale-webui-trigger
|
||||
systemctl disable tailscale-webui-trigger
|
||||
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui.service
|
||||
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui-trigger.service
|
||||
rm /lib/systemd/system/tailscale-webui.service
|
||||
rm /lib/systemd/system/tailscale-webui-trigger.service
|
||||
systemctl daemon-reload
|
||||
echo "Tailscale Web UI Stopped and Disabled"
|
||||
remount_ro
|
||||
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui-trigger.service
|
||||
rm /lib/systemd/system/tailscale-webui.service
|
||||
rm /lib/systemd/system/tailscale-webui-trigger.service
|
||||
systemctl daemon-reload
|
||||
echo "Tailscale Web UI Stopped and Disabled"
|
||||
remount_ro
|
||||
;;
|
||||
3) $TAILSCALE_DIR/tailscale up;;
|
||||
4) $TAILSCALE_DIR/tailscale up --ssh;;
|
||||
5) $TAILSCALE_DIR/tailscale up --reset;;
|
||||
6) $TAILSCALE_DIR/tailscale down;;
|
||||
7) $TAILSCALE_DIR/tailscale logout;;
|
||||
8) break;;
|
||||
*) echo "Invalid option";;
|
||||
3) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
|
||||
4) $TAILSCALE_DIR/tailscale up --ssh --accept-dns=false --reset;;
|
||||
5) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
|
||||
6) $TAILSCALE_DIR/tailscale down;;
|
||||
7) $TAILSCALE_DIR/tailscale logout;;
|
||||
8) break;;
|
||||
*) echo "Invalid option";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
@@ -773,7 +653,7 @@ manage_reboot_timer() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Function to create systemd service and timer files with the user-specified time
|
||||
# Function to create systemd service and timer files with the user-specified time for the reboot timer
|
||||
create_service_and_timer() {
|
||||
remount_rw
|
||||
# Define the path for the modem reboot script
|
||||
@@ -880,20 +760,17 @@ WantedBy=multi-user.target" > "$cfun_service_path"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Main menu
|
||||
while true; do
|
||||
echo "Welcome to iamromulan's RGMII Toolkit script for Quectel RMxxx Series modems!"
|
||||
echo "Select an option:"
|
||||
echo "1) Send AT Commands"
|
||||
echo "2) Install/Update/Uninstall or Configure Simple Firewall"
|
||||
echo "3) Install/Update or remove AT Telnet Daemon"
|
||||
echo "4) Install/Update or remove Simple Admin"
|
||||
echo "5) Tailscale Management"
|
||||
echo "6) Install/Change or remove Daily Reboot Timer"
|
||||
echo "7) Install/Uninstall CFUN 0 Fix"
|
||||
echo "8) Exit"
|
||||
echo "2) Install/Update/Uninstall Simple Admin"
|
||||
echo "3) Simple Firewall Management"
|
||||
echo "4) Tailscale Management"
|
||||
echo "5) Install/Change or remove Daily Reboot Timer"
|
||||
echo "6) Install/Uninstall CFUN 0 Fix"
|
||||
echo "7) Exit"
|
||||
read -p "Enter your choice: " choice
|
||||
|
||||
case $choice in
|
||||
@@ -901,53 +778,38 @@ while true; do
|
||||
send_at_commands
|
||||
;;
|
||||
2)
|
||||
simplefirewall_menu
|
||||
;;
|
||||
3)
|
||||
if is_at_telnet_installed; then
|
||||
echo "AT Telnet Daemon is already installed."
|
||||
echo "1) Update"
|
||||
echo "2) Remove"
|
||||
read -p "Enter your choice: " at_telnet_choice
|
||||
case $at_telnet_choice in
|
||||
1) install_update_at_telnet;;
|
||||
2) remove_at_telnet;;
|
||||
*) echo "Invalid option";;
|
||||
esac
|
||||
else
|
||||
echo "Installing AT Telnet Daemon..."
|
||||
install_update_at_telnet
|
||||
fi
|
||||
;;
|
||||
4)
|
||||
if is_simple_admin_installed; then
|
||||
echo "Simple Admin is already installed."
|
||||
echo "1) Update"
|
||||
echo "2) Remove"
|
||||
echo "Simple Admin is already installed. It must be removed first"
|
||||
echo "1) Remove"
|
||||
echo "2) Return to main menu"
|
||||
read -p "Enter your choice: " simple_admin_choice
|
||||
case $simple_admin_choice in
|
||||
1) install_update_simple_admin;;
|
||||
2) remove_simple_admin;;
|
||||
1) uninstall_simpleadmin_components;;
|
||||
2) break;;
|
||||
*) echo "Invalid option";;
|
||||
esac
|
||||
else
|
||||
echo "Installing Simple Admin..."
|
||||
install_update_simple_admin
|
||||
install_simple_admin
|
||||
fi
|
||||
;;
|
||||
5)
|
||||
tailscale_menu
|
||||
;;
|
||||
6)
|
||||
3)
|
||||
configure_simple_firewall
|
||||
;;
|
||||
|
||||
4)
|
||||
tailscale_menu
|
||||
;;
|
||||
5)
|
||||
manage_reboot_timer
|
||||
;;
|
||||
7)
|
||||
6)
|
||||
manage_cfun_fix
|
||||
;;
|
||||
8)
|
||||
echo "Goodbye!"
|
||||
7)
|
||||
echo "Goodbye!"
|
||||
break
|
||||
;;
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option"
|
||||
;;
|
||||
@@ -1,281 +0,0 @@
|
||||
#!/usrdata/micropython/micropython
|
||||
|
||||
# Add the /usrdata/micropython directory to sys.path so we can find the external modules.
|
||||
# TODO: Move external modules to lib?
|
||||
# TODO: Recompile Micropython with a syspath set up for our use case.
|
||||
import sys
|
||||
# Remove the home directory from sys.path.
|
||||
if "~/.micropython/lib" in sys.path:
|
||||
sys.path.remove("~/.micropython/lib")
|
||||
sys.path.append("/usrdata/micropython/lib")
|
||||
sys.path.append("/usrdata/micropython")
|
||||
|
||||
import uos
|
||||
import usocket as socket
|
||||
import _thread as thread
|
||||
import serial
|
||||
import select
|
||||
import traceback
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
|
||||
# Set up logging
|
||||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s: %(levelname)s/%(msecs)ims] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
|
||||
# Globally define client_sockets and serialport. That way, we can access them from handle_output and make it a separate thread, so responses (and unsolicited responses) can come in while we're waiting for input.
|
||||
global client_sockets, serialport
|
||||
client_sockets = []
|
||||
# We are referencing one of the two ports exposed by our socat command. The other one is /dev/ttyIN, and two running "cat" commands are keeping it sync'd with /dev/smd11.
|
||||
serialport = serial.Serial("/dev/ttyOUT", baudrate=115200)
|
||||
|
||||
# These will be set in the main routine.
|
||||
global firewall_is_setup, fwpublicinterface, port
|
||||
firewall_is_setup = 0
|
||||
|
||||
# Make these configurable via /etc/default or similar
|
||||
port = 5000
|
||||
fwpublicinterface = "rmnet+"
|
||||
|
||||
# Block access to port 5000 via ipv4 and ipv6 on public-facing interfaces.
|
||||
def add_firewll_rules(port=port, fwpublicinterface=fwpublicinterface):
|
||||
if not port or not fwpublicinterface:
|
||||
logging.error(f"Port or fwpublicinterface not set. Values: fwpublicinterface: {fwpublicinterface} port: {port}")
|
||||
exit(1)
|
||||
|
||||
logging.info(f"Adding firewall rules for port {port} on interface {fwpublicinterface}.")
|
||||
|
||||
# Check if the rule already exists in iptables
|
||||
iptables_check_cmd = f"iptables -C INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT &> /dev/null"
|
||||
iptables_check_result = uos.system(iptables_check_cmd)
|
||||
if iptables_check_result != 0:
|
||||
# Rule doesn't exist, add it to iptables
|
||||
iptables_add_cmd = f"iptables -A INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
|
||||
iptables_add_result = uos.system(iptables_add_cmd)
|
||||
if iptables_add_result:
|
||||
logging.error(f"ERROR: Failed to add iptables rule - input interface {fwpublicinterface} port {port}")
|
||||
# Treat this as fatal.
|
||||
sys.exit(1)
|
||||
else:
|
||||
logging.debug(f"Added iptables rule - input interface {fwpublicinterface} port {port}")
|
||||
|
||||
# Check if the rule already exists in ip6tables
|
||||
ip6tables_check_cmd = f"ip6tables -C INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT &> /dev/null"
|
||||
ip6tables_check_result = uos.system(ip6tables_check_cmd)
|
||||
if ip6tables_check_result != 0:
|
||||
# Rule doesn't exist, add it to ip6tables
|
||||
ip6tables_add_cmd = f"ip6tables -A INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
|
||||
ip6tables_add_result = uos.system(ip6tables_add_cmd)
|
||||
if ip6tables_add_result:
|
||||
logging.error(f"ERROR: Failed to add ip6tables rule - input interface {fwpublicinterface} port {port}")
|
||||
# Treat this as fatal.
|
||||
sys.exit(1)
|
||||
else:
|
||||
logging.debug(f"Added ip6tables rule - input interface {fwpublicinterface} port {port}")
|
||||
|
||||
global firewall_is_setup
|
||||
firewall_is_setup = 1
|
||||
|
||||
logging.info(f"Successfully firewall rules for port {port} on interface {fwpublicinterface}.")
|
||||
|
||||
|
||||
def remove_firewall_rules(port=port, fwpublicinterface=fwpublicinterface):
|
||||
if firewall_is_setup:
|
||||
iptables_del_cmd = f"iptables -D INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
|
||||
ip6tables_del_cmd = f"ip6tables -D INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
|
||||
iptables_del_result = uos.system(iptables_del_cmd)
|
||||
ip6tables_del_result = uos.system(ip6tables_del_cmd)
|
||||
|
||||
if iptables_del_result or ip6tables_del_result:
|
||||
logging.error(f"ERROR: Failed to remove iptables or ip6tables rule - input interface {fwpublicinterface} port {port}")
|
||||
else:
|
||||
logging.info(f"Removed iptables and ip6tables rule - input interface {fwpublicinterface} port {port}")
|
||||
|
||||
else:
|
||||
logging.info(f"Firewall rules not set up; not removing.")
|
||||
|
||||
# This routine pulls data from the serial port and sends it to all connected clients.
|
||||
def handle_output():
|
||||
while True:
|
||||
# Make data an empty bytes list
|
||||
data = b''
|
||||
|
||||
try:
|
||||
while serialport.in_waiting > 0:
|
||||
data += serialport.read(1)
|
||||
except Exception as e:
|
||||
# This will keep trying.
|
||||
print(f"Exception reading data from serialport: {e}")
|
||||
traceback.print_exc()
|
||||
|
||||
if data:
|
||||
logging.info(f"Got data from modem: {data}")
|
||||
for client_socket in client_sockets:
|
||||
client_socket.send(data)
|
||||
|
||||
# Start the server on the specified port, listen for clients, etc.
|
||||
def start_at_server(port):
|
||||
|
||||
# Server initialization stuff
|
||||
# NOTE: This now supports IPv6. And means that on many connections it'll be directly exposed
|
||||
# to the internet. So we're adding firewall rules to block access to it via rmnet+.
|
||||
try:
|
||||
server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
addr_info = socket.getaddrinfo("::", port)
|
||||
addr = addr_info[0][4]
|
||||
server_socket.bind(addr)
|
||||
server_socket.listen(1)
|
||||
|
||||
logging.info(f"AT Server listening on TCP port {port}")
|
||||
|
||||
# Disable echo so user doesn't see a second copy of all their commands.
|
||||
serialport.write("ATE0\r\n")
|
||||
# time.sleep() segfaults?! ugh.
|
||||
uos.system("sleep 0.025s")
|
||||
# wait for an OK
|
||||
out=b''
|
||||
while serialport.in_waiting > 0:
|
||||
out += serialport.read(1)
|
||||
|
||||
if "OK" not in str(out):
|
||||
logging.warning(f"Did not get expected OK when running ATE0. Result: {str(out)}")
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error initializing server: {e}")
|
||||
traceback.print_exc()
|
||||
raise
|
||||
|
||||
# Start the output handler in its own thread
|
||||
try:
|
||||
thread.start_new_thread(handle_output, ())
|
||||
except Exception as e:
|
||||
print("Error with output handler:", e)
|
||||
traceback.print_exc()
|
||||
raise
|
||||
|
||||
# Set up a select.poll object to listen for input from the server socket and all client sockets.
|
||||
# Logic mostly from https://pymotw.com/2/select/
|
||||
try:
|
||||
poll_obj = select.poll()
|
||||
poll_obj.register(server_socket, select.POLLIN)
|
||||
|
||||
# Register the server socket in the fd_to_socket dict; this will also be used to register the rest of the clients.
|
||||
fd_to_socket = { server_socket.fileno(): server_socket,
|
||||
}
|
||||
|
||||
while True:
|
||||
events = poll_obj.poll()
|
||||
|
||||
for fd, flag in events:
|
||||
logging.debug(f"Pool loop event. fd: {fd} flag: {flag} fd_to_socket.keys(): {fd_to_socket.keys()}")
|
||||
|
||||
# Check if the client already exists in the fd_to_socket dict.
|
||||
if fd.fileno() in fd_to_socket.keys():
|
||||
s = fd_to_socket[fd.fileno()]
|
||||
logging.debug("Event matches existing socket.")
|
||||
else:
|
||||
s = fd
|
||||
logging.debug(f"Event doesn't match existing socket. fd: {fd} fd_to_socket: {fd_to_socket}")
|
||||
|
||||
# If the flag is POLLIN, then we have data to process.
|
||||
if flag & (select.POLLIN):
|
||||
# If the server socket is ready to read, then we have a new client connection.
|
||||
if s is server_socket:
|
||||
# Accept the connection.
|
||||
client_socket, client_address = s.accept()
|
||||
# TODO: This gives a garbled IP. Figure it out.
|
||||
#client_address_translated = socket.inet_ntop(socket.AF_INET, client_address)
|
||||
logging.info(f"New connection")
|
||||
|
||||
# Set the client socket to non-blocking, and add it to the list of client sockets.
|
||||
# TODO: trim down to just storing one copy of the client sockets..
|
||||
client_socket.setblocking(0)
|
||||
fd_to_socket[ client_socket.fileno() ] = client_socket
|
||||
client_sockets.append(client_socket)
|
||||
poll_obj.register(client_socket, select.POLLIN)
|
||||
|
||||
# Send a good 'ol hello message to the client.
|
||||
client_socket.send("** Welcome to the AT server!\r\n".encode())
|
||||
client_socket.send("** Note that your commands are interleaved with any other connected clients,\r\n** so responses may appear out of order.\r\n".encode())
|
||||
client_socket.send("** \r\n".encode())
|
||||
client_socket.send("** You may also receive unsolicited responses (URC's) depending on the\r\n** modem configuration.\r\n".encode())
|
||||
client_socket.send("** \r\n".encode())
|
||||
client_socket.send("** Echo is off (ATE0); if you change it you'll see what you've typed both\r\n** locally and echo'd back.\r\n".encode())
|
||||
client_socket.send("** \r\n".encode())
|
||||
client_socket.send("** I have tested this with telnet.netkit and netcat on Linux. If your client\r\n** doesn't work,\r\n** please open an issue at:\r\n** https://github.com/natecarlson/quectel-rgmii-at-command-client/ **\r\n".encode())
|
||||
client_socket.send("**\r\n".encode())
|
||||
client_socket.send("** If you would like to support further development, you can at:\r\n** https://www.buymeacoffee.com/natecarlson **\r\n".encode())
|
||||
client_socket.send("\r\n".encode())
|
||||
|
||||
|
||||
# Otherwise, we have data from a client socket.
|
||||
else:
|
||||
data = s.recv(1024)
|
||||
logging.info(f"Got data from client: {data}")
|
||||
if data:
|
||||
# Ensure it ends with \r\n
|
||||
if not data.endswith("\r\n"):
|
||||
# Just stripping \n for now; add others in the future if needed.
|
||||
data = re.sub(b"\n$", "", data) + "\r\n"
|
||||
logging.info(f"Modified client data to end with \\r\\n: {data}")
|
||||
|
||||
# Good client data; write out to the serial port.
|
||||
serialport.write(data)
|
||||
# Write out out to the rest of the clients too
|
||||
for fd in fd_to_socket.keys():
|
||||
if fd != server_socket.fileno() and fd != s.fileno():
|
||||
logging.debug(f"Writing data to other connected client: {data}")
|
||||
try:
|
||||
fd_to_socket[fd].send(data)
|
||||
except Exception as e:
|
||||
logging.info(f"Failed to write data to an additional client. Ignorning. Result: {e}")
|
||||
pass
|
||||
else:
|
||||
# Client disconnected
|
||||
print("Client disconnected")
|
||||
client_sockets.remove(s)
|
||||
poll_obj.unregister(s)
|
||||
del fd_to_socket[s.fileno()]
|
||||
s.close()
|
||||
|
||||
# Not sure if this can happen. But , if it does, we should close the socket.
|
||||
elif flag & select.POLLERR:
|
||||
logging.warn(f"Strange connection issue with a client; closing.")
|
||||
# Stop listening for input on the connection
|
||||
poll_obj.unregister(s)
|
||||
client_sockets.remove(s)
|
||||
del fd_to_socket[s.fileno()]
|
||||
s.close()
|
||||
|
||||
# TODO: I don't believe we need this here, since the output is now handled in its own thread.
|
||||
#uos.system("sleep 0.025s")
|
||||
|
||||
except Exception as e:
|
||||
print("Error after server initialization:", e)
|
||||
serialport.write("ATE1\r\n")
|
||||
traceback.print_exc()
|
||||
# I believe this will drop out of the while loop, so we'll close the sockets and exit.
|
||||
|
||||
# Close client sockets and server socket
|
||||
for client_socket in client_sockets:
|
||||
client_socket.close()
|
||||
|
||||
server_socket.close()
|
||||
|
||||
# TODO: By using the dict, we shouldn't need this code. Clean it up.
|
||||
#def fd_to_socket(fd, client_sockets):
|
||||
# for client_socket in client_sockets:
|
||||
# if client_socket.fileno() == fd:
|
||||
# return client_socket
|
||||
# return None
|
||||
|
||||
# App startup. TODO: Make the port configurable.
|
||||
if __name__ == "__main__":
|
||||
# Register an atexit handler to remove the firewall rules.
|
||||
sys.atexit(remove_firewall_rules)
|
||||
|
||||
# Add the firewall rules before starting anything
|
||||
add_firewll_rules(port=port, fwpublicinterface=fwpublicinterface)
|
||||
|
||||
# Light 'er up!
|
||||
start_at_server(port)
|
||||
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
[Unit]
|
||||
Description=Telnet daemon for AT command smd7
|
||||
|
||||
After=socat-smd7.service
|
||||
Requires=socat-smd7.service socat-smd7-from-ttyIN.service socat-smd7-to-ttyIN.service
|
||||
ReloadPropagatedFrom=socat-smd7.service socat-smd7-from-ttyIN.service socat-smd7-to-ttyIN.service
|
||||
|
||||
StartLimitIntervalSec=2m
|
||||
StartLimitBurst=100
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/at-telnet/modem-multiclient.py
|
||||
Nice=5
|
||||
Restart=always
|
||||
RestartSec=2s
|
||||
# Increased log rate limits, so we can see what's going on.
|
||||
LogRateLimitIntervalSec=5s
|
||||
LogRateLimitBurst=100
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,25 +0,0 @@
|
||||
[Unit]
|
||||
Description=Telnet daemon for AT command
|
||||
|
||||
# Being extra silly with the dependencies for this.
|
||||
# TODO: Update the python code to validate that the serial port
|
||||
# is working on a regular basis, and keep attempting to retry
|
||||
# if not. Then these dependencies won't need to be so strict.
|
||||
After=socat-smd11.service
|
||||
Requires=socat-smd11.service socat-smd11-from-ttyIN.service socat-smd11-to-ttyIN.service
|
||||
ReloadPropagatedFrom=socat-smd11.service socat-smd11-from-ttyIN.service socat-smd11-to-ttyIN.service
|
||||
|
||||
StartLimitIntervalSec=2m
|
||||
StartLimitBurst=100
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/at-telnet/modem-multiclient.py
|
||||
Nice=5
|
||||
Restart=always
|
||||
RestartSec=2s
|
||||
# Increased log rate limits, so we can see what's going on.
|
||||
LogRateLimitIntervalSec=5s
|
||||
LogRateLimitBurst=100
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,38 +0,0 @@
|
||||
EPERM = 1 # Operation not permitted
|
||||
ENOENT = 2 # No such file or directory
|
||||
ESRCH = 3 # No such process
|
||||
EINTR = 4 # Interrupted system call
|
||||
EIO = 5 # I/O error
|
||||
ENXIO = 6 # No such device or address
|
||||
E2BIG = 7 # Argument list too long
|
||||
ENOEXEC = 8 # Exec format error
|
||||
EBADF = 9 # Bad file number
|
||||
ECHILD = 10 # No child processes
|
||||
EAGAIN = 11 # Try again
|
||||
ENOMEM = 12 # Out of memory
|
||||
EACCES = 13 # Permission denied
|
||||
EFAULT = 14 # Bad address
|
||||
ENOTBLK = 15 # Block device required
|
||||
EBUSY = 16 # Device or resource busy
|
||||
EEXIST = 17 # File exists
|
||||
EXDEV = 18 # Cross-device link
|
||||
ENODEV = 19 # No such device
|
||||
ENOTDIR = 20 # Not a directory
|
||||
EISDIR = 21 # Is a directory
|
||||
EINVAL = 22 # Invalid argument
|
||||
ENFILE = 23 # File table overflow
|
||||
EMFILE = 24 # Too many open files
|
||||
ENOTTY = 25 # Not a typewriter
|
||||
ETXTBSY = 26 # Text file busy
|
||||
EFBIG = 27 # File too large
|
||||
ENOSPC = 28 # No space left on device
|
||||
ESPIPE = 29 # Illegal seek
|
||||
EROFS = 30 # Read-only file system
|
||||
EMLINK = 31 # Too many links
|
||||
EPIPE = 32 # Broken pipe
|
||||
EDOM = 33 # Math argument out of domain of func
|
||||
ERANGE = 34 # Math result not representable
|
||||
EAFNOSUPPORT = 97 # Address family not supported by protocol
|
||||
ECONNRESET = 104 # Connection timed out
|
||||
ETIMEDOUT = 110 # Connection timed out
|
||||
EINPROGRESS = 115 # Operation now in progress
|
||||
@@ -1,36 +0,0 @@
|
||||
import ffi
|
||||
import os_compat as os
|
||||
import ffilib
|
||||
|
||||
libc = ffilib.libc()
|
||||
|
||||
fcntl_l = libc.func("i", "fcntl", "iil")
|
||||
fcntl_s = libc.func("i", "fcntl", "iip")
|
||||
ioctl_l = libc.func("i", "ioctl", "iil")
|
||||
ioctl_s = libc.func("i", "ioctl", "iip")
|
||||
|
||||
|
||||
def fcntl(fd, op, arg=0):
|
||||
if type(arg) is int:
|
||||
r = fcntl_l(fd, op, arg)
|
||||
os.check_error(r)
|
||||
return r
|
||||
else:
|
||||
r = fcntl_s(fd, op, arg)
|
||||
os.check_error(r)
|
||||
# TODO: Not compliant. CPython says that arg should be immutable,
|
||||
# and possibly mutated buffer is returned.
|
||||
return r
|
||||
|
||||
|
||||
def ioctl(fd, op, arg=0, mut=False):
|
||||
if type(arg) is int:
|
||||
r = ioctl_l(fd, op, arg)
|
||||
os.check_error(r)
|
||||
return r
|
||||
else:
|
||||
# TODO
|
||||
assert mut
|
||||
r = ioctl_s(fd, op, arg)
|
||||
os.check_error(r)
|
||||
return r
|
||||
@@ -1,51 +0,0 @@
|
||||
import sys
|
||||
try:
|
||||
import ffi
|
||||
except ImportError:
|
||||
ffi = None
|
||||
|
||||
_cache = {}
|
||||
|
||||
|
||||
def open(name, maxver=10, extra=()):
|
||||
if not ffi:
|
||||
return None
|
||||
try:
|
||||
return _cache[name]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def libs():
|
||||
if sys.platform == "linux":
|
||||
yield '%s.so' % name
|
||||
for i in range(maxver, -1, -1):
|
||||
yield '%s.so.%u' % (name, i)
|
||||
else:
|
||||
for ext in ('dylib', 'dll'):
|
||||
yield '%s.%s' % (name, ext)
|
||||
for n in extra:
|
||||
yield n
|
||||
|
||||
err = None
|
||||
for n in libs():
|
||||
try:
|
||||
l = ffi.open(n)
|
||||
_cache[name] = l
|
||||
return l
|
||||
except OSError as e:
|
||||
err = e
|
||||
raise err
|
||||
|
||||
|
||||
def libc():
|
||||
return open("libc", 6)
|
||||
|
||||
|
||||
# Find out bitness of the platform, even if long ints are not supported
|
||||
# TODO: All bitness differences should be removed from micropython-lib, and
|
||||
# this snippet too.
|
||||
bitness = 1
|
||||
v = sys.maxsize
|
||||
while v:
|
||||
bitness += 1
|
||||
v >>= 1
|
||||
@@ -1,245 +0,0 @@
|
||||
from micropython import const
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
CRITICAL = const(50)
|
||||
ERROR = const(40)
|
||||
WARNING = const(30)
|
||||
INFO = const(20)
|
||||
DEBUG = const(10)
|
||||
NOTSET = const(0)
|
||||
|
||||
_DEFAULT_LEVEL = const(WARNING)
|
||||
|
||||
_level_dict = {
|
||||
CRITICAL: "CRITICAL",
|
||||
ERROR: "ERROR",
|
||||
WARNING: "WARNING",
|
||||
INFO: "INFO",
|
||||
DEBUG: "DEBUG",
|
||||
NOTSET: "NOTSET",
|
||||
}
|
||||
|
||||
_loggers = {}
|
||||
_stream = sys.stderr
|
||||
_default_fmt = "%(levelname)s:%(name)s:%(message)s"
|
||||
_default_datefmt = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
|
||||
class LogRecord:
|
||||
def set(self, name, level, message):
|
||||
self.name = name
|
||||
self.levelno = level
|
||||
self.levelname = _level_dict[level]
|
||||
self.message = message
|
||||
self.ct = time.time()
|
||||
self.msecs = int((self.ct - int(self.ct)) * 1000)
|
||||
self.asctime = None
|
||||
|
||||
|
||||
class Handler:
|
||||
def __init__(self, level=NOTSET):
|
||||
self.level = level
|
||||
self.formatter = None
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
def setLevel(self, level):
|
||||
self.level = level
|
||||
|
||||
def setFormatter(self, formatter):
|
||||
self.formatter = formatter
|
||||
|
||||
def format(self, record):
|
||||
return self.formatter.format(record)
|
||||
|
||||
|
||||
class StreamHandler(Handler):
|
||||
def __init__(self, stream=None):
|
||||
self.stream = _stream if stream is None else stream
|
||||
self.terminator = "\n"
|
||||
|
||||
def close(self):
|
||||
if hasattr(self.stream, "flush"):
|
||||
self.stream.flush()
|
||||
|
||||
def emit(self, record):
|
||||
if record.levelno >= self.level:
|
||||
self.stream.write(self.format(record) + self.terminator)
|
||||
|
||||
|
||||
class FileHandler(StreamHandler):
|
||||
def __init__(self, filename, mode="a", encoding="UTF-8"):
|
||||
super().__init__(stream=open(filename, mode=mode, encoding=encoding))
|
||||
|
||||
def close(self):
|
||||
super().close()
|
||||
self.stream.close()
|
||||
|
||||
|
||||
class Formatter:
|
||||
def __init__(self, fmt=None, datefmt=None):
|
||||
self.fmt = _default_fmt if fmt is None else fmt
|
||||
self.datefmt = _default_datefmt if datefmt is None else datefmt
|
||||
|
||||
def usesTime(self):
|
||||
return "asctime" in self.fmt
|
||||
|
||||
def formatTime(self, datefmt, record):
|
||||
if hasattr(time, "strftime"):
|
||||
return time.strftime(datefmt, time.localtime(record.ct))
|
||||
return None
|
||||
|
||||
def format(self, record):
|
||||
if self.usesTime():
|
||||
record.asctime = self.formatTime(self.datefmt, record)
|
||||
return self.fmt % {
|
||||
"name": record.name,
|
||||
"message": record.message,
|
||||
"msecs": record.msecs,
|
||||
"asctime": record.asctime,
|
||||
"levelname": record.levelname,
|
||||
}
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self, name, level=NOTSET):
|
||||
self.name = name
|
||||
self.level = level
|
||||
self.handlers = []
|
||||
self.record = LogRecord()
|
||||
|
||||
def setLevel(self, level):
|
||||
self.level = level
|
||||
|
||||
def isEnabledFor(self, level):
|
||||
return level >= self.getEffectiveLevel()
|
||||
|
||||
def getEffectiveLevel(self):
|
||||
return self.level or getLogger().level or _DEFAULT_LEVEL
|
||||
|
||||
def log(self, level, msg, *args):
|
||||
if self.isEnabledFor(level):
|
||||
if args:
|
||||
if isinstance(args[0], dict):
|
||||
args = args[0]
|
||||
msg = msg % args
|
||||
self.record.set(self.name, level, msg)
|
||||
handlers = self.handlers
|
||||
if not handlers:
|
||||
handlers = getLogger().handlers
|
||||
for h in handlers:
|
||||
h.emit(self.record)
|
||||
|
||||
def debug(self, msg, *args):
|
||||
self.log(DEBUG, msg, *args)
|
||||
|
||||
def info(self, msg, *args):
|
||||
self.log(INFO, msg, *args)
|
||||
|
||||
def warning(self, msg, *args):
|
||||
self.log(WARNING, msg, *args)
|
||||
|
||||
def error(self, msg, *args):
|
||||
self.log(ERROR, msg, *args)
|
||||
|
||||
def critical(self, msg, *args):
|
||||
self.log(CRITICAL, msg, *args)
|
||||
|
||||
def exception(self, msg, *args):
|
||||
self.log(ERROR, msg, *args)
|
||||
if hasattr(sys, "exc_info"):
|
||||
sys.print_exception(sys.exc_info()[1], _stream)
|
||||
|
||||
def addHandler(self, handler):
|
||||
self.handlers.append(handler)
|
||||
|
||||
def hasHandlers(self):
|
||||
return len(self.handlers) > 0
|
||||
|
||||
|
||||
def getLogger(name=None):
|
||||
if name is None:
|
||||
name = "root"
|
||||
if name not in _loggers:
|
||||
_loggers[name] = Logger(name)
|
||||
if name == "root":
|
||||
basicConfig()
|
||||
return _loggers[name]
|
||||
|
||||
|
||||
def log(level, msg, *args):
|
||||
getLogger().log(level, msg, *args)
|
||||
|
||||
|
||||
def debug(msg, *args):
|
||||
getLogger().debug(msg, *args)
|
||||
|
||||
|
||||
def info(msg, *args):
|
||||
getLogger().info(msg, *args)
|
||||
|
||||
|
||||
def warning(msg, *args):
|
||||
getLogger().warning(msg, *args)
|
||||
|
||||
|
||||
def error(msg, *args):
|
||||
getLogger().error(msg, *args)
|
||||
|
||||
|
||||
def critical(msg, *args):
|
||||
getLogger().critical(msg, *args)
|
||||
|
||||
|
||||
def exception(msg, *args):
|
||||
getLogger().exception(msg, *args)
|
||||
|
||||
|
||||
def shutdown():
|
||||
for k, logger in _loggers.items():
|
||||
for h in logger.handlers:
|
||||
h.close()
|
||||
_loggers.pop(logger, None)
|
||||
|
||||
|
||||
def addLevelName(level, name):
|
||||
_level_dict[level] = name
|
||||
|
||||
|
||||
def basicConfig(
|
||||
filename=None,
|
||||
filemode="a",
|
||||
format=None,
|
||||
datefmt=None,
|
||||
level=WARNING,
|
||||
stream=None,
|
||||
encoding="UTF-8",
|
||||
force=False,
|
||||
):
|
||||
if "root" not in _loggers:
|
||||
_loggers["root"] = Logger("root")
|
||||
|
||||
logger = _loggers["root"]
|
||||
|
||||
if force or not logger.handlers:
|
||||
for h in logger.handlers:
|
||||
h.close()
|
||||
logger.handlers = []
|
||||
|
||||
if filename is None:
|
||||
handler = StreamHandler(stream)
|
||||
else:
|
||||
handler = FileHandler(filename, filemode, encoding)
|
||||
|
||||
handler.setLevel(level)
|
||||
handler.setFormatter(Formatter(format, datefmt))
|
||||
|
||||
logger.setLevel(level)
|
||||
logger.addHandler(handler)
|
||||
|
||||
|
||||
if hasattr(sys, "atexit"):
|
||||
sys.atexit(shutdown)
|
||||
Binary file not shown.
@@ -1,312 +0,0 @@
|
||||
import array
|
||||
import ustruct as struct
|
||||
import errno as errno_
|
||||
import stat as stat_
|
||||
import ffilib
|
||||
import uos
|
||||
from micropython import const
|
||||
|
||||
R_OK = const(4)
|
||||
W_OK = const(2)
|
||||
X_OK = const(1)
|
||||
F_OK = const(0)
|
||||
|
||||
O_ACCMODE = 0o0000003
|
||||
O_RDONLY = 0o0000000
|
||||
O_WRONLY = 0o0000001
|
||||
O_RDWR = 0o0000002
|
||||
O_CREAT = 0o0000100
|
||||
O_EXCL = 0o0000200
|
||||
O_NOCTTY = 0o0000400
|
||||
O_TRUNC = 0o0001000
|
||||
O_APPEND = 0o0002000
|
||||
O_NONBLOCK = 0o0004000
|
||||
|
||||
error = OSError
|
||||
name = "posix"
|
||||
sep = "/"
|
||||
curdir = "."
|
||||
pardir = ".."
|
||||
environ = {"WARNING": "NOT_IMPLEMENTED"}
|
||||
|
||||
libc = ffilib.libc()
|
||||
|
||||
if libc:
|
||||
chdir_ = libc.func("i", "chdir", "s")
|
||||
mkdir_ = libc.func("i", "mkdir", "si")
|
||||
rename_ = libc.func("i", "rename", "ss")
|
||||
unlink_ = libc.func("i", "unlink", "s")
|
||||
rmdir_ = libc.func("i", "rmdir", "s")
|
||||
getcwd_ = libc.func("s", "getcwd", "si")
|
||||
opendir_ = libc.func("P", "opendir", "s")
|
||||
readdir_ = libc.func("P", "readdir", "P")
|
||||
open_ = libc.func("i", "open", "sii")
|
||||
read_ = libc.func("i", "read", "ipi")
|
||||
write_ = libc.func("i", "write", "iPi")
|
||||
close_ = libc.func("i", "close", "i")
|
||||
dup_ = libc.func("i", "dup", "i")
|
||||
access_ = libc.func("i", "access", "si")
|
||||
fork_ = libc.func("i", "fork", "")
|
||||
pipe_ = libc.func("i", "pipe", "p")
|
||||
_exit_ = libc.func("v", "_exit", "i")
|
||||
getpid_ = libc.func("i", "getpid", "")
|
||||
waitpid_ = libc.func("i", "waitpid", "ipi")
|
||||
system_ = libc.func("i", "system", "s")
|
||||
execvp_ = libc.func("i", "execvp", "PP")
|
||||
kill_ = libc.func("i", "kill", "ii")
|
||||
getenv_ = libc.func("s", "getenv", "P")
|
||||
|
||||
|
||||
def check_error(ret):
|
||||
# Return True is error was EINTR (which usually means that OS call
|
||||
# should be restarted).
|
||||
if ret == -1:
|
||||
e = uos.errno()
|
||||
if e == errno_.EINTR:
|
||||
return True
|
||||
raise OSError(e)
|
||||
|
||||
|
||||
def raise_error():
|
||||
raise OSError(uos.errno())
|
||||
|
||||
|
||||
stat = uos.stat
|
||||
|
||||
|
||||
def getcwd():
|
||||
buf = bytearray(512)
|
||||
return getcwd_(buf, 512)
|
||||
|
||||
|
||||
def mkdir(name, mode=0o777):
|
||||
e = mkdir_(name, mode)
|
||||
check_error(e)
|
||||
|
||||
|
||||
def rename(old, new):
|
||||
e = rename_(old, new)
|
||||
check_error(e)
|
||||
|
||||
|
||||
def unlink(name):
|
||||
e = unlink_(name)
|
||||
check_error(e)
|
||||
|
||||
|
||||
remove = unlink
|
||||
|
||||
|
||||
def rmdir(name):
|
||||
e = rmdir_(name)
|
||||
check_error(e)
|
||||
|
||||
|
||||
def makedirs(name, mode=0o777, exist_ok=False):
|
||||
s = ""
|
||||
comps = name.split("/")
|
||||
if comps[-1] == "":
|
||||
comps.pop()
|
||||
for i, c in enumerate(comps):
|
||||
s += c + "/"
|
||||
try:
|
||||
uos.mkdir(s)
|
||||
except OSError as e:
|
||||
if e.args[0] != errno_.EEXIST:
|
||||
raise
|
||||
if i == len(comps) - 1:
|
||||
if exist_ok:
|
||||
return
|
||||
raise e
|
||||
|
||||
|
||||
if hasattr(uos, "ilistdir"):
|
||||
ilistdir = uos.ilistdir
|
||||
else:
|
||||
|
||||
def ilistdir(path="."):
|
||||
dir = opendir_(path)
|
||||
if not dir:
|
||||
raise_error()
|
||||
res = []
|
||||
dirent_fmt = "LLHB256s"
|
||||
while True:
|
||||
dirent = readdir_(dir)
|
||||
if not dirent:
|
||||
break
|
||||
import uctypes
|
||||
dirent = uctypes.bytes_at(dirent, struct.calcsize(dirent_fmt))
|
||||
dirent = struct.unpack(dirent_fmt, dirent)
|
||||
dirent = (dirent[-1].split(b'\0', 1)[0], dirent[-2], dirent[0])
|
||||
yield dirent
|
||||
|
||||
|
||||
def listdir(path="."):
|
||||
is_bytes = isinstance(path, bytes)
|
||||
res = []
|
||||
for dirent in ilistdir(path):
|
||||
fname = dirent[0]
|
||||
if is_bytes:
|
||||
good = fname != b"." and fname == b".."
|
||||
else:
|
||||
good = fname != "." and fname != ".."
|
||||
if good:
|
||||
if not is_bytes:
|
||||
fname = fsdecode(fname)
|
||||
res.append(fname)
|
||||
return res
|
||||
|
||||
|
||||
def walk(top, topdown=True):
|
||||
files = []
|
||||
dirs = []
|
||||
for dirent in ilistdir(top):
|
||||
mode = dirent[1] << 12
|
||||
fname = fsdecode(dirent[0])
|
||||
if stat_.S_ISDIR(mode):
|
||||
if fname != "." and fname != "..":
|
||||
dirs.append(fname)
|
||||
else:
|
||||
files.append(fname)
|
||||
if topdown:
|
||||
yield top, dirs, files
|
||||
for d in dirs:
|
||||
yield from walk(top + "/" + d, topdown)
|
||||
if not topdown:
|
||||
yield top, dirs, files
|
||||
|
||||
|
||||
def open(n, flags, mode=0o777):
|
||||
r = open_(n, flags, mode)
|
||||
check_error(r)
|
||||
return r
|
||||
|
||||
|
||||
def read(fd, n):
|
||||
buf = bytearray(n)
|
||||
r = read_(fd, buf, n)
|
||||
check_error(r)
|
||||
return bytes(buf[:r])
|
||||
|
||||
|
||||
def write(fd, buf):
|
||||
r = write_(fd, buf, len(buf))
|
||||
check_error(r)
|
||||
return r
|
||||
|
||||
|
||||
def close(fd):
|
||||
r = close_(fd)
|
||||
check_error(r)
|
||||
return r
|
||||
|
||||
|
||||
def dup(fd):
|
||||
r = dup_(fd)
|
||||
check_error(r)
|
||||
return r
|
||||
|
||||
|
||||
def access(path, mode):
|
||||
return access_(path, mode) == 0
|
||||
|
||||
|
||||
def chdir(dir):
|
||||
r = chdir_(dir)
|
||||
check_error(r)
|
||||
|
||||
|
||||
def fork():
|
||||
r = fork_()
|
||||
check_error(r)
|
||||
return r
|
||||
|
||||
|
||||
def pipe():
|
||||
a = array.array('i', [0, 0])
|
||||
r = pipe_(a)
|
||||
check_error(r)
|
||||
return a[0], a[1]
|
||||
|
||||
|
||||
def _exit(n):
|
||||
_exit_(n)
|
||||
|
||||
|
||||
def execvp(f, args):
|
||||
import uctypes
|
||||
args_ = array.array("P", [0] * (len(args) + 1))
|
||||
i = 0
|
||||
for a in args:
|
||||
args_[i] = uctypes.addressof(a)
|
||||
i += 1
|
||||
r = execvp_(f, uctypes.addressof(args_))
|
||||
check_error(r)
|
||||
|
||||
|
||||
def getpid():
|
||||
return getpid_()
|
||||
|
||||
|
||||
def waitpid(pid, opts):
|
||||
a = array.array('i', [0])
|
||||
r = waitpid_(pid, a, opts)
|
||||
check_error(r)
|
||||
return (r, a[0])
|
||||
|
||||
|
||||
def kill(pid, sig):
|
||||
r = kill_(pid, sig)
|
||||
check_error(r)
|
||||
|
||||
|
||||
def system(command):
|
||||
r = system_(command)
|
||||
check_error(r)
|
||||
return r
|
||||
|
||||
|
||||
def getenv(var, default=None):
|
||||
var = getenv_(var)
|
||||
if var is None:
|
||||
return default
|
||||
return var
|
||||
|
||||
|
||||
def fsencode(s):
|
||||
if type(s) is bytes:
|
||||
return s
|
||||
return bytes(s, "utf-8")
|
||||
|
||||
|
||||
def fsdecode(s):
|
||||
if type(s) is str:
|
||||
return s
|
||||
return str(s, "utf-8")
|
||||
|
||||
|
||||
def urandom(n):
|
||||
import builtins
|
||||
with builtins.open("/dev/urandom", "rb") as f:
|
||||
return f.read(n)
|
||||
|
||||
|
||||
def popen(cmd, mode="r"):
|
||||
import builtins
|
||||
i, o = pipe()
|
||||
if mode[0] == "w":
|
||||
i, o = o, i
|
||||
pid = fork()
|
||||
if not pid:
|
||||
if mode[0] == "r":
|
||||
close(1)
|
||||
else:
|
||||
close(0)
|
||||
close(i)
|
||||
dup(o)
|
||||
close(o)
|
||||
s = system(cmd)
|
||||
_exit(s)
|
||||
else:
|
||||
close(o)
|
||||
return builtins.open(i, mode)
|
||||
@@ -1,79 +0,0 @@
|
||||
#
|
||||
# serial - pySerial-like interface for Micropython
|
||||
# based on https://github.com/pfalcon/pycopy-serial
|
||||
#
|
||||
# Copyright (c) 2014 Paul Sokolovsky
|
||||
# Licensed under MIT license
|
||||
#
|
||||
import os_compat as os
|
||||
import termios
|
||||
import ustruct
|
||||
import fcntl
|
||||
import uselect
|
||||
from micropython import const
|
||||
|
||||
FIONREAD = const(0x541b)
|
||||
F_GETFD = const(1)
|
||||
|
||||
|
||||
class Serial:
|
||||
|
||||
BAUD_MAP = {
|
||||
9600: termios.B9600,
|
||||
# From Linux asm-generic/termbits.h
|
||||
19200: 14,
|
||||
57600: termios.B57600,
|
||||
115200: termios.B115200
|
||||
}
|
||||
|
||||
def __init__(self, port, baudrate, timeout=None, **kwargs):
|
||||
self.port = port
|
||||
self.baudrate = baudrate
|
||||
self.timeout = -1 if timeout is None else timeout * 1000
|
||||
self.open()
|
||||
|
||||
def open(self):
|
||||
self.fd = os.open(self.port, os.O_RDWR | os.O_NOCTTY)
|
||||
termios.setraw(self.fd)
|
||||
iflag, oflag, cflag, lflag, ispeed, ospeed, cc = termios.tcgetattr(
|
||||
self.fd)
|
||||
baudrate = self.BAUD_MAP[self.baudrate]
|
||||
termios.tcsetattr(self.fd, termios.TCSANOW,
|
||||
[iflag, oflag, cflag, lflag, baudrate, baudrate, cc])
|
||||
self.poller = uselect.poll()
|
||||
self.poller.register(self.fd, uselect.POLLIN | uselect.POLLHUP)
|
||||
|
||||
def close(self):
|
||||
if self.fd:
|
||||
os.close(self.fd)
|
||||
self.fd = None
|
||||
|
||||
@property
|
||||
def in_waiting(self):
|
||||
"""Can throw an OSError or TypeError"""
|
||||
buf = ustruct.pack('I', 0)
|
||||
fcntl.ioctl(self.fd, FIONREAD, buf, True)
|
||||
return ustruct.unpack('I', buf)[0]
|
||||
|
||||
@property
|
||||
def is_open(self):
|
||||
"""Can throw an OSError or TypeError"""
|
||||
return fcntl.fcntl(self.fd, F_GETFD) == 0
|
||||
|
||||
def write(self, data):
|
||||
if self.fd:
|
||||
os.write(self.fd, data)
|
||||
|
||||
def read(self, size=1):
|
||||
buf = b''
|
||||
while self.fd and size > 0:
|
||||
if not self.poller.poll(self.timeout):
|
||||
break
|
||||
chunk = os.read(self.fd, size)
|
||||
l = len(chunk)
|
||||
if l == 0: # port has disappeared
|
||||
self.close()
|
||||
return buf
|
||||
size -= l
|
||||
buf += bytes(chunk)
|
||||
return buf
|
||||
@@ -1,142 +0,0 @@
|
||||
"""Constants/functions for interpreting results of os.stat() and os.lstat().
|
||||
|
||||
Suggested usage: from stat import *
|
||||
"""
|
||||
|
||||
# Indices for stat struct members in the tuple returned by os.stat()
|
||||
|
||||
ST_MODE = 0
|
||||
ST_INO = 1
|
||||
ST_DEV = 2
|
||||
ST_NLINK = 3
|
||||
ST_UID = 4
|
||||
ST_GID = 5
|
||||
ST_SIZE = 6
|
||||
ST_ATIME = 7
|
||||
ST_MTIME = 8
|
||||
ST_CTIME = 9
|
||||
|
||||
# Extract bits from the mode
|
||||
|
||||
|
||||
def S_IMODE(mode):
|
||||
"""Return the portion of the file's mode that can be set by
|
||||
os.chmod().
|
||||
"""
|
||||
return mode & 0o7777
|
||||
|
||||
|
||||
def S_IFMT(mode):
|
||||
"""Return the portion of the file's mode that describes the
|
||||
file type.
|
||||
"""
|
||||
return mode & 0o170000
|
||||
|
||||
|
||||
# Constants used as S_IFMT() for various file types
|
||||
# (not all are implemented on all systems)
|
||||
|
||||
S_IFDIR = 0o040000 # directory
|
||||
S_IFCHR = 0o020000 # character device
|
||||
S_IFBLK = 0o060000 # block device
|
||||
S_IFREG = 0o100000 # regular file
|
||||
S_IFIFO = 0o010000 # fifo (named pipe)
|
||||
S_IFLNK = 0o120000 # symbolic link
|
||||
S_IFSOCK = 0o140000 # socket file
|
||||
|
||||
# Functions to test for each file type
|
||||
|
||||
|
||||
def S_ISDIR(mode):
|
||||
"""Return True if mode is from a directory."""
|
||||
return S_IFMT(mode) == S_IFDIR
|
||||
|
||||
|
||||
def S_ISCHR(mode):
|
||||
"""Return True if mode is from a character special device file."""
|
||||
return S_IFMT(mode) == S_IFCHR
|
||||
|
||||
|
||||
def S_ISBLK(mode):
|
||||
"""Return True if mode is from a block special device file."""
|
||||
return S_IFMT(mode) == S_IFBLK
|
||||
|
||||
|
||||
def S_ISREG(mode):
|
||||
"""Return True if mode is from a regular file."""
|
||||
return S_IFMT(mode) == S_IFREG
|
||||
|
||||
|
||||
def S_ISFIFO(mode):
|
||||
"""Return True if mode is from a FIFO (named pipe)."""
|
||||
return S_IFMT(mode) == S_IFIFO
|
||||
|
||||
|
||||
def S_ISLNK(mode):
|
||||
"""Return True if mode is from a symbolic link."""
|
||||
return S_IFMT(mode) == S_IFLNK
|
||||
|
||||
|
||||
def S_ISSOCK(mode):
|
||||
"""Return True if mode is from a socket."""
|
||||
return S_IFMT(mode) == S_IFSOCK
|
||||
|
||||
|
||||
# Names for permission bits
|
||||
|
||||
S_ISUID = 0o4000 # set UID bit
|
||||
S_ISGID = 0o2000 # set GID bit
|
||||
S_ENFMT = S_ISGID # file locking enforcement
|
||||
S_ISVTX = 0o1000 # sticky bit
|
||||
S_IREAD = 0o0400 # Unix V7 synonym for S_IRUSR
|
||||
S_IWRITE = 0o0200 # Unix V7 synonym for S_IWUSR
|
||||
S_IEXEC = 0o0100 # Unix V7 synonym for S_IXUSR
|
||||
S_IRWXU = 0o0700 # mask for owner permissions
|
||||
S_IRUSR = 0o0400 # read by owner
|
||||
S_IWUSR = 0o0200 # write by owner
|
||||
S_IXUSR = 0o0100 # execute by owner
|
||||
S_IRWXG = 0o0070 # mask for group permissions
|
||||
S_IRGRP = 0o0040 # read by group
|
||||
S_IWGRP = 0o0020 # write by group
|
||||
S_IXGRP = 0o0010 # execute by group
|
||||
S_IRWXO = 0o0007 # mask for others (not in group) permissions
|
||||
S_IROTH = 0o0004 # read by others
|
||||
S_IWOTH = 0o0002 # write by others
|
||||
S_IXOTH = 0o0001 # execute by others
|
||||
|
||||
# Names for file flags
|
||||
|
||||
UF_NODUMP = 0x00000001 # do not dump file
|
||||
UF_IMMUTABLE = 0x00000002 # file may not be changed
|
||||
UF_APPEND = 0x00000004 # file may only be appended to
|
||||
UF_OPAQUE = 0x00000008 # directory is opaque when viewed through a union stack
|
||||
UF_NOUNLINK = 0x00000010 # file may not be renamed or deleted
|
||||
UF_COMPRESSED = 0x00000020 # OS X: file is hfs-compressed
|
||||
UF_HIDDEN = 0x00008000 # OS X: file should not be displayed
|
||||
SF_ARCHIVED = 0x00010000 # file may be archived
|
||||
SF_IMMUTABLE = 0x00020000 # file may not be changed
|
||||
SF_APPEND = 0x00040000 # file may only be appended to
|
||||
SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted
|
||||
SF_SNAPSHOT = 0x00200000 # file is a snapshot file
|
||||
|
||||
_filemode_table = (((S_IFLNK, "l"), (S_IFREG, "-"), (S_IFBLK, "b"),
|
||||
(S_IFDIR, "d"), (S_IFCHR, "c"),
|
||||
(S_IFIFO, "p")), ((S_IRUSR, "r"), ), ((S_IWUSR, "w"), ),
|
||||
((S_IXUSR | S_ISUID, "s"), (S_ISUID, "S"),
|
||||
(S_IXUSR, "x")), ((S_IRGRP, "r"), ), ((S_IWGRP, "w"), ),
|
||||
((S_IXGRP | S_ISGID, "s"), (S_ISGID, "S"),
|
||||
(S_IXGRP, "x")), ((S_IROTH, "r"), ), ((S_IWOTH, "w"), ),
|
||||
((S_IXOTH | S_ISVTX, "t"), (S_ISVTX, "T"), (S_IXOTH, "x")))
|
||||
|
||||
|
||||
def filemode(mode):
|
||||
"""Convert a file's mode to a string of the form '-rwxrwxrwx'."""
|
||||
perm = []
|
||||
for table in _filemode_table:
|
||||
for bit, char in table:
|
||||
if mode & bit == bit:
|
||||
perm.append(char)
|
||||
break
|
||||
else:
|
||||
perm.append("-")
|
||||
return "".join(perm)
|
||||
@@ -1,79 +0,0 @@
|
||||
from utime import *
|
||||
from micropython import const
|
||||
|
||||
_TS_YEAR = const(0)
|
||||
_TS_MON = const(1)
|
||||
_TS_MDAY = const(2)
|
||||
_TS_HOUR = const(3)
|
||||
_TS_MIN = const(4)
|
||||
_TS_SEC = const(5)
|
||||
_TS_WDAY = const(6)
|
||||
_TS_YDAY = const(7)
|
||||
_TS_ISDST = const(8)
|
||||
|
||||
_WDAY = const(("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))
|
||||
_MDAY = const(
|
||||
(
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def strftime(datefmt, ts):
|
||||
from io import StringIO
|
||||
|
||||
fmtsp = False
|
||||
ftime = StringIO()
|
||||
for k in datefmt:
|
||||
if fmtsp:
|
||||
if k == "a":
|
||||
ftime.write(_WDAY[ts[_TS_WDAY]][0:3])
|
||||
elif k == "A":
|
||||
ftime.write(_WDAY[ts[_TS_WDAY]])
|
||||
elif k == "b":
|
||||
ftime.write(_MDAY[ts[_TS_MON] - 1][0:3])
|
||||
elif k == "B":
|
||||
ftime.write(_MDAY[ts[_TS_MON] - 1])
|
||||
elif k == "d":
|
||||
ftime.write("%02d" % ts[_TS_MDAY])
|
||||
elif k == "H":
|
||||
ftime.write("%02d" % ts[_TS_HOUR])
|
||||
elif k == "I":
|
||||
ftime.write("%02d" % (ts[_TS_HOUR] % 12))
|
||||
elif k == "j":
|
||||
ftime.write("%03d" % ts[_TS_YDAY])
|
||||
elif k == "m":
|
||||
ftime.write("%02d" % ts[_TS_MON])
|
||||
elif k == "M":
|
||||
ftime.write("%02d" % ts[_TS_MIN])
|
||||
elif k == "P":
|
||||
ftime.write("AM" if ts[_TS_HOUR] < 12 else "PM")
|
||||
elif k == "S":
|
||||
ftime.write("%02d" % ts[_TS_SEC])
|
||||
elif k == "w":
|
||||
ftime.write(str(ts[_TS_WDAY]))
|
||||
elif k == "y":
|
||||
ftime.write("%02d" % (ts[_TS_YEAR] % 100))
|
||||
elif k == "Y":
|
||||
ftime.write(str(ts[_TS_YEAR]))
|
||||
else:
|
||||
ftime.write(k)
|
||||
fmtsp = False
|
||||
elif k == "%":
|
||||
fmtsp = True
|
||||
else:
|
||||
ftime.write(k)
|
||||
val = ftime.getvalue()
|
||||
ftime.close()
|
||||
return val
|
||||
Binary file not shown.
@@ -1,31 +0,0 @@
|
||||
#!/usrdata/micropython/micropython
|
||||
|
||||
# Add the /usrdata/micropython directory to sys.path so we can find the external modules.
|
||||
# TODO: Move external modules to lib?
|
||||
# TODO: Recompile Micropython with a syspath set up for our use case.
|
||||
import sys
|
||||
# Remove the home directory from sys.path.
|
||||
if "~/.micropython/lib" in sys.path:
|
||||
sys.path.remove("~/.micropython/lib")
|
||||
sys.path.append("/usrdata/micropython")
|
||||
|
||||
import serial
|
||||
import uos
|
||||
|
||||
|
||||
atcmd = sys.argv[1]
|
||||
|
||||
ser = serial.Serial("/dev/ttyOUT", baudrate=115200)
|
||||
ser.write(atcmd + "\r\n")
|
||||
|
||||
uos.system("sleep 0.025s")
|
||||
# wait for an OK
|
||||
out=r''
|
||||
while ser.in_waiting > 0:
|
||||
out += ser.read(1)
|
||||
|
||||
if "OK" not in str(out):
|
||||
print('Error NOT OK')
|
||||
|
||||
print(out.decode('utf-8'))
|
||||
ser.close()
|
||||
@@ -21,7 +21,6 @@ MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
x=$(urldecode "$atcmd")
|
||||
runcmd=$(echo -en "$x\r\n" | microcom -t 2000 /dev/ttyOUT)
|
||||
# runcmd=$(/usrdata/simpleadmin/scripts/doAT.py "$MYATCMD")
|
||||
fi
|
||||
|
||||
echo "Content-type: text/plain"
|
||||
|
||||
@@ -22,7 +22,7 @@ setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
|
||||
|
||||
if [ -n "${setTTL}" ]; then
|
||||
# Stop Service To Remove Rules
|
||||
/usrdata/simpleadmin/ttl/ttl-override stop
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
|
||||
# Check iptables is still set
|
||||
ttlcheck=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
@@ -34,10 +34,10 @@ if [ -n "${setTTL}" ]; then
|
||||
fi
|
||||
|
||||
# Echo TTL to file
|
||||
echo $setTTL > /usrdata/simpleadmin/ttl/ttlvalue
|
||||
echo $setTTL > /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Set Start Service
|
||||
/usrdata/simpleadmin/ttl/ttl-override start
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usrdata/simpleadmin/ttl/ttl-override start
|
||||
ExecStart=/usrdata/simplefirewall/ttl-override start
|
||||
User=root
|
||||
|
||||
[Install]
|
||||
@@ -4,7 +4,7 @@
|
||||
# Uses ttlvalue file to read what ttl should be set to
|
||||
|
||||
|
||||
if [ -f /usrdata/simpleadmin/ttl/ttlvalue ];
|
||||
if [ -f /usrdata/simplefirewall/ttlvalue ];
|
||||
then
|
||||
ttlfile=$(</usrdata/simpleadmin/ttl/ttlvalue)
|
||||
TTLVALUE=$(echo $ttlfile | grep -o "[0-9]\{1,3\}")
|
||||
Reference in New Issue
Block a user