mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
336 lines
11 KiB
336 lines
11 KiB
/*
|
|
* DEPEND.SPR. Overview:
|
|
*
|
|
* This SProlog program supports the stoplist/2 predicate.
|
|
*
|
|
* (stoplist "ServiceName" ListOfServicesToStop)
|
|
*
|
|
* This predicate examines the Registry and recursively
|
|
* expands the dependent services and groups of the service.
|
|
* As dependencies are discovered, new facts are asserted
|
|
* into the database, along with the recursion depth at
|
|
* which they were discovered.
|
|
*
|
|
* The result is a simple list of services to be stopped
|
|
* in the correct order.
|
|
*
|
|
* Before a new "stop" fact is asserted, a check is made to
|
|
* if a record for this service already exists. If so, the
|
|
* recursion depth is checked and the deeper record is retained.
|
|
*
|
|
* Three types of facts are asserted here:
|
|
*
|
|
* (group ServiceName GroupItBelongsTo)
|
|
*
|
|
* (stop ServiceName RecursionLevel)
|
|
*
|
|
* (depends ServiceName {service|group} ServiceOrGroupName)
|
|
*
|
|
* Variables named with the suffix "ci" mean "case-insensitive".
|
|
* These are usually converted to upper case. This is necessary
|
|
* since all textual information in the Registry is
|
|
* case-insensitive, but SProlog string matching is not.
|
|
*/
|
|
|
|
// Interactive test driver predicate
|
|
|
|
/*******************
|
|
( (run)
|
|
(stoplist "lanmanworkstation" StopList)
|
|
(display StopList)
|
|
(nl)
|
|
(nl)
|
|
)
|
|
*******************/
|
|
|
|
//
|
|
// The primary predicate:
|
|
// (stoplist "ServiceName" ResultListOfServicesToStop)
|
|
//
|
|
( (stoplist SvcNameCi StopList)
|
|
(assertgroups) // Assert all group membership info
|
|
(not (retractstops)) // Retract any old "stop" facts
|
|
(string_upper SvcNameCi SvcName) // Convert service name to upper case
|
|
(assertz (stop SvcName 100)) // Create "stop this service" fact
|
|
(alldependencies SvcName 100) // Expand this service's dependencies
|
|
(not (specialstops SvcName 100)) // Expand the "special" service(s)
|
|
(basestoplevel 100 Level) // Get the lowest level found among facts
|
|
(orderstops () Level StopList) // Create the topologically correct list
|
|
)
|
|
|
|
//
|
|
// Walk the dependency tree for this service.
|
|
//
|
|
( (alldependencies SvcName Level)
|
|
(stopupper SvcName Level) // Stop services dependent upon this service
|
|
(iplus Level 1 NextLevel) // Increment recursion level
|
|
(svcinfo SvcName SvcList GroupList) // Get DependOnService and DependOnGroup lists
|
|
(stopsvclist NextLevel SvcList) // Expand the DependOnService list
|
|
(stopgrouplist NextLevel GroupList) // Expand the DependOnGroup list
|
|
)
|
|
|
|
//
|
|
// stopgrouplist/2: stop all services in all groups in the list
|
|
//
|
|
( (stopgrouplist Level ())
|
|
(cut) // Termination condition: list is empty
|
|
)
|
|
( (stopgrouplist Level (Group|T)) // Stop the next group
|
|
(not (stopgroup Level Group)) // Stop its member services
|
|
(stopgrouplist Level T) // Recurse to next group
|
|
)
|
|
|
|
( (stopgroup Level Group) // Generate a stop record for each member
|
|
(group SvcName Group) // of this group through backtracking.
|
|
(stopsvc SvcName Level down) // Stop this service.
|
|
(fail) // Force group/2 predicate to backtrack.
|
|
)
|
|
|
|
//
|
|
// Assert "stop a service" records for all
|
|
// services in a list.
|
|
//
|
|
( (stopsvclist Level ())
|
|
(cut) // Termination condition: list is empty
|
|
)
|
|
( (stopsvclist Level (SvcName|T)) // Stop the next service
|
|
(stopsvc SvcName Level down)
|
|
(stopsvclist Level T) // Recurse on the tail of the list
|
|
)
|
|
|
|
//
|
|
// Assert a "stop a service" record:
|
|
// (stop ServiceName DepthLevel {down|up})
|
|
//
|
|
// The 3rd argument is "down" or "up", indicating the direction
|
|
// of dependency expansion and, hence, the recursion method.
|
|
//
|
|
( (stopsvc SvcName Level _) // Check if there's already an
|
|
(stop SvcName Level) // identical record; if so,
|
|
(cut) // ignore this one.
|
|
)
|
|
( (stopsvc SvcName Level down) // See if there's already a record
|
|
(stop SvcName OtherLevel) // at a different depth index.
|
|
(iless Level OtherLevel) // If this index < other index,
|
|
(cut) // ignore this record.
|
|
)
|
|
( (stopsvc SvcName Level down) // We know that this is a dup at
|
|
(stop SvcName OtherLevel) // at a deeper level. We must retract
|
|
(retract (stop SvcName OtherLevel)) // the older record and asssert the new.
|
|
(assertz (stop SvcName Level))
|
|
(cut)
|
|
)
|
|
( (stopsvc SvcName Level down) // Assert a unique stop record.
|
|
(assertz (stop SvcName Level)) // Assert the record, then
|
|
(alldependencies SvcName Level) // expand its dependencies.
|
|
(cut)
|
|
)
|
|
( (stopsvc SvcName Level up) // See if there's already a record
|
|
(stop SvcName OtherLevel) // at a different depth index.
|
|
(iless OtherLevel Level) // If this index > other index,
|
|
(cut) // ignore this record.
|
|
)
|
|
( (stopsvc SvcName Level up) // We know that this is a dup at
|
|
(stop SvcName OtherLevel) // at a higher level. We must retract
|
|
(retract (stop SvcName OtherLevel)) // the older record and asssert the new.
|
|
(assertz (stop SvcName Level))
|
|
(cut)
|
|
)
|
|
( (stopsvc SvcName Level up) // Assert a unique stop record.
|
|
(assertz (stop SvcName Level)) // Assert the record, then
|
|
(stopupper SvcName Level) // expand its dependencies.
|
|
)
|
|
|
|
//
|
|
// svckey/2: Open a Registry key for a service.
|
|
//
|
|
( (svckey Svc Key)
|
|
(string_concat "system\currentcontrolset\services\" Svc Keyname)
|
|
(regopenkey machine Keyname Key)
|
|
)
|
|
|
|
//
|
|
// svcinfo/3: Return the list of dependent service and the list
|
|
// of dependent groups for the named service.
|
|
//
|
|
( (svcinfo Svc SvcList GroupList)
|
|
(svckey Svc SvcKey)
|
|
(or (regqueryvalue SvcKey "DependOnService" SvcListCi) (eq SvcListCi ()))
|
|
(or (regqueryvalue SvcKey "DependOnGroup" GroupListCi) (eq GroupListCi ()))
|
|
(regclosekey SvcKey)
|
|
(upcaseList SvcListCi SvcList)
|
|
(upcaseList GroupListCi GroupList)
|
|
(cut)
|
|
)
|
|
|
|
//
|
|
// assertgroups/0: populate the database with group membership info.
|
|
// fact format is: (group ServiceName GroupName)
|
|
// This top-level predicate retracts all previous
|
|
// facts and starts the numeration of the services.
|
|
//
|
|
( (assertgroups)
|
|
(not (retractgroups))
|
|
(not (retractdepends))
|
|
(regopenkey machine "system\currentcontrolset\services" Key)
|
|
(not (enumGroups 0 Key))
|
|
(regclosekey Key)
|
|
)
|
|
|
|
//
|
|
// retractgroups/0: Retract all group/2 facts from the database.
|
|
//
|
|
( (retractgroups)
|
|
(retract (group _ _))
|
|
(fail)
|
|
)
|
|
|
|
//
|
|
// retractdepends/0: Retract all depends/3 facts from the database.
|
|
//
|
|
( (retractdepends)
|
|
(retract (depends _ _ _))
|
|
(fail)
|
|
)
|
|
|
|
//
|
|
// enumGroups/2: Recursively enumerate services in the Registry.
|
|
//
|
|
( (enumGroups Index Key)
|
|
(regenumkey Key Index SvcNameCi)
|
|
(string_upper SvcNameCi SvcName)
|
|
(not (getGroup Key SvcName))
|
|
(iplus Index 1 Newindex)
|
|
(enumGroups Newindex Key)
|
|
)
|
|
|
|
//
|
|
// getGroup/2: Query the "Group" value from the service and
|
|
// assert the group/2 facts.
|
|
//
|
|
( (getGroup Key SvcName)
|
|
(regopenkey Key SvcName Svckey)
|
|
(or (regqueryvalue Svckey "Group" GroupCi) (eq GroupCi ""))
|
|
(regclosekey Svckey)
|
|
(getDepends SvcName)
|
|
(not (eq GroupCi ""))
|
|
(string_upper GroupCi Group)
|
|
(assertz (group SvcName Group))
|
|
(fail)
|
|
)
|
|
|
|
( (getDepends SvcName)
|
|
(svcinfo SvcName SvcList GroupList)
|
|
(assertDependList service SvcName SvcList)
|
|
(assertDependList group SvcName GroupList)
|
|
)
|
|
|
|
//
|
|
// assertdependlist/3: Assert a fact for each members of a list
|
|
// which is not already known.
|
|
( (assertDependList Type SvcName ())
|
|
(cut)
|
|
)
|
|
( (assertDependList Type SvcName (H|T))
|
|
(depends SvcName Type H)
|
|
(cut)
|
|
(assertDependList Type SvcName T)
|
|
)
|
|
( (assertDependList Type SvcName (H|T))
|
|
(assertz (depends SvcName Type H))
|
|
(assertDependList Type SvcName T)
|
|
)
|
|
|
|
//
|
|
// retractstop/0: Retract all stop/2 facts from the database.
|
|
//
|
|
( (retractstops)
|
|
(retract (stop _ _))
|
|
(fail)
|
|
)
|
|
|
|
//
|
|
// orderstops/3: (orderstops InList RecursionLevel OutList)
|
|
// This predicate is invoked as:
|
|
//
|
|
// (orderstops () 0 StopList)
|
|
//
|
|
// The result is a list of all services to
|
|
// be stopped in the correct order. NOTE:
|
|
// this predicate assumes that the recursion
|
|
// level is monotonically increasing without
|
|
// gaps.
|
|
//
|
|
( (orderstops L Level L) // Check to see if this level
|
|
(not (stop _ Level)) // is empty -- termination condition.
|
|
(cut)
|
|
)
|
|
( (orderstops Inlist Level OutList) // Find all facts for this recursion level
|
|
(findall Sname (stop Sname Level) Slist) // Build list of this level's facts
|
|
(append Inlist Slist NewList) // Append the lists
|
|
(iplus Level 1 NewLevel) // Increment the recursion level
|
|
(orderstops NewList NewLevel OutList) // Recurse to the next level
|
|
)
|
|
|
|
|
|
//
|
|
// basestoplevel/2: Given a starting guess, return the lowest stop level
|
|
// number found in the database.
|
|
//
|
|
( (basestoplevel Level Level)
|
|
(iminus Level 1 TestLevel)
|
|
(not (stop _ TestLevel))
|
|
(cut)
|
|
)
|
|
( (basestoplevel Level LowestLevel)
|
|
(iminus Level 1 NextLevel)
|
|
(basestoplevel NextLevel LowestLevel)
|
|
)
|
|
|
|
//
|
|
// specialstops/2: Generate stop facts for all services associated
|
|
// with the given service by "magicStop" fact. The
|
|
// level is lower by 1 so that such services
|
|
// are stopped before the primary service.
|
|
//
|
|
( (specialstops SvcName Level)
|
|
(iminus Level 1 NewLevel)
|
|
(magicStop SvcName SvcToStop)
|
|
(alldependencies SvcToStop NewLevel)
|
|
(fail)
|
|
)
|
|
|
|
(magicStop "LANMANWORKSTATION" "NETDDE")
|
|
|
|
//
|
|
// upcaseList/2: Convert a list of strings to their upper case
|
|
// representations.
|
|
//
|
|
( (upcaseList () ())
|
|
(cut)
|
|
)
|
|
( (upcaseList (H|T) (HU|TU))
|
|
(string_upper H HU)
|
|
(upcaseList T TU)
|
|
)
|
|
|
|
( (stopupper SvcName Level)
|
|
(findall Sname (depends Sname service SvcName) SvcList)
|
|
(iminus Level 1 NewLevel)
|
|
(stopupperlist SvcList NewLevel)
|
|
)
|
|
( (stopupperlist () _)
|
|
(cut)
|
|
)
|
|
( (stopupperlist (SvcName|T) Level)
|
|
(stopsvc SvcName Level up)
|
|
(stopupperlist T Level)
|
|
)
|
|
|
|
|
|
//
|
|
// Include the default rules (SPROLOG.INI, et al.).
|
|
//
|
|
#include "..\default.spr"
|
|
|
|
// End of DEPEND.SPR
|