netatalk: add uci support
authorAntonio Pastor <antonio.pastor@gmail.com>
Thu, 30 Jan 2025 23:58:58 +0000 (18:58 -0500)
committerTianling Shen <cnsztl@gmail.com>
Sun, 2 Feb 2025 11:12:30 +0000 (19:12 +0800)
Signed-off-by: Antonio Pastor <antonio.pastor@gmail.com>
13 files changed:
net/netatalk/Makefile
net/netatalk/files/a2boot.conf [new file with mode: 0644]
net/netatalk/files/a2boot.init [new file with mode: 0755]
net/netatalk/files/afpd.conf [new file with mode: 0644]
net/netatalk/files/afpd.init
net/netatalk/files/atalkd.conf [new file with mode: 0644]
net/netatalk/files/atalkd.init [new file with mode: 0755]
net/netatalk/files/macipgw.conf [new file with mode: 0644]
net/netatalk/files/macipgw.init [new file with mode: 0755]
net/netatalk/files/papd.conf [new file with mode: 0644]
net/netatalk/files/papd.init [new file with mode: 0755]
net/netatalk/files/timelord.conf [new file with mode: 0644]
net/netatalk/files/timelord.init [new file with mode: 0755]

index 8d54a25f108fa7fd53fa64d1326404d2c6192b7d..89afb91e3145ae340805cd9586ad3f236ae73478 100644 (file)
@@ -169,6 +169,7 @@ define Package/netatalk-small/install
        $(INSTALL_DIR) $(1)/usr/lib/netatalk
        $(INSTALL_DIR) $(1)/usr/sbin
        $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_DIR) $(1)/etc/config
        $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/libatalk.so* $(1)/usr/lib/
        $(CP) $(PKG_INSTALL_DIR)/usr/lib/netatalk/*.so $(1)/usr/lib/netatalk/
@@ -176,6 +177,7 @@ define Package/netatalk-small/install
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/afp.conf $(1)/etc/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/extmap.conf $(1)/etc/
        $(INSTALL_BIN) ./files/afpd.init $(1)/etc/init.d/afpd
+       $(INSTALL_DATA) ./files/afpd.conf $(1)/etc/config/afpd
 endef
 
 define Package/netatalk/install
@@ -183,6 +185,16 @@ define Package/netatalk/install
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/atalkd.conf $(1)/etc/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/macipgw.conf $(1)/etc/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/papd.conf $(1)/etc/
+       $(INSTALL_BIN) ./files/atalkd.init $(1)/etc/init.d/atalkd
+       $(INSTALL_BIN) ./files/macipgw.init $(1)/etc/init.d/macipgw
+       $(INSTALL_BIN) ./files/timelord.init $(1)/etc/init.d/timelord
+       $(INSTALL_BIN) ./files/a2boot.init $(1)/etc/init.d/a2boot
+       $(INSTALL_BIN) ./files/papd.init $(1)/etc/init.d/papd
+       $(INSTALL_DATA) ./files/atalkd.conf $(1)/etc/config/atalkd
+       $(INSTALL_DATA) ./files/macipgw.conf $(1)/etc/config/macipgw
+       $(INSTALL_DATA) ./files/timelord.conf $(1)/etc/config/timelord
+       $(INSTALL_DATA) ./files/a2boot.conf $(1)/etc/config/a2boot
+       $(INSTALL_DATA) ./files/papd.conf $(1)/etc/config/papd
 endef
 
 define Package/netatalk-full/install
@@ -190,6 +202,16 @@ define Package/netatalk-full/install
        $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/atalkd.conf $(1)/etc/,)
        $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/macipgw.conf $(1)/etc/,)
        $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/papd.conf $(1)/etc/,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_BIN) ./files/atalkd.init $(1)/etc/init.d/atalkd,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_BIN) ./files/macipgw.init $(1)/etc/init.d/macipgw,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_BIN) ./files/timelord.init $(1)/etc/init.d/timelord,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_BIN) ./files/a2boot.init $(1)/etc/init.d/a2boot,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_BIN) ./files/papd.init $(1)/etc/init.d/papd,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) ./files/atalkd.conf $(1)/etc/config/atalkd,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) ./files/macipgw.conf $(1)/etc/config/macipgw,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) ./files/timelord.conf $(1)/etc/config/timelord,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) ./files/a2boot.conf $(1)/etc/config/a2boot,)
+       $(if $(PACKAGE_NETATALK_APPLETALK),$(INSTALL_DATA) ./files/papd.conf $(1)/etc/config/papd,)
 endef
 
 $(eval $(call BuildPackage,netatalk-small))
diff --git a/net/netatalk/files/a2boot.conf b/net/netatalk/files/a2boot.conf
new file mode 100644 (file)
index 0000000..88ad84a
--- /dev/null
@@ -0,0 +1,3 @@
+config a2boot 'a2boot'
+       option disabled '1'
+       option nbpname 'Apple]['
diff --git a/net/netatalk/files/a2boot.init b/net/netatalk/files/a2boot.init
new file mode 100755 (executable)
index 0000000..781a2e2
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh /etc/rc.common
+
+START=94
+
+USE_PROCD=1
+PROG=/usr/sbin/a2boot
+
+start_service() {
+       config_load a2boot
+
+       config_get disabled a2boot disabled '0'
+       [ "$disabled" == "0" ] || { 
+               logger -p info -t a2boot "Disabled by config" && exit 
+       }
+
+       config_get nbpname a2boot nbpname
+       [ -z "$nbpname" ] || nbpname="-n $nbpname"
+
+       procd_open_instance
+       procd_set_param command $PROG -d $nbpname
+       procd_set_param respawn
+       procd_close_instance
+}
diff --git a/net/netatalk/files/afpd.conf b/net/netatalk/files/afpd.conf
new file mode 100644 (file)
index 0000000..05a704a
--- /dev/null
@@ -0,0 +1,27 @@
+config setup
+       # set config_overwrite to 0 if manually editing afpd.conf and to have init ignore this file
+       option config_overwrite '1'
+       # comment out or set to /etc/afpd.conf to use config file provided with package (useful if manually editing)
+       option config_file '/var/netatalk/afp.conf'
+
+config global
+       # available UAMs will vary depending on variant or build options
+       #option uam_list 'uams_guest.so uams_clrtxt.so uams_randnum.so uams_dhx.so uams_dhx2.so uam_gss.so'
+       option uam_list 'uams_dhx.so uams_dhx2.so'
+       #option afp_interfaces 'br-lan'
+       option afp_listen '192.168.1.1'
+       option log_file '/var/log/afpd.log'
+       option appletalk 'yes'
+
+# sample user home shares
+#config homes
+       #option basedir_regex '/home'
+       #option home_name '$u'\''s_home'
+
+# sample TM share, CNID DB beside shared directory (folder must exist)
+#config volume
+       #option share_name 'Backups'
+       #option vol_dbpath '/tmp/afp/data_db'
+       #option path '/tmp/afp/data'
+       #option valid_users '@users'
+       #option time_machine 'yes'
index 8fab349e31d3c76e06bb894aa74c5a06fd5c9ef3..e139c1e61ccd6218c2f9f4cc649b8aaf710a68e0 100644 (file)
 #!/bin/sh /etc/rc.common
-# Copyright (C) 2010-2012 OpenWrt.org
+# Copyright (C) 2010-2025 OpenWrt.org
 
-START=80
+START=85
 STOP=10
-
 USE_PROCD=1
+PROG_afpd='/usr/sbin/afpd'
+PROG_cnid='/usr/sbin/cnid_metad'
+
+# Default config file location
+config_file='/etc/afp.conf'
+
+# Config file contents and status
+afpd_config=''
+config_overwrite=''
+config_error=0
+setup_error=0
+# Log tag
+log_tag='afpd-init'
+
+# Configuration dictionary
+valid_global='|'
+valid_global=$valid_global'ad_domain|admin_auth_user|admin_group|force_user|force_group|k5_keytab|k5_service|k5_realm|'
+valid_global=$valid_global'nt_domain|nt_separator|save_password|set_password|uam_list|uam_path|mac_charset|unix_charset|'
+valid_global=$valid_global'vol_charset|passwd_file|passwd_minlen|afp_interfaces|afp_listen|afp_port|appletalk|'
+valid_global=$valid_global'cnid_listen|cnid_server|ddp_address|ddp_zone|disconnect_time|dsireadbuf|hostname|'
+valid_global=$valid_global'max_connections|sleep_time|zeroconf|chmod_request|dircachesize|extmap_file|'
+valid_global=$valid_global'force_xattr_with_sticky_bit|guest_account|ignored_attributes|legacy_icon|login_message|'
+valid_global=$valid_global'mimic_model|vol_dbpath|zeroconf_name|log_file|log_level|map_acls|ldap_auth_method|'
+valid_global=$valid_global'ldap_auth_dn|ldap_auth_pw|ldap_uri|ldap_userbase|ldap_userscope|ldap_groupbase|'
+valid_global=$valid_global'ldap_groupscope|ldap_uuid_attr|ldap_name_attr|ldap_group_attr|ldap_uuid_string|'
+valid_global=$valid_global'ldap_uuid_encoding|ldap_user_filter|ldap_group_filter|vol_dbnest|'
+valid_homes='|basedir_regex|path|home_name|'
+valid_volume='|'
+valid_volume=$valid_volume'mac_charset|unix_charset|vol_charset|casefold|chmod_request|force_xattr_with_sticky_bit|'
+valid_volume=$valid_volume'ignored_attributes|login_message|vol_dbpath|path|appledouble|vol_size_limit|valid_users|'
+valid_volume=$valid_volume'invalid_users|hosts_allow|hosts_deny|ea|password|file_perm|directory_perm|umask|preexec|'
+valid_volume=$valid_volume'postexec|root_preexec|root_postexec|rolist|rwlist|veto_files|acls|case_sensitive|prodos|'
+valid_volume=$valid_volume'read_only|time_machine|vol_dbnest|cnid_scheme|'
+valid_share='share_name'
+
+NL=$'\n'
+
+generate_config() {
+       # Save name of sections
+       config_name=''
+       global_name=''
+       homes_name=''
+       volume_names=''
+       # Volume name validation
+       share_names=''
+       fixed_names=''
+
+       # Call-back per section
+       config_cb() {
+               section_type="$1"
+               section_name="$2"
+
+               # Call-back per option
+               option_cb() {
+                       local name="$1"
+                       local value="$2"
+                       # Validate options against dictionary of possible values
+                       if [ "$section_type" = 'setup' -a "$CONFIG_SECTION" = "$config_name" ]; then
+                               if [ "$name" = 'config_overwrite' ]; then
+                                       if [ "$value" = "0" -o "$value" = "1" ]; then
+                                               config_overwrite=$value
+                                       else
+                                               # Garbage on this option means we should not proceed no matter what
+                                               logger -p err -t $log_tag "Invalid SETUP config_overwrite option: $value"
+                                               setup_error=1
+                                       fi
+                               elif [ "$name" = 'config_file' ]; then
+                                       config_file="$value"
+                               else
+                                       config_error=1 && logger -p err -t $log_tag "Invalid SETUP configuration option: $name:$value"
+                               fi
+                       elif [ "$section_type" = 'global' -a "$CONFIG_SECTION" = "$global_name" ]; then
+                                       case "$valid_global" in
+                                               *'|'$name'|'*) afpd_config=$afpd_config"${name//_/ } = $value$NL" ;;
+                                               *) config_error=1 && logger -p err -t $log_tag "Invalid GLOBAL configuration option: $name:$value" ;;
+                                       esac
+                       elif [ "$section_type" = 'homes' -a "$CONFIG_SECTION" = "$homes_name" ]; then
+                                       case "$valid_homes" in
+                                               *'|'$name'|'*) afpd_config=$afpd_config"${name//_/ } = $value$NL" ;;
+                                               *) config_error=1 && logger -p err -t $log_tag "Invalid HOMES configuration option: $name:$value" ;;
+                                       esac
+                       elif [ "$section_type" = 'volume' ]; then
+                               if [ "$name" = "$valid_share" ]; then
+                                       # Special case - share name... check for duplicates... track changes... fix heading.
+                                       case "||$share_names" in
+                                               *'||'$value'||'*) config_error=1 && logger -p err -t $log_tag "Duplicated share name $CONFIG_SECTION-$name:$value" ;;
+                                               *) ;;
+                                       esac
+                                       share_names=$share_names"$value||"
+                                       fixed_names=$fixed_names"$CONFIG_SECTION "
+                                       afpd_config="${afpd_config//\[\[$CONFIG_SECTION\]\]/[$value]}"
+                               else
+                                       case "$valid_volume" in
+                                               *'|'$name'|'*) afpd_config=$afpd_config"${name//_/ } = $value$NL" ;;
+                                               *) config_error=1 && logger -p err -t $log_tag "Invalid VOLUME $CONFIG_SECTION configuration option: $name:$value" ;;
+                                       esac
+                               fi
+                       else
+                               config_error=1 && logger -p err -t $log_tag "Invalid option. Section: $CONFIG_SECTION ($section_type), option: $name:$value" 
+                       fi
+               }
+
+               # Call-back per list - error, we don't use lists
+               list_cb() {
+                       config_error=1 && logger -p err -t $log_tag "Invalid list in $CONFIG_SECTION: $1:$2"
+               }
+
+               # Identify sections and create section headers (placeholder for volumes)
+               if [ "$section_type" = 'setup' ]; then
+                       # Find the name of the first (and only?) setup (control) section
+                       if [ -z "$config_name" ]; then
+                               config_name=$section_name
+                       else
+                               config_error=1 && logger -p err -t $log_tag 'Multiple SETUP sections defined'
+                       fi
+               elif [ "$section_type" = 'global' ]; then
+                       # Find the name of the first (and only?) global section
+                       if [ -z "$global_name" ]; then
+                               global_name=$section_name
+                               [ -z "$afpd_config" ] || afpd_config=$afpd_config"$NL"
+                               afpd_config=$afpd_config"[Global]$NL"
+                       else
+                               config_error=1 && logger -p err -t $log_tag 'Multiple GLOBAL sections defined'
+                       fi
+               elif [ "$section_type" = 'homes' ]; then
+                       # Find the name of the first (and only?) homes section
+                       if [ -z "$homes_name" ]; then
+                               homes_name=$section_name
+                               [ -z "$afpd_config" ] || afpd_config=$afpd_config"$NL"
+                               afpd_config=$afpd_config"[Homes]$NL"
+                       else
+                               config_error=1 && logger -p err -t $log_tag 'Multiple HOMES sections defined'
+                       fi
+               elif [ "$section_type" = 'volume' ]; then
+                       # Collect the names of the volume sections
+                       volume_names=$volume_names"$section_name "
+                       [ -z "$afpd_config" ] || afpd_config=$afpd_config"$NL"
+                       afpd_config=$afpd_config"[[$section_name]]$NL"
+               elif [ "$section_type" != '' ]; then
+                       # It's not the end of file
+                       config_error=1 && logger -p err -t $log_tag "Invalid $section_type section defined"
+               fi
+       }
+
+       # Load config (trigger callbacks)
+       config_load afpd
+
+       # config_overwrite is messed up... don't know what to do
+       if [ "$setup_error" -eq 1 ]; then
+               exit 1
+       fi
+       # So, should we? Shouldn't? Nobody said but gave us share details.
+       [ -z "$config_overwrite" ] && [ -n "$volume_names" -o -n "$homes_name" ] && { 
+               logger -p warn -t $log_tag "No valid config_overwrite at SETUP config. Ignoring defined VOLUMES and/or HOMES" 
+       }
+
+       # Only update configuration file if UCI config asks for it
+       build_config=$(expr "${config_overwrite}" == "1")
+       if [ "$build_config" -eq 1 ]; then
+               # One last check for valid volume names
+               [ "$volume_names" = "$fixed_names" ] || { 
+                       config_error=1 && logger -p err -t $log_tag "Not all volumes have valid option $valid_share"
+               }
+               # Continue only if configuration was decent - any errors were logged already
+               if [ "$config_error" -eq 1 ]; then
+                       exit 1
+               fi
+               # Create file
+               mkdir -p `dirname "$config_file"`
+               echo "$afpd_config" > "$config_file"
+               logger -p info -t $log_tag "Configuration written to $config_file"
+       else
+               logger -p info -t $log_tag 'Configuration not modified - setup:config_overwrite=0 or missing'
+       fi
+}
 
 start_service() {
-        mkdir -p /var/netatalk/CNID/
+       mkdir -p /var/netatalk/CNID/
 
+       generate_config
+
+       # afpd
        procd_open_instance
-       procd_set_param command /usr/sbin/afpd -d -F /etc/afp.conf
-       procd_set_param file /etc/afp.conf
+       procd_set_param command $PROG_afpd -d -F $config_file
+       procd_set_param file $config_file
        procd_set_param respawn
        procd_close_instance
 
+       # cnid
        procd_open_instance
-       procd_set_param command /usr/sbin/cnid_metad -d
+       procd_set_param command $PROG_cnid -d -F $config_file
        procd_set_param respawn
        procd_close_instance
 }
-
diff --git a/net/netatalk/files/atalkd.conf b/net/netatalk/files/atalkd.conf
new file mode 100644 (file)
index 0000000..2b67480
--- /dev/null
@@ -0,0 +1,18 @@
+config atalkd 'atalkd'
+       option disabled '1'
+       # set config_overwrite to 0 if manually editing config file and to have init ignore this file
+       option config_overwrite '1'
+       # set to /etc & atalkd.conf to use config file provided with package (useful if manually editing it)
+       option config_file '/var/netatalk/atalkd.conf'
+
+#config interface
+       # interface option is mandatory
+       #option interface 'br-lan'
+       #option mode '<none>|router|seed|donotroute'
+       #option mode 'router'
+       #option net '100-200'
+       #option addr '100.160'
+       #option phase '2'
+       #list zone 'Here'
+       #list zone 'There'
+       #list zone 'And Everywhere'
diff --git a/net/netatalk/files/atalkd.init b/net/netatalk/files/atalkd.init
new file mode 100755 (executable)
index 0000000..871fe6e
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010-2025 OpenWrt.org
+
+START=80
+STOP=10
+USE_PROCD=1
+PROG='/usr/sbin/atalkd'
+
+# Config file, contents and status
+default_config="/etc/atalkd.conf"
+atalkd_config=''
+atalkd_error=0
+
+# Log tag
+log_tag='atalkd-init'
+
+NL=$'\n'
+
+generate_config() {
+       # Setup section
+       config_file=''
+       config_overwrite=''
+
+       handle_zone() {
+               local value="$1"
+               atalkd_config="$atalkd_config -zone $value"
+       }
+
+       parse_interface() {
+               local section="$1"
+               local _buffer=''
+               local _value
+               local _interface=''
+               config_get _interface "$section" "interface"
+               append _buffer "$_interface"
+               [ -n "$_interface" ] || { 
+                       atalkd_error=1 && logger -p err -t "$log_tag" "Missing interface name for interface $section"
+               }
+               config_get _value "$section" "mode"
+               [ -z "$_value" ] || append _buffer "-$_value"
+               config_get _value "$section" "net"
+               [ -z "$_value" ] || append _buffer "-net $_value"
+               config_get _value "$section" "addr"
+               [ -z "$_value" ] || append _buffer "-addr $_value"
+               config_get _value "$section" "phase"
+               [ -z "$_value" ] || append _buffer "-phase $_value"
+               atalkd_config="$atalkd_config$_buffer"
+               config_list_foreach "$section" zone handle_zone
+               atalkd_config="$atalkd_config$NL"
+       }
+
+       config_load atalkd
+
+       config_get disabled atalkd disabled '0'
+       if [ "$disabled" = "1" ] ; then 
+               logger -p info -t $log_tag "Disabled by config"
+               exit 
+       fi
+       config_get config_file atalkd config_file "$default_config"
+       config_get config_overwrite atalkd config_overwrite
+       if [ "$config_overwrite" == "1" ] ; then
+               config_foreach parse_interface interface
+               mkdir -p `dirname "$config_file"`
+               echo "$atalkd_config" > "$config_file"
+               logger -p info -t $log_tag "Configuration written to $config_file"
+       else
+               logger -p info -t $log_tag 'Configuration not modified - atalkd:config_overwrite=0 or missing'
+       fi
+}
+
+start_service() {
+       generate_config
+
+       [ "$atalkd_error" == "0" ] || exit
+
+       procd_open_instance
+       procd_set_param command $PROG -d -f "$config_file"
+       procd_set_param file "$config_file"
+       procd_set_param respawn
+       procd_close_instance
+}
diff --git a/net/netatalk/files/macipgw.conf b/net/netatalk/files/macipgw.conf
new file mode 100644 (file)
index 0000000..1c24c05
--- /dev/null
@@ -0,0 +1,6 @@
+config macipgw 'macipgw'
+       option disabled '1'
+       #option zone 'Gateway'
+       option nameserver '192.168.1.1'
+       option network '192.168.100.0'
+       option netmask '255.255.225.0'
diff --git a/net/netatalk/files/macipgw.init b/net/netatalk/files/macipgw.init
new file mode 100755 (executable)
index 0000000..cd6c7af
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh /etc/rc.common
+
+START=94
+
+USE_PROCD=1
+PROG=/usr/sbin/macipgw
+
+start_service() {
+       config_load macipgw
+
+       config_get disabled macipgw disabled '0'
+       [ "$disabled" = "0" ] || { 
+               logger -p info -t macipgw "Disabled by config" && exit 
+       }
+       config_get network macipgw network 127.0.0.1
+       config_get netmask macipgw netmask 255.255.255.0
+       config_get nameserver macipgw nameserver
+       [ -z "$nameserver" ] || nameserver="-n $nameserver"
+       config_get zone macipgw zone
+       [ -z "$zone" ] || zone="-z $zone"
+
+       procd_open_instance
+       procd_set_param command $PROG -d 0x1 $zone $nameserver $network $netmask
+       procd_set_param respawn
+       procd_close_instance
+}
diff --git a/net/netatalk/files/papd.conf b/net/netatalk/files/papd.conf
new file mode 100644 (file)
index 0000000..02f955d
--- /dev/null
@@ -0,0 +1,20 @@
+config papd 'papd'
+       # set enable to 0 to skip service startup
+       option papd_enable '0'
+       # set config_overwrite to 0 if manually editing config file and to have init ignore this file
+       option config_overwrite '1'
+       # set to /etc/papd.con to use config file provided with package (useful if manually editing it)
+       option config_file '/var/netatalk/papd.conf'
+
+config printer 'LaserWriter8500'
+       option name 'Apple LaserWriter 8500'
+       option disabled '0'
+       option pr '|/usr/bin/lpr -Plp'
+       option sp ''
+       option ca '/tmp/print'
+       option am 'uams_guest.so,uams_clrtxt.s'
+       option pd '/etc/atalk/ppds/LW8500.ppd'
+
+config printer 'Broken'
+       option name 'Printer 2:LaserWriter@My Zone'
+       option disabled '1'
diff --git a/net/netatalk/files/papd.init b/net/netatalk/files/papd.init
new file mode 100755 (executable)
index 0000000..3f80de5
--- /dev/null
@@ -0,0 +1,88 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010-2025 OpenWrt.org
+
+START=82
+STOP=10
+USE_PROCD=1
+PROG='/usr/sbin/papd'
+
+# Config file, contents and status
+default_config="/etc/papd.conf"
+papd_config=''
+papd_error=0
+
+# Log tag
+log_tag='papd-init'
+
+NL=$'\n'
+
+generate_config() {
+       # Setup section
+       config_file=''
+       config_overwrite=''
+
+       parse_printer() {
+               local section="$1"
+               local _buffer=''
+               local _value
+               local _printer=''
+               local _disabled=1
+               config_get _printer "$section" "name"
+               append _buffer "$_printer: "
+               [ -n "$_printer" ] || { 
+                       papd_error=1 && logger -p err -t "$log_tag" "Missing printer name for printer $section"
+               }
+               config_get _disabled "$section" 'disabled' '1'
+               config_get _value "$section" 'am'
+               [ -z "$_value" ] || append _buffer " :am=$_value:"
+               config_get _value "$section" 'au'
+               [ -z "$_value" ] || append _buffer " :au=$_value:"
+               config_get _value "$section" 'co'
+               [ -z "$_value" ] || append _buffer " :co=$_value:"
+               config_get _value "$section" 'fo'
+               [ -z "$_value" ] || append _buffer " :fo=$_value:"
+               config_get _value "$section" 'op'
+               [ -z "$_value" ] || append _buffer " :op=$_value:"
+               config_get _value "$section" 'pa'
+               [ -z "$_value" ] || append _buffer " :pa=$_value:"
+               config_get _value "$section" 'pd'
+               [ -z "$_value" ] || append _buffer " :pd=$_value:"
+               config_get _value "$section" 'pr'
+               [ -z "$_value" ] || append _buffer " :pr=$_value:"
+               config_get _value "$section" 'sp'
+               [ -z "$_value" ] || append _buffer " :sp=$_value:"
+               config_get _value "$section" 'ca'
+               [ -z "$_value" ] || append _buffer " :ca=$_value:"
+               [ "$_disabled" == '1' ] || papd_config="$papd_config$_buffer$NL$NL"
+       }
+
+       config_load papd
+
+       config_get disabled papd disabled '0'
+       if [ "$disabled" = "1" ] ; then 
+               logger -p info -t $log_tag "Disabled by config"
+               exit 
+       fi
+       config_get config_file papd config_file "$default_config"
+       config_get config_overwrite papd config_overwrite
+       if [ "$config_overwrite" == "1" ] ; then
+               config_foreach parse_printer printer
+               mkdir -p `dirname "$config_file"`
+               echo "$papd_config" > "$config_file"
+               logger -p info -t $log_tag "Configuration written to $config_file"
+       else
+               logger -p info -t $log_tag 'Configuration not modified - papd:config_overwrite=0 or missing'
+       fi
+}
+
+start_service() {
+       generate_config
+
+       [ "$papd_error" == "0" ] || exit
+
+       procd_open_instance
+       procd_set_param command $PROG -d -f "$config_file"
+       procd_set_param file "$config_file"
+       procd_set_param respawn
+       procd_close_instance
+}
diff --git a/net/netatalk/files/timelord.conf b/net/netatalk/files/timelord.conf
new file mode 100644 (file)
index 0000000..4421aef
--- /dev/null
@@ -0,0 +1,4 @@
+config timelord 'timelord'
+       option disabled '1'
+       option localtime '1'
+       option nbpname 'Apple]['
diff --git a/net/netatalk/files/timelord.init b/net/netatalk/files/timelord.init
new file mode 100755 (executable)
index 0000000..e45402b
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh /etc/rc.common
+
+START=94
+
+USE_PROCD=1
+PROG=/usr/sbin/timelord
+
+start_service() {
+       config_load timelord
+
+       config_get disabled timelord disabled '0'
+       [ "$disabled" = "0" ] || { 
+               logger -p info -t timelord "Disabled by config" && exit 
+       }
+       config_get nbpname timelord nbpname
+       [ -z "$nbpname" ] || nbpname="-n $nbpname"
+       config_get localtime timelord localtime
+       [ -z "$localtime" ] || localtime="-l"
+
+       procd_open_instance
+       procd_set_param command $PROG -d $localtime $nbpname
+       procd_set_param respawn
+       procd_close_instance
+}