Index: /trunk/Makefile.in
===================================================================
--- /trunk/Makefile.in	(revision 533)
+++ /trunk/Makefile.in	(revision 534)
@@ -128,5 +128,5 @@
 	sh_restrict.h sh_sub.h sh_fInotify.h sh_checksum.h \
 	sh_dbIO.h sh_dbIO_int.h sh_guid.h sh_dbCheck.h sh_dbCreate.h \
-	sh_sem.h
+	sh_sem.h sh_subuid.h
 
 
@@ -175,4 +175,5 @@
 	$(srcsrc)/sh_checksum.c $(srcsrc)/sh_guid.c $(srcsrc)/sh_sem.c \
 	$(srcsrc)/sh_dbIO.c $(srcsrc)/sh_dbCheck.c  $(srcsrc)/sh_dbCreate.c \
+	$(srcsrc)/sh_subuid.c \
 	$(srcsrc)/t-test1.c 
 
@@ -197,5 +198,6 @@
 	sh_audit.o sh_registry.o sh_ipvx.o sh_restrict.o \
 	sh_filetype.o sh_sub.o sh_fInotify.o sh_checksum.o \
-	sh_guid.o sh_sem.o sh_dbIO.o sh_dbCheck.o sh_dbCreate.o 
+	sh_guid.o sh_sem.o sh_dbIO.o sh_dbCheck.o sh_dbCreate.o \
+	sh_subuid.o
 
 
@@ -1631,5 +1633,5 @@
 
 samhain.o: $(srcsrc)/samhain.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_getopt.h $(srcinc)/sh_readconf.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_restrict.h $(srcinc)/sh_nmail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_mem.h $(srcinc)/sh_xfer.h $(srcinc)/sh_tools.h $(srcinc)/sh_hash.h $(srcinc)/sh_extern.h $(srcinc)/sh_modules.h $(srcinc)/sh_ignore.h $(srcinc)/sh_prelink.h $(srcinc)/sh_sem.h sh_MK.h $(srcinc)/sh_schedule.h 
-sh_unix.o: $(srcsrc)/sh_unix.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_hash.h $(srcinc)/sh_tools.h $(srcinc)/sh_restrict.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_tiger.h $(srcinc)/sh_prelink.h $(srcinc)/sh_pthread.h $(srcinc)/sh_sem.h $(srcinc)/sh_static.h $(srcinc)/sh_prelude.h $(srcinc)/zAVLTree.h $(srcinc)/sh_ignore.h 
+sh_unix.o: $(srcsrc)/sh_unix.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_hash.h $(srcinc)/sh_tools.h $(srcinc)/sh_restrict.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_tiger.h $(srcinc)/sh_prelink.h $(srcinc)/sh_pthread.h $(srcinc)/sh_sem.h $(srcinc)/sh_static.h $(srcinc)/sh_prelude.h $(srcinc)/zAVLTree.h $(srcinc)/sh_subuid.h $(srcinc)/sh_ignore.h 
 sh_utils.o: $(srcsrc)/sh_utils.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_entropy.h $(srcinc)/sh_pthread.h 
 sh_error.o: $(srcsrc)/sh_error.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_database.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_nmail.h $(srcinc)/sh_xfer.h $(srcinc)/sh_prelude.h $(srcinc)/sh_pthread.h $(srcinc)/sh_tools.h $(srcinc)/sh_extern.h $(srcinc)/sh_checksum.h 
@@ -1727,2 +1729,3 @@
 sh_xload_client.o: $(srcsrc)/sh_xload_client.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_guid.h 
 sh_sem.o: $(srcsrc)/sh_sem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_sem.h $(srcinc)/sh_error_min.h 
+sh_subuid.o: $(srcsrc)/sh_subuid.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_unix.h 
Index: /trunk/config.h.in
===================================================================
--- /trunk/config.h.in	(revision 533)
+++ /trunk/config.h.in	(revision 534)
@@ -907,4 +907,7 @@
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#undef HAVE_SYS_SYSMACROS_H
 
 /* Define to 1 if you have the <sys/types.h> header file. */
Index: /trunk/configure.ac
===================================================================
--- /trunk/configure.ac	(revision 533)
+++ /trunk/configure.ac	(revision 534)
@@ -12,5 +12,5 @@
 dnl start
 dnl
-AM_INIT_AUTOMAKE(samhain, 4.2.4)
+AM_INIT_AUTOMAKE(samhain, 4.3.0)
 AC_DEFINE([SAMHAIN], 1, [Application is samhain])
 AC_CANONICAL_HOST
