docs: def EnumerateConfig(self, service, path, cache, filter_type=None):
      """Return PamConfigEntries it finds as it recursively follows PAM configs.
  
      Args:
        service: A string containing the service name we are processing.
        path: A string containing the file path name we want.
        cache: A dictionary keyed on path, with the file contents (list of str).
        filter_type: A string containing type name of the results we want.
  
      Returns:
        A tuple of a list of RDFValue PamConfigEntries found & a list of strings
        which are the external config references found.
      """
  
      result = []
      external = []
      path = self._FixPath(path)
  
      # Make sure we only look at files under PAMDIR.
      # Check we have the file in our artifact/cache. If not, our artifact
      # didn't give it to us, and that's a problem.
      # Note: This should only ever happen if it was referenced
      # from /etc/pam.conf so we can assume that was the file.
      if path not in cache:
        external.append("%s -> %s", self.OLD_PAMCONF_FILENAME, path)
        return result, external
  
      for tokens in self.ParseEntries(cache[path]):
        if path == self.OLD_PAMCONF_FILENAME:
          # We are processing the old style PAM conf file. It's a special case.
          # It's format is "service type control module-path module-arguments"
          # i.e. the 'service' is the first arg, the rest is line
          # is like everything else except for that addition.
          try:
            service = tokens[0]  # Grab the service from the start line.
            tokens = tokens[1:]  # Make the rest of the line look like "normal".
          except IndexError:
            continue  # It's a blank line, skip it.
  
        # Process any inclusions in the line.
        new_path = None
        filter_request = None
        try:
          # If a line starts with @include, then include the entire referenced
          # file.
          # e.g. "@include common-auth"
          if tokens[0] == "@include":
            new_path = tokens[1]
          # If a line's second arg is an include/substack, then filter the
          # referenced file only including entries that match the 'type'
          # requested.
          # e.g. "auth include common-auth-screensaver"
          elif tokens[1] in ["include", "substack"]:
            new_path = tokens[2]
            filter_request = tokens[0]
        except IndexError:
          # It's not a valid include line, so keep processing as normal.
          pass
  
        # If we found an include file, enumerate that file now, and
        # included it where we are in this config file.
        if new_path:
          # Preemptively check to see if we have a problem where the config
          # is referencing a file outside of the expected/defined artifact.
          # Doing it here allows us to produce a better context for the
          # problem. Hence the slight duplication of code.
  
          new_path = self._FixPath(new_path)
          if new_path not in cache:
            external.append("%s -> %s" % (path, new_path))
            continue  # Skip to the next line of the file.
          r, e = self.EnumerateConfig(service, new_path, cache, filter_request)
          result.extend(r)
          external.extend(e)
        else:
          # If we have been asked to filter on types, skip over any types
          # we are not interested in.
          if filter_type and tokens[0] != filter_type:
            continue  # We can skip this line.
  
          # If we got here, then we want to include this line in this service's
          # config.
  
          # Reform the line and break into the correct fields as best we can.
          # Note: ParseEntries doesn't cope with what we need to do.
          match = self.PAMCONF_RE.match(" ".join(tokens))
          if match:
            p_type, control, module_path, module_args = match.group(1, 2, 3, 4)
            # Trim a leading "-" from the type field if present.
            if p_type.startswith("-"):
              p_type = p_type[1:]
            result.append(
                rdf_config_file.PamConfigEntry(
                    service=service,
                    type=p_type,
                    control=control,
                    module_path=module_path,
                    module_args=module_args))
      return result, external