avoid using strok - eliminates use of hidden global variable

function                                             old     new   delta
udhcp_str2optset                                     616     650     +34
setpriv_main                                         950     975     +25
switch_root_main                                     688     706     +18
parse                                                958     970     +12
getopt_main                                          622     628      +6
parse_resolvconf                                     302     306      +4
mpstat_main                                         1139    1142      +3
static.p                                               4       -      -4
cdcmd                                                717     702     -15
strtok                                               148       -    -148
------------------------------------------------------------------------------
(add/remove: 0/3 grow/shrink: 7/1 up/down: 102/-167)          Total: -65 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/libbb/kernel_version.c b/libbb/kernel_version.c
index 7769a09..6bb32ce 100644
--- a/libbb/kernel_version.c
+++ b/libbb/kernel_version.c
@@ -19,15 +19,17 @@
 {
 	struct utsname name;
 	char *t;
-	int i, r;
+	int r;
 
 	uname(&name); /* never fails */
-	t = name.release;
-	r = 0;
-	for (i = 0; i < 3; i++) {
-		t = strtok(t, ".");
-		r = r * 256 + (t ? atoi(t) : 0);
-		t = NULL;
-	}
-	return r;
+	t = name.release - 1;
+	r = 1;
+	do {
+		r <<= 8;
+		if (t) {
+			r += atoi(++t);
+			t = strchr(t, '.');
+		}
+	} while (r < 0x1000000);
+	return r - 0x1000000;
 }
diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c
index c605c4c..7b67f30 100644
--- a/libbb/update_passwd.c
+++ b/libbb/update_passwd.c
@@ -18,17 +18,20 @@
 #if ENABLE_SELINUX
 static void check_selinux_update_passwd(const char *username)
 {
-	security_context_t context;
-	char *seuser;
+	security_context_t seuser;
+	char *p;
 
 	if (getuid() != (uid_t)0 || is_selinux_enabled() == 0)
 		return;  /* No need to check */
 
-	if (getprevcon_raw(&context) < 0)
+	if (getprevcon_raw(&seuser) < 0)
 		bb_simple_perror_msg_and_die("getprevcon failed");
-	seuser = strtok(context, ":");
-	if (!seuser)
-		bb_error_msg_and_die("invalid context '%s'", context);
+
+	p = strchr(seuser, ':');
+	if (!p)
+		bb_error_msg_and_die("invalid context '%s'", seuser);
+	*p = '\0';
+
 	if (strcmp(seuser, username) != 0) {
 		security_class_t tclass;
 		access_vector_t av;
diff --git a/mailutils/reformime.c b/mailutils/reformime.c
index 321729e..307656a 100644
--- a/mailutils/reformime.c
+++ b/mailutils/reformime.c
@@ -115,6 +115,7 @@
 		/* Split to tokens */
 		{
 			char *s, *p;
+			char *tokstate;
 			unsigned ntokens;
 			const char *delims = ";=\" \t\n";
 
@@ -127,13 +128,13 @@
 			}
 			dbg_error_msg("L:'%s'", p);
 			ntokens = 0;
-			s = strtok(s, delims);
+			s = strtok_r(s, delims, &tokstate);
 			while (s) {
 				tokens[ntokens] = s;
 				if (ntokens < ARRAY_SIZE(tokens) - 1)
 					ntokens++;
 				dbg_error_msg("L[%d]='%s'", ntokens, s);
-				s = strtok(NULL, delims);
+				s = strtok_r(NULL, delims, &tokstate);
 			}
 			tokens[ntokens] = NULL;
 			dbg_error_msg("EMPTYLINE, ntokens:%d", ntokens);
diff --git a/networking/nslookup.c b/networking/nslookup.c
index c43e605..759de5c 100644
--- a/networking/nslookup.c
+++ b/networking/nslookup.c
@@ -703,12 +703,13 @@
 
 		while (fgets(line, sizeof(line), resolv)) {
 			char *p, *arg;
+			char *tokstate;
 
-			p = strtok(line, " \t\n");
+			p = strtok_r(line, " \t\n", &tokstate);
 			if (!p)
 				continue;
 			dbg("resolv_key:'%s'\n", p);
-			arg = strtok(NULL, "\n");
+			arg = strtok_r(NULL, "\n", &tokstate);
 			dbg("resolv_arg:'%s'\n", arg);
 			if (!arg)
 				continue;
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 20d843b..4bc7190 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -526,7 +526,7 @@
 
 	/* Cheat, the only *const* str possible is "" */
 	str = (char *) const_str;
-	opt = strtok(str, " \t=:");
+	opt = strtok_r(str, " \t=:", &str);
 	if (!opt)
 		return 0;
 
@@ -550,10 +550,10 @@
 		char *val;
 
 		if (optflag->flags == OPTION_BIN) {
-			val = strtok(NULL, ""); /* do not split "'q w e'" */
+			val = strtok_r(NULL, "", &str); /* do not split "'q w e'" */
 			if (val) trim(val);
 		} else
-			val = strtok(NULL, ", \t");
+			val = strtok_r(NULL, ", \t", &str);
 		if (!val)
 			break;
 
@@ -567,7 +567,7 @@
 			break;
 		case OPTION_IP_PAIR:
 			retval = udhcp_str2nip(val, buffer);
-			val = strtok(NULL, ", \t/-");
+			val = strtok_r(NULL, ", \t/-", &str);
 			if (!val)
 				retval = 0;
 			if (retval)
@@ -631,7 +631,7 @@
 				*slash = '\0';
 				retval = udhcp_str2nip(val, buffer + 1);
 				buffer[0] = mask = bb_strtou(slash + 1, NULL, 10);
-				val = strtok(NULL, ", \t/-");
+				val = strtok_r(NULL, ", \t/-", &str);
 				if (!val || mask > 32 || errno)
 					retval = 0;
 				if (retval) {
diff --git a/procps/mpstat.c b/procps/mpstat.c
index 52a436a..c78c1f0 100644
--- a/procps/mpstat.c
+++ b/procps/mpstat.c
@@ -923,7 +923,7 @@
 		char *t;
 		G.p_option = 1;
 
-		for (t = strtok(opt_set_cpu, ","); t; t = strtok(NULL, ",")) {
+		for (t = strtok_r(opt_set_cpu, ",", &opt_set_cpu); t; t = strtok_r(NULL, ",", &opt_set_cpu)) {
 			if (strcmp(t, "ALL") == 0) {
 				/* Select every CPU */
 				memset(G.cpu_bitmap, 0xff, G.cpu_bitmap_len);
diff --git a/shell/ash.c b/shell/ash.c
index 07aa2da..58da0a2 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2770,7 +2770,7 @@
 			lim++;
 		}
 	}
-	p = strtok(cdcomppath, "/");
+	p = strtok_r(cdcomppath, "/", &cdcomppath);
 	while (p) {
 		switch (*p) {
 		case '.':
@@ -2789,7 +2789,7 @@
 			new = stack_putstr(p, new);
 			USTPUTC('/', new);
 		}
-		p = strtok(NULL, "/");
+		p = strtok_r(NULL, "/", &cdcomppath);
 	}
 	if (new > lim)
 		STUNPUTC(new);
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index db7db6f..1fa4024 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -289,12 +289,13 @@
 {
 	int long_nr = 0;
 	int arg_opt, tlen;
-	char *tokptr = strtok(options, ", \t\n");
+	char *tokptr;
 
 	if (long_options)
 		while (long_options[long_nr].name)
 			long_nr++;
 
+	tokptr = strtok_r(options, ", \t\n", &options);
 	while (tokptr) {
 		arg_opt = no_argument;
 		tlen = strlen(tokptr);
@@ -318,7 +319,7 @@
 			long_nr++;
 			/*memset(&long_options[long_nr], 0, sizeof(long_options[0])); - xrealloc_vector did it */
 		}
-		tokptr = strtok(NULL, ", \t\n");
+		tokptr = strtok_r(NULL, ", \t\n", &options);
 	}
 	return long_options;
 }
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 19ac139..fc5161d 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -1230,6 +1230,7 @@
 	 * then data pointer is interpreted as a string. */
 	struct nfs_mount_data data;
 	char *opt;
+	char *tokstate;
 	struct hostent *hp;
 	struct sockaddr_in server_addr;
 	struct sockaddr_in mount_server_addr;
@@ -1348,7 +1349,7 @@
 	nfsvers = 0;
 
 	/* parse options */
-	if (filteropts)	for (opt = strtok(filteropts, ","); opt; opt = strtok(NULL, ",")) {
+	if (filteropts)	for (opt = strtok_r(filteropts, ",", &tokstate); opt; opt = strtok_r(NULL, ",", &tokstate)) {
 		char *opteq = strchr(opt, '=');
 		if (opteq) {
 			int val, idx;
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index 37e8821..1e4b201 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -144,10 +144,11 @@
 static void set_inh_caps(char *capstring)
 {
 	struct caps caps;
+	char *string;
 
 	getcaps(&caps);
 
-	capstring = strtok(capstring, ",");
+	capstring = strtok_r(capstring, ",", &string);
 	while (capstring) {
 		unsigned cap;
 
@@ -159,7 +160,7 @@
 			caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap);
 		else
 			caps.data[CAP_TO_INDEX(cap)].inheritable &= ~CAP_TO_MASK(cap);
-		capstring = strtok(NULL, ",");
+		capstring = strtok_r(NULL, ",", &string);
 	}
 
 	if (capset(&caps.header, caps.data) != 0)
@@ -170,7 +171,7 @@
 {
 	char *cap;
 
-	cap = strtok(string, ",");
+	cap = strtok_r(string, ",", &string);
 	while (cap) {
 		unsigned idx;
 
@@ -182,7 +183,7 @@
 			if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, idx, 0, 0) < 0)
 				bb_simple_perror_msg("cap_ambient_lower");
 		}
-		cap = strtok(NULL, ",");
+		cap = strtok_r(NULL, ",", &string);
 	}
 }
 #endif /* FEATURE_SETPRIV_CAPABILITIES */
diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c
index c65096c..f2674b5 100644
--- a/util-linux/switch_root.c
+++ b/util-linux/switch_root.c
@@ -164,7 +164,7 @@
 {
 	char *cap;
 
-	cap = strtok(string, ",");
+	cap = strtok_r(string, ",", &string);
 	while (cap) {
 		unsigned cap_idx;
 
@@ -174,7 +174,7 @@
 		drop_bounding_set(cap_idx);
 		drop_capset(cap_idx);
 		bb_error_msg("dropped capability: %s", cap);
-		cap = strtok(NULL, ",");
+		cap = strtok_r(NULL, ",", &string);
 	}
 }
 #endif