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.
 
 
 
 
 
 

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