diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2019-09-30 09:30:27 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2019-09-30 09:30:27 +0300 |
commit | 19d98c30087cef57226ee5e68cb8555b03344181 (patch) | |
tree | 8e11b75777af6139d4cde700e1aaf973eaf43071 | |
parent | 08702cab6c2312103f3f4515a64b54a3a176533e (diff) | |
download | proto-19d98c30087cef57226ee5e68cb8555b03344181.tar.gz proto-19d98c30087cef57226ee5e68cb8555b03344181.tar.bz2 |
Implement the "recursive" mode: automatically add any dependencies needed for the new service
-rw-r--r-- | main.go | 119 | ||||
-rw-r--r-- | rcd.go | 2 |
2 files changed, 60 insertions, 61 deletions
@@ -13,7 +13,7 @@ var opts struct { List bool `long:"list" description:"List services"` Add bool `long:"add" description:"Add services"` Del bool `long:"del" description:"Delete services"` - Recurse bool `long:"recursive" short:"t" description:"Recursively process dependencies"` + Recursive bool `long:"recursive" short:"t" description:"Recursively process dependencies"` Defaults bool `long:"defaults" short:"D" description:"Restore defaults"` LF func(string) `short:"l" long:"level" value-name:"L[L...]" description:"apply to these runlevels"` Level []string @@ -144,10 +144,8 @@ type NameChecker func () bool func LoadListing(initdir *InitDir, sel NameSelector) (*Listing, error) { var lst Listing next := initdir.Iterator(sel) - srv := next() - for srv != nil { + for srv := next(); srv != nil; srv = next() { lst.rows = append(lst.rows, ListingRow{name: srv.BaseName()}) - srv = next() } return &lst, nil } @@ -183,30 +181,25 @@ func List(args *ArgList) { // Iterate over selected runlevels next := rs.Iterator() - r := next() - for r.IsValid() { - // Scan the rc<r>,d directory. + for r := next(); r.IsValid(); r = next() { + // Scan the rc<r>.d directory. rcd, err := LoadRCDir(r, initdir) if err != nil { continue } // Iterate over all SystemV services in its start sequence. nextserv := rcd.Start.SysVServiceIterator() - srv := nextserv() - for srv != nil { + for srv := nextserv(); srv != nil; srv = nextserv() { // Mark each such service as enabled for the runlevel. lst.Set(srv.BaseName(), r) - srv = nextserv() } - r = next() } // Print the resulting listing. for _, row := range lst.rows { fmt.Printf("%-16s", row.name) next = rs.Iterator() - r = next() - for r.IsValid() { + for r := next(); r.IsValid(); r = next() { var s string if (row.on[r.Index()]) { s = "on" @@ -214,7 +207,6 @@ func List(args *ArgList) { s = "off" } fmt.Printf(" %s:%-3s", r.Letter(), s) - r = next() } fmt.Println() } @@ -243,12 +235,10 @@ func Del(args *ArgList) { // Repeat for each service named in the command line: nextservice := initdir.Iterator(args.GetNameSelector()) - wanted := nextservice() - for wanted != nil { + for wanted := nextservice(); wanted != nil; wanted = nextservice() { // iterate over all requested runlevels nextlevel := rs.Iterator() - r := nextlevel() - for r.IsValid() { + for r := nextlevel(); r.IsValid(); r = nextlevel() { // Scan the rc<r>,d directory. rcd, err := LoadRCDir(r, initdir) if err != nil { @@ -258,31 +248,23 @@ func Del(args *ArgList) { // Iterate over all SystemV services in its start // sequence: nextsysv := rcd.Start.SysVServiceIterator() - srv := nextsysv() - for srv != nil { + for srv := nextsysv(); srv != nil; srv = nextsysv() { // If the service basename matches, add its // file name to the list. if srv.BaseName() == wanted.BaseName() { oplist.Append(NewUnlink(srv.FileName())) } - srv = nextsysv() } // Do the same for all services in the stop // sequence. nextsysv = rcd.Stop.SysVServiceIterator() - srv = nextsysv() - for srv != nil { + for srv := nextsysv(); srv != nil; srv = nextsysv() { if srv.BaseName() == wanted.BaseName() { oplist.Append(NewUnlink(srv.FileName())) } - srv = nextsysv() } - - r = nextlevel() } - - wanted = nextservice() } // Check and report any unconsumed arguments args.Report() @@ -368,10 +350,6 @@ func (d *InitDir) AddDependencies(srvin []Service) (srvout []Service) { } func Add(args *ArgList) { - if args.Len() == 0 { - Logger.Fatal(`not enough arguments`) - } - // Load the content of the init.d directory. initdir, err := LoadInitDir(InitDirectory) if err != nil { @@ -384,18 +362,48 @@ func Add(args *ArgList) { var services []Service // Services to be added var rsStart Runlevels // Start levels var rsStop Runlevels // Stop levels + var rcdir [NumLevels]*RCDir // All needed rcN.d directories // Collect services to be added - nextservice := initdir.Iterator(args.GetNameSelector()) - srv := nextservice() - for srv != nil { - services = append(services, srv) - srv = nextservice() + if args.Len() > 0 { + nextservice := initdir.Iterator(args.GetNameSelector()) + for srv := nextservice(); srv != nil; srv = nextservice() { + services = append(services, srv) + } + // If any unused arguments remain, report them and exit. + args.Report() + } else if opts.Defaults { + s := make(map[string]bool) + nextlevel := GetRunlevels().Iterator() + for r := nextlevel(); r.IsValid(); r = nextlevel() { + rcd, err := LoadRCDir(r, initdir) + if err != nil { + Logger.Fatal("failed to load rc directory: " + err.Error()) + } + rcdir[r.Index()] = rcd + + nextserv := rcd.Start.SysVServiceIterator() + for srv := nextserv(); srv != nil; srv = nextserv() { + if ! s[srv.BaseName()] { + services = append(services, srv) + s[srv.BaseName()] = true + } + } + + nextserv = rcd.Stop.SysVServiceIterator() + for srv := nextserv(); srv != nil; srv = nextserv() { + if ! s[srv.BaseName()] { + services = append(services, srv) + s[srv.BaseName()] = true + } + } + } + } else { + Logger.Fatal(`not enough arguments`) } - // If any unused arguments remain, report them and exit. - args.Report() - if opts.Recurse { + + if opts.Recursive { services = initdir.AddDependencies(services) } @@ -410,20 +418,19 @@ func Add(args *ArgList) { rsStop.And(rsmask) // Load rc directories - var rcdir [NumLevels]*RCDir // All needed rcN.d directories var rs Runlevels // A union of start and stop runlevels rs.Or(rsStart) rs.Or(rsStop) // Iterate over all runlevels and load the corresponding rc directories nextlevel := rs.Iterator() - r := nextlevel() - for r.IsValid() { - rcd, err := LoadRCDir(r, initdir) - if err != nil { - Logger.Fatal("failed to load startup directory: " + err.Error()) + for r := nextlevel(); r.IsValid(); r = nextlevel() { + if rcdir[r.Index()] == nil { + rcd, err := LoadRCDir(r, initdir) + if err != nil { + Logger.Fatal("failed to load rc directory: " + err.Error()) + } + rcdir[r.Index()] = rcd } - rcdir[r.Index()] = rcd - r = nextlevel() } // Array of symlinks to be created @@ -436,21 +443,17 @@ func Add(args *ArgList) { } nextlevel := rsStart.Iterator() - r := nextlevel() - for r.IsValid() { + for r := nextlevel(); r.IsValid(); r = nextlevel() { if s := rcdir[r.Index()].Start.Inc(srv); s != nil { oplist.Concat(s) } - r = nextlevel() } nextlevel = rsStop.Iterator() - r = nextlevel() - for r.IsValid() { + for r := nextlevel(); r.IsValid(); r = nextlevel() { if s := rcdir[r.Index()].Stop.Inc(srv); s != nil { oplist.Concat(s) } - r = nextlevel() } } @@ -622,8 +625,7 @@ func (rseq *RCSeq) Inc(newsrv Service) *FileOpList { prio := NewPriority(rseq.Isstart) next := rseq.StartTraversal(srvno) - srv := next() - for srv != nil { + for srv := next(); srv != nil; srv = next() { // fmt.Printf("Traversing: %s\n", srv.BaseName()) if ok, diag := srv.Enabled(); !ok { Logger.Printf("%s: %s depends on %s, which is not enabled\n", @@ -634,16 +636,13 @@ func (rseq *RCSeq) Inc(newsrv Service) *FileOpList { return nil } prio.Update(srv.Priority()) - srv = next() } prio.Incr() // Traverse services that have the same dependencies next = rseq.TraverseEquidependentServices(srvno) - srv = next() - for srv != nil { + for srv := next(); srv != nil; srv = next() { // fmt.Printf("Traversing: %s %d\n", srv.BaseName(), srv.Priority()) prio.Update(srv.Priority()) - srv = next() } rseq.Service[srvno].SetPriority(prio.Value()) @@ -112,7 +112,7 @@ func (seq *RCSeq) BuildDependencies() { // Return an interator over all SystemV services in SEQ. func (seq *RCSeq) SysVServiceIterator() ServiceIterator { - i := 0 + i := 1 // Skip the initial $undefined return func () Service { for i < len(seq.Service) { srv := seq.Service[i] |