diff miscutil/imei-luhn.c @ 271:cd043e690621

imei-luhn utility written
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Fri, 07 Feb 2014 05:00:24 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/miscutil/imei-luhn.c	Fri Feb 07 05:00:24 2014 +0000
@@ -0,0 +1,76 @@
+/*
+ * This program computes the Luhn check digit for an IMEI number given
+ * the first 14 digits, or verifies the correctness of this check digit
+ * given a 15-digit number as input.
+ *
+ * The number given on the command line may optionally include punctuation,
+ * which is skipped and ignored.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+char digits[15];
+
+compute_cd()
+{
+	int i, dig, sum;
+
+	sum = 0;
+	for (i = 0; i < 14; i++) {
+		dig = digits[i];
+		if (i & 1) {
+			dig *= 2;
+			if (dig > 9)
+				dig -= 9;
+		}
+		sum += dig;
+	}
+	dig = sum % 10;
+	if (dig)
+		dig = 10 - dig;
+	return dig;
+}
+
+main(argc, argv)
+	char **argv;
+{
+	char *cp;
+	int i;
+
+	if (argc != 2) {
+usage:		fprintf(stderr, "usage: %s number\n", argv[0]);
+		exit(2);
+	}
+	cp = argv[1];
+	if (!isdigit(*cp))
+		goto usage;
+	for (i = 0; *cp; ) {
+		if (ispunct(*cp))
+			cp++;
+		if (!isdigit(*cp))
+			goto usage;
+		if (i >= 15) {
+wrong_len:		fprintf(stderr,
+				"error: argument must have 14 or 15 digits\n");
+			exit(2);
+		}
+		digits[i++] = *cp++ - '0';
+	}
+	switch (i) {
+	case 14:
+		printf("%d\n", compute_cd());
+		exit(0);
+	case 15:
+		if (digits[14] == compute_cd()) {
+			printf("IMEI OK\n");
+			exit(0);
+		} else {
+			printf("Check digit mismatch!\n");
+			exit(1);
+		}
+	default:
+		goto wrong_len;
+	}
+}