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