ecuchdir.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /*+-------------------------------------------------------------------------
  2. ecuchdir.c - ECU change directory command/history
  3. wht@wht.net
  4. Defined functions:
  5. cd_array_delete(arg, narg)
  6. cd_array_delete_usage()
  7. cd_array_init()
  8. cd_array_read()
  9. cd_array_save()
  10. change_directory(dirname, arg_present_flag)
  11. expand_dirname(dirname, maxlen)
  12. pop_directory(arg, arg_present, pcmd)
  13. push_directory(dirname, arg_present, pcmd)
  14. Paraphrase: "It just goes to show you: no matter where you find
  15. yourself -- there you are!" -- Pogo
  16. --------------------------------------------------------------------------*/
  17. /*+:EDITS:*/
  18. /*:04-26-2000-11:15-wht@bob-RELEASE 4.42 */
  19. /*:01-24-1997-02:37-wht@yuriatin-SOURCE RELEASE 4.00 */
  20. /*:09-11-1996-20:00-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  21. /*:08-20-1996-12:39-wht@kepler-locale/ctype fixes from ache@nagual.ru */
  22. /*:12-06-1995-13:30-wht@n4hgf-termecu w/errno -1 consideration */
  23. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  24. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  25. /*:03-12-1995-01:03-wht@kepler-use ECU_MAXPN */
  26. /*:01-12-1995-15:19-wht@n4hgf-apply Andrew Chernov 8-bit clean+FreeBSD patch */
  27. /*:05-04-1994-04:38-wht@n4hgf-ECU release 3.30 */
  28. /*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  29. /*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  30. /*:09-25-1991-18:24-wht@n4hgf2-fix seg viol in popd w/o argument on Sun */
  31. /*:07-25-1991-12:55-wht@n4hgf-ECU release 3.10 */
  32. /*:07-14-1991-18:18-wht@n4hgf-new ttygets functions */
  33. /*:05-21-1991-18:53-wht@n4hgf-add push_directory and pop_directory */
  34. /*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  35. #include "ecu.h"
  36. #include "ecukey.h"
  37. #include "ecutty.h"
  38. #include "termecu.h"
  39. int push_directory();
  40. #define CD_QUAN 44
  41. char *cd_array[CD_QUAN];
  42. int cd_in_use = 0;
  43. #define DIR_PUSH_MAX 10
  44. char *dir_push_stack[DIR_PUSH_MAX];
  45. int dir_push_level = 0;
  46. extern char errmsg[];
  47. extern int errno;
  48. /*+-------------------------------------------------------------------------
  49. cd_array_read() - read ~/.ecu/dir
  50. --------------------------------------------------------------------------*/
  51. void
  52. cd_array_read()
  53. {
  54. char dirpath[ECU_MAXPN];
  55. FILE *fpcd;
  56. FILE *fopen();
  57. char *cp;
  58. char *skip_ld_break();
  59. get_home_dir(dirpath);
  60. strcat(dirpath, "/.ecu/dir");
  61. if ((fpcd = fopen(dirpath, "r")) == (FILE *) 0)
  62. return; /* none found */
  63. for (cd_in_use = 0; cd_in_use < CD_QUAN; cd_in_use++)
  64. {
  65. if (fgets(dirpath, sizeof(dirpath), fpcd) == (char *)0)
  66. break;
  67. dirpath[strlen(dirpath) - 1] = 0;
  68. cp = skip_ld_break(dirpath);
  69. if (strlen(cp) == 0)
  70. {
  71. --cd_in_use;
  72. continue;
  73. }
  74. strcpy(cd_array[cd_in_use], cp);
  75. }
  76. fclose(fpcd);
  77. } /* end of cd_array_read */
  78. /*+-------------------------------------------------------------------------
  79. cd_array_save() - save ~/.ecu/dir
  80. --------------------------------------------------------------------------*/
  81. void
  82. cd_array_save()
  83. {
  84. int icd;
  85. char savepath[256];
  86. FILE *fpcd;
  87. FILE *fopen();
  88. get_home_dir(savepath);
  89. strcat(savepath, "/.ecu/dir");
  90. if (cd_in_use == 0)
  91. {
  92. ff(se, "No directory list to save in %s\r\n", savepath);
  93. return;
  94. }
  95. if ((fpcd = fopen(savepath, "w")) == (FILE *) 0)
  96. {
  97. ff(se, "%s could not be opened\r\n", savepath);
  98. return;
  99. }
  100. for (icd = 0; icd < cd_in_use; icd++)
  101. fprintf(fpcd, "%s\n", cd_array[icd]);
  102. fclose(fpcd);
  103. ff(se, "%d entries saved in %s\r\n", cd_in_use, savepath);
  104. } /* end of cd_array_save */
  105. /*+-------------------------------------------------------------------------
  106. cd_array_delete_usage()
  107. --------------------------------------------------------------------------*/
  108. void
  109. cd_array_delete_usage()
  110. {
  111. ff(se, "usage: d[elete] <1st> [<last>]\r\n");
  112. } /* end of cd_array_delete_usage */
  113. /*+-------------------------------------------------------------------------
  114. cd_array_delete(arg,narg)
  115. --------------------------------------------------------------------------*/
  116. int
  117. cd_array_delete(arg, narg)
  118. char **arg;
  119. int narg;
  120. {
  121. int first; /* 1st to delete */
  122. int last; /* last to delete */
  123. if ((narg < 2) || (narg > 3))
  124. {
  125. cd_array_delete_usage();
  126. return (-1);
  127. }
  128. first = atoi(arg[1]) - 1;
  129. if (narg == 2)
  130. last = first;
  131. else
  132. last = atoi(arg[2]) - 1;
  133. if ((first > (cd_in_use - 1)) || (last > (cd_in_use - 1)) || (last < first))
  134. {
  135. cd_array_delete_usage();
  136. return (-1);
  137. }
  138. if (last == (cd_in_use - 1))
  139. {
  140. cd_in_use = first;
  141. }
  142. else
  143. {
  144. int count_less = last - first + 1;
  145. last++;
  146. while (last != cd_in_use)
  147. strcpy(cd_array[first++], cd_array[last++]);
  148. cd_in_use -= count_less;
  149. }
  150. return (0);
  151. } /* end of cd_array_delete */
  152. /*+-------------------------------------------------------------------------
  153. cd_array_init()
  154. --------------------------------------------------------------------------*/
  155. void
  156. cd_array_init()
  157. {
  158. int itmp;
  159. /*allocate change_directory stack */
  160. for (itmp = 0; itmp < CD_QUAN; itmp++)
  161. {
  162. if (!(cd_array[itmp] = malloc(ECU_MAXPN + 1)))
  163. {
  164. ff(se, "Not enough memory for cd stack\r\n");
  165. errno = -1;
  166. termecu(TERMECU_MALLOC);
  167. }
  168. *cd_array[itmp] = 0;
  169. }
  170. (void)cd_array_read();
  171. } /* end of cd_array_init */
  172. /*+-------------------------------------------------------------------------
  173. expand_dirname(dirname,maxlen) - convert dirname with shell chars
  174. --------------------------------------------------------------------------*/
  175. int
  176. expand_dirname(dirname, maxlen)
  177. char *dirname;
  178. int maxlen;
  179. {
  180. char s256[256];
  181. char *expcmd;
  182. if (!find_shell_chars(dirname))
  183. return (0);
  184. sprintf(s256, "`ls -d %s`", dirname);
  185. if (expand_wildcard_list(s256, &expcmd))
  186. {
  187. strcpy(errmsg, "No such directory");
  188. return (-1);
  189. }
  190. strncpy(dirname, expcmd, maxlen);
  191. dirname[maxlen - 1] = 0;
  192. free(expcmd);
  193. if (strchr(dirname, ' '))
  194. {
  195. strcpy(errmsg, "Too many files");
  196. return (-1);
  197. }
  198. return (0);
  199. } /* end of expand_dirname */
  200. /*+-------------------------------------------------------------------------
  201. change_directory(dirname,arg_present_flag) - 'cd' interactive cmd hdlr
  202. Change directory to 'dirname' if arg_present_flag is true,
  203. else if flag 0, ask for new directory name and change to it
  204. This procedure maintains the global variable 'curr_dir' that
  205. reflects the ecu transmitter process current working directory.
  206. --------------------------------------------------------------------------*/
  207. int
  208. change_directory(dirname, arg_present_flag)
  209. char *dirname;
  210. int arg_present_flag;
  211. {
  212. int icd;
  213. int itmp;
  214. char s256[256];
  215. UINT delim;
  216. #define BLD_ARG_MAX 5
  217. char *arg[BLD_ARG_MAX];
  218. int narg;
  219. int longest;
  220. int pushing = 0;
  221. if (cd_in_use == 0)
  222. cd_array_read();
  223. fputs(" ", se);
  224. if (arg_present_flag) /* if there is an argument ... */
  225. {
  226. if (isdigit((uchar) * dirname)) /* ... and first char is digit */
  227. {
  228. icd = atoi(dirname) - 1;
  229. if ((icd < 0) || (icd >= cd_in_use))
  230. goto DISPLAY_CD_ARRAY;
  231. strncpy(s256, cd_array[icd], sizeof(s256));
  232. }
  233. else
  234. strncpy(s256, dirname, sizeof(s256)); /* literal dir spec */
  235. s256[sizeof(s256) - 1] = 0;
  236. }
  237. else
  238. /* no arg to cd command */
  239. {
  240. DISPLAY_CD_ARRAY:
  241. fputs("\r\n", se);
  242. longest = 0;
  243. for (icd = 0; icd < CD_QUAN / 2; icd++)
  244. {
  245. if (icd >= cd_in_use)
  246. break;
  247. if (longest < (itmp = strlen(cd_array[icd])))
  248. longest = itmp;
  249. }
  250. longest += 4;
  251. if (longest < 36)
  252. longest += 4;
  253. for (icd = 0; icd < CD_QUAN / 2; icd++)
  254. {
  255. if (icd >= cd_in_use)
  256. break;
  257. sprintf(s256, "%2d %s ", icd + 1, cd_array[icd]);
  258. fputs(s256, se);
  259. if (icd + CD_QUAN / 2 >= cd_in_use)
  260. fputs("\r\n", se);
  261. else
  262. {
  263. itmp = longest - strlen(s256);
  264. while (itmp-- > 0)
  265. fputc(' ', se);
  266. sprintf(s256, "%2d %s\r\n",
  267. icd + 1 + CD_QUAN / 2, cd_array[icd + CD_QUAN / 2]);
  268. fputs(s256, se);
  269. }
  270. }
  271. fputs("current dir: ", se);
  272. tcap_stand_out();
  273. ff(se, " %s ", curr_dir);
  274. tcap_stand_end();
  275. tcap_eeol();
  276. fputs("\r\n", se);
  277. GET_NEW_DIR:
  278. fputs(
  279. "New dir, <#>, %save, %read, %del, %xmitcd, %pushd, <enter>: ", se);
  280. ttygets(s256, sizeof(s256), TG_CRLF, &delim, (int *)0);
  281. TRY_AGAIN:
  282. if ((delim == ESC) || !strlen(s256))
  283. {
  284. ff(se, "no directory change\r\n");
  285. return (0);
  286. }
  287. else if (s256[0] == '%')
  288. {
  289. if (pushing)
  290. {
  291. ff(se, "syntax error\r\n");
  292. return (-1);
  293. }
  294. build_str_array(s256, arg, BLD_ARG_MAX, &narg);
  295. if (minunique("save", &s256[1], 1))
  296. {
  297. cd_array_save();
  298. goto GET_NEW_DIR;
  299. }
  300. else if (minunique("read", &s256[1], 1))
  301. {
  302. cd_array_read();
  303. goto DISPLAY_CD_ARRAY;
  304. }
  305. else if (minunique("delete", &s256[1], 1))
  306. {
  307. if (cd_array_delete(arg, narg))
  308. goto GET_NEW_DIR;
  309. else
  310. goto DISPLAY_CD_ARRAY;
  311. }
  312. else if (minunique("xmitcd", &s256[1], 1))
  313. {
  314. lputs("cd ");
  315. lputs(curr_dir);
  316. lputc('\r');
  317. return (0);
  318. }
  319. else if (minunique("pushd", &s256[1], 1))
  320. {
  321. strcpy(s256, arg[1]);
  322. pushing = 1;
  323. goto TRY_AGAIN;
  324. }
  325. else
  326. {
  327. ff(se, "Invalid cd subcommand\r\n");
  328. goto GET_NEW_DIR;
  329. }
  330. }
  331. else if (icd = atoi(s256))
  332. {
  333. icd--;
  334. if (icd >= cd_in_use)
  335. goto GET_NEW_DIR;
  336. strncpy(s256, cd_array[icd], sizeof(s256));
  337. s256[sizeof(s256) - 1] = 0;
  338. }
  339. }
  340. if (pushing)
  341. {
  342. if (push_directory(s256, 1, 1))
  343. return (-1);
  344. }
  345. else
  346. {
  347. if (expand_dirname(s256, sizeof(s256)))
  348. {
  349. ff(se, "%s\r\n", errmsg);
  350. return (-1);
  351. }
  352. if (chdir(s256) < 0) /* now change to the new directory */
  353. {
  354. perror(s256); /* print error if we get one */
  355. ff(se, "\r\n");
  356. return (-1);
  357. }
  358. get_curr_dir(curr_dir, sizeof(curr_dir));
  359. fputs("confirmed: ", se);
  360. tcap_stand_out();
  361. ff(se, " %s ", curr_dir);
  362. tcap_stand_end();
  363. fputs("\r\n", se);
  364. }
  365. for (icd = 0; icd < cd_in_use; icd++)
  366. {
  367. if (strcmp(curr_dir, cd_array[icd]) == 0)
  368. return (0);
  369. }
  370. if (cd_in_use == CD_QUAN)
  371. {
  372. for (icd = 1; icd < CD_QUAN; icd++)
  373. {
  374. strcpy(cd_array[icd - 1], cd_array[icd]);
  375. }
  376. strcpy(cd_array[CD_QUAN - 1], curr_dir);
  377. }
  378. else
  379. strcpy(cd_array[cd_in_use++], curr_dir);
  380. return (0);
  381. } /* end of change_directory */
  382. /*+-------------------------------------------------------------------------
  383. push_directory(dirname,arg_present,pcmd) - 'pushd' function
  384. This function performs 'pushd' actions for both the interactive
  385. and procedure 'pushd' commands
  386. dirname is new directory name if arg_present true
  387. pcmd true if procedure command or cd %p interactive, else interactive command
  388. returns -1 if error, else 0
  389. --------------------------------------------------------------------------*/
  390. int
  391. push_directory(dirname, arg_present, pcmd)
  392. char *dirname;
  393. int arg_present;
  394. int pcmd;
  395. {
  396. int itmp;
  397. char s256[256];
  398. if (!pcmd)
  399. ff(se, "\r\n");
  400. if (!arg_present)
  401. {
  402. if (!dir_push_level)
  403. {
  404. if (!pcmd || proc_trace)
  405. pprintf("---: no directories pushed\n");
  406. }
  407. else
  408. {
  409. for (itmp = 0; itmp < dir_push_level; itmp++)
  410. pprintf("%3d: %s\n", itmp, dir_push_stack[itmp]);
  411. }
  412. pprintf("cwd: %s\n", curr_dir);
  413. return (0);
  414. }
  415. if (dir_push_level == DIR_PUSH_MAX)
  416. {
  417. pputs("too many pushds\n");
  418. return (-1);
  419. }
  420. if (!dir_push_stack[dir_push_level])
  421. {
  422. if (!(dir_push_stack[dir_push_level] = malloc(ECU_MAXPN)))
  423. {
  424. pputs("no memory for pushd\n");
  425. return (-1);
  426. }
  427. }
  428. get_curr_dir(dir_push_stack[dir_push_level], ECU_MAXPN);
  429. strncpy(s256, dirname, sizeof(s256));
  430. s256[sizeof(s256) - 1] = 0;
  431. if (expand_dirname(s256, sizeof(s256)))
  432. {
  433. pprintf("'%s': %s\n", s256, errmsg);
  434. return (-1);
  435. }
  436. if (chdir(s256) < 0) /* now change to the new directory */
  437. {
  438. pperror(s256); /* print error if we get one */
  439. return (-1);
  440. }
  441. get_curr_dir(curr_dir, sizeof(curr_dir));
  442. if (pcmd && proc_trace)
  443. pprintf("pushed to directory %s\n", curr_dir);
  444. else
  445. {
  446. fputs("confirmed: ", se);
  447. tcap_stand_out();
  448. ff(se, " %s ", curr_dir);
  449. tcap_stand_end();
  450. ff(se, " (level %d)\r\n", dir_push_level);
  451. }
  452. dir_push_level++;
  453. return (0);
  454. } /* end of push_directory */
  455. /*+-------------------------------------------------------------------------
  456. pop_directory(arg,arg_present,pcmd) - 'popd' function
  457. This function performs 'popd' actions for both the interactive
  458. and procedure 'popd' commands
  459. arg is empty if arg_present false
  460. if not empty, it is == 'all' or a numeric level to pop to
  461. pcmd true if procedure command, else interactive command
  462. returns -1 if error, else 0
  463. --------------------------------------------------------------------------*/
  464. int
  465. pop_directory(arg, arg_present, pcmd)
  466. char *arg;
  467. int arg_present;
  468. int pcmd;
  469. {
  470. int new_level = -1;
  471. if (!pcmd)
  472. pputs("\n");
  473. if (!dir_push_level)
  474. {
  475. if (!pcmd || proc_trace)
  476. {
  477. pprintf("---: no directories pushed\n");
  478. pprintf("cwd: %s\n", curr_dir);
  479. }
  480. return (-1);
  481. }
  482. if (!arg_present)
  483. new_level = dir_push_level - 1;
  484. else if (minunique("all", arg, 1))
  485. new_level = 0;
  486. else if (isdigit((uchar) * arg))
  487. new_level = atoi(arg);
  488. else
  489. {
  490. pprintf("argument error: '%s'\n", arg);
  491. return (-1);
  492. }
  493. if ((new_level < 0) || (new_level > (dir_push_level - 1)))
  494. {
  495. pprintf("invalid popd argument (or not pushed to level): '%s'\n", arg);
  496. return (-1);
  497. }
  498. dir_push_level = new_level;
  499. if (chdir(dir_push_stack[dir_push_level]) < 0)
  500. {
  501. pperror(dir_push_stack[dir_push_level]);
  502. return (-1);
  503. }
  504. get_curr_dir(curr_dir, sizeof(curr_dir));
  505. if (pcmd && proc_trace)
  506. pprintf("popped to directory %s (level %d)\n", curr_dir, dir_push_level);
  507. else
  508. {
  509. fputs("confirmed: ", se);
  510. tcap_stand_out();
  511. ff(se, " %s ", curr_dir);
  512. tcap_stand_end();
  513. ff(se, " (level %d)\r\n", dir_push_level);
  514. }
  515. return (0);
  516. } /* end of pop_directory */
  517. /* end of ecuchdir.c */
  518. /* vi: set tabstop=4 shiftwidth=4: */