@@ -244,5 +244,5 @@
 
 AC_CHECK_HEADERS(stddef.h libgen.h sched.h malloc.h sys/uio.h \
-	sys/mman.h sys/param.h sys/inotify.h \
+	sys/mman.h sys/param.h sys/inotify.h sys/sysmacros.h \
 	sys/vfs.h mntent.h \
 	sys/select.h sys/socket.h netinet/in.h ifaddrs.h \
Index: /trunk/depend.dep
===================================================================
--- /trunk/depend.dep	(revision 533)
+++ /trunk/depend.dep	(revision 534)
@@ -2,5 +2,5 @@
 # DO NOT DELETE THIS LINE
 samhain.o: $(srcsrc)/samhain.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_getopt.h $(srcinc)/sh_readconf.h $(srcinc)/sh_hash.h $(srcinc)/sh_dbIO.h $(srcinc)/sh_restrict.h $(srcinc)/sh_nmail.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_mem.h $(srcinc)/sh_xfer.h $(srcinc)/sh_tools.h $(srcinc)/sh_hash.h $(srcinc)/sh_extern.h $(srcinc)/sh_modules.h $(srcinc)/sh_ignore.h $(srcinc)/sh_prelink.h $(srcinc)/sh_sem.h sh_MK.h $(srcinc)/sh_schedule.h 
-sh_unix.o: $(srcsrc)/sh_unix.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_hash.h $(srcinc)/sh_tools.h $(srcinc)/sh_restrict.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_tiger.h $(srcinc)/sh_prelink.h $(srcinc)/sh_pthread.h $(srcinc)/sh_sem.h $(srcinc)/sh_static.h $(srcinc)/sh_prelude.h $(srcinc)/zAVLTree.h $(srcinc)/sh_ignore.h 
+sh_unix.o: $(srcsrc)/sh_unix.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_hash.h $(srcinc)/sh_tools.h $(srcinc)/sh_restrict.h $(srcinc)/sh_ipvx.h $(srcinc)/sh_tiger.h $(srcinc)/sh_prelink.h $(srcinc)/sh_pthread.h $(srcinc)/sh_sem.h $(srcinc)/sh_static.h $(srcinc)/sh_prelude.h $(srcinc)/zAVLTree.h $(srcinc)/sh_subuid.h $(srcinc)/sh_ignore.h 
 sh_utils.o: $(srcsrc)/sh_utils.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_entropy.h $(srcinc)/sh_pthread.h 
 sh_error.o: $(srcsrc)/sh_error.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_cat.h $(srcinc)/sh_database.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_nmail.h $(srcinc)/sh_xfer.h $(srcinc)/sh_prelude.h $(srcinc)/sh_pthread.h $(srcinc)/sh_tools.h $(srcinc)/sh_extern.h $(srcinc)/sh_checksum.h 
@@ -100,2 +100,3 @@
 sh_xload_client.o: $(srcsrc)/sh_xload_client.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_guid.h 
 sh_sem.o: $(srcsrc)/sh_sem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_sem.h $(srcinc)/sh_error_min.h 
+sh_subuid.o: $(srcsrc)/sh_subuid.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_unix.h 
Index: /trunk/depend.sum
===================================================================
--- /trunk/depend.sum	(revision 533)
+++ /trunk/depend.sum	(revision 534)
@@ -1,1 +1,1 @@
-2959213307
+3903466696
Index: /trunk/docs/Changelog
===================================================================
--- /trunk/docs/Changelog	(revision 533)
+++ /trunk/docs/Changelog	(revision 534)
@@ -1,2 +1,6 @@
+4.3.0:
+	* add support for /etc/subuid, /etc/subgid maps
+	* fix compiler warning on Ubuntu 18.04
+
 4.2.4:
 	* fix 'clobbered by..' compiler warning is src/sh_portcheck.c
Index: /trunk/src/sh_hash.c
===================================================================
--- /trunk/src/sh_hash.c	(revision 533)
+++ /trunk/src/sh_hash.c	(revision 534)
@@ -24,4 +24,7 @@
 #include <stdio.h>
 #include <sys/types.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+#endif
 #include <sys/stat.h>
 #include <unistd.h>
Index: /trunk/src/sh_subuid.c
===================================================================
--- /trunk/src/sh_subuid.c	(revision 534)
+++ /trunk/src/sh_subuid.c	(revision 534)
@@ -0,0 +1,242 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 2018 Rainer Wichmann                                      */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#undef  FIL__
+#define FIL__  _("sh_subuid.c")
+
+#if defined(__linux__)
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "samhain.h"
+#include "sh_unix.h"
+
+#define SH_SUBUID_FILE _("/etc/subuid")
+#define SH_SUBGID_FILE _("/etc/subgid")
+
+struct subuid_t {
+  char name[32];
+  unsigned long first;
+  unsigned long last;
+  struct subuid_t * next;
+};
+
+static time_t last_subuid = 0;
+static time_t last_subgid = 0;
+
+struct subuid_t * list_subuid = NULL;
+struct subuid_t * list_subgid = NULL;
+
+/* Check whether we need to re-read the subuid/subgid file
+ */
+static int needs_reread (char * file, time_t * last)
+{
+  int retval = S_FALSE;
+  struct stat   buf;
+  int status = retry_lstat (FIL__, __LINE__, file, &buf);
+
+  if (status == 0)
+    {
+      if ((buf.st_mtime - *last) > 1)
+	{
+	  *last = buf.st_mtime;
+	  retval = S_TRUE;
+	}
+    }
+  else if (status && errno == ENOENT)
+    {
+      /* If there was a file make sure we attempt to re-read
+       * to zero out the list. 
+       */
+      if (*last > 0) retval = S_TRUE;
+      *last = 0;
+    }
+  return retval;
+}
+
+/* free the whole list
+ */
+static void free_subordinate(struct subuid_t * head)
+{
+  struct subuid_t * prev;
+  struct subuid_t * curr = head;
+  
+  while (curr)
+    {
+      prev = curr;
+      curr = curr->next;
+      SH_FREE(prev);
+    }
+  return;
+}
+
+#define NFIELDS_SUBUID 3
+
+static int get_ulong(char * str, unsigned long * result)
+{
+  char * endptr;
+
+  errno = 0;
+  *result = strtoul(str, &endptr, 0);
+  if (*str != '\0' && *endptr == '\0' && errno != ERANGE)
+    return S_TRUE;
+  return S_FALSE;
+}
+
+/* Parse a single line into name / startuid / lastuid 
+ */
+static struct subuid_t * parse_subordinate(char * line)
+{
+  unsigned int      nfields = NFIELDS_SUBUID;
+  size_t            lengths[NFIELDS_SUBUID];
+  unsigned long     start, count;
+  struct subuid_t * new;
+  
+  char ** array = split_array(line, &nfields, ':', lengths);
+
+  if (nfields != NFIELDS_SUBUID)
+    { SH_FREE(array); return NULL; }
+
+  if (S_TRUE != get_ulong(array[1], &start))
+    { SH_FREE(array); return NULL; }
+  if ((S_TRUE != get_ulong(array[2], &count)) || (count == 0))
+    { SH_FREE(array); return NULL; }
+  if (lengths[0] == 0)
+    { SH_FREE(array); return NULL; }
+
+  /* we have checked that count != 0 */
+  --count;
+
+  if (start > (ULONG_MAX - count))
+    { SH_FREE(array); return NULL; }
+    
+  new = SH_ALLOC(sizeof(struct subuid_t));
+  sl_strlcpy(new->name, array[0], 32);
+  new->first = start;
+  new->last  = start + count; /* start+count-1, but we already did --count */
+  new->next  = NULL;
+
+  SH_FREE(array);
+  return new;
+}
+
+/* (re-)read the subuid/subgid file
+ */
+static void reread_subordinate (char * file, struct subuid_t ** head_ref)
+{
+  SL_TICKET fd = (-1);
+  char      line[1024];
+  
+  if (*head_ref) { free_subordinate(*head_ref); *head_ref = NULL; }
+
+  fd = sl_open_read (FIL__, __LINE__, file, SL_YESPRIV);
+  if (!SL_ISERROR(fd))
+    {
+      while ( sh_unix_getline(fd, line, sizeof(line)) > 0 ) 
+        {
+	  /* for invalid lines, NULL will be returned 
+	   */
+	  struct subuid_t * new = parse_subordinate(line);
+
+	  if (new)
+	    {
+	      new->next = *head_ref;
+	      *head_ref = new;
+	    }
+        }
+      sl_close(fd);
+    }
+  return;
+}
+
+/* Return the username for a given subuid/subgid 
+ */
+static char * get_name4id (unsigned long id, struct subuid_t * head)
+{
+  struct subuid_t * cur = head;
+  
+  while (cur)
+    {
+      if (id >= cur->first && id <= cur->last)
+	return cur->name;
+      cur = cur->next;
+    }
+  return NULL;
+}
+
+/***********************************************
+ *
+ * Public functions
+ *
+ ***********************************************/
+
+/* Returns username or NULL for a subuid
+ */
+char * sh_get_subuid (unsigned long subuid)
+{
+  static int  init = 0;
+  static char file[256];
+
+  if (!init) { sl_strlcpy(file, SH_SUBUID_FILE, sizeof(file)); init = 1; }
+  
+  if (S_TRUE == needs_reread(file, &last_subuid))
+    reread_subordinate(file, &list_subuid); 
+  
+  return get_name4id (subuid, list_subuid);
+}
+
+/* Returns group name or NULL for subgid
+ */
+char * sh_get_subgid (unsigned long subgid)
+{
+  static int  init = 0;
+  static char file[256];
+
+  if (!init) { sl_strlcpy(file, SH_SUBGID_FILE, sizeof(file)); init = 1; }
+  
+  if (S_TRUE == needs_reread(file, &last_subgid))
+    reread_subordinate(file, &list_subgid); 
+  
+  return get_name4id (subgid, list_subgid);
+}
+
+/* Not Linux, hence no sub(u|g)id
+ */
+#else
+
+char * sh_get_subuid (unsigned long subuid)
+{
+  return NULL;
+}
+
+char * sh_get_subgid (unsigned long subgid)
+{
+  return NULL;
+}
+
+#endif
Index: /trunk/src/sh_unix.c
===================================================================
--- /trunk/src/sh_unix.c	(revision 533)
+++ /trunk/src/sh_unix.c	(revision 534)
@@ -2827,5 +2827,7 @@
 
 /* --------- end caching code --------- */
-  
+
+#include "sh_subuid.h"
+
 char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len)
 {
@@ -2863,19 +2865,8 @@
   status = errno;
 #endif
- 
-  if (tempres == NULL) 
-    {
-      sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
-		       sh_error_message(status, errbuf, sizeof(errbuf)),
-		       _("getpwuid"), (long) uid, _("completely missing"));
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
-      SH_FREE(buffer);
-#endif
-      sh_userid_add(uid, NULL, CACHE_UID);
-      SL_RETURN( NULL, _("sh_unix_getUIDname"));
-    }
-
-
-  if (tempres->pw_name != NULL) 
+
+  /* case 1: we have it
+   */
+  if (tempres && tempres->pw_name != NULL) 
     {
 
@@ -2888,16 +2879,35 @@
 
       SL_RETURN( out, _("sh_unix_getUIDname"));
-    } 
-  else 
-    {
+    }
+
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
+  SH_FREE(buffer);
+#endif
+  
+  if (tempres == NULL) 
+    {
+      char * pwname = sh_get_subuid ((unsigned long) uid);
+
+      if (pwname)
+	{
+	  sl_strlcpy(out, pwname, len);
+	  sh_userid_add(uid, out, CACHE_UID);
+	  SL_RETURN( out, _("sh_unix_getUIDname"));
+	}
+
       sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
 		       sh_error_message(status, errbuf, sizeof(errbuf)),
-		       _("getpwuid"), (long) uid, _("pw_user"));
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
-      SH_FREE(buffer);
-#endif
+		       _("getpwuid"), (long) uid, _("completely missing"));
+      sh_userid_add(uid, NULL, CACHE_UID);
       SL_RETURN( NULL, _("sh_unix_getUIDname"));
     }
