1/*
2 * Shell-like utility functions
3 *
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id: shutils.c 337155 2012-06-06 12:17:08Z $
19 */
20
21#ifndef _GNU_SOURCE
22#define _GNU_SOURCE
23#endif
24#include <typedefs.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <dirent.h>
28
29#include <stdarg.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <limits.h>
33#include <unistd.h>
34#include <signal.h>
35#include <string.h>
36#include <ctype.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <sys/wait.h>
40#include <sys/ioctl.h>
41#include <assert.h>
42#include <sys/sysinfo.h>
43#include <sys/mman.h>
44#include <syslog.h>
45#include <typedefs.h>
46#include <wlioctl.h>
47
48#include <bcmnvram.h>
49#include <shutils.h>
50
51/* Linux specific headers */
52#ifdef linux
53#include <error.h>
54#include <termios.h>
55#include <sys/time.h>
56//#include <net/ethernet.h>
57#else
58#include <proto/ethernet.h>
59#endif /* linux */
60
61#include "shared.h"
62
63#define T(x)		__TXT(x)
64#define __TXT(s)	L ## s
65
66#ifndef B_L
67#define B_L		T(__FILE__),__LINE__
68#define B_ARGS_DEC	char *file, int line
69#define B_ARGS		file, line
70#endif /* B_L */
71
72#define bfree(B_ARGS, p) free(p)
73#define balloc(B_ARGS, num) malloc(num)
74#define brealloc(B_ARGS, p, num) realloc(p, num)
75
76#define STR_REALLOC		0x1				/* Reallocate the buffer as required */
77#define STR_INC			64				/* Growth increment */
78
79unsigned char	used_shift='C';
80
81typedef struct {
82	char		*s;						/* Pointer to buffer */
83	int		size;						/* Current buffer size */
84	int		max;						/* Maximum buffer size */
85	int		count;						/* Buffer count */
86	int		flags;						/* Allocation flags */
87} strbuf_t;
88
89/*
90 *	Sprintf formatting flags
91 */
92enum flag {
93	flag_none = 0,
94	flag_minus = 1,
95	flag_plus = 2,
96	flag_space = 4,
97	flag_hash = 8,
98	flag_zero = 16,
99	flag_short = 32,
100	flag_long = 64
101};
102
103/*
104 * Print out message on console.
105 */
106void dbgprintf (const char * format, ...)
107{
108	FILE *f;
109	int nfd;
110	va_list args;
111
112	if((nfd = open("/dev/console", O_WRONLY | O_NONBLOCK)) > 0){
113		if((f = fdopen(nfd, "w")) != NULL){
114			va_start(args, format);
115			vfprintf(f, format, args);
116			va_end(args);
117			fclose(f);
118		}
119		close(nfd);
120	}
121}
122
123void dbg(const char * format, ...)
124{
125	FILE *f;
126	int nfd;
127	va_list args;
128
129	if (((nfd = open("/dev/console", O_WRONLY | O_NONBLOCK)) > 0) &&
130	    (f = fdopen(nfd, "w")))
131	{
132		va_start(args, format);
133		vfprintf(f, format, args);
134		va_end(args);
135		fclose(f);
136	}
137	else
138	{
139		va_start(args, format);
140		vfprintf(stderr, format, args);
141		va_end(args);
142	}
143
144	if (nfd != -1) close(nfd);
145}
146
147/*
148 * Reads file and returns contents
149 * @param	fd	file descriptor
150 * @return	contents of file or NULL if an error occurred
151 */
152char *
153fd2str(int fd)
154{
155	char *buf = NULL;
156	size_t count = 0, n;
157
158	do {
159		buf = realloc(buf, count + 512);
160		n = read(fd, buf + count, 512);
161		if (n < 0) {
162			free(buf);
163			buf = NULL;
164		}
165		count += n;
166	} while (n == 512);
167
168	close(fd);
169	if (buf)
170		buf[count] = '\0';
171	return buf;
172}
173
174/*
175 * Reads file and returns contents
176 * @param	path	path to file
177 * @return	contents of file or NULL if an error occurred
178 */
179char *
180file2str(const char *path)
181{
182	int fd;
183
184	if ((fd = open(path, O_RDONLY)) == -1) {
185		perror(path);
186		return NULL;
187	}
188
189	return fd2str(fd);
190}
191
192/*
193 * Waits for a file descriptor to change status or unblocked signal
194 * @param	fd	file descriptor
195 * @param	timeout	seconds to wait before timing out or 0 for no timeout
196 * @return	1 if descriptor changed status or 0 if timed out or -1 on error
197 */
198int
199waitfor(int fd, int timeout)
200{
201	fd_set rfds;
202	struct timeval tv = { timeout, 0 };
203
204	FD_ZERO(&rfds);
205	FD_SET(fd, &rfds);
206	return select(fd + 1, &rfds, NULL, NULL, (timeout > 0) ? &tv : NULL);
207}
208
209/*
210 * Concatenates NULL-terminated list of arguments into a single
211 * commmand and executes it
212 * @param	argv	argument list
213 * @param	path	NULL, ">output", or ">>output"
214 * @param	timeout	seconds to wait before timing out or 0 for no timeout
215 * @param	ppid	NULL to wait for child termination or pointer to pid
216 * @return	return value of executed command or errno
217 *
218 * Ref: http://www.open-std.org/jtc1/sc22/WG15/docs/rr/9945-2/9945-2-28.html
219 */
220int _eval(char *const argv[], const char *path, int timeout, int *ppid)
221{
222	sigset_t set, sigmask;
223	sighandler_t chld = SIG_IGN;
224	pid_t pid, w;
225	int status = 0;
226	int fd;
227	int flags;
228	int sig;
229	int n;
230	const char *p;
231	char s[256];
232	//char *cpu0_argv[32] = { "taskset", "-c", "0"};
233	//char *cpu1_argv[32] = { "taskset", "-c", "1"};
234
235	if (!ppid) {
236		// block SIGCHLD
237		sigemptyset(&set);
238		sigaddset(&set, SIGCHLD);
239		sigprocmask(SIG_BLOCK, &set, &sigmask);
240		// without this we cannot rely on waitpid() to tell what happened to our children
241		chld = signal(SIGCHLD, SIG_DFL);
242	}
243
244	pid = fork();
245	if (pid == -1) {
246		perror("fork");
247		status = errno;
248		goto EXIT;
249	}
250	if (pid != 0) {
251		// parent
252		if (ppid) {
253			*ppid = pid;
254			return 0;
255		}
256		do {
257			if ((w = waitpid(pid, &status, 0)) == -1) {
258				status = errno;
259				perror("waitpid");
260				goto EXIT;
261			}
262		} while (!WIFEXITED(status) && !WIFSIGNALED(status));
263
264		if (WIFEXITED(status)) status = WEXITSTATUS(status);
265EXIT:
266		if (!ppid) {
267			// restore signals
268			sigprocmask(SIG_SETMASK, &sigmask, NULL);
269			signal(SIGCHLD, chld);
270			// reap zombies
271			chld_reap(0);
272		}
273		return status;
274	}
275
276	// child
277
278	// reset signal handlers
279	for (sig = 0; sig < (_NSIG - 1); sig++)
280		signal(sig, SIG_DFL);
281
282	// unblock signals if called from signal handler
283	sigemptyset(&set);
284	sigprocmask(SIG_SETMASK, &set, NULL);
285
286	setsid();
287
288	close(STDIN_FILENO);
289	close(STDOUT_FILENO);
290	close(STDERR_FILENO);
291	open("/dev/null", O_RDONLY);
292	open("/dev/null", O_WRONLY);
293	open("/dev/null", O_WRONLY);
294
295	if (nvram_match("debug_logeval", "1")) {
296		pid = getpid();
297
298		cprintf("_eval +%ld pid=%d ", uptime(), pid);
299		for (n = 0; argv[n]; ++n) cprintf("%s ", argv[n]);
300		cprintf("\n");
301
302		if ((fd = open("/dev/console", O_RDWR | O_NONBLOCK)) >= 0) {
303			dup2(fd, STDIN_FILENO);
304			dup2(fd, STDOUT_FILENO);
305			dup2(fd, STDERR_FILENO);
306		}
307		else {
308			sprintf(s, "/tmp/eval.%d", pid);
309			if ((fd = open(s, O_CREAT | O_RDWR | O_NONBLOCK, 0600)) >= 0) {
310				dup2(fd, STDOUT_FILENO);
311				dup2(fd, STDERR_FILENO);
312			}
313		}
314		if (fd > STDERR_FILENO) close(fd);
315	}
316
317	// Redirect stdout & stderr to <path>
318	if (path) {
319		flags = O_WRONLY | O_CREAT | O_NONBLOCK;
320		if (*path == '>') {
321			++path;
322			if (*path == '>') {
323				++path;
324				// >>path, append
325				flags |= O_APPEND;
326			}
327			else {
328				// >path, overwrite
329				flags |= O_TRUNC;
330			}
331		}
332
333		if ((fd = open(path, flags, 0644)) < 0) {
334			perror(path);
335		}
336		else {
337			dup2(fd, STDOUT_FILENO);
338			dup2(fd, STDERR_FILENO);
339			close(fd);
340		}
341	}
342
343	// execute command
344
345	p = nvram_safe_get("env_path");
346	snprintf(s, sizeof(s), "%s%s/sbin:/bin:/usr/sbin:/usr/bin:/opt/sbin:/opt/bin", *p ? p : "", *p ? ":" : "");
347	setenv("PATH", s, 1);
348
349	alarm(timeout);
350#if 1
351	execvp(argv[0], argv);
352
353	perror(argv[0]);
354#elif 0
355	for(n = 0; argv[n]; ++n)
356		cpu0_argv[n+3] = argv[n];
357	execvp(cpu0_argv[0], cpu0_argv);
358
359	perror(cpu0_argv[0]);
360#else
361	for(n = 0; argv[n]; ++n)
362		cpu1_argv[n+3] = argv[n];
363	execvp(cpu1_argv[0], cpu1_argv);
364
365	perror(cpu1_argv[0]);
366
367#endif
368
369	_exit(errno);
370}
371
372static int get_cmds_size(char **cmds)
373{
374        int i=0;
375        for(; cmds[i]; ++i);
376        return i;
377}
378
379int _cpu_eval(int *ppid, char *cmds[])
380{
381        int ncmds=0, n=0, i;
382        int maxn = get_cmds_size(cmds)
383#if defined (SMP)
384                + 4;
385#else
386                +1;
387#endif
388        char *cpucmd[maxn];
389
390        for(i=0; i<maxn; ++i)
391                cpucmd[i]=NULL;
392
393#if defined (SMP)
394        cpucmd[ncmds++]="taskset";
395        cpucmd[ncmds++]="-c";
396        if(!strcmp(cmds[n], CPU0) || !strcmp(cmds[n], CPU1)) {
397                cpucmd[ncmds++]=cmds[n++];
398        } else
399                cpucmd[ncmds++]=CPU0;
400#else
401        if(strcmp(cmds[n], CPU0) && strcmp(cmds[n], CPU1))
402                cpucmd[ncmds++]=cmds[n++];
403        else
404                n++;
405#endif
406        for(; cmds[n]; cpucmd[ncmds++]=cmds[n++]);
407
408        return _eval(cpucmd, NULL, 0, ppid);;
409}
410
411/*
412 * Concatenates NULL-terminated list of arguments into a single
413 * commmand and executes it
414 * @param	argv	argument list
415 * @return	stdout of executed command or NULL if an error occurred
416 */
417char *
418_backtick(char *const argv[])
419{
420	int filedes[2];
421	pid_t pid;
422	int status;
423	char *buf = NULL;
424
425	/* create pipe */
426	if (pipe(filedes) == -1) {
427		perror(argv[0]);
428		return NULL;
429	}
430
431	switch (pid = fork()) {
432	case -1:	/* error */
433		return NULL;
434	case 0:		/* child */
435		close(filedes[0]);	/* close read end of pipe */
436		dup2(filedes[1], 1);	/* redirect stdout to write end of pipe */
437		close(filedes[1]);	/* close write end of pipe */
438		execvp(argv[0], argv);
439		exit(errno);
440		break;
441	default:	/* parent */
442		close(filedes[1]);	/* close write end of pipe */
443		buf = fd2str(filedes[0]);
444		waitpid(pid, &status, 0);
445		break;
446	}
447
448	return buf;
449}
450
451
452/*
453 * fread() with automatic retry on syscall interrupt
454 * @param	ptr	location to store to
455 * @param	size	size of each element of data
456 * @param	nmemb	number of elements
457 * @param	stream	file stream
458 * @return	number of items successfully read
459 */
460int
461safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
462{
463	size_t ret = 0;
464
465	do {
466		clearerr(stream);
467		ret += fread((char *)ptr + (ret * size), size, nmemb - ret, stream);
468	} while (ret < nmemb && ferror(stream) && errno == EINTR);
469
470	return ret;
471}
472
473/*
474 * fwrite() with automatic retry on syscall interrupt
475 * @param	ptr	location to read from
476 * @param	size	size of each element of data
477 * @param	nmemb	number of elements
478 * @param	stream	file stream
479 * @return	number of items successfully written
480 */
481int
482safe_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
483{
484	size_t ret = 0;
485
486	do {
487		clearerr(stream);
488		ret += fwrite((char *)ptr + (ret * size), size, nmemb - ret, stream);
489	} while (ret < nmemb && ferror(stream) && errno == EINTR);
490
491	return ret;
492}
493
494/*
495 * Returns the process ID.
496 *
497 * @param	name	pathname used to start the process.  Do not include the
498 *                      arguments.
499 * @return	pid
500 */
501pid_t
502get_pid_by_name(char *name)
503{
504	pid_t           pid = -1;
505	DIR             *dir;
506	struct dirent   *next;
507
508	if ((dir = opendir("/proc")) == NULL) {
509		perror("Cannot open /proc");
510		return -1;
511	}
512
513	while ((next = readdir(dir)) != NULL) {
514		FILE *fp;
515		char filename[256];
516		char buffer[256];
517
518		/* If it isn't a number, we don't want it */
519		if (!isdigit(*next->d_name))
520			continue;
521
522		sprintf(filename, "/proc/%s/cmdline", next->d_name);
523		fp = fopen(filename, "r");
524		if (!fp) {
525			continue;
526		}
527		buffer[0] = '\0';
528		fgets(buffer, 256, fp);
529		fclose(fp);
530
531		if (!strcmp(name, buffer)) {
532			pid = strtol(next->d_name, NULL, 0);
533			break;
534		}
535	}
536
537	return pid;
538}
539
540/*
541 * Convert Ethernet address string representation to binary data
542 * @param	a	string in xx:xx:xx:xx:xx:xx notation
543 * @param	e	binary data
544 * @return	TRUE if conversion was successful and FALSE otherwise
545 */
546int
547ether_atoe(const char *a, unsigned char *e)
548{
549	char *c = (char *) a;
550	int i = 0;
551
552	memset(e, 0, ETHER_ADDR_LEN);
553	for (;;) {
554		e[i++] = (unsigned char) strtoul(c, &c, 16);
555		if (!*c++ || i == ETHER_ADDR_LEN)
556			break;
557	}
558	return (i == ETHER_ADDR_LEN);
559}
560
561/*
562 * Convert Ethernet address binary data to string representation
563 * @param	e	binary data
564 * @param	a	string in xx:xx:xx:xx:xx:xx notation
565 * @return	a
566 */
567char *
568ether_etoa(const unsigned char *e, char *a)
569{
570	char *c = a;
571	int i;
572
573	for (i = 0; i < ETHER_ADDR_LEN; i++) {
574		if (i)
575			*c++ = ':';
576		c += sprintf(c, "%02X", e[i] & 0xff);
577	}
578	return a;
579}
580
581char *ether_etoa2(const unsigned char *e, char *a)
582{
583	sprintf(a, "%02X%02X%02X%02X%02X%02X", e[0], e[1], e[2], e[3], e[4], e[5]);
584	return a;
585}
586
587void cprintf(const char *format, ...)
588{
589	FILE *f;
590	int nfd;
591	va_list args;
592
593#ifdef DEBUG_NOISY
594	{
595#else
596	if (nvram_match("debug_cprintf", "1")) {
597#endif
598		if((nfd = open("/dev/console", O_WRONLY | O_NONBLOCK)) > 0){
599			if((f = fdopen(nfd, "w")) != NULL){
600				va_start(args, format);
601				vfprintf(f, format, args);
602				va_end(args);
603				fclose(f);
604			}
605			close(nfd);
606		}
607	}
608#if 1
609	if (nvram_match("debug_cprintf_file", "1")) {
610//		char s[32];
611//		sprintf(s, "/tmp/cprintf.%d", getpid());
612//		if ((f = fopen(s, "a")) != NULL) {
613		if ((f = fopen("/tmp/cprintf", "a")) != NULL) {
614			va_start(args, format);
615			vfprintf(f, format, args);
616			va_end(args);
617			fclose(f);
618		}
619	}
620#endif
621#if 0
622	if (nvram_match("debug_cprintf_log", "1")) {
623		char s[512];
624
625		va_start(args, format);
626		vsnprintf(s, sizeof(s), format, args);
627		s[sizeof(s) - 1] = 0;
628		va_end(args);
629
630		if ((s[0] != '\n') || (s[1] != 0)) syslog(LOG_DEBUG, "%s", s);
631	}
632#endif
633}
634
635#ifndef WL_BSS_INFO_VERSION
636#error WL_BSS_INFO_VERSION
637#endif
638
639#if WL_BSS_INFO_VERSION >= 108
640// xref (all): nas, wlconf
641#if 0
642/*
643 * Get the ip configuration index if it exists given the
644 * eth name.
645 *
646 * @param	wl_ifname 	pointer to eth interface name
647 * @return	index or -1 if not found
648 */
649int
650get_ipconfig_index(char *eth_ifname)
651{
652	char varname[64];
653	char varval[64];
654	char *ptr;
655	char wl_ifname[NVRAM_MAX_PARAM_LEN];
656	int index;
657
658	/* Bail if we get a NULL or empty string */
659
660	if (!eth_ifname) return -1;
661	if (!*eth_ifname) return -1;
662
663	/* Look up wl name from the eth name */
664	if (osifname_to_nvifname(eth_ifname, wl_ifname, sizeof(wl_ifname)) != 0)
665		return -1;
666
667	snprintf(varname, sizeof(varname), "%s_ipconfig_index", wl_ifname);
668
669	ptr = nvram_get(varname);
670
671	if (ptr) {
672	/* Check ipconfig_index pointer to see if it is still pointing
673	 * the correct lan config block
674	 */
675		if (*ptr) {
676			int index;
677			char *ifname;
678			char buf[64];
679			index = atoi(ptr);
680
681			snprintf(buf, sizeof(buf), "lan%d_ifname", index);
682
683			ifname = nvram_get(buf);
684
685			if (ifname) {
686				if  (!(strcmp(ifname, wl_ifname)))
687					return index;
688			}
689			nvram_unset(varname);
690		}
691	}
692
693	/* The index pointer may not have been configured if the
694	 * user enters the variables manually. Do a brute force search
695	 *  of the lanXX_ifname variables
696	 */
697	for (index = 0; index < MAX_NVPARSE; index++) {
698		snprintf(varname, sizeof(varname), "lan%d_ifname", index);
699		if (nvram_match(varname, wl_ifname)) {
700			/* if a match is found set up a corresponding index pointer for wlXX */
701			snprintf(varname, sizeof(varname), "%s_ipconfig_index", wl_ifname);
702			snprintf(varval, sizeof(varval), "%d", index);
703			nvram_set(varname, varval);
704			nvram_commit();
705			return index;
706		};
707	}
708	return -1;
709}
710
711/*
712 * Set the ip configuration index given the eth name
713 * Updates both wlXX_ipconfig_index and lanYY_ifname.
714 *
715 * @param	eth_ifname 	pointer to eth interface name
716 * @return	0 if successful -1 if not.
717 */
718int
719set_ipconfig_index(char *eth_ifname, int index)
720{
721	char varname[255];
722	char varval[16];
723	char wl_ifname[NVRAM_MAX_PARAM_LEN];
724
725	/* Bail if we get a NULL or empty string */
726
727	if (!eth_ifname) return -1;
728	if (!*eth_ifname) return -1;
729
730	if (index >= MAX_NVPARSE) return -1;
731
732	/* Look up wl name from the eth name only if the name contains
733	   eth
734	*/
735
736	if (osifname_to_nvifname(eth_ifname, wl_ifname, sizeof(wl_ifname)) != 0)
737		return -1;
738
739	snprintf(varname, sizeof(varname), "%s_ipconfig_index", wl_ifname);
740	snprintf(varval, sizeof(varval), "%d", index);
741	nvram_set(varname, varval);
742
743	snprintf(varname, sizeof(varname), "lan%d_ifname", index);
744	nvram_set(varname, wl_ifname);
745
746	nvram_commit();
747
748	return 0;
749}
750
751/*
752 * Get interfaces belonging to a specific bridge.
753 *
754 * @param	bridge_name 	pointer to bridge interface name
755 * @return	list of interfaces belonging to the bridge or NULL
756 *              if not found/empty
757 */
758char *
759get_bridged_interfaces(char *bridge_name)
760{
761	static char interfaces[255];
762	char *ifnames = NULL;
763	char bridge[64];
764
765	if (!bridge_name) return NULL;
766
767	memset(interfaces, 0, sizeof(interfaces));
768	snprintf(bridge, sizeof(bridge), "%s_ifnames", bridge_name);
769
770	ifnames = nvram_get(bridge);
771
772	if (ifnames)
773		strncpy(interfaces, ifnames, sizeof(interfaces));
774	else
775		return NULL;
776
777	return  interfaces;
778
779}
780
781#endif	// 0
782
783/*
784 * Search a string backwards for a set of characters
785 * This is the reverse version of strspn()
786 *
787 * @param	s	string to search backwards
788 * @param	accept	set of chars for which to search
789 * @return	number of characters in the trailing segment of s
790 *		which consist only of characters from accept.
791 */
792static size_t
793sh_strrspn(const char *s, const char *accept)
794{
795	const char *p;
796	size_t accept_len = strlen(accept);
797	int i;
798
799
800	if (s[0] == '\0')
801		return 0;
802
803	p = s + strlen(s);
804	i = 0;
805
806	do {
807		p--;
808		if (memchr(accept, *p, accept_len) == NULL)
809			break;
810		i++;
811	} while (p != s);
812
813	return i;
814}
815
816/*
817 * Parse the unit and subunit from an interface string such as wlXX or wlXX.YY
818 *
819 * @param	ifname	interface string to parse
820 * @param	unit	pointer to return the unit number, may pass NULL
821 * @param	subunit	pointer to return the subunit number, may pass NULL
822 * @return	Returns 0 if the string ends with digits or digits.digits, -1 otherwise.
823 *		If ifname ends in digits.digits, then unit and subuint are set
824 *		to the first and second values respectively. If ifname ends
825 *		in just digits, unit is set to the value, and subunit is set
826 *		to -1. On error both unit and subunit are -1. NULL may be passed
827 *		for unit and/or subuint to ignore the value.
828 */
829int
830get_ifname_unit(const char* ifname, int *unit, int *subunit)
831{
832	const char digits[] = "0123456789";
833	char str[64];
834	char *p;
835	size_t ifname_len = strlen(ifname);
836	size_t len;
837	unsigned long val;
838
839	if (unit)
840		*unit = -1;
841	if (subunit)
842		*subunit = -1;
843
844	if (ifname_len + 1 > sizeof(str))
845		return -1;
846
847	strcpy(str, ifname);
848
849	/* find the trailing digit chars */
850	len = sh_strrspn(str, digits);
851
852	/* fail if there were no trailing digits */
853	if (len == 0)
854		return -1;
855
856	/* point to the beginning of the last integer and convert */
857	p = str + (ifname_len - len);
858	val = strtoul(p, NULL, 10);
859
860	/* if we are at the beginning of the string, or the previous
861	 * character is not a '.', then we have the unit number and
862	 * we are done parsing
863	 */
864	if (p == str || p[-1] != '.') {
865		if (unit)
866			*unit = val;
867		return 0;
868	} else {
869		if (subunit)
870			*subunit = val;
871	}
872
873	/* chop off the '.NNN' and get the unit number */
874	p--;
875	p[0] = '\0';
876
877	/* find the trailing digit chars */
878	len = sh_strrspn(str, digits);
879
880	/* fail if there were no trailing digits */
881	if (len == 0)
882		return -1;
883
884	/* point to the beginning of the last integer and convert */
885	p = p - len;
886	val = strtoul(p, NULL, 10);
887
888	/* save the unit number */
889	if (unit)
890		*unit = val;
891
892	return 0;
893}
894
895/* In the space-separated/null-terminated list(haystack), try to
896 * locate the string "needle"
897 */
898char *
899find_in_list(const char *haystack, const char *needle)
900{
901	const char *ptr = haystack;
902	int needle_len = 0;
903	int haystack_len = 0;
904	int len = 0;
905
906	if (!haystack || !needle || !*haystack || !*needle)
907		return NULL;
908
909	needle_len = strlen(needle);
910	haystack_len = strlen(haystack);
911
912	while (*ptr != 0 && ptr < &haystack[haystack_len])
913	{
914		/* consume leading spaces */
915		ptr += strspn(ptr, " ");
916
917		/* what's the length of the next word */
918		len = strcspn(ptr, " ");
919
920		if ((needle_len == len) && (!strncmp(needle, ptr, len)))
921			return (char*) ptr;
922
923		ptr += len;
924	}
925	return NULL;
926}
927
928
929/**
930 *	remove_from_list
931 *	Remove the specified word from the list.
932
933 *	@param name word to be removed from the list
934 *	@param list Space separated list to modify
935 *	@param listsize Max size the list can occupy
936
937 *	@return	error code
938 */
939int
940remove_from_list(const char *name, char *list, int listsize)
941{
942//	int listlen = 0;
943	int namelen = 0;
944	char *occurrence = list;
945
946	if (!list || !name || (listsize <= 0))
947		return EINVAL;
948
949//	listlen = strlen(list);
950	namelen = strlen(name);
951
952	occurrence = find_in_list(occurrence, name);
953
954	if (!occurrence)
955		return EINVAL;
956
957	/* last item in list? */
958	if (occurrence[namelen] == 0)
959	{
960		/* only item in list? */
961		if (occurrence != list)
962			occurrence--;
963		occurrence[0] = 0;
964	}
965	else if (occurrence[namelen] == ' ')
966	{
967		strncpy(occurrence, &occurrence[namelen+1 /* space */],
968		        strlen(&occurrence[namelen+1 /* space */]) +1 /* terminate */);
969	}
970
971	return 0;
972}
973
974/**
975 *		add_to_list
976 *	Add the specified interface(string) to the list as long as
977 *	it will fit in the space left in the list.
978
979 *	NOTE: If item is already in list, it won't be added again.
980
981 *	@param name Name of interface to be added to the list
982 *	@param list List to modify
983 *	@param listsize Max size the list can occupy
984
985 *	@return	error code
986 */
987int
988add_to_list(const char *name, char *list, int listsize)
989{
990	int listlen = 0;
991	int namelen = 0;
992
993	if (!list || !name || (listsize <= 0))
994		return EINVAL;
995
996	listlen = strlen(list);
997	namelen = strlen(name);
998
999	/* is the item already in the list? */
1000	if (find_in_list(list, name))
1001		return 0;
1002
1003	if (listsize <= listlen + namelen + 1 /* space */ + 1 /* NULL */)
1004		return EMSGSIZE;
1005
1006	/* add a space if the list isn't empty and it doesn't already have space */
1007	if (list[0] != 0 && list[listlen-1] != ' ')
1008	{
1009		list[listlen++] = 0x20;
1010	}
1011
1012	strncpy(&list[listlen], name, namelen + 1 /* terminate */);
1013
1014	return 0;
1015}
1016
1017/* Utility function to remove duplicate entries in a space separated list
1018 */
1019
1020char *
1021remove_dups(char *inlist, int inlist_size)
1022{
1023	char name[256], *next = NULL;
1024	char *outlist;
1025
1026	if (!inlist_size)
1027		return NULL;
1028
1029	if (!inlist)
1030		return NULL;
1031
1032	outlist = (char *) malloc(inlist_size);
1033
1034	if (!outlist) return NULL;
1035
1036	memset(outlist, 0, inlist_size);
1037
1038	foreach(name, inlist, next)
1039	{
1040		if (!find_in_list(outlist, name))
1041		{
1042			if (strlen(outlist) == 0)
1043			{
1044				snprintf(outlist, inlist_size, "%s", name);
1045			}
1046			else
1047			{
1048				strncat(outlist, " ", inlist_size - strlen(outlist));
1049				strncat(outlist, name, inlist_size - strlen(outlist));
1050			}
1051		}
1052	}
1053
1054	strncpy(inlist, outlist, inlist_size);
1055
1056	free(outlist);
1057	return inlist;
1058
1059}
1060
1061/* Initialization of strbuf structure */
1062void
1063str_binit(struct strbuf *b, char *buf, unsigned int size)
1064{
1065        b->origsize = b->size = size;
1066        b->origbuf = b->buf = buf;
1067}
1068
1069/* Buffer sprintf wrapper to guard against buffer overflow */
1070int
1071str_bprintf(struct strbuf *b, const char *fmt, ...)
1072{
1073        va_list ap;
1074        int r;
1075
1076        va_start(ap, fmt);
1077
1078        r = vsnprintf(b->buf, b->size, fmt, ap);
1079
1080	/* Non Ansi C99 compliant returns -1,
1081	 * Ansi compliant return r >= b->size,
1082	 * bcmstdlib returns 0, handle all
1083	 */
1084	/* r == 0 is also the case when strlen(fmt) is zero.
1085	 * typically the case when "" is passed as argument.
1086	 */
1087        if ((r == -1) || (r >= (int)b->size)) {
1088                b->size = 0;
1089        } else {
1090                b->size -= r;
1091                b->buf += r;
1092        }
1093
1094        va_end(ap);
1095
1096        return r;
1097}
1098
1099/*
1100	 return true/false if any wireless interface has URE enabled.
1101*/
1102int
1103ure_any_enabled(void)
1104{
1105	return nvram_match("ure_disable", "0");
1106}
1107
1108
1109#define WLMBSS_DEV_NAME	"wlmbss"
1110#define WL_DEV_NAME "wl"
1111#define WDS_DEV_NAME	"wds"
1112
1113/**
1114 *	 nvifname_to_osifname()
1115 *  The intent here is to provide a conversion between the OS interface name
1116 *  and the device name that we keep in NVRAM.
1117 * This should eventually be placed in a Linux specific file with other
1118 * OS abstraction functions.
1119
1120 * @param nvifname pointer to ifname to be converted
1121 * @param osifname_buf storage for the converted osifname
1122 * @param osifname_buf_len length of storage for osifname_buf
1123 */
1124int
1125nvifname_to_osifname(const char *nvifname, char *osifname_buf,
1126                     int osifname_buf_len)
1127{
1128	char varname[NVRAM_MAX_PARAM_LEN];
1129	char *ptr;
1130
1131	/* Bail if we get a NULL or empty string */
1132	if ((!nvifname) || (!*nvifname) || (!osifname_buf)) {
1133		return -1;
1134	}
1135
1136	memset(osifname_buf, 0, osifname_buf_len);
1137
1138	if (strstr(nvifname, "eth") || strstr(nvifname, ".")) {
1139		strncpy(osifname_buf, nvifname, osifname_buf_len);
1140		return 0;
1141	}
1142
1143#ifdef RTCONFIG_RALINK
1144	if (strstr(nvifname, "ra") || strstr(nvifname, ".")) {
1145		strncpy(osifname_buf, nvifname, osifname_buf_len);
1146		return 0;
1147	}
1148#elif defined(RTCONFIG_QCA)
1149	if (strstr(nvifname, "ath") || strstr(nvifname, "wifi")) {
1150		strncpy(osifname_buf, nvifname, osifname_buf_len);
1151		return 0;
1152	}
1153#endif
1154
1155	snprintf(varname, sizeof(varname), "%s_ifname", nvifname);
1156	ptr = nvram_get(varname);
1157	if (ptr) {
1158		/* Bail if the string is empty */
1159		if (!*ptr) return -1;
1160		strncpy(osifname_buf, ptr, osifname_buf_len);
1161		return 0;
1162	}
1163
1164	return -1;
1165}
1166
1167
1168/* osifname_to_nvifname()
1169 * Convert the OS interface name to the name we use internally(NVRAM, GUI, etc.)
1170 * This is the Linux version of this function
1171
1172 * @param osifname pointer to osifname to be converted
1173 * @param nvifname_buf storage for the converted ifname
1174 * @param nvifname_buf_len length of storage for nvifname_buf
1175 */
1176int
1177osifname_to_nvifname(const char *osifname, char *nvifname_buf,
1178                     int nvifname_buf_len)
1179{
1180	char varname[NVRAM_MAX_PARAM_LEN];
1181	int pri, sec;
1182
1183	/* Bail if we get a NULL or empty string */
1184
1185	if ((!osifname) || (!*osifname) || (!nvifname_buf))
1186	{
1187		return -1;
1188	}
1189
1190	memset(nvifname_buf, 0, nvifname_buf_len);
1191
1192	if (strstr(osifname, "wl") || strstr(osifname, "br") ||
1193	     strstr(osifname, "wds")) {
1194		strncpy(nvifname_buf, osifname, nvifname_buf_len);
1195		return 0;
1196	}
1197
1198	/* look for interface name on the primary interfaces first */
1199	for (pri = 0; pri < MAX_NVPARSE; pri++) {
1200		snprintf(varname, sizeof(varname),
1201					"wl%d_ifname", pri);
1202		if (nvram_match(varname, (char *)osifname)) {
1203					snprintf(nvifname_buf, nvifname_buf_len, "wl%d", pri);
1204					return 0;
1205				}
1206	}
1207
1208	/* look for interface name on the multi-instance interfaces */
1209	for (pri = 0; pri < MAX_NVPARSE; pri++)
1210		for (sec = 0; sec < MAX_NVPARSE; sec++) {
1211			snprintf(varname, sizeof(varname),
1212					"wl%d.%d_ifname", pri, sec);
1213			if (nvram_match(varname, (char *)osifname)) {
1214				snprintf(nvifname_buf, nvifname_buf_len, "wl%d.%d", pri, sec);
1215				return 0;
1216			}
1217		}
1218
1219	return -1;
1220}
1221
1222#endif	// #if WL_BSS_INFO_VERSION >= 108
1223
1224/******************************************************************************/
1225/*
1226 *	Add a character to a string buffer
1227 */
1228
1229static void put_char(strbuf_t *buf, char c)
1230{
1231	if (buf->count >= (buf->size - 1)) {
1232		if (! (buf->flags & STR_REALLOC)) {
1233			return;
1234		}
1235		buf->size += STR_INC;
1236		if (buf->size > buf->max && buf->size > STR_INC) {
1237/*
1238 *			Caller should increase the size of the calling buffer
1239 */
1240			buf->size -= STR_INC;
1241			return;
1242		}
1243		if (buf->s == NULL) {
1244			buf->s = balloc(B_L, buf->size * sizeof(char));
1245		} else {
1246			buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char));
1247		}
1248	}
1249	buf->s[buf->count] = c;
1250	if (c != '\0') {
1251		++buf->count;
1252	}
1253}
1254
1255/******************************************************************************/
1256/*
1257 *	Add a string to a string buffer
1258 */
1259
1260static void put_string(strbuf_t *buf, char *s, int len, int width,
1261		int prec, enum flag f)
1262{
1263	int		i;
1264
1265	if (len < 0) {
1266		len = strnlen(s, prec >= 0 ? prec : ULONG_MAX);
1267	} else if (prec >= 0 && prec < len) {
1268		len = prec;
1269	}
1270	if (width > len && !(f & flag_minus)) {
1271		for (i = len; i < width; ++i) {
1272			put_char(buf, ' ');
1273		}
1274	}
1275	for (i = 0; i < len; ++i) {
1276		put_char(buf, s[i]);
1277	}
1278	if (width > len && f & flag_minus) {
1279		for (i = len; i < width; ++i) {
1280			put_char(buf, ' ');
1281		}
1282	}
1283}
1284
1285/******************************************************************************/
1286/*
1287 *	Add a long to a string buffer
1288 */
1289
1290static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
1291		int upper, char *prefix, int width, int prec, enum flag f)
1292{
1293	unsigned long	x, x2;
1294	int				len, zeros, i;
1295
1296	for (len = 1, x = 1; x < ULONG_MAX / base; ++len, x = x2) {
1297		x2 = x * base;
1298		if (x2 > value) {
1299			break;
1300		}
1301	}
1302	zeros = (prec > len) ? prec - len : 0;
1303	width -= zeros + len;
1304	if (prefix != NULL) {
1305		width -= strnlen(prefix, ULONG_MAX);
1306	}
1307	if (!(f & flag_minus)) {
1308		if (f & flag_zero) {
1309			for (i = 0; i < width; ++i) {
1310				put_char(buf, '0');
1311			}
1312		} else {
1313			for (i = 0; i < width; ++i) {
1314				put_char(buf, ' ');
1315			}
1316		}
1317	}
1318	if (prefix != NULL) {
1319		put_string(buf, prefix, -1, 0, -1, flag_none);
1320	}
1321	for (i = 0; i < zeros; ++i) {
1322		put_char(buf, '0');
1323	}
1324	for ( ; x > 0; x /= base) {
1325		int digit = (value / x) % base;
1326		put_char(buf, (char) ((digit < 10 ? '0' : (upper ? 'A' : 'a') - 10) +
1327			digit));
1328	}
1329	if (f & flag_minus) {
1330		for (i = 0; i < width; ++i) {
1331			put_char(buf, ' ');
1332		}
1333	}
1334}
1335
1336/******************************************************************************/
1337/*
1338 *	Dynamic sprintf implementation. Supports dynamic buffer allocation.
1339 *	This function can be called multiple times to grow an existing allocated
1340 *	buffer. In this case, msize is set to the size of the previously allocated
1341 *	buffer. The buffer will be realloced, as required. If msize is set, we
1342 *	return the size of the allocated buffer for use with the next call. For
1343 *	the first call, msize can be set to -1.
1344 */
1345
1346static int dsnprintf(char **s, int size, char *fmt, va_list arg, int msize)
1347{
1348	strbuf_t	buf;
1349	char		c;
1350
1351	assert(s);
1352	assert(fmt);
1353
1354	memset(&buf, 0, sizeof(buf));
1355	buf.s = *s;
1356
1357	if (*s == NULL || msize != 0) {
1358		buf.max = size;
1359		buf.flags |= STR_REALLOC;
1360		if (msize != 0) {
1361			buf.size = max(msize, 0);
1362		}
1363		if (*s != NULL && msize != 0) {
1364			buf.count = strlen(*s);
1365		}
1366	} else {
1367		buf.size = size;
1368	}
1369
1370	while ((c = *fmt++) != '\0') {
1371		if (c != '%' || (c = *fmt++) == '%') {
1372			put_char(&buf, c);
1373		} else {
1374			enum flag f = flag_none;
1375			int width = 0;
1376			int prec = -1;
1377			for ( ; c != '\0'; c = *fmt++) {
1378				if (c == '-') {
1379					f |= flag_minus;
1380				} else if (c == '+') {
1381					f |= flag_plus;
1382				} else if (c == ' ') {
1383					f |= flag_space;
1384				} else if (c == '#') {
1385					f |= flag_hash;
1386				} else if (c == '0') {
1387					f |= flag_zero;
1388				} else {
1389					break;
1390				}
1391			}
1392			if (c == '*') {
1393				width = va_arg(arg, int);
1394				if (width < 0) {
1395					f |= flag_minus;
1396					width = -width;
1397				}
1398				c = *fmt++;
1399			} else {
1400				for ( ; isdigit((int)c); c = *fmt++) {
1401					width = width * 10 + (c - '0');
1402				}
1403			}
1404			if (c == '.') {
1405				f &= ~flag_zero;
1406				c = *fmt++;
1407				if (c == '*') {
1408					prec = va_arg(arg, int);
1409					c = *fmt++;
1410				} else {
1411					for (prec = 0; isdigit((int)c); c = *fmt++) {
1412						prec = prec * 10 + (c - '0');
1413					}
1414				}
1415			}
1416			if (c == 'h' || c == 'l') {
1417				f |= (c == 'h' ? flag_short : flag_long);
1418				c = *fmt++;
1419			}
1420			if (c == 'd' || c == 'i') {
1421				long int value;
1422				if (f & flag_short) {
1423					value = (short int) va_arg(arg, int);
1424				} else if (f & flag_long) {
1425					value = va_arg(arg, long int);
1426				} else {
1427					value = va_arg(arg, int);
1428				}
1429				if (value >= 0) {
1430					if (f & flag_plus) {
1431						put_ulong(&buf, value, 10, 0, ("+"), width, prec, f);
1432					} else if (f & flag_space) {
1433						put_ulong(&buf, value, 10, 0, (" "), width, prec, f);
1434					} else {
1435						put_ulong(&buf, value, 10, 0, NULL, width, prec, f);
1436					}
1437				} else {
1438					put_ulong(&buf, -value, 10, 0, ("-"), width, prec, f);
1439				}
1440			} else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
1441				unsigned long int value;
1442				if (f & flag_short) {
1443					value = (unsigned short int) va_arg(arg, unsigned int);
1444				} else if (f & flag_long) {
1445					value = va_arg(arg, unsigned long int);
1446				} else {
1447					value = va_arg(arg, unsigned int);
1448				}
1449				if (c == 'o') {
1450					if (f & flag_hash && value != 0) {
1451						put_ulong(&buf, value, 8, 0, ("0"), width, prec, f);
1452					} else {
1453						put_ulong(&buf, value, 8, 0, NULL, width, prec, f);
1454					}
1455				} else if (c == 'u') {
1456					put_ulong(&buf, value, 10, 0, NULL, width, prec, f);
1457				} else {
1458					if (f & flag_hash && value != 0) {
1459						if (c == 'x') {
1460							put_ulong(&buf, value, 16, 0, ("0x"), width,
1461								prec, f);
1462						} else {
1463							put_ulong(&buf, value, 16, 1, ("0X"), width,
1464								prec, f);
1465						}
1466					} else {
1467                  /* 04 Apr 02 BgP -- changed so that %X correctly outputs
1468                   * uppercase hex digits when requested.
1469						put_ulong(&buf, value, 16, 0, NULL, width, prec, f);
1470                   */
1471						put_ulong(&buf, value, 16, ('X' == c) , NULL, width, prec, f);
1472					}
1473				}
1474
1475			} else if (c == 'c') {
1476				char value = va_arg(arg, int);
1477				put_char(&buf, value);
1478
1479			} else if (c == 's' || c == 'S') {
1480				char *value = va_arg(arg, char *);
1481				if (value == NULL) {
1482					put_string(&buf, ("(null)"), -1, width, prec, f);
1483				} else if (f & flag_hash) {
1484					put_string(&buf,
1485						value + 1, (char) *value, width, prec, f);
1486				} else {
1487					put_string(&buf, value, -1, width, prec, f);
1488				}
1489			} else if (c == 'p') {
1490				void *value = va_arg(arg, void *);
1491				put_ulong(&buf,
1492					(unsigned long int) value, 16, 0, ("0x"), width, prec, f);
1493			} else if (c == 'n') {
1494				if (f & flag_short) {
1495					short int *value = va_arg(arg, short int *);
1496					*value = buf.count;
1497				} else if (f & flag_long) {
1498					long int *value = va_arg(arg, long int *);
1499					*value = buf.count;
1500				} else {
1501					int *value = va_arg(arg, int *);
1502					*value = buf.count;
1503				}
1504			} else {
1505				put_char(&buf, c);
1506			}
1507		}
1508	}
1509	if (buf.s == NULL) {
1510		put_char(&buf, '\0');
1511	}
1512
1513/*
1514 *	If the user requested a dynamic buffer (*s == NULL), ensure it is returned.
1515 */
1516	if (*s == NULL || msize != 0) {
1517		*s = buf.s;
1518	}
1519
1520	if (*s != NULL && size > 0) {
1521		if (buf.count < size) {
1522			(*s)[buf.count] = '\0';
1523		} else {
1524			(*s)[buf.size - 1] = '\0';
1525		}
1526	}
1527
1528	if (msize != 0) {
1529		return buf.size;
1530	}
1531	return buf.count;
1532}
1533
1534/******************************************************************************/
1535/*
1536 *	sprintf and vsprintf are bad, ok. You can easily clobber memory. Use
1537 *	fmtAlloc and fmtValloc instead! These functions do _not_ support floating
1538 *	point, like %e, %f, %g...
1539 */
1540
1541int fmtAlloc(char **s, int n, char *fmt, ...)
1542{
1543	va_list	ap;
1544	int		result;
1545
1546	assert(s);
1547	assert(fmt);
1548
1549	*s = NULL;
1550	va_start(ap, fmt);
1551	result = dsnprintf(s, n, fmt, ap, 0);
1552	va_end(ap);
1553	return result;
1554}
1555
1556/******************************************************************************/
1557/*
1558 *	A vsprintf replacement.
1559 */
1560
1561int fmtValloc(char **s, int n, char *fmt, va_list arg)
1562{
1563	assert(s);
1564	assert(fmt);
1565
1566	*s = NULL;
1567	return dsnprintf(s, n, fmt, arg, 0);
1568}
1569
1570/*
1571 *  * description: parse va and do system
1572 *  */
1573int doSystem(char *fmt, ...)
1574{
1575	va_list		vargs;
1576	char		*cmd = NULL;
1577	int 		rc = 0;
1578	#define CMD_BUFSIZE 256
1579	va_start(vargs, fmt);
1580	if (fmtValloc(&cmd, CMD_BUFSIZE, fmt, vargs) >= CMD_BUFSIZE) {
1581		fprintf(stderr, "doSystem: lost data, buffer overflow\n");
1582	}
1583	va_end(vargs);
1584
1585	if(cmd) {
1586		if (!strncmp(cmd, "iwpriv", 6))
1587			_dprintf("[doSystem] %s\n", cmd);
1588		rc = system(cmd);
1589		bfree(B_L, cmd);
1590	}
1591	return rc;
1592}
1593
1594int
1595swap_check()
1596{
1597	struct sysinfo info;
1598
1599	sysinfo(&info);
1600
1601	if(info.totalswap > 0)
1602		return 1;
1603	else	return 0;
1604}
1605
1606// -----------------------------------------------------------------------------
1607
1608/*
1609 * Kills process whose PID is stored in plaintext in pidfile
1610 * @param	pidfile	PID file
1611 * @return	0 on success and errno on failure
1612 */
1613
1614int kill_pidfile(char *pidfile)
1615{
1616	FILE *fp;
1617	char buf[256];
1618
1619	if ((fp = fopen(pidfile, "r")) != NULL) {
1620		if (fgets(buf, sizeof(buf), fp)) {
1621			pid_t pid = strtoul(buf, NULL, 0);
1622			fclose(fp);
1623			return kill(pid, SIGTERM);
1624		}
1625		fclose(fp);
1626  	}
1627	return errno;
1628}
1629
1630
1631int kill_pidfile_s(char *pidfile, int sig)
1632{
1633	FILE *fp;
1634	char buf[256];
1635
1636	if ((fp = fopen(pidfile, "r")) != NULL) {
1637		if (fgets(buf, sizeof(buf), fp)) {
1638			pid_t pid = strtoul(buf, NULL, 0);
1639			fclose(fp);
1640			return kill(pid, sig);
1641		}
1642		fclose(fp);
1643  	}
1644	return errno;
1645}
1646
1647int kill_pidfile_s_rm(char *pidfile, int sig)
1648{
1649	FILE *fp;
1650	char buf[256];
1651
1652	if ((fp = fopen(pidfile, "r")) != NULL) {
1653		if (fgets(buf, sizeof(buf), fp)) {
1654			pid_t pid = strtoul(buf, NULL, 0);
1655			fclose(fp);
1656			unlink(pidfile);
1657			return kill(pid, sig);
1658		}
1659		fclose(fp);
1660	}
1661	return errno;
1662}
1663
1664long uptime(void)
1665{
1666	struct sysinfo info;
1667	sysinfo(&info);
1668
1669	return info.uptime;
1670}
1671
1672int _vstrsep(char *buf, const char *sep, ...)
1673{
1674	va_list ap;
1675	char **p;
1676	int n;
1677
1678	n = 0;
1679	va_start(ap, sep);
1680	while ((p = va_arg(ap, char **)) != NULL) {
1681		if ((*p = strsep(&buf, sep)) == NULL) break;
1682		++n;
1683	}
1684	va_end(ap);
1685	return n;
1686}
1687
1688#ifdef CONFIG_BCMWL5
1689char *
1690wl_ether_etoa(const struct ether_addr *n)
1691{
1692	static char etoa_buf[ETHER_ADDR_LEN * 3];
1693	char *c = etoa_buf;
1694	int i;
1695
1696	for (i = 0; i < ETHER_ADDR_LEN; i++) {
1697		if (i)
1698			*c++ = ':';
1699		c += sprintf(c, "%02X", n->octet[i] & 0xff);
1700	}
1701	return etoa_buf;
1702}
1703#endif
1704
1705void
1706shortstr_encrypt(unsigned char *src, unsigned char *dst, unsigned char *shift)
1707{
1708    unsigned char carry, temp, bytes, bits;
1709    int i;
1710
1711    bytes = (*shift % (DATA_WORDS_LEN - 1)) + 1;
1712    for(i=0; i<DATA_WORDS_LEN; i++) {
1713        dst[(i + bytes) % DATA_WORDS_LEN] = src[i];
1714    }
1715
1716    carry = 0;
1717    bits = (*shift % 7) + 1;
1718    for(i=0; i<DATA_WORDS_LEN; i++) {
1719        temp = dst[i] << (8 - bits);
1720        dst[i] = (dst[i] >> bits) | carry;
1721        carry = temp;
1722    }
1723    dst[0] |= carry;
1724
1725    for(i=0; i<DATA_WORDS_LEN; i++) {
1726        dst[i] ^= ENC_XOR + i * 5;
1727    }
1728}
1729
1730void
1731shortstr_decrypt(unsigned char *src, unsigned char *dst, unsigned char shift)
1732{
1733    unsigned char carry, temp, bytes, bits;
1734    int i;
1735
1736    for(i=0; i<DATA_WORDS_LEN; i++) {
1737        src[i] ^= ENC_XOR + i * 5;
1738    }
1739    carry = 0;
1740    bits = (shift % 7) + 1;
1741    for(i=DATA_WORDS_LEN - 1; i>=0; i--) {
1742        temp = src[i] >> (8 - bits);
1743        src[i] = (src[i] << bits) | carry;
1744        carry = temp;
1745    }
1746    src[DATA_WORDS_LEN - 1] |= carry;
1747
1748    bytes = (shift % (DATA_WORDS_LEN - 1)) + 1;
1749    for(i=0; i<DATA_WORDS_LEN; i++) {
1750        dst[i] = src[(i + bytes) % DATA_WORDS_LEN];
1751    }
1752
1753    dst[DATA_WORDS_LEN] = 0;
1754}
1755
1756
1757char *enc_str(char *str, char *enc_buf)
1758{
1759        unsigned char buf[DATA_WORDS_LEN + 1];
1760        unsigned char buf2[DATA_WORDS_LEN + 1];
1761
1762        memset(buf, 0, sizeof(buf));
1763        memset(buf2, 0, sizeof(buf2));
1764        memset(enc_buf, 0, sizeof(enc_buf));
1765
1766        strcpy(buf, str);
1767
1768        shortstr_encrypt(buf, buf2, &used_shift);
1769        memcpy(enc_buf, buf2, DATA_WORDS_LEN);
1770        enc_buf[DATA_WORDS_LEN] = used_shift;
1771
1772        return enc_buf;
1773}
1774
1775char *dec_str(char *ec_str, char *dec_buf)
1776{
1777        unsigned char buf[DATA_WORDS_LEN + 1];
1778
1779        memset(buf, 0, sizeof(buf));
1780        memset(dec_buf, 0, sizeof(dec_buf));
1781        memcpy(buf, ec_str, DATA_WORDS_LEN+1);
1782        buf[DATA_WORDS_LEN] = 0;
1783        shortstr_decrypt(buf, dec_buf, used_shift);
1784
1785        return dec_buf;
1786}
1787
1788int
1789strArgs(int argc, char **argv, char *fmt, ...)
1790{
1791	va_list	ap;
1792	int arg;
1793	char *c;
1794
1795	if (!argv)
1796		return 0;
1797
1798	va_start(ap, fmt);
1799	for (arg = 0, c = fmt; c && *c && arg < argc;) {
1800		if (*c++ != '%')
1801			continue;
1802		switch (*c) {
1803		case 'd':
1804			*(va_arg(ap, int *)) = atoi(argv[arg]);
1805			break;
1806		case 's':
1807			*(va_arg(ap, char **)) = argv[arg];
1808			break;
1809		}
1810		arg++;
1811	}
1812	va_end(ap);
1813
1814	return arg;
1815}
1816
1817/**
1818** trimNL()
1819** trim trailing new line character(including '\r' and '\n')
1820**/
1821char *trimNL(char *str)
1822{
1823	int len = 0;
1824
1825	if(!str)
1826	{
1827		return NULL;
1828	}
1829
1830	len = strlen(str);
1831
1832	while((len!=0)&&((str[len-1] == '\r' || str[len-1] == '\n')))
1833	{
1834		len--;
1835	}
1836	str[len] = '\0';
1837	return str;
1838}
1839
1840char *get_process_name_by_pid(const int pid)
1841{
1842	static char name[1024];
1843	sprintf(name, "/proc/%d/cmdline",pid);
1844	FILE* f = fopen(name,"r");
1845	if(f){
1846		size_t size;
1847		size = fread(name, sizeof(char), 1024, f);
1848		if(size>0){
1849			if('\n'==name[size-1])
1850			name[size-1]='\0';
1851		}
1852		else memset(name, 0, 1024);
1853		fclose(f);
1854	}
1855	else memset(name, 0, 1024);
1856	return name;
1857}
1858