[PATCH] cygcheck parsing of id output

Igor Pechtchanski pechtcha@cs.nyu.edu
Thu May 1 22:50:00 GMT 2003


Hi,

The attached patch allows cygcheck to handle spaces, commas, and
*matching* parentheses in user and group names in the "id" output.
There's some code sharing in parsing the user and group names, but that
could be refactored in a later cleanup.

One issue that also came up is the old "run a cygwin program from a
non-cygwin program from an xterm" issue -- when running cygcheck from an
xterm, id pops up a separate window and cygcheck gets no output from id...
I'm not sure how to fix this.  One thing that comes to mind is making
cygcheck aware of Cygwin ptys, but I don't know how hard that would be...
	Igor
==============================================================================
ChangeLog:
2003-05-01  Igor Pechtchanski  <pechtcha@cs.nyu.edu>

	* cygcheck.cc (pretty_id): Parse id output without
	using strtok.
	(match_paren): New static function.

-- 
				http://cs.nyu.edu/~pechtcha/
      |\      _,,,---,,_		pechtcha@cs.nyu.edu
ZZZzz /,`.-'`'    -.  ;-;;,_		igor@watson.ibm.com
     |,4-  ) )-,_. ,\ (  `'-'		Igor Pechtchanski
    '---''(_/--'  `-'\_) fL	a.k.a JaguaR-R-R-r-r-r-.-.-.  Meow!

Knowledge is an unending adventure at the edge of uncertainty.
  -- Leto II
-------------- next part --------------
Index: cygcheck.cc
===================================================================
RCS file: /cvs/src/src/winsup/utils/cygcheck.cc,v
retrieving revision 1.34
diff -u -p -r1.34 cygcheck.cc
--- cygcheck.cc	26 Apr 2003 21:52:03 -0000	1.34
+++ cygcheck.cc	1 May 2003 22:35:17 -0000
@@ -761,6 +761,22 @@ scan_registry (RegInfo * prev, HKEY hKey
   free (subkey_name);
 }
 
+/* If *str=='(', returns a pointer to matching parenthesis or NULL if none. */
+static char *match_paren(char *str)
+{
+  char *p = str;
+  int pcount = 1;
+  if (*p != '(') return NULL;
+  for (p++; *p; p++)
+    {
+      if (*p == '(') pcount++;
+      if (*p == ')') pcount--;
+      if (pcount == 0) break;
+    }
+  if (!*p) return NULL;
+  return p;
+}
+
 void
 pretty_id (const char *s, char *cygwin, size_t cyglen)
 {
@@ -784,20 +800,91 @@ pretty_id (const char *s, char *cygwin, 
 
   char buf[16384];
   fgets (buf, sizeof (buf), f);
-  char *uid = strtok (buf, " ") + sizeof ("uid=") - 1;
-  char *gid = strtok (NULL, " ") + sizeof ("gid=") - 1;
+  if (!*buf)
+    {
+      printf("Unable to parse id output: no output\n");
+      return;
+    }
+  char *uid = buf;
+  char *p = uid + sizeof("uid=") - 1;
+  if (strncmp(uid, "uid=", p - uid) || !isdigit(*p))
+    {
+      printf("Unable to parse id output: no uid= part; full output is\n%s\n", uid);
+      return;
+    }
+  uid = p;
+  for (; *p && isdigit(*p); p++)
+    ;
+  if (*p != '(')
+    {
+      printf("Unable to parse id output: no uid name; full output is\n%s\n", uid);
+      return;
+    }
+  p = match_paren(p);
+  if (p == NULL || *++p != ' ')
+    {
+      printf("Unable to parse id output: uid name parens unmatched; full output is\n%s\n", uid);
+      return;
+    }
+  *p++ = '\0';
+  char *gid = p;
+  p = gid + sizeof("gid=") - 1;
+  if (strncmp(gid, "gid=", p - gid) || !isdigit(*p))
+    {
+      printf("Unable to parse id output: no gid= part; full output is\n%s %s\n", uid, gid);
+      return;
+    }
+  gid = p;
+  for (; *p && isdigit(*p); p++)
+    ;
+  if (*p != '(')
+    {
+      printf("Unable to parse id output: no gid name; full output is\n%s %s\n", uid, gid);
+      return;
+    }
+  p = match_paren(p);
+  if (p == NULL || *++p != ' ')
+    {
+      printf("Unable to parse id output: gid name parens unmatched; full output is\n%s %s\n", uid, gid);
+      return;
+    }
+  *p++ = '\0';
+  char *grp = p;
+  p = grp + sizeof("groups=") - 1;
+  if (strncmp(grp, "groups=", p - grp) || !isdigit(*p))
+    {
+      printf("Unable to parse id output: no groups= part; full output is\n%s %s %s\n", uid, gid, grp);
+      return;
+    }
   char **ng;
   size_t sz = 0;
-  for (ng = groups; (*ng = strtok (NULL, ",")); ng++)
+  for (ng = groups; isdigit(*p); ng++)
     {
-      char *p = strchr (*ng, '\n');
-      if (p)
-	*p = '\0';
-      if (ng == groups)
-	*ng += sizeof ("groups=") - 1;
-      size_t len = strlen (*ng);
+      *ng = p;
+      for (; *p && isdigit(*p); p++)
+	;
+      if (*p != '(')
+	{
+	  printf("Unable to parse id output: no group name: %s; full output is\n%s %s %s", ng, uid, gid, grp);
+          for (char **g = groups; g != ng; g++)
+	    printf("%s,", g);
+	  printf("%s\n", ng);
+	  return;
+	}
+      p = match_paren(p);
+      if (p == NULL || (*++p != ',' && *p != '\n' && *p))
+	{
+	  printf("Unable to parse id output: group name paren unmatched: %s; full output is\n%s %s %s", ng, uid, gid, grp);
+          for (char **g = groups; g != ng; g++)
+	    printf("%s,", g);
+	  printf("%s\n", ng);
+	  return;
+	}
+      size_t len = p - *ng;
       if (sz < len)
 	sz = len;
+      if (*p)
+        *p++ = '\0';
     }
 
   printf ("\n%s output (%s)\n", id, s);
@@ -807,7 +894,6 @@ pretty_id (const char *s, char *cygwin, 
   sz += 1;
   int n = 80 / (int) sz;
   sz = -sz;
-  ng[0] += sizeof ("groups=") - 1;
   printf ("UID: %*s GID: %s\n", sz + (sizeof ("UID: ") - 1), uid, gid);
   int i = 0;
   for (char **g = groups; g < ng; g++)


More information about the Cygwin-patches mailing list