1// Package ddwrt implements the dd-wrt init system. 2 3package ddwrt 4 5import ( 6 "os" 7 "os/exec" 8 "strings" 9 10 "github.com/nextdns/nextdns/host/service" 11 "github.com/nextdns/nextdns/host/service/internal" 12) 13 14type Service struct { 15 service.Config 16 service.ConfigFileStorer 17 Path string 18} 19 20func New(c service.Config) (Service, error) { 21 if b, err := exec.Command("uname", "-o").Output(); err != nil || 22 !strings.HasPrefix(string(b), "DD-WRT") { 23 return Service{}, service.ErrNotSuported 24 } 25 return Service{ 26 Config: c, 27 ConfigFileStorer: service.ConfigFileStorer{File: "/jffs/etc/" + c.Name + ".conf"}, 28 Path: "/jffs/etc/config/" + c.Name + ".startup", 29 }, nil 30} 31 32func (s Service) Install() error { 33 return internal.CreateWithTemplate(s.Path, tmpl, 0755, s.Config) 34} 35 36func (s Service) Uninstall() error { 37 return os.Remove(s.Path) 38} 39 40func (s Service) Status() (service.Status, error) { 41 if _, err := os.Stat(s.Path); os.IsNotExist(err) { 42 return service.StatusNotInstalled, nil 43 } 44 45 err := internal.Run(s.Path, "status") 46 if internal.ExitCode(err) == 1 { 47 return service.StatusStopped, nil 48 } else if err != nil { 49 return service.StatusUnknown, err 50 } 51 return service.StatusRunning, nil 52} 53 54func (s Service) Start() error { 55 return internal.Run(s.Path, "start") 56} 57 58func (s Service) Stop() error { 59 return internal.Run(s.Path, "stop") 60} 61 62func (s Service) Restart() error { 63 return internal.Run(s.Path, "restart") 64} 65 66var tmpl = `#!/bin/sh 67 68name="{{.Name}}" 69cmd="{{.Executable}}{{range .Arguments}} {{.}}{{end}}" 70pid_file="/tmp/$name.pid" 71 72get_pid() { 73 cat "$pid_file" 74} 75 76is_running() { 77 test -f "$pid_file" && ps | grep -q "^ *$(get_pid) " 78} 79 80action=$1 81if [ -z "$action" ]; then 82 action=start 83fi 84 85case "$action" in 86 start) 87 if is_running; then 88 echo "Already started" 89 else 90 echo "Starting $name" 91 export {{.RunModeEnv}}=1 92 $cmd & 93 echo $! > "$pid_file" 94 if ! is_running; then 95 echo "Unable to start" 96 exit 1 97 fi 98 fi 99 ;; 100 stop) 101 if is_running; then 102 echo -n "Stopping $name.." 103 kill $(get_pid) 104 for i in 1 2 3 4 5 6 7 8 9 10; do 105 if ! is_running; then 106 break 107 fi 108 echo -n "." 109 sleep 1 110 done 111 echo 112 if is_running; then 113 echo "Not stopped; may still be shutting down or shutdown may have failed" 114 exit 1 115 else 116 echo "Stopped" 117 if [ -f "$pid_file" ]; then 118 rm "$pid_file" 119 fi 120 fi 121 else 122 echo "Not running" 123 fi 124 ;; 125 restart) 126 $0 stop 127 if is_running; then 128 echo "Unable to stop, will not attempt to start" 129 exit 1 130 fi 131 $0 start 132 ;; 133 status) 134 if is_running; then 135 echo "Running" 136 else 137 echo "Stopped" 138 exit 1 139 fi 140 ;; 141 *) 142 echo "Usage: $0 {start|stop|restart|status}" 143 exit 1 144 ;; 145esac 146exit 0 147` 148