You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

719 lines
15 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2007-2008 by Øyvind Harboe *
  3. * *
  4. * This program is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 2 of the License, or *
  7. * (at your option) any later version. *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. /* this file contains various functionality useful to standalone systems */
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "log.h"
  24. #include "time_support.h"
  25. #ifdef HAVE_ARPA_INET_H
  26. #include <arpa/inet.h>
  27. #endif
  28. #ifdef HAVE_DIRENT_H
  29. #include <dirent.h>
  30. #endif
  31. #ifdef HAVE_NETDB_H
  32. #include <netdb.h>
  33. #endif
  34. #ifdef HAVE_NET_IF_H
  35. #include <net/if.h>
  36. #endif
  37. //#ifdef HAVE_NETINET_TCP_H
  38. //#include <netinet/tcp.h>
  39. //#endif
  40. #ifdef HAVE_SYS_IOCTL_H
  41. #include <sys/ioctl.h>
  42. #endif
  43. #ifdef HAVE_SYS_STAT_H
  44. #include <sys/stat.h>
  45. #endif
  46. #ifdef HAVE_IFADDRS_H
  47. #include <ifaddrs.h>
  48. #endif
  49. #ifdef HAVE_MALLOC_H
  50. #if !BUILD_ECOSBOARD
  51. #include <malloc.h>
  52. #endif
  53. #endif
  54. //#ifdef HAVE_STRINGS_H
  55. //#include <strings.h>
  56. //#endif
  57. int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
  58. char **args, int argc)
  59. {
  60. if (argc != 1)
  61. {
  62. command_print(cmd_ctx, "rm <filename>");
  63. return ERROR_INVALID_ARGUMENTS;
  64. }
  65. if (unlink(args[0]) != 0)
  66. {
  67. command_print(cmd_ctx, "failed: %d", errno);
  68. }
  69. return ERROR_OK;
  70. }
  71. /* loads a file and returns a pointer to it in memory. The file contains
  72. * a 0 byte(sentinel) after len bytes - the length of the file. */
  73. int loadFile(const char *fileName, void **data, size_t *len)
  74. {
  75. // ensure returned length is always sane
  76. *len = 0;
  77. FILE * pFile;
  78. pFile = fopen(fileName,"rb");
  79. if (pFile==NULL)
  80. {
  81. LOG_ERROR("Can't open %s\n", fileName);
  82. return ERROR_FAIL;
  83. }
  84. if (fseek(pFile, 0, SEEK_END)!=0)
  85. {
  86. LOG_ERROR("Can't open %s\n", fileName);
  87. fclose(pFile);
  88. return ERROR_FAIL;
  89. }
  90. long fsize = ftell(pFile);
  91. if (fsize == -1)
  92. {
  93. LOG_ERROR("Can't open %s\n", fileName);
  94. fclose(pFile);
  95. return ERROR_FAIL;
  96. }
  97. *len = fsize;
  98. if (fseek(pFile, 0, SEEK_SET)!=0)
  99. {
  100. LOG_ERROR("Can't open %s\n", fileName);
  101. fclose(pFile);
  102. return ERROR_FAIL;
  103. }
  104. *data = malloc(*len + 1);
  105. if (*data==NULL)
  106. {
  107. LOG_ERROR("Can't open %s\n", fileName);
  108. fclose(pFile);
  109. return ERROR_FAIL;
  110. }
  111. if (fread(*data, 1, *len, pFile)!=*len)
  112. {
  113. fclose(pFile);
  114. free(*data);
  115. LOG_ERROR("Can't open %s\n", fileName);
  116. return ERROR_FAIL;
  117. }
  118. fclose(pFile);
  119. // 0-byte after buffer (not included in *len) serves as a sentinel
  120. char *buf = (char *)*data;
  121. buf[*len] = 0;
  122. return ERROR_OK;
  123. }
  124. int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
  125. char **args, int argc)
  126. {
  127. if (argc != 1)
  128. {
  129. command_print(cmd_ctx, "cat <filename>");
  130. return ERROR_INVALID_ARGUMENTS;
  131. }
  132. // NOTE!!! we only have line printing capability so we print the entire file as a single line.
  133. void *data;
  134. size_t len;
  135. int retval = loadFile(args[0], &data, &len);
  136. if (retval == ERROR_OK)
  137. {
  138. command_print(cmd_ctx, "%s", data);
  139. free(data);
  140. }
  141. else
  142. {
  143. command_print(cmd_ctx, "%s not found %d", args[0], retval);
  144. }
  145. return ERROR_OK;
  146. }
  147. int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
  148. char **args, int argc)
  149. {
  150. if (argc != 1)
  151. {
  152. command_print(cmd_ctx, "trunc <filename>");
  153. return ERROR_INVALID_ARGUMENTS;
  154. }
  155. FILE *config_file = NULL;
  156. config_file = fopen(args[0], "w");
  157. if (config_file != NULL)
  158. fclose(config_file);
  159. return ERROR_OK;
  160. }
  161. int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
  162. {
  163. static int prev = 0;
  164. struct mallinfo info;
  165. if (argc != 0)
  166. {
  167. command_print(cmd_ctx, "meminfo");
  168. return ERROR_INVALID_ARGUMENTS;
  169. }
  170. info = mallinfo();
  171. if (prev > 0)
  172. {
  173. command_print(cmd_ctx, "Diff: %d", prev - info.fordblks);
  174. }
  175. prev = info.fordblks;
  176. command_print(cmd_ctx, "Available ram: %d", info.fordblks );
  177. return ERROR_OK;
  178. }
  179. int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
  180. char **args, int argc)
  181. {
  182. if (argc < 1)
  183. {
  184. command_print(cmd_ctx,
  185. "append <filename> [<string1>, [<string2>, ...]]");
  186. return ERROR_INVALID_ARGUMENTS;
  187. }
  188. int retval=ERROR_FAIL;
  189. FILE *config_file = NULL;
  190. config_file = fopen(args[0], "a");
  191. if (config_file != NULL)
  192. {
  193. int i;
  194. fseek(config_file, 0, SEEK_END);
  195. for (i = 1; i < argc; i++)
  196. {
  197. if (fwrite(args[i], strlen(args[i]), 1, config_file)!=strlen(args[i]))
  198. break;
  199. if (i != argc - 1)
  200. {
  201. if (fwrite(" ", 1, 1, config_file)!=1)
  202. break;
  203. }
  204. }
  205. if ((i==argc)&&(fwrite("\n", 1, 1, config_file)==1))
  206. {
  207. retval=ERROR_OK;
  208. }
  209. fclose(config_file);
  210. }
  211. return retval;
  212. }
  213. int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
  214. {
  215. if (argc != 2)
  216. {
  217. return ERROR_INVALID_ARGUMENTS;
  218. }
  219. // NOTE!!! we only have line printing capability so we print the entire file as a single line.
  220. void *data;
  221. size_t len;
  222. int retval = loadFile(args[0], &data, &len);
  223. if (retval != ERROR_OK)
  224. return retval;
  225. FILE *f = fopen(args[1], "wb");
  226. if (f == NULL)
  227. retval = ERROR_INVALID_ARGUMENTS;
  228. size_t pos = 0;
  229. for (;;)
  230. {
  231. size_t chunk = len - pos;
  232. static const size_t maxChunk = 512 * 1024; // ~1/sec
  233. if (chunk > maxChunk)
  234. {
  235. chunk = maxChunk;
  236. }
  237. if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
  238. retval = ERROR_INVALID_ARGUMENTS;
  239. if (retval != ERROR_OK)
  240. {
  241. break;
  242. }
  243. command_print(cmd_ctx, "%d", len - pos);
  244. pos += chunk;
  245. if (pos == len)
  246. break;
  247. }
  248. if (retval == ERROR_OK)
  249. {
  250. command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
  251. } else
  252. {
  253. command_print(cmd_ctx, "Failed: %d", retval);
  254. }
  255. if (data != NULL)
  256. free(data);
  257. if (f != NULL)
  258. fclose(f);
  259. if (retval != ERROR_OK)
  260. unlink(args[1]);
  261. return retval;
  262. }
  263. #define SHOW_RESULT(a, b) LOG_ERROR(#a " failed %d\n", (int)b)
  264. #define IOSIZE 512
  265. void copyfile(char *name2, char *name1)
  266. {
  267. int err;
  268. char buf[IOSIZE];
  269. int fd1, fd2;
  270. ssize_t done, wrote;
  271. fd1 = open(name1, O_WRONLY | O_CREAT);
  272. if (fd1 < 0)
  273. SHOW_RESULT( open, fd1 );
  274. fd2 = open(name2, O_RDONLY);
  275. if (fd2 < 0)
  276. SHOW_RESULT( open, fd2 );
  277. for (;;)
  278. {
  279. done = read(fd2, buf, IOSIZE );
  280. if (done < 0)
  281. {
  282. SHOW_RESULT( read, done );
  283. break;
  284. }
  285. if( done == 0 ) break;
  286. wrote = write(fd1, buf, done);
  287. if( wrote != done ) SHOW_RESULT( write, wrote );
  288. if( wrote != done ) break;
  289. }
  290. err = close(fd1);
  291. if( err < 0 ) SHOW_RESULT( close, err );
  292. err = close(fd2);
  293. if( err < 0 ) SHOW_RESULT( close, err );
  294. }
  295. /* utility fn to copy a directory */
  296. void copydir(char *name, char *destdir)
  297. {
  298. int err;
  299. DIR *dirp;
  300. dirp = opendir(destdir);
  301. if (dirp==NULL)
  302. {
  303. mkdir(destdir, 0777);
  304. } else
  305. {
  306. err = closedir(dirp);
  307. }
  308. dirp = opendir(name);
  309. if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
  310. for (;;)
  311. {
  312. struct dirent *entry = readdir(dirp);
  313. if (entry == NULL)
  314. break;
  315. if (strcmp(entry->d_name, ".") == 0)
  316. continue;
  317. if (strcmp(entry->d_name, "..") == 0)
  318. continue;
  319. int isDir = 0;
  320. struct stat buf;
  321. char fullPath[PATH_MAX];
  322. strncpy(fullPath, name, PATH_MAX);
  323. strcat(fullPath, "/");
  324. strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
  325. if (stat(fullPath, &buf) == -1)
  326. {
  327. LOG_ERROR("unable to read status from %s", fullPath);
  328. break;
  329. }
  330. isDir = S_ISDIR(buf.st_mode) != 0;
  331. if (isDir)
  332. continue;
  333. // diag_printf("<INFO>: entry %14s",entry->d_name);
  334. char fullname[PATH_MAX];
  335. char fullname2[PATH_MAX];
  336. strcpy(fullname, name);
  337. strcat(fullname, "/");
  338. strcat(fullname, entry->d_name);
  339. strcpy(fullname2, destdir);
  340. strcat(fullname2, "/");
  341. strcat(fullname2, entry->d_name);
  342. // diag_printf("from %s to %s\n", fullname, fullname2);
  343. copyfile(fullname, fullname2);
  344. // diag_printf("\n");
  345. }
  346. err = closedir(dirp);
  347. if( err < 0 ) SHOW_RESULT( stat, err );
  348. }
  349. static int
  350. zylinjtag_Jim_Command_rm(Jim_Interp *interp,
  351. int argc,
  352. Jim_Obj * const *argv)
  353. {
  354. int del;
  355. if (argc != 2)
  356. {
  357. Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
  358. return JIM_ERR;
  359. }
  360. del = 0;
  361. if (unlink(Jim_GetString(argv[1], NULL)) == 0)
  362. del = 1;
  363. if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
  364. del = 1;
  365. return del ? JIM_OK : JIM_ERR;
  366. }
  367. static int
  368. zylinjtag_Jim_Command_ls(Jim_Interp *interp,
  369. int argc,
  370. Jim_Obj * const *argv)
  371. {
  372. if (argc != 2)
  373. {
  374. Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
  375. return JIM_ERR;
  376. }
  377. char *name = (char*) Jim_GetString(argv[1], NULL);
  378. DIR *dirp = NULL;
  379. dirp = opendir(name);
  380. if (dirp == NULL)
  381. {
  382. return JIM_ERR;
  383. }
  384. Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
  385. for (;;)
  386. {
  387. struct dirent *entry = NULL;
  388. entry = readdir(dirp);
  389. if (entry == NULL)
  390. break;
  391. if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
  392. continue;
  393. Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
  394. }
  395. closedir(dirp);
  396. Jim_SetResult(interp, objPtr);
  397. return JIM_OK;
  398. }
  399. int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
  400. {
  401. if (argc != 1)
  402. {
  403. return ERROR_COMMAND_SYNTAX_ERROR;
  404. }
  405. unsigned long addr = strtoul(args[0], NULL, 0);
  406. volatile unsigned *address = (volatile unsigned *)addr;
  407. unsigned value = *address;
  408. command_print(cmd_ctx, "0x%x : 0x%x", address, value);
  409. return ERROR_OK;
  410. }
  411. int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
  412. {
  413. if (argc != 2)
  414. {
  415. return ERROR_INVALID_ARGUMENTS;
  416. }
  417. unsigned long addr = strtoul(args[0], NULL, 0);
  418. volatile int *address = (volatile int *)addr;
  419. int value=strtoul(args[1], NULL, 0);
  420. *address=value;
  421. return ERROR_OK;
  422. }
  423. static int
  424. zylinjtag_Jim_Command_peek(Jim_Interp *interp,
  425. int argc,
  426. Jim_Obj * const *argv)
  427. {
  428. if (argc != 2)
  429. {
  430. Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
  431. return JIM_ERR;
  432. }
  433. long address;
  434. if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
  435. return JIM_ERR;
  436. int value = *((volatile int *) address);
  437. Jim_SetResult(interp, Jim_NewIntObj(interp, value));
  438. return JIM_OK;
  439. }
  440. static int
  441. zylinjtag_Jim_Command_poke(Jim_Interp *interp,
  442. int argc,
  443. Jim_Obj * const *argv)
  444. {
  445. if (argc != 3)
  446. {
  447. Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
  448. return JIM_ERR;
  449. }
  450. long address;
  451. if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
  452. return JIM_ERR;
  453. long value;
  454. if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
  455. return JIM_ERR;
  456. *((volatile int *) address) = value;
  457. return JIM_OK;
  458. }
  459. /* not so pretty code to fish out ip number*/
  460. static int zylinjtag_Jim_Command_ip(Jim_Interp *interp, int argc,
  461. Jim_Obj * const *argv)
  462. {
  463. #if !defined(__CYGWIN__)
  464. Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
  465. struct ifaddrs *ifa = NULL, *ifp = NULL;
  466. if (getifaddrs(&ifp) < 0)
  467. {
  468. return JIM_ERR;
  469. }
  470. for (ifa = ifp; ifa; ifa = ifa->ifa_next)
  471. {
  472. char ip[200];
  473. socklen_t salen;
  474. if (ifa->ifa_addr->sa_family == AF_INET)
  475. salen = sizeof(struct sockaddr_in);
  476. else if (ifa->ifa_addr->sa_family == AF_INET6)
  477. salen = sizeof(struct sockaddr_in6);
  478. else
  479. continue;
  480. if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
  481. NI_NUMERICHOST) < 0)
  482. {
  483. continue;
  484. }
  485. Jim_AppendString(interp, tclOutput, ip, strlen(ip));
  486. break;
  487. }
  488. freeifaddrs(ifp);
  489. #else
  490. Jim_Obj *tclOutput = Jim_NewStringObj(interp, "fixme!!!", 0);
  491. LOG_ERROR("NOT IMPLEMENTED!!!");
  492. #endif
  493. Jim_SetResult(interp, tclOutput);
  494. return JIM_OK;
  495. }
  496. /* not so pretty code to fish out eth0 mac address */
  497. static int zylinjtag_Jim_Command_mac(Jim_Interp *interp, int argc,
  498. Jim_Obj * const *argv)
  499. {
  500. struct ifreq *ifr, *ifend;
  501. struct ifreq ifreq;
  502. struct ifconf ifc;
  503. struct ifreq ifs[5];
  504. int SockFD;
  505. SockFD = socket(AF_INET, SOCK_DGRAM, 0);
  506. if (SockFD < 0)
  507. {
  508. return JIM_ERR;
  509. }
  510. ifc.ifc_len = sizeof(ifs);
  511. ifc.ifc_req = ifs;
  512. if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0)
  513. {
  514. close(SockFD);
  515. return JIM_ERR;
  516. }
  517. ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
  518. for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
  519. {
  520. //if (ifr->ifr_addr.sa_family == AF_INET)
  521. {
  522. if (strcmp("eth0", ifr->ifr_name)!=0)
  523. continue;
  524. strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
  525. if (ioctl(SockFD, SIOCGIFHWADDR, &ifreq) < 0)
  526. {
  527. close(SockFD);
  528. return JIM_ERR;
  529. }
  530. close(SockFD);
  531. Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
  532. char buffer[256];
  533. sprintf(buffer, "%02x-%02x-%02x-%02x-%02x-%02x",
  534. ifreq.ifr_hwaddr.sa_data[0]&0xff,
  535. ifreq.ifr_hwaddr.sa_data[1]&0xff,
  536. ifreq.ifr_hwaddr.sa_data[2]&0xff,
  537. ifreq.ifr_hwaddr.sa_data[3]&0xff,
  538. ifreq.ifr_hwaddr.sa_data[4]&0xff,
  539. ifreq.ifr_hwaddr.sa_data[5]&0xff);
  540. Jim_AppendString(interp, tclOutput, buffer, strlen(buffer));
  541. Jim_SetResult(interp, tclOutput);
  542. return JIM_OK;
  543. }
  544. }
  545. close(SockFD);
  546. return JIM_ERR;
  547. }
  548. int ioutil_init(struct command_context_s *cmd_ctx)
  549. {
  550. register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
  551. "remove file");
  552. register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
  553. "display file content");
  554. register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
  555. "truncate a file to 0 size");
  556. register_command(cmd_ctx, NULL, "cp", handle_cp_command,
  557. COMMAND_ANY, "copy a file <from> <to>");
  558. register_command(cmd_ctx, NULL, "append_file", handle_append_command,
  559. COMMAND_ANY, "append a variable number of strings to a file");
  560. register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
  561. COMMAND_ANY, "display available ram memory");
  562. Jim_CreateCommand(interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
  563. Jim_CreateCommand(interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
  564. Jim_CreateCommand(interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
  565. Jim_CreateCommand(interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
  566. Jim_CreateCommand(interp, "mac", zylinjtag_Jim_Command_mac,
  567. NULL, NULL);
  568. Jim_CreateCommand(interp, "ip", zylinjtag_Jim_Command_ip,
  569. NULL, NULL);
  570. return ERROR_OK;
  571. }