Index: trunk/src/sh_portcheck.c
===================================================================
--- trunk/src/sh_portcheck.c	(revision 212)
+++ trunk/src/sh_portcheck.c	(revision 218)
@@ -283,6 +283,97 @@
 #endif
 
+static char * sh_getrpcbynumber (int number, char * buf, size_t len)
+{
+  FILE * fp;
+
+  if (NULL != (fp = fopen(_("/etc/rpc"), "r")))
+    {
+      sh_string * s = sh_string_new(0);
+      while (0 < sh_string_read(s, fp, 1024))
+	{
+	  char * p = sh_string_str(s);
+	  while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
+	  if (*p == '\0' || *p == '#') 
+	    continue; /* skip comment */
+	  else
+	    {
+	      size_t lengths[3];
+ 	      unsigned int  fields = 3;
+ 	      char * q             = sh_string_str(s);
+	      char ** splits       = split_array_ws(q, &fields, lengths);
+
+	      if (fields >= 2)
+		{
+		  int n = atoi(splits[1]);
+		  if (n == number)
+		    {
+		      sl_strlcpy(buf, splits[0], len);
+		      SH_FREE(splits);
+		      sh_string_destroy(&s);
+		      fclose(fp);
+		      return buf;
+		    }
+		}
+	      SH_FREE(splits);
+	    }
+	}
+      sh_string_destroy(&s);
+      fclose(fp);
+    }
+  return NULL;
+}
+
+static char * sh_getservbyport (int port, const char * proto_in, char * buf, size_t len)
+{
+  FILE * fp;
+  char   proto[8];
+
+  sl_strlcpy(proto, proto_in, sizeof(proto));
+
+  if (NULL != (fp = fopen(_("/etc/services"), "r")))
+    {
+      sh_string * s = sh_string_new(0);
+      while (0 < sh_string_read(s, fp, 1024))
+	{
+	  char * p = sh_string_str(s);
+	  while (*p && (*p == ' ' || *p == '\t')) ++p; /* skip whitespace */
+	  if (*p == '\0' || *p == '#')
+	    continue; /* skip comment */
+	  else
+	    {
+	      size_t lengths[3];
+ 	      unsigned int  fields = 3;
+ 	      char * q             = sh_string_str(s);
+	      char ** splits       = split_array_ws(q, &fields, lengths);
+
+	      if (fields >= 2)
+		{
+		  char * end;
+		  long n = strtol(splits[1], &end, 10);
+		  if (n == port && end && (*end == '/' || *end == ','))
+		    {
+		      ++end;
+		      if (0 == strcmp(end, proto))
+			{
+			  sl_strlcpy(buf, splits[0], len);
+			  SH_FREE(splits);
+			  sh_string_destroy(&s);
+			  fclose(fp);
+			  return buf;
+			}
+		    }
+		}
+	      SH_FREE(splits);
+	    }
+	}
+      sh_string_destroy(&s);
+      fclose(fp);
+    }
+  return NULL;
+}
+
 static void sh_portchk_add_to_list (int proto, 
-				    int port, struct in_addr haddr, char * service,
+				    int port, struct in_addr haddr, 
+				    char * service,
 				    int flag, int status)
 {
@@ -648,11 +739,7 @@
 {
   static char buf[256];
-  struct servent * service = getservbyport(htons(port), SH_PROTO_STR(proto));
-
-  if (service && service->s_name && service->s_name[0] != '\0')
-    {
-      snprintf (buf, sizeof(buf), _("maybe_%s"), service->s_name);
-    }
-  else
+  char * service = sh_getservbyport(port, SH_PROTO_STR(proto), buf, sizeof(buf));
+
+  if (!service)
     {
       snprintf (buf, sizeof(buf), "%s",_("unknown"));
@@ -669,5 +756,5 @@
 {
   struct pmaplist * head;
-  struct rpcent *r;
+  char *r;
   static char buf[256];
 
@@ -681,8 +768,8 @@
 	      (port == (int)head->pml_map.pm_port)) 
 	    {
-	      r = getrpcbynumber((int)head->pml_map.pm_prog);
-	      if (r && r->r_name && r->r_name[0] != '\0')
+	      r = sh_getrpcbynumber((int)head->pml_map.pm_prog, 
+				    buf, sizeof(buf));
+	      if (r)
 		{
-		  snprintf (buf, sizeof(buf), "%s", r->r_name);
 		  return buf;
 		}
@@ -1568,4 +1655,32 @@
   struct in_addr   haddr_local;
   struct sh_portentry * portent;
+  char   buf[256];
+  char * p;
+
+  p = sh_getrpcbynumber(0, buf, sizeof(buf));
+  CuAssertTrue(tc, p == NULL);
+
+  p = sh_getrpcbynumber(100000, buf, sizeof(buf));
+  CuAssertPtrNotNull(tc, p);
+  CuAssertTrue(tc, (0 == strcmp(p, "portmapper") || 0 == strcmp(p, "rpcbind")));
+  CuAssertTrue(tc, (0 == strcmp(buf, "portmapper") || 0 == strcmp(p, "rpcbind")));
+
+  p = sh_getrpcbynumber(100007, buf, sizeof(buf));
+  CuAssertPtrNotNull(tc, p);
+  CuAssertTrue(tc, 0 == strcmp(p, "ypbind"));
+  CuAssertTrue(tc, 0 == strcmp(buf, "ypbind"));
+
+  p = sh_getservbyport(0, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf));
+  CuAssertTrue(tc, p == NULL);
+
+  p = sh_getservbyport(22, SH_PROTO_STR(IPPROTO_TCP), buf, sizeof(buf));
+  CuAssertPtrNotNull(tc, p);
+  CuAssertTrue(tc, 0 == strcmp(p, "ssh"));
+  CuAssertTrue(tc, 0 == strcmp(buf, "ssh"));
+
+  p = sh_getservbyport(13, SH_PROTO_STR(IPPROTO_UDP), buf, sizeof(buf));
+  CuAssertPtrNotNull(tc, p);
+  CuAssertTrue(tc, 0 == strcmp(p, "daytime"));
+  CuAssertTrue(tc, 0 == strcmp(buf, "daytime"));
 
   CuAssertTrue(tc, 0 != inet_aton("127.0.0.1", &haddr_local));
