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.
 
 
 
 
 
 

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