lib: Add new tst_kvcmp for shell

Add tst_kvcmp inspired by the shell test syntax.

Now we can write the kernel version checks as:

if tst_kvcmp -ge 3.8.0 -a -le 4.3.2; then
	tst_brk TCONF "Needs kernel older than 3.8.0 or newer than 4.3.2"
fi

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
diff --git a/lib/tst_kvercmp.c b/lib/tst_kvercmp.c
index 068befc..c497f5d 100644
--- a/lib/tst_kvercmp.c
+++ b/lib/tst_kvercmp.c
@@ -39,13 +39,10 @@
 
 	*d = v;
 
-	if (*end != '.')
-		return NULL;
-
-	return end + 1;
+	return end;
 }
 
-void tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
+int tst_parse_kver(const char *str_kver, int *v1, int *v2, int *v3)
 {
 	const char *str = str_kver;
 
@@ -54,21 +51,31 @@
 	*v3 = 0;
 
 	if (!(str = parse_digit(str, v1)))
-		goto err;
+		return 1;
+
+	if (*(str++) != '.')
+		return 1;
 
 	if (!(str = parse_digit(str, v2)))
-		goto err;
+		return 1;
 
 	/*
-	 * We ignore all errors here in order not to fail with versions as
-	 * "2.4" or "2.6.18".
+	 * Check for a short version e.g '2.4'
 	 */
-	parse_digit(str, v3);
+	if (*str == ' ' || *str == '\0')
+		return 0;
 
-	return;
-err:
-	tst_resm(TWARN,
-		 "Invalid kernel version %s, expected %%d.%%d.%%d", str_kver);
+	if (*(str++) != '.')
+		return 1;
+
+	/*
+	 * Ignore rest of the string in order not to break on versions as
+	 * 4.8.1-52-default.
+	 */
+	if (!parse_digit(str, v3))
+		return 1;
+
+	return 0;
 }
 
 int tst_kvercmp(int r1, int r2, int r3)
@@ -78,7 +85,11 @@
 	struct utsname uval;
 
 	uname(&uval);
-	tst_parse_kver(uval.release, &a1, &a2, &a3);
+	if (tst_parse_kver(uval.release, &a1, &a2, &a3)) {
+		tst_resm(TWARN,
+			 "Invalid kernel version %s, expected %%d.%%d.%%d",
+		         uval.release);
+	}
 
 	testver = (r1 << 16) + (r2 << 8) + r3;
 	currver = (a1 << 16) + (a2 << 8) + a3;