scan.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2020 Igor van den Hoven *
  5. * *
  6. * TinTin++ is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  18. ******************************************************************************/
  19. /******************************************************************************
  20. * T I N T I N + + *
  21. * *
  22. * coded by Igor van den Hoven 2005 *
  23. ******************************************************************************/
  24. #include "tintin.h"
  25. #ifdef HAVE_PTY_H
  26. #include <pty.h>
  27. #else
  28. #ifdef HAVE_UTIL_H
  29. #include <util.h>
  30. #endif
  31. #endif
  32. /* support routines for comma separated value files */
  33. char *get_arg_in_quotes(struct session *ses, char *string, char *result, int flag)
  34. {
  35. char *pti, *pto;
  36. int nest = 0;
  37. pti = space_out(string);
  38. pto = result;
  39. if (*pti == '"')
  40. {
  41. nest = TRUE;
  42. pti++;
  43. }
  44. while (*pti)
  45. {
  46. if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
  47. {
  48. *pto++ = *pti++;
  49. *pto++ = *pti++;
  50. continue;
  51. }
  52. if (*pti == '"')
  53. {
  54. if (pti[1] == '"')
  55. {
  56. *pto++ = *pti++;
  57. }
  58. else if (nest)
  59. {
  60. nest = FALSE;
  61. }
  62. pti++;
  63. continue;
  64. }
  65. else if (nest == TRUE)
  66. {
  67. *pto++ = *pti++;
  68. }
  69. else if (*pti == ' ' || *pti == '\t')
  70. {
  71. pti++;
  72. }
  73. else if (*pti == ',')
  74. {
  75. pti++;
  76. break;
  77. }
  78. else
  79. {
  80. *pto++ = *pti++;
  81. }
  82. }
  83. if (nest)
  84. {
  85. tintin_printf2(ses, "#SCAN CSV: GET QUOTED ARGUMENT: UNMATCHED QUOTE.");
  86. }
  87. *pto = 0;
  88. return pti;
  89. }
  90. struct session *scan_bulk_file(struct session *ses, FILE *fp, char *filename, char *arg)
  91. {
  92. char line[STRING_SIZE], *str_out, *str_rip, *str_sub;
  93. int cnt = 0;
  94. str_out = str_dup("");
  95. while (fgets(line, BUFFER_SIZE - 1, fp))
  96. {
  97. cnt++;
  98. str_cat(&str_out, line);
  99. }
  100. str_rip = str_alloc(str_len(str_out));
  101. strip_vt102_codes(str_out, str_rip);
  102. RESTRING(gtd->cmds[0], str_out);
  103. RESTRING(gtd->cmds[1], str_rip);
  104. RESTRING(gtd->cmds[2], ntos(str_len(str_out)));
  105. RESTRING(gtd->cmds[3], ntos(strlen(str_rip)));
  106. RESTRING(gtd->cmds[4], ntos(cnt));
  107. str_sub = str_alloc(strlen(arg) + STRING_SIZE);
  108. substitute(ses, arg, str_sub, SUB_CMD);
  109. show_message(ses, LIST_COMMAND, "#SCAN BULK: FILE {%s} SCANNED.", filename);
  110. DEL_BIT(ses->flags, SES_FLAG_SCAN);
  111. ses = script_driver(ses, LIST_COMMAND, str_sub);
  112. return ses;
  113. }
  114. struct session *scan_csv_file(struct session *ses, FILE *fp, char *filename)
  115. {
  116. char line[STRING_SIZE], temp[BUFFER_SIZE], *arg;
  117. int i, header = FALSE;
  118. SET_BIT(ses->flags, SES_FLAG_SCAN);
  119. while (fgets(line, BUFFER_SIZE, fp))
  120. {
  121. arg = strchr(line, '\r');
  122. if (arg)
  123. {
  124. *arg = 0;
  125. }
  126. else
  127. {
  128. arg = strchr(line, '\n');
  129. if (arg)
  130. {
  131. *arg = 0;
  132. }
  133. }
  134. RESTRING(gtd->vars[0], line);
  135. arg = line;
  136. for (i = 1 ; i < 100 ; i++)
  137. {
  138. arg = get_arg_in_quotes(ses, arg, temp, FALSE);
  139. RESTRING(gtd->vars[i], temp);
  140. if (*arg == 0)
  141. {
  142. while (++i < 100)
  143. {
  144. if (*gtd->vars[i])
  145. {
  146. RESTRING(gtd->vars[i], "");
  147. }
  148. }
  149. break;
  150. }
  151. }
  152. if (header == FALSE)
  153. {
  154. header = TRUE;
  155. check_all_events(ses, SUB_ARG|SUB_SEC, 0, 0, "SCAN CSV HEADER");
  156. }
  157. else
  158. {
  159. check_all_events(ses, SUB_ARG|SUB_SEC, 0, 0, "SCAN CSV LINE");
  160. }
  161. if (HAS_BIT(ses->flags, SES_FLAG_SCANABORT))
  162. {
  163. break;
  164. }
  165. }
  166. DEL_BIT(ses->flags, SES_FLAG_SCAN);
  167. if (HAS_BIT(ses->flags, SES_FLAG_SCANABORT))
  168. {
  169. DEL_BIT(ses->flags, SES_FLAG_SCANABORT);
  170. show_message(ses, LIST_COMMAND, "#SCAN CSV: FILE {%s} PARTIALLY SCANNED.", filename);
  171. }
  172. else
  173. {
  174. show_message(ses, LIST_COMMAND, "#SCAN CSV: FILE {%s} SCANNED.", filename);
  175. }
  176. fclose(fp);
  177. return ses;
  178. }
  179. /* support routines for tab separated value files */
  180. char *get_arg_stop_tabs(struct session *ses, char *string, char *result, int flag)
  181. {
  182. char *pti, *pto;
  183. pti = string;
  184. pto = result;
  185. while (*pti)
  186. {
  187. if (*pti == '\t')
  188. {
  189. pti++;
  190. break;
  191. }
  192. *pto++ = *pti++;
  193. }
  194. *pto = 0;
  195. return pti;
  196. }
  197. struct session *scan_tsv_file(struct session *ses, FILE *fp, char *filename)
  198. {
  199. char line[STRING_SIZE], temp[BUFFER_SIZE], *arg;
  200. int i, header = FALSE;
  201. SET_BIT(ses->flags, SES_FLAG_SCAN);
  202. while (fgets(line, BUFFER_SIZE, fp))
  203. {
  204. arg = strchr(line, '\r');
  205. if (arg)
  206. {
  207. *arg = 0;
  208. }
  209. else
  210. {
  211. arg = strchr(line, '\n');
  212. if (arg)
  213. {
  214. *arg = 0;
  215. }
  216. }
  217. RESTRING(gtd->vars[0], line);
  218. arg = line;
  219. for (i = 1 ; i < 100 ; i++)
  220. {
  221. arg = get_arg_stop_tabs(ses, arg, temp, FALSE);
  222. RESTRING(gtd->vars[i], temp);
  223. if (*arg == 0)
  224. {
  225. while (++i < 100)
  226. {
  227. if (*gtd->vars[i])
  228. {
  229. RESTRING(gtd->vars[i], "");
  230. }
  231. }
  232. break;
  233. }
  234. }
  235. if (header == FALSE)
  236. {
  237. header = TRUE;
  238. check_all_events(ses, SUB_ARG|SUB_SEC, 0, 0, "SCAN TSV HEADER");
  239. }
  240. else
  241. {
  242. check_all_events(ses, SUB_ARG|SUB_SEC, 0, 0, "SCAN TSV LINE");
  243. }
  244. if (HAS_BIT(ses->flags, SES_FLAG_SCANABORT))
  245. {
  246. break;
  247. }
  248. }
  249. DEL_BIT(ses->flags, SES_FLAG_SCAN);
  250. if (HAS_BIT(ses->flags, SES_FLAG_SCANABORT))
  251. {
  252. DEL_BIT(ses->flags, SES_FLAG_SCANABORT);
  253. show_message(ses, LIST_COMMAND, "#SCAN TSV: FILE {%s} PARTIALLY SCANNED.", filename);
  254. }
  255. else
  256. {
  257. show_message(ses, LIST_COMMAND, "#SCAN TSV: FILE {%s} SCANNED.", filename);
  258. }
  259. return ses;
  260. }
  261. /* support routines for text files */
  262. struct session *scan_txt_file(struct session *ses, FILE *fp, char *filename)
  263. {
  264. char line[STRING_SIZE], *arg;
  265. SET_BIT(ses->flags, SES_FLAG_SCAN);
  266. while (fgets(line, BUFFER_SIZE - 1, fp))
  267. {
  268. arg = strchr(line, '\r');
  269. if (arg)
  270. {
  271. *arg = 0;
  272. }
  273. else
  274. {
  275. arg = strchr(line, '\n');
  276. if (arg)
  277. {
  278. *arg = 0;
  279. }
  280. }
  281. process_mud_output(ses, line, FALSE);
  282. if (HAS_BIT(ses->flags, SES_FLAG_SCANABORT))
  283. {
  284. break;
  285. }
  286. }
  287. DEL_BIT(ses->flags, SES_FLAG_SCAN);
  288. if (HAS_BIT(ses->flags, SES_FLAG_SCANABORT))
  289. {
  290. DEL_BIT(ses->flags, SES_FLAG_SCANABORT);
  291. show_message(ses, LIST_COMMAND, "#SCAN TXT: FILE {%s} PARTIALLY SCANNED.", filename);
  292. }
  293. else
  294. {
  295. show_message(ses, LIST_COMMAND, "#SCAN TXT: FILE {%s} SCANNED.", filename);
  296. }
  297. return ses;
  298. }
  299. DO_COMMAND(do_scan)
  300. {
  301. FILE *fp;
  302. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  303. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  304. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  305. if (*arg1 == 0)
  306. {
  307. show_error(ses, LIST_COMMAND, "#SYNTAX: #SCAN {ABORT|CSV|TXT} {<FILENAME>}");
  308. return ses;
  309. }
  310. if (is_abbrev(arg1, "ABORT"))
  311. {
  312. if (!HAS_BIT(ses->flags, SES_FLAG_SCAN))
  313. {
  314. show_error(ses, LIST_COMMAND, "#SCAN ABORT: NOT CURRENTLY SCANNING.");
  315. }
  316. else
  317. {
  318. SET_BIT(ses->flags, SES_FLAG_SCANABORT);
  319. }
  320. return ses;
  321. }
  322. if (*arg2 == 0)
  323. {
  324. show_error(ses, LIST_COMMAND, "#SYNTAX: #SCAN {ABORT|CSV|TXT} {<FILENAME>}");
  325. return ses;
  326. }
  327. if ((fp = fopen(arg2, "r")) == NULL)
  328. {
  329. show_error(ses, LIST_COMMAND, "#ERROR: #SCAN - FILE {%s} NOT FOUND.", arg2);
  330. return ses;
  331. }
  332. SET_BIT(ses->flags, SES_FLAG_SCAN);
  333. if (is_abbrev(arg1, "FILE"))
  334. {
  335. ses = scan_bulk_file(ses, fp, arg2, arg);
  336. }
  337. else if (is_abbrev(arg1, "CSV"))
  338. {
  339. ses = scan_csv_file(ses, fp, arg2);
  340. }
  341. else if (is_abbrev(arg1, "TSV"))
  342. {
  343. ses = scan_tsv_file(ses, fp, arg2);
  344. }
  345. else if (is_abbrev(arg1, "TXT"))
  346. {
  347. ses = scan_txt_file(ses, fp, arg2);
  348. }
  349. else
  350. {
  351. DEL_BIT(ses->flags, SES_FLAG_SCAN);
  352. show_error(ses, LIST_COMMAND, "#SYNTAX: #SCAN {ABORT|CSV|FILE|TSV|TXT} {<FILENAME>}");
  353. }
  354. DEL_BIT(ses->flags, SES_FLAG_SCAN);
  355. fclose(fp);
  356. return ses;
  357. }