aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2019-09-30 09:30:27 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2019-09-30 09:30:27 +0300
commit19d98c30087cef57226ee5e68cb8555b03344181 (patch)
tree8e11b75777af6139d4cde700e1aaf973eaf43071
parent08702cab6c2312103f3f4515a64b54a3a176533e (diff)
downloadproto-19d98c30087cef57226ee5e68cb8555b03344181.tar.gz
proto-19d98c30087cef57226ee5e68cb8555b03344181.tar.bz2
Implement the "recursive" mode: automatically add any dependencies needed for the new service
-rw-r--r--main.go119
-rw-r--r--rcd.go2
2 files changed, 60 insertions, 61 deletions
diff --git a/main.go b/main.go
index 105c2a2..3d7c662 100644
--- a/main.go
+++ b/main.go
@@ -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())
diff --git a/rcd.go b/rcd.go
index ad8c5fd..1813226 100644
--- a/rcd.go
+++ b/rcd.go
@@ -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]

Return to:

Send suggestions and report system problems to the System administrator.