fdisk: sync up with some util-linux 2.31 behavior

= display default is no longer in cylinders
= +sizeC is no longer supported
= add +sizeT suffix - terabytes are here
= K,M,G,T and k,m,g,t suffixes all are binary, not decimal
= +sizeM results in last sector +(size * 1Mbyte - 1), not +(size * 1Mbyte)
= fix comparison to "YES" answer for sgi/sun

function                                             old     new   delta
read_int                                             492     519     +27
fdisk_main                                          2644    2640      -4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 27/-4)              Total: 23 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index e47bc73..2967165 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -426,7 +426,7 @@
 	unsigned sector_offset; // = 1;
 	unsigned g_heads, g_sectors, g_cylinders;
 	smallint /* enum label_type */ current_label_type;
-	smallint display_in_cyl_units; // = 1;
+	smallint display_in_cyl_units;
 #if ENABLE_FEATURE_OSF_LABEL
 	smallint possibly_osf_label;
 #endif
@@ -488,7 +488,6 @@
 	sector_size = DEFAULT_SECTOR_SIZE; \
 	sector_offset = 1; \
 	g_partitions = 4; \
-	display_in_cyl_units = 1; \
 	units_per_sector = 1; \
 	dos_compatible_flag = 1; \
 } while (0)
@@ -639,25 +638,6 @@
 }
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
-/* Read line; return 0 or first printable char */
-static int
-read_line(const char *prompt)
-{
-	int sz;
-
-	sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer));
-	if (sz <= 0)
-		exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
-
-	if (line_buffer[sz-1] == '\n')
-		line_buffer[--sz] = '\0';
-
-	line_ptr = line_buffer;
-	while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
-		line_ptr++;
-	return *line_ptr;
-}
-
 static void
 set_all_unchanged(void)
 {
@@ -680,6 +660,25 @@
 	b[511] = 0xaa;
 }
 
+/* Read line; return 0 or first printable non-space char */
+static int
+read_line(const char *prompt)
+{
+	int sz;
+
+	sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer));
+	if (sz <= 0)
+		exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
+
+	if (line_buffer[sz-1] == '\n')
+		line_buffer[--sz] = '\0';
+
+	line_ptr = line_buffer;
+	while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
+		line_ptr++;
+	return *line_ptr;
+}
+
 static char
 read_nonempty(const char *mesg)
 {
@@ -1614,7 +1613,7 @@
 
 		if (*line_ptr == '+' || *line_ptr == '-') {
 			int minus = (*line_ptr == '-');
-			int absolute = 0;
+			unsigned scale_shift;
 
 			if (sizeof(value) <= sizeof(long))
 				value = strtoul(line_ptr + 1, NULL, 10);
@@ -1622,48 +1621,46 @@
 				value = strtoull(line_ptr + 1, NULL, 10);
 
 			/* (1) if 2nd char is digit, use_default = 0.
-			 * (2) move line_ptr to first non-digit. */
+			 * (2) move line_ptr to first non-digit.
+			 */
 			while (isdigit(*++line_ptr))
 				use_default = 0;
 
-			switch (*line_ptr) {
-			case 'c':
-			case 'C':
-				if (!display_in_cyl_units)
-					value *= g_heads * g_sectors;
-				break;
-			case 'K':
-				absolute = 1024;
-				break;
+			scale_shift = 0;
+			switch (*line_ptr | 0x20) {
 			case 'k':
-				absolute = 1000;
+				scale_shift = 10; /* 1024 */
 				break;
 			case 'm':
-			case 'M':
-				absolute = 1000000;
+				scale_shift = 20; /* 1024*1024 */
 				break;
 			case 'g':
-			case 'G':
-				absolute = 1000000000;
+				scale_shift = 30; /* 1024*1024*1024 */
+				break;
+			case 't':
+				scale_shift = 40; /* 1024*1024*1024*1024 */
 				break;
 			default:
 				break;
 			}
-			if (absolute) {
+			if (scale_shift) {
 				ullong bytes;
 				unsigned long unit;
 
-				bytes = (ullong) value * absolute;
+				bytes = (ullong) value << scale_shift;
 				unit = sector_size * units_per_sector;
 				bytes += unit/2; /* round */
 				bytes /= unit;
-				value = bytes;
+				value = (bytes != 0 ? bytes - 1 : 0);
 			}
 			if (minus)
 				value = -value;
 			value += base;
 		} else {
-			value = atoi(line_ptr);
+			if (sizeof(value) <= sizeof(long))
+				value = strtoul(line_ptr, NULL, 10);
+			else
+				value = strtoull(line_ptr, NULL, 10);
 			while (isdigit(*line_ptr)) {
 				line_ptr++;
 				use_default = 0;
@@ -2529,8 +2526,9 @@
 		stop = limit;
 	} else {
 		snprintf(mesg, sizeof(mesg),
-			 "Last %s or +size or +sizeM or +sizeK",
-			 str_units(SINGULAR));
+			 "Last %s or +size{,K,M,G,T}",
+			 str_units(SINGULAR)
+		);
 		stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
 		if (display_in_cyl_units) {
 			stop = stop * units_per_sector - 1;
@@ -2614,9 +2612,9 @@
 	} else {
 		char c, line[80];
 		snprintf(line, sizeof(line),
-			"Command action\n"
-			"   %s\n"
-			"   p   primary partition (1-4)\n",
+			"Partition type\n"
+			"   p   primary partition (1-4)\n"
+			"   %s\n",
 			(extended_offset ?
 			"l   logical (5 or over)" : "e   extended"));
 		while (1) {