-  /* notreached */
+
+
+  /* getwpuid returns struct, but no pw_name
+   */
+  sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
+		   sh_error_message(status, errbuf, sizeof(errbuf)),
+		   _("getpwuid"), (long) uid, _("pw_user"));
+  SL_RETURN( NULL, _("sh_unix_getUIDname"));
 }
 
@@ -2959,19 +2969,5 @@
     }
 
-  if (tempres == NULL) 
-    {
-      sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
-		       sh_error_message(status, errbuf, sizeof(errbuf)),
-		       _("getgrgid"), (long) gid, _("completely missing"));
-      
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
-      SH_FREE(buffer);
-#endif
-
-      sh_userid_add(gid, NULL, CACHE_GID);
-      SL_RETURN( NULL, _("sh_unix_getGIDname"));
-    }
-
-  if (tempres->gr_name != NULL) 
+  if (tempres && tempres->gr_name != NULL) 
     {
 
@@ -2985,17 +2981,31 @@
       SL_RETURN( out, _("sh_unix_getGIDname"));
     } 
-  else 
-    {
+
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
+  SH_FREE(buffer);
+#endif
+
+  if (tempres == NULL) 
+    {
+      char * grname = sh_get_subgid ((unsigned long) gid);
+
+      if (grname)
+	{
+	  sl_strlcpy(out, grname, len);
+	  sh_userid_add((uid_t)gid, out, CACHE_GID);
+	  SL_RETURN( out, _("sh_unix_getGIDname"));
+	}
+
       sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
 		       sh_error_message(status, errbuf, sizeof(errbuf)),
-		       _("getgrgid"), (long) gid, _("gr_name"));
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
-      SH_FREE(buffer);
-#endif
-
+		       _("getgrgid"), (long) gid, _("completely missing"));
+      sh_userid_add(gid, NULL, CACHE_GID);
       SL_RETURN( NULL, _("sh_unix_getGIDname"));
     }
-  /* notreached */
+
+  sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
+		   sh_error_message(status, errbuf, sizeof(errbuf)),
+		   _("getgrgid"), (long) gid, _("gr_name"));
+  SL_RETURN( NULL, _("sh_unix_getGIDname"));
 }
 
@@ -3066,5 +3076,5 @@
 }
 
-
+/* return >0 on success, -1 on EOF */
 int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline)
 {
