1/*
2 * Shell-like utility functions
3 *
4 * Copyright 2005, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id: shutils.h,v 1.8 2005/03/07 08:35:32 kanki Exp $
13 */
14
15#ifndef _shutils_h_
16#define _shutils_h_
17#include <string.h>
18#include <rtconfig.h>
19
20#ifndef MAX_NVPARSE
21#define MAX_NVPARSE 16
22#endif
23#define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
24
25#ifndef max
26#define max(a,b)  (((a) > (b)) ? (a) : (b))
27#endif /* max */
28
29#ifndef min
30#define min(a,b)  (((a) < (b)) ? (a) : (b))
31#endif /* min */
32
33#define ENC_XOR     (0x74)
34#define DATA_WORDS_LEN (120)
35#define ENC_WORDS_LEN  (384)
36
37extern int doSystem(char *fmt, ...);
38
39/*
40 * Reads file and returns contents
41 * @param	fd	file descriptor
42 * @return	contents of file or NULL if an error occurred
43 */
44extern char * fd2str(int fd);
45
46/*
47 * Reads file and returns contents
48 * @param	path	path to file
49 * @return	contents of file or NULL if an error occurred
50 */
51extern char * file2str(const char *path);
52
53/*
54 * Waits for a file descriptor to become available for reading or unblocked signal
55 * @param	fd	file descriptor
56 * @param	timeout	seconds to wait before timing out or 0 for no timeout
57 * @return	1 if descriptor changed status or 0 if timed out or -1 on error
58 */
59extern int waitfor(int fd, int timeout);
60
61/*
62 * Concatenates NULL-terminated list of arguments into a single
63 * commmand and executes it
64 * @param	argv	argument list
65 * @param	path	NULL, ">output", or ">>output"
66 * @param	timeout	seconds to wait before timing out or 0 for no timeout
67 * @param	ppid	NULL to wait for child termination or pointer to pid
68 * @return	return value of executed command or errno
69 */
70extern int _eval(char *const argv[], const char *path, int timeout, pid_t *ppid);
71
72/*
73 * Evaluate cmds using taskset while SMP.
74 * @param	ppid	NULL to wait for child termination or pointer to pid
75 * @param	cmds	command argument list
76 * The normal command elements protype is as [cpu0/cpu1], [cmd_arg0, cmd_arg1, ..., NULL]
77 * If smp defined, it should specify cpu0/cpu1 at the fist element,
78 * if it is not specified, cpu0 will be the default choice.
79 * On UP case, no need to specify cpu0/1, otherwise will be ignored.
80 */
81#define CPU0	"0"
82#define CPU1	"1"
83
84extern int _cpu_eval(int *ppid, char *cmds[]);
85
86/*
87 * Concatenates NULL-terminated list of arguments into a single
88 * commmand and executes it
89 * @param	argv	argument list
90 * @return	stdout of executed command or NULL if an error occurred
91 */
92//	extern char * _backtick(char *const argv[]);
93
94/*
95 * Kills process whose PID is stored in plaintext in pidfile
96 * @param	pidfile	PID file
97 * @return	0 on success and errno on failure
98 */
99extern int kill_pidfile(char *pidfile);
100extern int kill_pidfile_s(char *pidfile, int sig);
101extern int kill_pidfile_s_rm(char *pidfile, int sig);
102
103/*
104 * fread() with automatic retry on syscall interrupt
105 * @param	ptr	location to store to
106 * @param	size	size of each element of data
107 * @param	nmemb	number of elements
108 * @param	stream	file stream
109 * @return	number of items successfully read
110 */
111extern int safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
112
113/*
114 * fwrite() with automatic retry on syscall interrupt
115 * @param	ptr	location to read from
116 * @param	size	size of each element of data
117 * @param	nmemb	number of elements
118 * @param	stream	file stream
119 * @return	number of items successfully written
120 */
121extern int safe_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
122
123/*
124 * Convert Ethernet address string representation to binary data
125 * @param	a	string in xx:xx:xx:xx:xx:xx notation
126 * @param	e	binary data
127 * @return	TRUE if conversion was successful and FALSE otherwise
128 */
129extern int ether_atoe(const char *a, unsigned char *e);
130
131/*
132 * Convert Ethernet address binary data to string representation
133 * @param	e	binary data
134 * @param	a	string in xx:xx:xx:xx:xx:xx notation
135 * @return	a
136 */
137extern char * ether_etoa(const unsigned char *e, char *a);
138
139/*
140 * Concatenate two strings together into a caller supplied buffer
141 * @param	s1	first string
142 * @param	s2	second string
143 * @param	buf	buffer large enough to hold both strings
144 * @return	buf
145 */
146static inline char * strcat_r(const char *s1, const char *s2, char *buf)
147{
148	strcpy(buf, s1);
149	strcat(buf, s2);
150	return buf;
151}
152
153/* Strip trailing CR/NL from string <s> */
154#define chomp(s) ({ \
155	char *c = (s) + strlen((s)) - 1; \
156	while ((c > (s)) && (*c == '\n' || *c == '\r' || *c == ' ')) \
157		*c-- = '\0'; \
158	s; \
159})
160
161
162/* Simple version of _eval() (no timeout and wait for child termination) */
163#if 1
164#define eval(cmd, args...) ({ \
165	char * const argv[] = { cmd, ## args, NULL }; \
166	_eval(argv, NULL, 0, NULL); \
167})
168#else
169#define eval(cmd, args...) ({ \
170	char * const argv[] = { cmd, ## args, NULL }; \
171	_eval(argv, ">/dev/console", 0, NULL); \
172})
173#endif
174
175/* another _cpu_eval form */
176#define cpu_eval(ppid, cmd, args...) ({ \
177	char * argv[] = { cmd, ## args, NULL }; \
178	_cpu_eval(ppid, argv); \
179})
180
181/* Copy each token in wordlist delimited by space into word */
182#define foreach(word, wordlist, next) \
183		for (next = &wordlist[strspn(wordlist, " ")], \
184				strncpy(word, next, sizeof(word)), \
185				word[strcspn(word, " ")] = '\0', \
186				word[sizeof(word) - 1] = '\0', \
187				next = strchr(next, ' '); \
188				strlen(word); \
189				next = next ? &next[strspn(next, " ")] : "", \
190				strncpy(word, next, sizeof(word)), \
191				word[strcspn(word, " ")] = '\0', \
192				word[sizeof(word) - 1] = '\0', \
193				next = strchr(next, ' '))
194
195/* Copy each token in wordlist delimited by ascii_44 into word */
196#define foreach_44(word, wordlist, next) \
197		for (next = &wordlist[strspn(wordlist, ",")], \
198				strncpy(word, next, sizeof(word)), \
199				word[strcspn(word, ",")] = '\0', \
200				word[sizeof(word) - 1] = '\0', \
201				next = strchr(next, ','); \
202				strlen(word); \
203				next = next ? &next[strspn(next, ",")] : "", \
204				strncpy(word, next, sizeof(word)), \
205				word[strcspn(word, ",")] = '\0', \
206				word[sizeof(word) - 1] = '\0', \
207				next = strchr(next, ','))
208
209/* Copy each token in wordlist delimited by ascii_58 into word */
210#define foreach_58(word, wordlist, next) \
211		for (next = &wordlist[strspn(wordlist, ":")], \
212				strncpy(word, next, sizeof(word)), \
213				word[strcspn(word, ":")] = '\0', \
214				word[sizeof(word) - 1] = '\0', \
215				next = strchr(next, ':'); \
216				strlen(word); \
217				next = next ? &next[strspn(next, ":")] : "", \
218				strncpy(word, next, sizeof(word)), \
219				word[strcspn(word, ":")] = '\0', \
220				word[sizeof(word) - 1] = '\0', \
221				next = strchr(next, ':'))
222
223/* Copy each token in wordlist delimited by ascii_60 into word */
224#define foreach_60(word, wordlist, next) \
225		for (next = &wordlist[strspn(wordlist, "<")], \
226				strncpy(word, next, sizeof(word)), \
227				word[strcspn(word, "<")] = '\0', \
228				word[sizeof(word) - 1] = '\0', \
229				next = strchr(next, '<'); \
230				strlen(word); \
231				next = next ? &next[strspn(next, "<")] : "", \
232				strncpy(word, next, sizeof(word)), \
233				word[strcspn(word, "<")] = '\0', \
234				word[sizeof(word) - 1] = '\0', \
235				next = strchr(next, '<'))
236
237/* Copy each token in wordlist delimited by ascii_62 into word */
238#define foreach_62(word, wordlist, next) \
239		for (next = &wordlist[strspn(wordlist, ">")], \
240				strncpy(word, next, sizeof(word)), \
241				word[strcspn(word, ">")] = '\0', \
242				word[sizeof(word) - 1] = '\0', \
243				next = strchr(next, '>'); \
244				strlen(word); \
245				next = next ? &next[strspn(next, ">")] : "", \
246				strncpy(word, next, sizeof(word)), \
247				word[strcspn(word, ">")] = '\0', \
248				word[sizeof(word) - 1] = '\0', \
249				next = strchr(next, '>'))
250
251/* Return NUL instead of NULL if undefined */
252#define safe_getenv(s) (getenv(s) ? : "")
253
254#define ONE_ENTRANT()                               \
255do {                                                            \
256	static int served = 0;  \
257	if(served ++ > 0)       \
258		return;         \
259} while (0)
260
261//#define dbg(fmt, args...) do { FILE *fp = fopen("/dev/console", "w"); if (fp) { fprintf(fp, fmt, ## args); fclose(fp); } else fprintf(stderr, fmt, ## args); } while (0)
262extern void dbg(const char * format, ...);
263#define dbG(fmt, args...) dbg("%s(0x%04x): " fmt , __FUNCTION__ , __LINE__, ## args)
264extern void cprintf(const char *format, ...);
265
266
267/*
268 * Parse the unit and subunit from an interface string such as wlXX or wlXX.YY
269 *
270 * @param	ifname	interface string to parse
271 * @param	unit	pointer to return the unit number, may pass NULL
272 * @param	subunit	pointer to return the subunit number, may pass NULL
273 * @return	Returns 0 if the string ends with digits or digits.digits, -1 otherwise.
274 *		If ifname ends in digits.digits, then unit and subuint are set
275 *		to the first and second values respectively. If ifname ends
276 *		in just digits, unit is set to the value, and subunit is set
277 *		to -1. On error both unit and subunit are -1. NULL may be passed
278 *		for unit and/or subuint to ignore the value.
279 */
280extern int get_ifname_unit(const char* ifname, int *unit, int *subunit);
281
282/*
283 * Set the ip configuration index given the eth name
284 * Updates both wlXX_ipconfig_index and lanYY_ifname.
285 *
286 * @param	eth_ifname 	pointer to eth interface name
287 * @return	0 if successful -1 if not.
288 */
289extern int set_ipconfig_index(char *eth_ifname, int index);
290
291/*
292 * Get the ip configuration index if it exists given the
293 * eth name.
294 *
295 * @param	wl_ifname 	pointer to eth interface name
296 * @return	index or -1 if not found
297 */
298extern int get_ipconfig_index(char *eth_ifname);
299
300/*
301 * Get interfaces belonging to a specific bridge.
302 *
303 * @param	bridge_name 	pointer to bridge interface name
304 * @return	list on interfaces beloging to the bridge
305 */
306extern char *
307get_bridged_interfaces(char *bridge_name);
308
309/*
310		remove_from_list
311		Remove the specified word from the list.
312
313		@param name word to be removed from the list
314		@param list List to modify
315		@param listsize Max size the list can occupy
316
317		@return	error code
318*/
319extern int remove_from_list(const char *name, char *list, int listsize);
320
321/*
322		add_to_list
323		Add the specified interface(string) to the list as long as
324		it will fit in the space left in the list.
325
326		@param name Name of interface to be added to the list
327		@param list List to modify
328		@param listsize Max size the list can occupy
329
330		@return	error code
331*/
332extern int add_to_list(const char *name, char *list, int listsize);
333
334extern char *find_in_list(const char *haystack, const char *needle);
335
336extern char *remove_dups(char *inlist, int inlist_size);
337
338extern int nvifname_to_osifname(const char *nvifname, char *osifname_buf,
339				int osifname_buf_len);
340extern int osifname_to_nvifname(const char *osifname, char *nvifname_buf,
341				int nvifname_buf_len);
342
343int ure_any_enabled(void);
344
345#define is_hwnat_loaded() module_loaded("hw_nat")
346
347#define vstrsep(buf, sep, args...) _vstrsep(buf, sep, args, NULL)
348extern int _vstrsep(char *buf, const char *sep, ...);
349
350/* Buffer structure for collecting string-formatted data
351 * using str_bprintf() API.
352 * Use str_binit() to initialize before use
353 */
354struct strbuf {
355        char *buf;              /* pointer to current position in origbuf */
356        unsigned int size;      /* current (residual) size in bytes */
357        char *origbuf;          /* unmodified pointer to orignal buffer */
358        unsigned int origsize;  /* unmodified orignal buffer size in bytes */
359};
360
361extern void str_binit(struct strbuf *b, char *buf, unsigned int size);
362extern int str_bprintf(struct strbuf *b, const char *fmt, ...);
363
364#endif /* _shutils_h_ */
365
366extern int strArgs(int argc, char **argv, char *fmt, ...);
367extern char *trimNL(char *str);
368extern pid_t get_pid_by_name(char *name);
369extern char *get_process_name_by_pid(const int pid);
370