diff -ru cfengine-2.1.20.orig/src/cf.defs.h cfengine-2.1.20/src/cf.defs.h
--- cfengine-2.1.20.orig/src/cf.defs.h	2006-03-29 13:11:29.000000000 +0000
+++ cfengine-2.1.20/src/cf.defs.h	2006-08-31 22:38:55.000000000 +0000
@@ -1191,6 +1191,7 @@
    pkgmgr_rpm,
    pkgmgr_dpkg,
    pkgmgr_sun,
+   pkgmgr_portage,
    pkgmgr_none
    };
 
diff -ru cfengine-2.1.20.orig/src/do.c cfengine-2.1.20/src/do.c
--- cfengine-2.1.20.orig/src/do.c	2006-03-02 07:33:45.000000000 +0000
+++ cfengine-2.1.20/src/do.c	2006-08-31 22:39:30.000000000 +0000
@@ -2721,6 +2721,9 @@
      case pkgmgr_sun:
        match = SUNPackageCheck(ptr->name, ptr->ver, ptr->cmp);
        break;
+     case pkgmgr_portage:
+       match = PortagePackageCheck(ptr->name, ptr->ver, ptr->cmp);
+       break;
      default:
        /* UGH!  This should *never* happen.  GetPkgMgr() and
         * InstallPackagesItem() should have caught this before it
diff -ru cfengine-2.1.20.orig/src/globals.c cfengine-2.1.20/src/globals.c
--- cfengine-2.1.20.orig/src/globals.c	2006-03-29 13:11:29.000000000 +0000
+++ cfengine-2.1.20/src/globals.c	2006-08-31 22:39:55.000000000 +0000
@@ -656,6 +656,7 @@
       "rpm",
       "dpkg",   /* aptget ? */
       "sun",    /* pkginfo/pkgadd/pkgrm */
+      "portage",
       NULL
       };
 
diff -ru cfengine-2.1.20.orig/src/package.c cfengine-2.1.20/src/package.c
--- cfengine-2.1.20.orig/src/package.c	2006-03-29 13:11:29.000000000 +0000
+++ cfengine-2.1.20/src/package.c	2006-08-31 22:41:11.000000000 +0000
@@ -327,6 +327,18 @@
                CF_BUFSIZE);
        break;
        
+       /* Portage */
+   case pkgmgr_portage:
+
+       if (!GetMacroValue(CONTEXTID,"PortageInstallCommand"))
+          {
+          Verbose("PortageInstallCommand NOT Set.  Package Installation Not Possible!\n");
+          return 0;
+          }
+       strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"PortageInstallCommand"),
+               CF_BUFSIZE);
+       break;
+
        /* Default */
    default:
        Verbose("InstallPackage(): Unknown package manager %d\n",pkgmgr);
@@ -816,6 +828,197 @@
   free(tmpcpy);  
 }
 
