home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume19 / xgetftp / part03 < prev    next >
Encoding:
Text File  |  1993-04-27  |  26.0 KB  |  1,203 lines

  1. Newsgroups: comp.sources.x
  2. From: salim@tigger.cs.colorado.edu (Salim Alam)
  3. Subject: v19i024:  xgetftp - Friendly anonymous ftp tool, Part03/04
  4. Message-ID: <1993Mar10.164853.21562@sparky.imd.sterling.com>
  5. X-Md4-Signature: 08e5c8b92b3306b9f05433d7bb7e540c
  6. Date: Wed, 10 Mar 1993 16:48:53 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: salim@tigger.cs.colorado.edu (Salim Alam)
  10. Posting-number: Volume 19, Issue 24
  11. Archive-name: xgetftp/part03
  12. Environment: X11, OSF/Motif
  13.  
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 3 (of 4)."
  22. # Contents:  main.c patchlevel.h prefs.c prefs.h
  23. # Wrapped by salim@anchor on Mon Mar  8 14:06:48 1993
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'main.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'main.c'\"
  27. else
  28. echo shar: Extracting \"'main.c'\" \(18209 characters\)
  29. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  30. X/*************************************************************************
  31. X * PROGRAM:
  32. X *  xgetftp
  33. X *
  34. X * USAGE:
  35. X *  xgetftp [hostname]
  36. X *
  37. X * AUTHOR:
  38. X *  Salim Alam
  39. X *  University of Colorado, Boulder
  40. X *
  41. X * MODIFICATION LOG:
  42. X *  93.02.15 S.A. - Mods for new ctrl_delete_cache
  43. X *  93.02.03 S.A. - Better error-handling: ctrl_start_session,ctrl_down_dir
  44. X *  93.01.26 S.A. - Now gets local hostname correctly
  45. X *
  46. X **************************************************************************/
  47. X
  48. X#include <X11/Xos.h>
  49. X#include <Xm/Xm.h>
  50. X#include <Xm/PushBG.h>
  51. X#include <Xm/Text.h>
  52. X#include <Xm/List.h>
  53. X#include <sys/stat.h>
  54. X#include <stdio.h>
  55. X#include <signal.h>
  56. X#include <pwd.h>
  57. X#include <sys/socket.h>
  58. X#include <netdb.h>
  59. X#include "prefs.h"
  60. X#include "control.h"
  61. X#include "ui_funcs.h"
  62. X#include "config.h"
  63. X#include "patchlevel.h"
  64. X
  65. X#ifndef TRUE
  66. X#define TRUE 1
  67. X#define FALSE 0
  68. X#endif
  69. X
  70. X
  71. X/*
  72. X * Imported vars
  73. X */
  74. Xextern int x_data_done;
  75. Xextern FILE *response_stream;
  76. X
  77. X/*
  78. X * Global variables
  79. X */
  80. X#define INBUFSIZE    1024        /* size of data input buffer    */
  81. X#define MAX_SELECTIONS     100        /* max# of user selections    */
  82. X
  83. X
  84. XXmString * list_items = NULL;        /* list of items in curr. dir.     */
  85. Xint        item_count = 0;        /* count of items in curr dir.  */
  86. X
  87. Xint       curr_sel_cnt = 0;        /* count of selected items    */
  88. Xint        curr_selections[MAX_SELECTIONS]; /* items selected by user   */
  89. X
  90. XPrefs        user_prefs;            /* User preferences        */
  91. X
  92. Xint        fConnected = FALSE;        /* Flag to indicate server conn */
  93. X
  94. Xchar        retrieve_dir[255];        /* Directory for file retrieval */
  95. X
  96. Xchar       password[100];        /* User@hostname        */
  97. X
  98. Xvoid set_currdir(void);
  99. X
  100. X
  101. X/************************** directory list functions *********************/
  102. X
  103. Xvoid alloc_list_mem(int x)
  104. X/* 
  105. X * allocates memory for the list
  106. X */
  107. X{
  108. X    void free_list_mem(XmString *);
  109. X
  110. X    if (list_items)
  111. X    free_list_mem(list_items);
  112. X
  113. X    list_items = (XmString *) XtMalloc(x * sizeof(XmString));
  114. X}
  115. X
  116. X
  117. Xvoid add_list_item(char *str)
  118. X/*
  119. X * adds an item to the list
  120. X */
  121. X{
  122. X    list_items[item_count++] = XmStringCreateLtoR(str,XmSTRING_DEFAULT_CHARSET);
  123. X}
  124. X
  125. X
  126. Xvoid free_list_mem(XmString *list)
  127. X/*
  128. X * free all the items in the list
  129. X */
  130. X{
  131. X    int i;
  132. X
  133. X    for (i=0; i < item_count; i++)
  134. X    XmStringFree(list_items[i]);
  135. X
  136. X    item_count = 0;
  137. X}
  138. X
  139. X/************************* user preference callback ********************/
  140. X
  141. Xvoid userprefCB(Widget w, int item, XmToggleButtonCallbackStruct *cb)
  142. X{
  143. X    switch (item)
  144. X    {
  145. X      case prefCACHE_VIEW:
  146. X    user_prefs.cache_view = cb->set;
  147. X    break;
  148. X
  149. X      case prefREUSE_VIEW:
  150. X    user_prefs.reuse_view = cb->set;
  151. X    break;
  152. X
  153. X      case prefREUSE_DIR:
  154. X    user_prefs.reuse_dir = cb->set;
  155. X
  156. X      case prefAUTOSAVE_DIR:
  157. X    user_prefs.autosave_dir = cb->set;
  158. X    break;
  159. X
  160. X      case prefCONFIRM:
  161. X    user_prefs.confirm = cb->set;
  162. X    break;
  163. X      
  164. X      default:
  165. X    fprintf(stderr, "pref_cb: unknown item '%d'\n", item);
  166. X    }
  167. X}
  168. X
  169. X
  170. X/************************* retreive directory callback *****************/
  171. X
  172. Xvoid setretrievedirCB(Widget w, caddr_t data, XmSelectionBoxCallbackStruct *cb)
  173. X{
  174. X    XmStringContext context;
  175. X    char *text;
  176. X    XmStringCharSet charset;
  177. X    XmStringDirection dir;
  178. X    Boolean seperator;
  179. X    int len;
  180. X    struct stat stat_buf;
  181. X
  182. X    XmStringInitContext(&context, cb->value);
  183. X
  184. X    /* look only at first segment */
  185. X    if (XmStringGetNextSegment(context, &text, &charset, &dir,
  186. X    &seperator))
  187. X    {
  188. X    len = strlen(text);
  189. X    if (text[len-1] == '/')
  190. X        text[len-1] = '\0';
  191. X
  192. X    if (stat(text, &stat_buf) == 0)    
  193. X    {
  194. X        if (!S_ISDIR(stat_buf.st_mode))
  195. X        {
  196. X        fprintf(stderr, "'%s' not a valid directory.\n", text);
  197. X        ui_beep(0);
  198. X        }
  199. X        else
  200. X        {
  201. X        strcpy(retrieve_dir, text);
  202. X#ifdef DEBUG
  203. X        fprintf(stderr, "New retreive dir: '%s'\n", retrieve_dir);
  204. X#endif
  205. X        }
  206. X    }
  207. X    else
  208. X    {
  209. X        fprintf(stderr, "'%s' not a valid directory.\n", text);
  210. X        ui_beep(0);
  211. X    }
  212. X    }
  213. X
  214. X    XmStringFreeContext(context);
  215. X}
  216. X
  217. X
  218. X/************************* archie widget function **********************/
  219. X
  220. X/*
  221. X * archie data callback
  222. X */
  223. Xvoid get_archie_data(int *ppos, int *fid, XtInputId *id)
  224. X{
  225. X    unsigned char buf[INBUFSIZE];
  226. X    int nbytes;
  227. X
  228. X    nbytes = read(*fid, buf, INBUFSIZE);
  229. X
  230. X    if (nbytes)
  231. X    {
  232. X    int i, len;
  233. X
  234. X    /*
  235. X     * add text in buffer to text widget, and clear any
  236. X     * unwritable characters (just in case this is a binary
  237. X     * file.  also get rid of "\r" characters, just in case
  238. X     * we got this thru an ASCII connection.
  239. X     *
  240. X     */
  241. X    for (i=0, len=0; i < nbytes; i++)
  242. X    {
  243. X        if ( (isprint(buf[i]) || isspace(buf[i])) && (buf[i]!='\r') )
  244. X        buf[len++] = buf[i];
  245. X    }
  246. X    buf[len] = '\0';
  247. X    XmTextInsert(archietextW, (XmTextPosition)*ppos, buf);
  248. X    *ppos += len;
  249. X    }
  250. X    else
  251. X    {
  252. X    char filename[50];
  253. X
  254. X    XtRemoveInput(*id);
  255. X    close (*fid);
  256. X    ui_set_cursor_normal(toplevelW);
  257. X       sprintf(filename, "/tmp/xgetftpARCHIE%ld", getpid());
  258. X       unlink(filename);
  259. X    }
  260. X}
  261. X
  262. X
  263. X/*
  264. X * archie search widget callback
  265. X */
  266. Xvoid archiefindCB(Widget w, caddr_t call_data, XmPushButtonCallbackStruct *cb)
  267. X{
  268. X   char *find_str;
  269. X   static int pos;
  270. X   FILE *fp;
  271. X   char dummy[256];
  272. X   char filename[50];
  273. X
  274. X   ui_set_cursor_busy(archiebbW);
  275. X
  276. X   find_str = (char *) XmTextGetString(archiefindtextW);
  277. X   fprintf(stderr, "Archie find: '%s'\n", find_str);
  278. X
  279. X   sprintf(filename, "/tmp/xgetftpARCHIE%ld", getpid());
  280. X
  281. X   sprintf(dummy, "%s -server %s %s > %s", ARCHIEBIN, ARCHIESERVER, find_str,
  282. X    filename);
  283. X   system(dummy);
  284. X   XtFree(find_str);
  285. X
  286. X   ui_set_cursor_normal(archiebbW);
  287. X
  288. X   if ((fp = fopen(filename, "r")) == NULL)
  289. X   {
  290. X    fprintf(stderr, "Can't open file '%s' !\n", filename);
  291. X    return;
  292. X   }
  293. X
  294. X   /* XtUnmanageChild(archietextW); */
  295. X   XmTextSetString(archietextW, " ");
  296. X
  297. X   pos = 0;
  298. X
  299. X   ui_set_cursor_busy(toplevelW);
  300. X   XtAppAddInput(app_context, fileno(fp), (XtPointer) XtInputReadMask,
  301. X    (XtInputCallbackProc) get_archie_data, (XtPointer) &pos);
  302. X}
  303. X
  304. X
  305. X/******************************* menu callback *************************/
  306. X
  307. X/*
  308. X * menu button callback
  309. X */
  310. Xvoid MenuButtonCB(Widget w, int menuitm, caddr_t call_data)
  311. X{
  312. X    switch (menuitm)
  313. X    {
  314. X      case menuFILE_ABOUT:
  315. X    XtManageChild(aboutdialogW);
  316. X    break;
  317. X
  318. X      case menuFILE_SET_PREFS:
  319. X    XtManageChild(prefdialogW);
  320. X    break;
  321. X
  322. X      case menuFILE_EXIT:
  323. X    if (fConnected && user_prefs.autosave_dir)
  324. X        ctrl_save_cache();
  325. X    exit(1);
  326. X    break;
  327. X
  328. X
  329. X
  330. X      case menuFTP_OPEN:
  331. X    XtManageChild(opendlgW);
  332. X    break;
  333. X
  334. X      case menuFTP_CLOSE:
  335. X    if (fConnected)
  336. X    {
  337. X        if (user_prefs.autosave_dir)
  338. X        ctrl_save_cache();
  339. X        ctrl_logout();
  340. X        fConnected = FALSE;
  341. X        curr_sel_cnt = 0;
  342. X        XmListDeleteAllItems(filelistW);
  343. X        ui_set_status_line(" ");
  344. X        ui_set_currdir(" ");
  345. X    }
  346. X    break;
  347. X
  348. X      case menuFTP_SET_DIR:
  349. X    XtManageChild(retrievedirdlgW);
  350. X    break;
  351. X
  352. X
  353. X
  354. X      case menuCACHE_PURGE_DIR:
  355. X    if (fConnected)
  356. X    {
  357. X        curr_sel_cnt = 0;
  358. X        XmListDeleteAllItems(filelistW);
  359. X        if (!ctrl_delete_cache())
  360. X        {
  361. X            ctrl_logout();
  362. X            fConnected = FALSE;
  363. X            ui_set_status_line("Unrecoverable Error! Disconnecting.");
  364. X            ui_set_currdir(" ");
  365. X        }
  366. X        else
  367. X        {
  368. X            XmListAddItems(filelistW, list_items, item_count, 0);
  369. X            set_currdir();
  370. X            ui_set_status_line("Directory cache deleted. Now at root.");
  371. X        }
  372. X    }
  373. X    else
  374. X        ui_beep(0);
  375. X    break;
  376. X
  377. X      case menuCACHE_PURGE_VIEW:
  378. X    if (fConnected)
  379. X    {
  380. X        ctrl_delete_file_cache();
  381. X        ui_set_status_line("Viewed file cache deleted.");
  382. X    }
  383. X    else
  384. X        ui_beep(0);
  385. X    break;
  386. X
  387. X      case menuCACHE_SAVE_DIR:
  388. X    if (fConnected)
  389. X    {
  390. X        ctrl_save_cache();
  391. X        ui_set_status_line("Directory cache saved.");
  392. X    }
  393. X    else
  394. X        ui_beep(0);
  395. X    break;
  396. X
  397. X
  398. X
  399. X      case menuARCHIE_SEARCH:
  400. X    XtManageChild(archiebbW);
  401. X    break;
  402. X
  403. X      default:
  404. X    fprintf(stderr, "Unknown menu item: %d\n", menuitm);
  405. X    break;
  406. X    }
  407. X}
  408. X
  409. X
  410. X/************************** file list callbacks ************************/
  411. X
  412. Xvoid doubleclickCB(Widget w, caddr_t client_data, XmListCallbackStruct *cb)
  413. X{
  414. X    if (!x_data_done)
  415. X    {
  416. X    ui_beep(0);
  417. X    fprintf(stderr,"Data connection busy\n");
  418. X    };
  419. X
  420. X    ui_set_cursor_busy(toplevelW);
  421. X
  422. X    if (ctrl_down_dir(cb->item_position-1)==TRUE)
  423. X    /* successful traversal */
  424. X    {
  425. X    XmListDeleteAllItems(w);
  426. X    XmListAddItems(w, list_items, item_count, 0);
  427. X    curr_sel_cnt = 0;
  428. X    set_currdir();
  429. X    }
  430. X    else
  431. X    /* was not a directory, or we had an error! */
  432. X    ui_beep(0);
  433. X
  434. X    ui_set_cursor_normal(toplevelW);
  435. X}
  436. X
  437. X
  438. Xvoid selectionCB(Widget w, caddr_t client_data, XmListCallbackStruct *cb)
  439. X{
  440. X    int i;
  441. X
  442. X#ifdef DEBUG
  443. X    printf("Selected items: ");
  444. X    for (i=0; i < cb->selected_item_count; i++)
  445. X    printf("%d ", cb->selected_item_positions[i]);
  446. X    printf("\n");
  447. X#endif
  448. X
  449. X    curr_sel_cnt = cb->selected_item_count;
  450. X    for (i=0; i < cb->selected_item_count; i++)
  451. X    curr_selections[i] = cb->selected_item_positions[i];
  452. X}
  453. X
  454. X
  455. X/************************** command callbacks **************************/
  456. X
  457. Xvoid cd_up(void)
  458. X{
  459. X    if (!fConnected) return;
  460. X
  461. X    if (ctrl_up_dir()==TRUE)
  462. X    /* successfully went up */
  463. X    {
  464. X    XmListDeleteAllItems(filelistW);
  465. X    XmListAddItems(filelistW, list_items, item_count, 0);
  466. X    curr_sel_cnt = 0;
  467. X    set_currdir();
  468. X    }
  469. X    else
  470. X    /* was already at root */
  471. X    {
  472. X    ui_beep(0);
  473. X    }
  474. X}
  475. X
  476. X
  477. X/*
  478. X * retrieve callback
  479. X */
  480. Xvoid retrieve_item(void)
  481. X{
  482. X    int i;
  483. X
  484. X    if (!fConnected) return;
  485. X
  486. X    if (!x_data_done)
  487. X    {
  488. X    ui_beep(0);
  489. X    fprintf(stderr,"Data connection busy\n");
  490. X    return;
  491. X    }
  492. X
  493. X    ui_set_cursor_busy(toplevelW);
  494. X
  495. X    for (i=0; i < curr_sel_cnt; i++)
  496. X    {
  497. X    char *name;
  498. X    char line[100];
  499. X
  500. X#ifdef DEBUG
  501. X    printf("Retrieving file index %d into %s\n", curr_selections[i]-1,
  502. X        retrieve_dir);
  503. X#endif
  504. X    name = ctrl_get_item_name(curr_selections[i]-1);
  505. X    sprintf(line, "Getting %s", name);
  506. X    ui_set_status_line(line);
  507. X    free(name);
  508. X
  509. X    if (!ctrl_get_selection(retrieve_dir, curr_selections[i]-1, NULL))
  510. X        fprintf(stderr, "Retrieve FAILED!\n");
  511. X
  512. X    ui_set_status_line("Selection retrieved.");
  513. X    }
  514. X
  515. X    ui_set_cursor_normal(toplevelW);
  516. X}
  517. X
  518. X
  519. X/*
  520. X * view callback
  521. X */
  522. Xvoid get_view_data(int *ppos, int *fid, XtInputId *id)
  523. X{
  524. X    unsigned char buf[INBUFSIZE];
  525. X    int nbytes, len;
  526. X
  527. X    nbytes = read(*fid, buf, INBUFSIZE);
  528. X
  529. X    if (nbytes)
  530. X    {
  531. X    int i;
  532. X
  533. X    /*
  534. X     * add text in buffer to text widget, and clear any
  535. X     * unwritable characters (just in case this is a binary
  536. X     * file.  also get rid of "\r" characters, just in case
  537. X     * we got this thru an ASCII connection.
  538. X     *
  539. X     */
  540. X    for (i=0, len=0; i < nbytes; i++)
  541. X    {
  542. X        if ( (isprint(buf[i]) || isspace(buf[i])) && (buf[i]!='\r') )
  543. X        buf[len++] = buf[i];
  544. X    }
  545. X    buf[len] = '\0';
  546. X    XmTextInsert(viewtextW, (XmTextPosition)*ppos, buf);
  547. X    *ppos += len;
  548. X    }
  549. X    else
  550. X    {
  551. X    XtRemoveInput(*id);
  552. X    close (*fid);
  553. X    ui_set_cursor_normal(toplevelW);
  554. X    }
  555. X}
  556. X
  557. X
  558. Xvoid view_text_file(void)
  559. X{
  560. X    static int pos;
  561. X    int len;
  562. X    char line[100];
  563. X    FILE *fp;
  564. X    void str_to_ascii(char *);
  565. X
  566. X    if (!fConnected) return;
  567. X
  568. X    if (!x_data_done)
  569. X    {
  570. X    ui_beep(0);
  571. X    fprintf(stderr,"Data connection busy\n");
  572. X    return;
  573. X    }
  574. X
  575. X    /*
  576. X     * read in the file
  577. X     */
  578. X    if (curr_sel_cnt <= 0)
  579. X    {
  580. X    ui_beep(0);
  581. X    fprintf(stderr, "No file SELECTED!\n");
  582. X    return;
  583. X    }
  584. X
  585. X    ui_set_cursor_busy(toplevelW);
  586. X    if ((fp=ctrl_view_file(curr_selections[0]-1)) == NULL)
  587. X    {
  588. X    ui_beep(0);
  589. X    fprintf(stderr, "Error trying to get file!\n");
  590. X    ui_set_cursor_normal(toplevelW);
  591. X    return;
  592. X    }
  593. X
  594. X    /*
  595. X     * pop up the dialog
  596. X     *
  597. X     * we need to do this before putting in the text due to a bug
  598. X     * in Motif 1.1.xxx . This bug has been corrected in later
  599. X     * versions of Motif.
  600. X     *
  601. X     */
  602. X    XtManageChild(viewbbW);
  603. X
  604. X
  605. X    /*
  606. X     * Hand over the data getting to X
  607. X     */
  608. X    pos = 0;
  609. X    XmTextSetString(viewtextW, " ");
  610. X
  611. X    ui_set_cursor_busy(toplevelW);
  612. X    XtAppAddInput(app_context, fileno(fp), (XtPointer) XtInputReadMask, 
  613. X    (XtInputCallbackProc) get_view_data, (XtPointer) &pos);
  614. X}
  615. X
  616. X
  617. X
  618. Xvoid commandCB(Widget w, int cmd, XmPushButtonCallbackStruct *cb)
  619. X{
  620. X    switch (cmd)
  621. X    {
  622. X      case cmdVIEW:
  623. X    view_text_file();
  624. X    break;
  625. X
  626. X      case cmdRETRIEVE:
  627. X    retrieve_item();
  628. X    break;
  629. X
  630. X      case cmdCD_UP:
  631. X    cd_up();
  632. X    break;
  633. X
  634. X      default:
  635. X    fprintf(stderr, "commandCB: Unknown command '%s'\n", cmd);
  636. X    }
  637. X}
  638. X
  639. X
  640. X/************************** command callbacks **************************/
  641. X
  642. X/*
  643. X * type toggle callback
  644. X */
  645. Xvoid typetoggleCB(Widget w, int type, XmToggleButtonCallbackStruct *cb)
  646. X{
  647. X    if (!fConnected) return;
  648. X
  649. X    if ((type==cmdASCII) && (cb->set==True))
  650. X    ctrl_set_type(typASCII);
  651. X    else if ((type==cmdIMAGE) && (cb->set==True))
  652. X    ctrl_set_type(typIMAGE);
  653. X}
  654. X
  655. X
  656. X/************************** new connection callback ********************/
  657. X
  658. X/*
  659. X * open connection "ok" callback
  660. X */
  661. Xvoid openconnokCB(Widget w, caddr_t calldata, XmSelectionBoxCallbackStruct *cb)
  662. X{
  663. X    XmStringContext context;
  664. X    char *text;
  665. X    XmStringCharSet charset;
  666. X    XmStringDirection dir;
  667. X    Boolean seperator;
  668. X    char *buf = NULL;
  669. X    char line[100];
  670. X
  671. X    XmStringInitContext(&context, cb->value);
  672. X
  673. X    /* look only at first segment */
  674. X    if (XmStringGetNextSegment(context, &text, &charset, &dir,
  675. X    &seperator))
  676. X    {
  677. X#ifdef DEBUG
  678. X    fprintf(stderr, "Connecting to: %s\n", text);
  679. X#endif
  680. X
  681. X    if (fConnected)
  682. X    {
  683. X        /* TO DO: Add "confirm" requester */
  684. X            if (user_prefs.autosave_dir)
  685. X        ctrl_save_cache();
  686. X        ctrl_logout();
  687. X        curr_sel_cnt = 0;
  688. X        XmListDeleteAllItems(filelistW);
  689. X        ui_set_status_line(" ");
  690. X        ui_set_currdir(" ");
  691. X        fConnected = FALSE;
  692. X    }
  693. X
  694. X    if (ctrl_login(text, "anonymous", password))
  695. X    {    
  696. X        fConnected = TRUE;
  697. X        if (ctrl_start_session(alloc_list_mem, add_list_item))
  698. X        {
  699. X            XmListAddItems(filelistW, list_items, item_count, 0);
  700. X
  701. X            /* Set status line */
  702. X            sprintf(line, "Connected to: %s", text);
  703. X            ui_set_status_line(line);
  704. X            set_currdir();
  705. X        }
  706. X        else
  707. X        ui_beep(0);
  708. X    }
  709. X    else
  710. X        ui_beep(0);
  711. X    }
  712. X    
  713. X    XmStringFreeContext(context);
  714. X}
  715. X
  716. X/************************** misc functions *****************************/
  717. X
  718. X
  719. Xvoid set_currdir(void)
  720. X{
  721. X    char *path;
  722. X
  723. X    path = ctrl_get_item_name(-1);
  724. X    ui_set_currdir(path);
  725. X
  726. X    free(path);
  727. X}
  728. X
  729. X
  730. Xvoid str_to_ascii(char *str)
  731. X{
  732. X    int i, len;
  733. X
  734. X    len = strlen(str);
  735. X    for (i=0; i < len; i++)
  736. X    {
  737. X    if (!isprint(str[i]) && !isspace(str[i])) str[i] = ' ';
  738. X    }
  739. X}
  740. X
  741. Xvoid handle_sigint(void)
  742. X{
  743. X    char filepath[50];
  744. X
  745. X    /*
  746. X     * Save cache, if needed
  747. X     */
  748. X    if (user_prefs.autosave_dir && fConnected)
  749. X    ctrl_save_cache();
  750. X
  751. X    /*
  752. X     * Heinous hack to clean up /tmp.  This stuff should really 
  753. X     * be done by the control module
  754. X     */
  755. X    sprintf(filepath, "/tmp/xgetftpVIEW%ld", getpid());
  756. X    unlink(filepath);
  757. X
  758. X    exit(1);
  759. X}
  760. X
  761. X
  762. X/************************** main program *******************************/
  763. X
  764. Xmain(int argc, char *argv[])
  765. X{
  766. X    Arg args[4];
  767. X    char *hostname = NULL;
  768. X    struct passwd *pwd;
  769. X    char myhostname[100];
  770. X    char mydomainname[100];
  771. X    char username[50];
  772. X    struct hostent *hent;
  773. X
  774. X    /*
  775. X     * init toolkit & create toplevel widgets 
  776. X     */
  777. X    ui_initialize(&argc, argv);
  778. X
  779. X
  780. X    /*
  781. X     * Check & get args
  782. X     */
  783. X    if (argc == 2)
  784. X    {
  785. X    if (strcmp(argv[1], "-q") == 0)
  786. X        response_stream = fopen("/dev/null", "w");
  787. X    else
  788. X        hostname = argv[1];
  789. X    }
  790. X    else if (argc == 3)
  791. X    {
  792. X    if (strcmp(argv[1], "-q") == 0)
  793. X        response_stream = fopen("/dev/null", "w");
  794. X    else
  795. X        fprintf(stderr, "usage: %s [-q] [hostname]\n", argv[0]);
  796. X
  797. X    hostname = argv[2];
  798. X    }
  799. X    else if (argc > 3)
  800. X    {
  801. X    fprintf(stderr, "usage: %s [-q] [hostname]\n", argv[0]);
  802. X    exit(1);
  803. X    }
  804. X
  805. X
  806. X    /*
  807. X     * create menus (ie, menubarW)
  808. X     */
  809. X    ui_create_menus(mainwindowW, (XtCallbackProc) MenuButtonCB);
  810. X
  811. X
  812. X    /*
  813. X     * create work window (file list, etc)
  814. X     */
  815. X    ui_create_work_window(mainwindowW, (XtCallbackProc) doubleclickCB,
  816. X    (XtCallbackProc) selectionCB);
  817. X
  818. X
  819. X    /*
  820. X     * create commands
  821. X     */
  822. X    ui_create_commands(mainwindowW, (XtCallbackProc) commandCB,
  823. X    (XtCallbackProc) typetoggleCB);
  824. X
  825. X
  826. X    /*
  827. X     * create info window (label)
  828. X     */
  829. X    ui_create_status_line(mainwindowW);
  830. X
  831. X    /*
  832. X     * put together all the components
  833. X     */
  834. X    XmMainWindowSetAreas(mainwindowW, menubarW, cmdrowcolW, NULL, NULL,
  835. X    workframeW);
  836. X    XtSetArg(args[0], XmNmessageWindow, statuslineW);
  837. X    XtSetValues(mainwindowW, args, 1);
  838. X
  839. X
  840. X    /*
  841. X     * create popup text viewing widget
  842. X     */
  843. X    ui_create_view_dialog(toplevelW);
  844. X
  845. X
  846. X    /*
  847. X     * create popup archie widget
  848. X     */
  849. X    ui_create_archie_dialog(toplevelW, (XtCallbackProc) archiefindCB);
  850. X
  851. X
  852. X    /*
  853. X     * create popup "About.." dialog
  854. X     */
  855. X    ui_create_about_dialog(toplevelW);            
  856. X
  857. X
  858. X    /*
  859. X     * create popup host prompt dialog
  860. X     */
  861. X    ui_create_open_dialog(toplevelW, (XtCallbackProc) openconnokCB);
  862. X
  863. X
  864. X    /*
  865. X     * check user preferences
  866. X     */
  867. X    user_prefs.cache_view = 1;
  868. X    user_prefs.reuse_view = 1;
  869. X    user_prefs.reuse_dir = 1;
  870. X    user_prefs.autosave_dir = 1;
  871. X    user_prefs.confirm = 0;
  872. X
  873. X    ui_create_pref_dialog(toplevelW, (XtCallbackProc) userprefCB, &user_prefs);
  874. X
  875. X
  876. X    /*
  877. X     * set retrieve directory
  878. X     */
  879. X    if (getcwd(retrieve_dir, 253) == NULL)
  880. X    retrieve_dir[0] = '\0';
  881. X
  882. X    ui_create_retrieve_dir_dialog(toplevelW, (XtCallbackProc) setretrievedirCB,
  883. X    retrieve_dir);
  884. X
  885. X
  886. X     /*
  887. X      * Figure out a password for anonymous login
  888. X      */
  889. X     if (pwd = getpwuid(getuid()))
  890. X    strcpy(username, pwd->pw_name);
  891. X     else
  892. X    strcpy(username, "nobody");
  893. X
  894. X     if (gethostname(myhostname, 100) != 0)
  895. X    strcpy(myhostname, "unknown");
  896. X
  897. X#ifdef NEVER
  898. X     if (getdomainname(mydomainname, 100) != 0)
  899. X    strcpy(mydomainname, "unknown");
  900. X#endif
  901. X
  902. X     if ((hent = gethostbyname(myhostname)) == NULL)
  903. X         sprintf(password, "%s@%s.%s", username, myhostname);
  904. X     else
  905. X    sprintf(password, "%s@%s", username, hent->h_name);
  906. X
  907. X#ifdef DEBUG
  908. X    printf("Anonymous password = %s\n", password);
  909. X#endif
  910. X
  911. X
  912. X    /*
  913. X     * connect to ftp server, if needed
  914. X     *
  915. X     * WARNING: We _MUST_ have the correct user_preferences before we
  916. X     *          give any ctrl commands!
  917. X     */
  918. X    if (hostname && ctrl_login(hostname, "anonymous", password))
  919. X    {
  920. X        char line[100];
  921. X
  922. X    fConnected = TRUE;
  923. X        ctrl_start_session(alloc_list_mem, add_list_item);
  924. X        XmListAddItems(filelistW, list_items, item_count, 0);
  925. X    sprintf(line, "Connected to: %s", hostname);
  926. X    ui_set_status_line(line);
  927. X    set_currdir();
  928. X    }
  929. X    else
  930. X    {
  931. X    ui_set_status_line(" ");
  932. X    }
  933. X
  934. X
  935. X    /*
  936. X     * Handle ^C
  937. X     */
  938. X    signal(SIGINT, handle_sigint);
  939. X
  940. X
  941. X    /*
  942. X     * get & dispatch events 
  943. X     */
  944. X    XtRealizeWidget(toplevelW);
  945. X    XtAppMainLoop(app_context);
  946. X}
  947. X
  948. END_OF_FILE
  949. if test 18209 -ne `wc -c <'main.c'`; then
  950.     echo shar: \"'main.c'\" unpacked with wrong size!
  951. fi
  952. # end of 'main.c'
  953. fi
  954. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  955.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  956. else
  957. echo shar: Extracting \"'patchlevel.h'\" \(40 characters\)
  958. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  959. X#define VERSION        1
  960. X#define PATCHLEVEL    0
  961. END_OF_FILE
  962. if test 40 -ne `wc -c <'patchlevel.h'`; then
  963.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  964. fi
  965. # end of 'patchlevel.h'
  966. fi
  967. if test -f 'prefs.c' -a "${1}" != "-c" ; then 
  968.   echo shar: Will not clobber existing file \"'prefs.c'\"
  969. else
  970. echo shar: Extracting \"'prefs.c'\" \(3209 characters\)
  971. sed "s/^X//" >'prefs.c' <<'END_OF_FILE'
  972. X/**************************************************************************
  973. X * MODULE:
  974. X *  prefs
  975. X *
  976. X * DESCRIPTION:
  977. X *  User preference routines
  978. X *
  979. X * AUTHOR:
  980. X *  Salim Alam
  981. X *  University of Colorado, Boulder
  982. X *
  983. X * MODIFICATION LOG:
  984. X *  92.12.31 S.A. Fixed bug in saving prefs
  985. X *
  986. X *************************************************************************/
  987. X
  988. X#include <X11/Xos.h>
  989. X#include <stdlib.h>
  990. X#include <stdio.h>
  991. X#include "prefs.h"
  992. X
  993. X#define RCFILENAME    ".xgetftprc"
  994. X
  995. X
  996. X#ifndef TRUE
  997. X#define TRUE 1
  998. X#define FALSE 0
  999. X#endif
  1000. X
  1001. X
  1002. Xint prefs_save(Prefs prefs)
  1003. X/*
  1004. X * Save the preferences in prefs to $HOME/.xgetftprc
  1005. X *
  1006. X * Returns TRUE if successful, FALSE otherwise.
  1007. X */
  1008. X{
  1009. X    FILE *fp;
  1010. X    char *home_path;
  1011. X    char *complete_name;
  1012. X
  1013. X    if ( (home_path = getenv("HOME")) == NULL )
  1014. X    {
  1015. X    fprintf(stderr, "prefs_save: can't find $HOME.\n");
  1016. X    return FALSE;
  1017. X    }
  1018. X
  1019. X    complete_name = malloc(strlen(home_path) + strlen(RCFILENAME) + 2);
  1020. X
  1021. X    sprintf(complete_name, "%s/%s", home_path, RCFILENAME);
  1022. X
  1023. X    if ( (fp=fopen(complete_name, "w")) == NULL )
  1024. X    {
  1025. X    fprintf(stderr, "prefs_save: can't open file '%s'.\n", complete_name);
  1026. X    free(complete_name);
  1027. X    return FALSE;
  1028. X    }
  1029. X
  1030. X    /*
  1031. X     * Save the preferences strings
  1032. X     */
  1033. X
  1034. X    if (prefs.reuse_dir)
  1035. X    fprintf(fp, "REUSE_DIR\n");
  1036. X    if (prefs.cache_view)
  1037. X    fprintf(fp, "CACHE_VIEW\n");
  1038. X    if (prefs.reuse_view)
  1039. X    fprintf(fp, "REUSE_VIEW\n");
  1040. X    if (prefs.autosave_dir)
  1041. X    fprintf(fp, "AUTOSAVE_DIR\n");
  1042. X    if (prefs.confirm)
  1043. X    fprintf(fp, "CONFIRM\n");
  1044. X
  1045. X
  1046. X    fclose(fp);
  1047. X    free(complete_name);
  1048. X    return TRUE;
  1049. X}
  1050. X
  1051. X
  1052. Xint prefs_load(Prefs *pprefs)
  1053. X/*
  1054. X * Save the preferences in prefs to $HOME/.xgetftprc
  1055. X *
  1056. X * Returns TRUE if successful, FALSE otherwise.
  1057. X */
  1058. X{
  1059. X    FILE *fp;
  1060. X    char *home_path;
  1061. X    char *complete_name;
  1062. X    char pref_str[50];
  1063. X
  1064. X    if ( (home_path = getenv("HOME")) == NULL )
  1065. X    {
  1066. X    fprintf(stderr, "prefs_load: can't find $HOME.\n");
  1067. X    return FALSE;
  1068. X    }
  1069. X
  1070. X    complete_name = malloc(strlen(home_path) + strlen(RCFILENAME) + 2);
  1071. X
  1072. X    sprintf(complete_name, "%s/%s", home_path, RCFILENAME);
  1073. X
  1074. X    if ( (fp=fopen(complete_name, "r")) == NULL )
  1075. X    {
  1076. X    fprintf(stderr, "prefs_load: can't open file '%s'.\n", complete_name);
  1077. X    free(complete_name);
  1078. X    return FALSE;
  1079. X    }
  1080. X
  1081. X    pprefs->reuse_dir = 0;
  1082. X    pprefs->cache_view = 0;
  1083. X    pprefs->reuse_view = 0;
  1084. X    pprefs->autosave_dir = 0;
  1085. X    pprefs->confirm = 0;
  1086. X
  1087. X    while (!feof(fp))
  1088. X    {
  1089. X    if (fgets(pref_str, 48, fp) == NULL)
  1090. X        break;
  1091. X    
  1092. X    if (strcmp(pref_str, "REUSE_DIR\n") == 0)
  1093. X        pprefs->reuse_dir = 1;
  1094. X    if (strcmp(pref_str, "CACHE_VIEW\n") == 0)
  1095. X        pprefs->cache_view = 1;
  1096. X    if (strcmp(pref_str, "REUSE_VIEW\n") == 0)
  1097. X        pprefs->reuse_view = 1;
  1098. X    if (strcmp(pref_str, "AUTOSAVE_DIR\n") == 0)
  1099. X        pprefs->autosave_dir = 1;
  1100. X    if (strcmp(pref_str, "CONFIRM\n") == 0)
  1101. X        pprefs->confirm = 1;
  1102. X    }
  1103. X
  1104. X    fclose(fp);
  1105. X    free(complete_name);
  1106. X    return TRUE;
  1107. X}
  1108. X
  1109. X
  1110. Xvoid prefs_print(Prefs prefs, char *name)
  1111. X{
  1112. X    printf("%s.reuse_dir = %d\n", name, prefs.reuse_dir);
  1113. X    printf("%s.cache_view = %d\n", name, prefs.cache_view);
  1114. X    printf("%s.reuse_view = %d\n", name, prefs.reuse_view);
  1115. X    printf("%s.autosave_dir = %d\n", name, prefs.autosave_dir);
  1116. X    printf("%s.confirm = %d\n\n", name, prefs.confirm);
  1117. X}
  1118. END_OF_FILE
  1119. if test 3209 -ne `wc -c <'prefs.c'`; then
  1120.     echo shar: \"'prefs.c'\" unpacked with wrong size!
  1121. fi
  1122. # end of 'prefs.c'
  1123. fi
  1124. if test -f 'prefs.h' -a "${1}" != "-c" ; then 
  1125.   echo shar: Will not clobber existing file \"'prefs.h'\"
  1126. else
  1127. echo shar: Extracting \"'prefs.h'\" \(957 characters\)
  1128. sed "s/^X//" >'prefs.h' <<'END_OF_FILE'
  1129. X/*************************************************************************
  1130. X *
  1131. X * HEADER: 
  1132. X *  prefs
  1133. X *
  1134. X **************************************************************************/
  1135. X
  1136. X/*
  1137. X * User Preference ids
  1138. X */
  1139. X#define prefCACHE_VIEW       1
  1140. X#define prefREUSE_VIEW       2
  1141. X#define prefREUSE_DIR        3
  1142. X#define prefAUTOSAVE_DIR     4
  1143. X#define prefCONFIRM          5
  1144. X
  1145. X
  1146. X/*
  1147. X * User Preference structure
  1148. X */
  1149. Xtypedef struct _pref
  1150. X{
  1151. X    char cache_view;        /* save viewed files or not?      */
  1152. X    char reuse_view;        /* reuse previous view caches?    */
  1153. X    char reuse_dir;        /* reuse previous dir cache?      */
  1154. X    char autosave_dir;        /* save directory cache upon exit?*/
  1155. X    char confirm;        /* ask user before reusing cache? */
  1156. X    char show_hidden;        /* show hidden files?          */
  1157. X    char log_session;        /* log ftp session?          */
  1158. X} Prefs;
  1159. X
  1160. X
  1161. X/*
  1162. X * Exported variables
  1163. X */
  1164. Xextern Prefs     user_prefs;    /* User preferences             */
  1165. X
  1166. Xint
  1167. Xprefs_save(Prefs prefs);
  1168. X
  1169. Xint
  1170. Xprefs_load(Prefs *pprefs);
  1171. X
  1172. END_OF_FILE
  1173. if test 957 -ne `wc -c <'prefs.h'`; then
  1174.     echo shar: \"'prefs.h'\" unpacked with wrong size!
  1175. fi
  1176. # end of 'prefs.h'
  1177. fi
  1178. echo shar: End of archive 3 \(of 4\).
  1179. cp /dev/null ark3isdone
  1180. MISSING=""
  1181. for I in 1 2 3 4 ; do
  1182.     if test ! -f ark${I}isdone ; then
  1183.     MISSING="${MISSING} ${I}"
  1184.     fi
  1185. done
  1186. if test "${MISSING}" = "" ; then
  1187.     echo You have unpacked all 4 archives.
  1188.     rm -f ark[1-9]isdone
  1189. else
  1190.     echo You still need to unpack the following archives:
  1191.     echo "        " ${MISSING}
  1192. fi
  1193. ##  End of shell archive.
  1194. exit 0
  1195.  
  1196. exit 0 # Just in case...
  1197. -- 
  1198.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  1199. \X/  Amiga - The only way to fly!      |
  1200.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  1201.   casual observer..."                  |
  1202.