+/*********************************************************************/
+/* Gentoo Portage                                                    */
+/*********************************************************************/
+
+int PortagePackageCheck(char *package,char *version,enum cmpsense cmp)
+
+{ FILE *pp;
+  struct Item *ebuildlist = NULL;
+  struct Item *ebuild;
+  enum cmpsense result;
+  int match = 0;
+
+  /* Yes, it's an ugly python one-liner that does something beautiful */
+  snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/python -c 'import portage, re, sys; "
+    "[sys.stdout.write(re.sub(\"\\w*?\\-\\w*?\\/([a-zA-Z0-9_+]|\\-(?![0-9]))*\\-\", \"\", package, 1) + "
+    "\"\\n\") for package in portage.db[\"/\"][\"vartree\"].dbapi.match("
+    "\"%s\")]'", package);
+
+  if ((pp = cfpopen(VBUFF, "r")) == NULL)
+  {
+    Verbose("Could not execute the equery command.  Assuming package not installed.\n");
+    return 0;
+  }
+
+  while(!feof(pp))
+  {
+    *VBUFF = '\0';
+
+    ReadLine(VBUFF,CF_BUFSIZE,pp);
+
+    if (*VBUFF != '\0')
+    {
+      AppendItem(&ebuildlist,VBUFF,"");
+    }
+  }
+ 
+  /* Non-zero exit status means that we could not find the package, so
+   * zero the list and bail. */
+
+  if (cfpclose(pp) != 0)
+  {
+    DeleteItemList(ebuildlist);
+    ebuildlist = NULL;
+  }
+ 
+  if (ebuildlist == NULL)
+  {
+    Verbose("Package %s not installed.\n", package);
+    return 0;
+  }
+ 
+
+  Verbose("PortageCheckPackage(): Requested %s %s %s\n", package, CMPSENSETEXT[cmp],(version[0] ? version : "ANY"));
+
+  /* If no version was specified, just return 1, because if we got this far
+   * some package by that name exists. */
+
+  if (!version[0])
+  {
+    DeleteItemList(ebuildlist);
+    return 1;
+  }
+
+  /* The rule here will be: if any package in the list matches, then the
+   * first one to match wins, and we bail out. */
+
+  char *comparehead = NULL;
+  char *comparetail = NULL;
+  char *installedhead = NULL;
+  char *installedtail = NULL;
+
+  for (ebuild = ebuildlist; ebuild != NULL; ebuild=ebuild->next)
+  {
+    char *ebuildver;
+    ebuildver = ebuild->name;
+
+    Verbose("PortageCheckPackage(): Trying installed version %s\n", ebuildver);
+
+    /* Start out assuming the comparison will be equal. */
+    result = cmpsense_eq;
+
+    comparehead = version;
+    comparetail = NULL;
+    installedhead = ebuildver;
+    installedtail = NULL;
+
+    /* Iterate over version portions delimited by `-' */
+    while (result == cmpsense_eq)
+    {
+      if (*comparehead == '\0' && *installedhead == '\0')
+      {
+        /* No substrings remain, break from while */
+        break;
+      }
+      else if (*comparehead == '\0')
+      {
+        /* Installed version has more version substrings than given */
+        result = cmpsense_gt;
+      }
+      else if (*installedhead == '\0')
+      {
+        /* Installed version has less version substrings than given */
+        result = cmpsense_lt;
+      }
+      else
+      {
+        /* New substring in both to test */
+        comparetail = strchr(comparehead, '-');
+        installedtail = strchr(installedhead, '-');
+
+        /* Throw a \0 over the `-' so just the substring is tested.
+         * If the tail is less than the head, we must be at last substring,
+         * as no `-'s were found (so the `\0' is already there) */
+        if (comparetail > comparehead) *comparetail = '\0';
+        if (installedtail > installedhead) *installedtail = '\0';
+
+        switch (rpmvercmp(installedhead, comparehead))
+        {
+        case 1:
+          result = cmpsense_gt;
+          break;
+        case -1:
+          result = cmpsense_lt;
+          break;
+        }
+
+        if (comparetail > comparehead)
+        {
+          /* Restore `-' at tail and move head just past it */
+          *comparetail = '-';
+          comparehead = comparetail + 1;
+        }
+        else
+        {
+          /* Move head to the end of the line (`\0') */
+          comparehead = comparehead + strlen(comparehead);
+        }
+        if (installedtail > installedhead)
+        {
+          /* Restore `-' at tail and move head just past it */
+          *installedtail = '-';
+          installedhead = installedtail + 1;
+        }
+        else
+        {
+          /* Move head to the end of the line (`\0') */
+          installedhead = installedhead + strlen(installedhead);
+        }
+      }
+    }
+
+    Verbose("Comparison result: %s\n",CMPSENSETEXT[result]);
+   
+    switch(cmp)
+    {
+    case cmpsense_gt:
+      match = (result == cmpsense_gt);
+      break;
+    case cmpsense_ge:
+      match = (result == cmpsense_gt || result == cmpsense_eq);
+      break;
+    case cmpsense_lt:
+      match = (result == cmpsense_lt);
+      break;
+    case cmpsense_le:
+      match = (result == cmpsense_lt || result == cmpsense_eq);
+      break;
+    case cmpsense_eq:
+      match = (result == cmpsense_eq);
+      break;
+    case cmpsense_ne:
+      match = (result != cmpsense_eq);
+      break;
+    }
+   
+    /* If we find a match, just return it now, and don't bother checking
+     * other ebuilds */
+   
+    if (match)
+    {
+      DeleteItemList(ebuildlist);
+      return 1;
+    }
+  }
+ 
+  /* if we manage to make it out of the loop, we did not find a match. */
+
+  DeleteItemList(ebuildlist);
+  return 0;
+
+}
 
 /*********************************************************************/
 /* RPM Version string comparison logic
diff -ru cfengine-2.1.20.orig/src/prototypes.h cfengine-2.1.20/src/prototypes.h
--- cfengine-2.1.20.orig/src/prototypes.h	2006-03-11 13:53:03.000000000 +0000
+++ cfengine-2.1.20/src/prototypes.h	2006-08-31 22:41:37.000000000 +0000
@@ -847,6 +847,7 @@
 int RPMPackageCheck (char *package, char *version, enum cmpsense cmp);
 int DPKGPackageCheck (char *package, char *version, enum cmpsense cmp);
 int SUNPackageCheck (char *package, char *version, enum cmpsense cmp);
+int PortagePackageCheck (char *package, char *version, enum cmpsense cmp);
 int InstallPackage  (char *name, enum pkgmgrs pkgmgr);
 int RemovePackage  (char *name, enum pkgmgrs pkgmgr);
 
