home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume20 / xarchie / part09 < prev    next >
Encoding:
Text File  |  1993-06-14  |  50.4 KB  |  1,725 lines

  1. Newsgroups: comp.sources.x
  2. From: ferguson@cs.rochester.edu (George Ferguson)
  3. Subject: v20i037:  xarchie - An X browser interface to Archie, v2.0.6, Part09/24
  4. Message-ID: <1993Jun15.223304.487@sparky.imd.sterling.com>
  5. X-Md4-Signature: cc5378f23dad705dff4ca42e79e71845
  6. Sender: chris@sparky.imd.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Tue, 15 Jun 1993 22:33:04 GMT
  9. Approved: chris@sparky.imd.sterling.com
  10.  
  11. Submitted-by: ferguson@cs.rochester.edu (George Ferguson)
  12. Posting-number: Volume 20, Issue 37
  13. Archive-name: xarchie/part09
  14. Environment: X11
  15. Supersedes: xarchie: Volume 14, Issue 82-90
  16.  
  17. Submitted-by: ferguson@cs.rochester.edu
  18. Archive-name: xarchie-2.0.6/part09
  19.  
  20. #!/bin/sh
  21. # this is Part.09 (part 9 of xarchie-2.0.6)
  22. # do not concatenate these parts, unpack them in order with /bin/sh
  23. # file xarchie-2.0.6/ftp.c continued
  24. #
  25. if test ! -r _shar_seq_.tmp; then
  26.     echo 'Please unpack part 1 first!'
  27.     exit 1
  28. fi
  29. (read Scheck
  30.  if test "$Scheck" != 9; then
  31.     echo Please unpack part "$Scheck" next!
  32.     exit 1
  33.  else
  34.     exit 0
  35.  fi
  36. ) < _shar_seq_.tmp || exit 1
  37. if test ! -f _shar_wnt_.tmp; then
  38.     echo 'x - still skipping xarchie-2.0.6/ftp.c'
  39. else
  40. echo 'x - continuing file xarchie-2.0.6/ftp.c'
  41. sed 's/^X//' << 'SHAR_EOF' >> 'xarchie-2.0.6/ftp.c' &&
  42. }
  43. X
  44. /*    -    -    -    -    -    -    -    -    */
  45. /* Functions called by ftpProcessReply(): */
  46. X
  47. static void
  48. ftpSendType(ftpc)
  49. FtpContext *ftpc;
  50. {
  51. X    char cmd[16];
  52. X
  53. X    DEBUG2("ftpSendType: ftpc=0x%x, type=%d\n",ftpc,ftpc->type);
  54. X    ftpc->state = FTPS_TYPE;
  55. X    switch (ftpc->type) {
  56. X      case TYPE_A:
  57. X     sprintf(cmd,"TYPE A");
  58. X    break;
  59. X      case TYPE_E:
  60. X    sprintf(cmd,"TYPE E");
  61. X    break;
  62. X      case TYPE_I:
  63. X    sprintf(cmd,"TYPE I");
  64. X    break;
  65. X      default:
  66. X    sprintf(cmd,"TYPE L %d",(char *)ftpc->type);
  67. X    }
  68. X    status0(cmd);
  69. X    ftpSendCmd(ftpc,cmd);
  70. X    DEBUG0("ftpSendType: done\n");
  71. }
  72. X
  73. static void
  74. ftpSendNextCwd(ftpc)
  75. FtpContext *ftpc;
  76. {
  77. X    char *slash,cmd[256];
  78. X
  79. X    DEBUG2("ftpSendNextCwd: ftpc=0x%x, wd=\"%s\"\n",ftpc,ftpc->wd);
  80. X    if (*(ftpc->wd) == '/') {    /* Leading slash treated specially... */
  81. X    ftpc->state = FTPS_CWD;
  82. X    ftpSendCmd(ftpc,"CWD /");
  83. X    ftpc->wd += 1;
  84. X    } else {            /* Normal case */
  85. X    if ((slash=index(ftpc->wd,'/')) != NULL) {
  86. X        *slash = '\0';
  87. X    }
  88. X    sprintf(cmd,"CWD %s",ftpc->wd);
  89. X    status0(cmd);
  90. X    ftpc->state = FTPS_CWD;
  91. X    ftpSendCmd(ftpc,cmd);
  92. X    if (slash) {
  93. X        ftpc->wd = slash+1;
  94. X    } else {
  95. X        /* set wd to end of string */
  96. X        while (*(ftpc->wd) != '\0')
  97. X        ftpc->wd += 1;
  98. X    }
  99. X    }
  100. X    DEBUG0("ftpSendNextCwd: done\n");
  101. }
  102. X
  103. /*
  104. X * Performs the PORT command. The new port is saved in f->port.
  105. X * Returns < 0 if some local error, otherwise 0 if we got to sending
  106. X * the command.
  107. X */
  108. static int
  109. ftpSendPort(ftpc)
  110. FtpContext *ftpc;
  111. {
  112. X    char cmd[64];
  113. X    struct sockaddr_in addr;
  114. X    int addrlen;
  115. X
  116. X    DEBUG1("ftpSendPort: ftpc=0x%lx\n",ftpc);
  117. X    if ((ftpc->port=socket(AF_INET,SOCK_STREAM,0)) < 0) {
  118. X    sysError("socket(ftpSendPort)");
  119. X    DEBUG0("ftpSendPort: returning -1\n");
  120. X    return(-1);
  121. X    }
  122. X    DEBUG1("ftpSendPort: socket() returned %d\n",ftpc->port);
  123. X    addr = ftpc->saddr;
  124. X    addr.sin_port = 0;
  125. X    if (bind(ftpc->port,(struct sockaddr *)&addr,
  126. X         sizeof(struct sockaddr_in)) < 0) {
  127. X    sysError("bind(ftpSendPort)");
  128. X    DEBUG1("ftpSendPort: closing port %d\n",ftpc->port);
  129. X    close(ftpc->port);
  130. X    DEBUG0("ftpSendPort: returning -1\n");
  131. X    return(-1);
  132. X    }
  133. X    DEBUG0("ftpSendPort: bind() succeeded\n");
  134. X    if (listen(ftpc->port,1) < 0) {
  135. X    sysError("listen(ftpSendPort)");
  136. X    DEBUG1("ftpSendPort: closing port %d\n",ftpc->port);
  137. X    close(ftpc->port);
  138. X    DEBUG0("ftpSendPort: returning -1\n");
  139. X    return(-1);
  140. X    }
  141. X    DEBUG0("ftpSendPort: listen() succeeded\n");
  142. X    addrlen = sizeof(struct sockaddr_in);
  143. X    if (getsockname(ftpc->port,(struct sockaddr *)&addr,&addrlen) < 0) {
  144. X    sysError("getsockname(ftpSendPort)");
  145. X    DEBUG1("ftpSendPort: closing port %d\n",ftpc->port);
  146. X    close(ftpc->port);
  147. X    DEBUG0("ftpSendPort: returning -1\n");
  148. X    return(-1);
  149. X    }
  150. X    DEBUG2("ftpSendPort: PORT address: %s; port: %d\n",
  151. X       inet_ntoa(addr.sin_addr),addr.sin_port);
  152. X    sprintf(cmd,"PORT %d,%d,%d,%d,%d,%d",
  153. X        (int)((unsigned char *)&addr.sin_addr.s_addr)[0],
  154. X        (int)((unsigned char *)&addr.sin_addr.s_addr)[1],
  155. X        (int)((unsigned char *)&addr.sin_addr.s_addr)[2],
  156. X        (int)((unsigned char *)&addr.sin_addr.s_addr)[3],
  157. X        (int)((unsigned char *)&addr.sin_port)[0],
  158. X        (int)((unsigned char *)&addr.sin_port)[1]);
  159. X    status0(cmd);
  160. X    ftpc->state = FTPS_PORT;
  161. X    ftpSendCmd(ftpc,cmd);
  162. X    DEBUG0("ftpSendPort: returning 0\n");
  163. X    return(0);
  164. }
  165. X
  166. X
  167. /*
  168. X * After PORT is ok, send GET or PUT to open the dataconn.
  169. X */
  170. static void
  171. ftpSendGetPut(ftpc)
  172. FtpContext *ftpc;
  173. {
  174. X    char cmd[MAXPATHLEN];
  175. X
  176. X    DEBUG2("ftpSendGetPut: ftpc=0x%x, fcmd=%d\n",ftpc,ftpc->filecmd);
  177. X    ftpc->state = FTPS_GETPUT;
  178. X    switch (ftpc->filecmd) {
  179. X      case FTP_GET:
  180. X    sprintf(cmd,"RETR %s",ftpc->files[ftpc->this_file]);
  181. X    break;
  182. X      case FTP_PUT:
  183. X    sprintf(cmd,"STOR %s",ftpc->files[ftpc->this_file]);
  184. X    break;
  185. X    }
  186. X    status0(cmd);
  187. X    ftpSendCmd(ftpc,cmd);
  188. X    DEBUG0("ftpSendGetPut: done\n");
  189. }
  190. X
  191. /*
  192. X * After GET/PUT, accepts the connection from the PORT and closes the
  193. X * the PORT. Returns the dataconn fd (also in ftpc->data).
  194. X */
  195. static int
  196. ftpAcceptDataConn(ftpc)
  197. FtpContext *ftpc;
  198. {
  199. X    int datacon,addrlen;
  200. X    struct sockaddr_in addr;
  201. X
  202. X    DEBUG1("ftpAcceptDataConn: fcmd %d successful\n",ftpc->filecmd);
  203. X    addrlen = sizeof(struct sockaddr_in);
  204. X    if ((datacon=accept(ftpc->port,(struct sockaddr *)&addr,&addrlen)) < 0) {
  205. X    sysError("accept(ftpAcceptDataConn)");
  206. X    DEBUG0("ftpAcceptDataConn: returning -1\n");
  207. X    return(-1);
  208. X    }
  209. X    DEBUG1("ftpAcceptDataConn: closing port %d\n",ftpc->port);
  210. X    close(ftpc->port);
  211. X    ftpc->port = -1;
  212. X    DEBUG1("ftpAcceptDataConn: registering dataconn %d\n",datacon);
  213. X    ftpc->data = datacon;
  214. X    MAKE_NONBLOCKING(ftpc->data);
  215. X    RegisterFtpFd(ftpc,ftpc->data,O_RDONLY,ftpDataCallback);
  216. X    DEBUG1("ftpAcceptDataConn: returning dataconn = %d\n",datacon);
  217. X    return(datacon);
  218. }
  219. X
  220. /*
  221. X * Once the remote file is ready for transfer through the dataconn, this
  222. X * function sets up the local end. Returns -1 on error, otherwise 0.
  223. X */
  224. static int
  225. ftpSetupLocalData(ftpc)
  226. FtpContext *ftpc;
  227. {
  228. X    char filename[MAXPATHLEN];
  229. X
  230. X    DEBUG1("ftpSetupLocalData: ftpc=0x%x\n",ftpc);
  231. X    if (ftpc->local_dir && *(ftpc->local_dir)) {
  232. X    sprintf(filename,"%s/%s",ftpc->local_dir,ftpc->files[ftpc->this_file]);
  233. X    } else {
  234. X    strcpy(filename,ftpc->files[ftpc->this_file]);
  235. X    }
  236. X    DEBUG1("ftpSetupLocalData: opening \"%s\"\n",filename);
  237. X    if (ftpc->filecmd == FTP_GET) {
  238. X    ftpc->local_fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0644);
  239. X    } else {
  240. X    ftpc->local_fd = open(filename,O_RDONLY,0);
  241. X    }
  242. X    if (ftpc->local_fd < 0) {
  243. X    sysError(filename);
  244. X    DEBUG0("ftpSetupLocalData: returning -1\n");
  245. X    return(-1);
  246. X    }
  247. X    DEBUG1("ftpSetupLocalData: got local fd = %d\n",ftpc->local_fd);
  248. X    ftpc->num_bytes = 0;
  249. X    DEBUG0("ftpSetupLocalData: returning 0\n");
  250. X    return(0);
  251. }
  252. X
  253. /*    -    -    -    -    -    -    -    -    */
  254. /* Data connection processing: */
  255. /*
  256. X * This function is called whenever the dataconn is ready for read/write.
  257. X */
  258. static void
  259. ftpDataCallback(ftpc)
  260. FtpContext *ftpc;
  261. {
  262. X    DEBUG2("ftpDataCallback: ftpc=0x%x, fcmd=%d\n",ftpc,ftpc->filecmd);
  263. X    switch (ftpc->filecmd) {
  264. X      case FTP_GET:
  265. X    ftpReadData(ftpc);
  266. X    break;
  267. X      case FTP_PUT:
  268. X    ftpWriteData(ftpc);
  269. X    break;
  270. X      default:
  271. X    fprintf(stderr,"ftpDataCallback: unknown cmd: %d\n",ftpc->filecmd);
  272. X    abort();
  273. X    }
  274. X    DEBUG0("ftpDataCallback: done\n");
  275. }
  276. X
  277. /*
  278. X * This function is called to read from the dataconn and write to the
  279. X * local_fd. On EOF, it sets the state field to FTPS_EOF and calls
  280. X * ftpInitReply() to continue the session. On error, it calls
  281. X * ftpSendAbort() and then ftpInitReply(). Otherwise the transfer
  282. X * is ongoing, so it doesn't do anything.
  283. X */
  284. static void
  285. ftpReadData(ftpc)
  286. FtpContext *ftpc;
  287. {
  288. X    char buf[BUFSIZ*4],*s,*t,msg[256];
  289. X    int nread,i;
  290. X
  291. X    DEBUG0("ftpReadData: reading\n");
  292. X    /* Read one chunk of stuff and write it locally (don't loop or
  293. X     * X won't get a chance to dispatch).
  294. X     */
  295. X    nread = read(ftpc->data,buf,sizeof(buf));
  296. X    if (nread > 0) {
  297. X    /* Strip CR's if necessary */
  298. X    if (ftpc->type == TYPE_A && ftpc->stripcr) {
  299. X        DEBUG0("ftpReadData: stripping <CR>\n");
  300. X        for (s=t=buf,i=nread; i--; ++s) {
  301. X        if (*s != '\r')
  302. X            *t++ = *s;
  303. X        }
  304. X    }
  305. X    /* Write locally */
  306. X    if (write(ftpc->local_fd,buf,nread) != nread) {
  307. X        /* Error when writing */
  308. X        sysError("write(ftpReadData)");
  309. X        ftpCleanupDataConn(ftpc);
  310. X        ftpSendAbort(ftpc);
  311. X        ftpInitReply(ftpc);
  312. X    } else {
  313. X        /* write was ok */
  314. X        ftpc->num_bytes += nread;
  315. X        DEBUG1("ftpReadData: total = %d\n",ftpc->num_bytes);
  316. X        if (ftpc->this_size != 0) {
  317. X        sprintf(msg,"%.200s: %d/%d",ftpc->files[ftpc->this_file],
  318. X            (char *)(ftpc->num_bytes),(char *)(ftpc->this_size));
  319. X        } else {
  320. X        sprintf(msg,"%.200s: %d bytes",ftpc->files[ftpc->this_file],
  321. X            (char *)(ftpc->num_bytes));
  322. X        }
  323. X        status0(msg);
  324. X    }
  325. X    } else if (nread < 0 && errno == ITWOULDBLOCK) {
  326. X    /* Nothing more ready now, keep waiting */
  327. X    DEBUG0("ftpReadData: dataconn would block\n");
  328. X    } else if (nread < 0) {
  329. X    /* Error when reading */
  330. X    sysError("read(ftpReadData)");
  331. X    DEBUG0("ftpReadData: error reading dataconn\n");
  332. X    ftpCleanupDataConn(ftpc);
  333. X    ftpSendAbort(ftpc);
  334. X    ftpInitReply(ftpc);
  335. X    } else if (nread == 0) {
  336. X    /* We got EOF on remote file. */
  337. X    DEBUG0("ftpReadData: EOF on dataconn\n");
  338. X    ftpCleanupDataConn(ftpc);
  339. X    if (ftpc->done1 != NULL)
  340. X        (*(ftpc->done1))(ftpc);
  341. X    ftpc->state = FTPS_EOF;
  342. X    ftpInitReply(ftpc);
  343. X    }
  344. }
  345. X
  346. /*ARGSUSED*/
  347. static void
  348. ftpWriteData(ftpc)
  349. FtpContext *ftpc;
  350. {
  351. X    /*EMPTY*/
  352. }
  353. X
  354. static void
  355. ftpCleanupDataConn(ftpc)
  356. FtpContext *ftpc;
  357. {
  358. X    /* Note: We may have already unregistered, eg, in ftpAbort(). */
  359. X    if (ftpc->state != FTPS_ABORT2)
  360. X    UnregisterFtpFd(ftpc,ftpc->data);
  361. X    if (ftpc->data != -1) {
  362. X    DEBUG1("ftpCleanupDataConn: closing data %d\n",ftpc->data);
  363. X    close(ftpc->data);
  364. X    ftpc->data = -1;
  365. X    }
  366. X    if (ftpc->local_fd != -1) {
  367. X    DEBUG1("ftpCleanupDataConn: closing local_fd %d\n",ftpc->local_fd);
  368. X    close(ftpc->local_fd);
  369. X    ftpc->local_fd = -1;
  370. X    }
  371. }
  372. X
  373. /*    -    -    -    -    -    -    -    -    */
  374. /* Sending commands to the server: */
  375. /*
  376. X * Adds CRLF and calls to ftpStartSendingCmd().
  377. X */
  378. static void
  379. ftpSendCmd(ftpc,cmd)
  380. FtpContext *ftpc;
  381. char *cmd;
  382. {
  383. X    char buf[MAXPATHLEN];
  384. X
  385. X    if (ftpc->trace) {
  386. X    (*(ftpc->trace))(ftpc,1,cmd);
  387. X    }
  388. X    sprintf(buf,"%s\r\n",cmd);
  389. X    ftpStartSendingCmd(ftpc,buf);
  390. }
  391. X
  392. /*
  393. X * Handles abort processing by sending the Telnet abort sequence in the
  394. X * out-of-band stream of the ctrl conn and the ABOR command on the regular
  395. X * stream.
  396. X */
  397. static void
  398. ftpSendAbort(ftpc)
  399. FtpContext *ftpc;
  400. {
  401. X    char buf[8];
  402. X    int sent;
  403. X
  404. X    DEBUG1("ftpSendAbort: ftpc=0x%lx\n",ftpc);
  405. X    DEBUG0("ftpSendAbort: sending <IAC><IP><IAC> in OOB\n");
  406. X    sprintf(buf,"%c%c%c",IAC,IP,IAC);
  407. X    do {
  408. X    sent = send(ftpc->ctrl,buf,3,MSG_OOB);
  409. X    } while (sent == -1 && errno == EINTR);
  410. X    if (sent != 3) {
  411. X    sysError("send(ftpSendAbort)");
  412. X    ftpDone(ftpc);
  413. X    }
  414. X    DEBUG0("ftpSendAbort: sending <DM>ABOR\n");
  415. X    sprintf(buf,"%cABOR\r\n",DM);
  416. X    do {
  417. X    sent = write(ftpc->ctrl,buf,strlen(buf));
  418. X    } while (sent == -1 && errno == EINTR);
  419. X    if (sent != strlen(buf)) {
  420. X    sysError("write(ftpSendAbort)");
  421. X    ftpDone(ftpc);
  422. X    }
  423. X    ftpc->state = FTPS_ABORT;
  424. X    ftpInitReply(ftpc);
  425. X    status0("Aborting...");
  426. X    DEBUG0("ftpSendAbort: done\n");
  427. }
  428. X
  429. /*
  430. X * This function starts sending CMD to the server over the control
  431. X * connection. The writes can block, hence this has to be able to finish
  432. X * later, but since they usually don't block, we don't set up to retry
  433. X * unless we have to. If the command is completely sent, then we call
  434. X * ftpInitReply() otherwise we setup to finish by registering the ctrlconn
  435. X * for writing via callback ftpWriteCallback().
  436. X */
  437. static void
  438. ftpStartSendingCmd(ftpc,cmd)
  439. FtpContext *ftpc;
  440. char *cmd;
  441. {
  442. X    int cmdlen,numsent;
  443. X
  444. X    DEBUG2("ftpStartSendingCmd: ftpc=0x%x: \"%s\"\n",ftpc,cmd);
  445. X    cmdlen = strlen(cmd);
  446. X    numsent = write(ftpc->ctrl,cmd,cmdlen);
  447. X    if (numsent < 0 && errno != ITWOULDBLOCK) {
  448. X    sysError("write(ftpStartSendingCmd)");
  449. X    DEBUG0("ftpStartSendingCmd: error writing ctrlconn\n");
  450. X    ftpDone(ftpc);
  451. X    return;
  452. X    } else if (numsent == cmdlen) {
  453. X    DEBUG0("ftpStartSendingCmd: write all done\n");
  454. X    ftpInitReply(ftpc);
  455. X    return;
  456. X    } else if (errno == ITWOULDBLOCK) {
  457. X    /* Otherwise the write would block, nothing sent */
  458. X    DEBUG0("ftpStartSendingCmd: write would block\n");
  459. X    numsent = 0;
  460. X    } else {
  461. X    /* Incomplete write */
  462. X    DEBUG1("ftpStartSendingCmd: write incomplete (%d bytes sent)\n",numsent);
  463. X    }
  464. X    /* Either way, if we get here there's something left do */
  465. X    cmd += numsent;
  466. X    if ((ftpc->cmd=malloc(strlen(cmd)+1)) == NULL) {
  467. X    sysError("malloc(ftpStartSendingCmd)");
  468. X    ftpDone(ftpc);
  469. X    return;
  470. X    }
  471. X    strcpy(ftpc->cmd,cmd);
  472. X    DEBUG1("ftpStartSendingCmd: pending: \"%s\"\n",ftpc->cmd);
  473. X    RegisterFtpFd(ftpc,ftpc->ctrl,O_WRONLY,ftpWriteCallback);
  474. }
  475. X
  476. /*
  477. X * This function is called when the ctrlconn is ready for writing.
  478. X * It sends as much as possible. If that completes the cmd, then it
  479. X * calls ftpInitReply(), otherwise updates the cmd with what's left
  480. X * and returns.
  481. X */
  482. static void
  483. ftpWriteCallback(ftpc)
  484. FtpContext *ftpc;
  485. {
  486. X    char *cmd;
  487. X    int cmdlen,numsent;
  488. X
  489. X    cmd = ftpc->cmd;
  490. X    DEBUG2("ftpWriteCallback: ftpc=0x%x: \"%s\"\n",ftpc,cmd);
  491. X    cmdlen = strlen(ftpc->cmd);
  492. X    numsent = write(ftpc->ctrl,cmd,cmdlen);
  493. X    if (numsent < 0 && errno != ITWOULDBLOCK) {
  494. X    sysError("write(ftpWriteCallback)");
  495. X    DEBUG0("ftpWriteCallback: error writing ctrlconn\n");
  496. X    ftpDone(ftpc);
  497. X    return;
  498. X    } else if (numsent == cmdlen) {
  499. X    DEBUG0("ftpWriteCallback: write all done\n");
  500. X    UnregisterFtpFd(ftpc,ftpc->ctrl);
  501. X    free(ftpc->cmd);
  502. X    ftpInitReply(ftpc);
  503. X    return;
  504. X    } else if (errno == ITWOULDBLOCK) {
  505. X    /* Otherwise the write would block, nothing sent */
  506. X    DEBUG0("ftpWriteCallback: write would block\n");
  507. X    numsent = 0;
  508. X    } else {
  509. X    /* Incomplete write */
  510. X    DEBUG1("ftpWriteCallback: write incomplete (%d bytes sent)\n",numsent);
  511. X    }
  512. X    /* Either way, if we get here there's something left do */
  513. X    cmd += numsent;
  514. X    free(ftpc->cmd);
  515. X    if ((ftpc->cmd=malloc(strlen(cmd)+1)) == NULL) {
  516. X    sysError("malloc(ftpWriteCallback)");
  517. X    ftpDone(ftpc);
  518. X    return;
  519. X    }
  520. X    strcpy(ftpc->cmd,cmd);
  521. X    DEBUG1("ftpWriteCallback: pending: \"%s\"\n",ftpc->cmd);
  522. }
  523. X
  524. /*    -    -    -    -    -    -    -    -    */
  525. /* Printing utilities for debugging */
  526. X
  527. #ifdef DEBUG
  528. char *
  529. ftpstatestr(state)
  530. int state;
  531. {
  532. X    char buf[8];
  533. X
  534. X    switch (state) {
  535. X    /* state */
  536. X      case FTPS_OPEN:        return("OPEN");
  537. X      case FTPS_CONNECT:    return("CONNECT");
  538. X      case FTPS_CONNECTED:    return("CONNECTED");
  539. X      case FTPS_USER:        return("USER");
  540. X      case FTPS_PASS:        return("PASS");
  541. X      case FTPS_CWD:        return("CWD");
  542. X      case FTPS_TYPE:        return("TYPE");
  543. X      case FTPS_READY:        return("READY");
  544. X      case FTPS_PORT:        return("PORT");
  545. X      case FTPS_GETPUT:        return("GETPUT");
  546. X      case FTPS_TRANSFER:    return("TRANSFER");
  547. X      case FTPS_EOF:        return("EOF");
  548. X      case FTPS_QUIT:        return("QUIT");
  549. X      case FTPS_ABORT:        return("ABORT");
  550. X      case FTPS_ABORT2:        return("ABORT2");
  551. X    /* reply_state */
  552. X      case FTPS_REPLY_CODE:    return("CODE");
  553. X      case FTPS_REPLY_CONT:    return("CONT");
  554. X      case FTPS_REPLY_LAST:    return("LAST");
  555. X      case FTPS_REPLY_MORE:    return("MORE");
  556. X      case FTPS_REPLY_CHCK:    return("CHCK");
  557. X      case FTPS_REPLY_IAC1:    return("IAC1");
  558. X      case FTPS_REPLY_IAC2:    return("IAC2");
  559. X      case FTPS_REPLY_IAC3:    return("IAC3");
  560. X      default:            sprintf(buf,"?%d?",state);
  561. X                return(buf);
  562. X    }
  563. }
  564. #endif /* DEBUG */
  565. X
  566. X
  567. /*    -    -    -    -    -    -    -    -    */
  568. /* Sample code for standalone client */
  569. X
  570. #ifdef STANDALONE
  571. X
  572. /* This is from Brendan... */
  573. #include <sys/types.h>        /* this may/will define FD_SET etc */
  574. #ifdef u3b2
  575. # include <sys/inet.h>        /* THIS does FD_SET etc on AT&T 3b2s.  */
  576. #endif
  577. X
  578. fd_set readfds,writefds;
  579. typedef void (*PF)();
  580. PF funcs[FD_SETSIZE];
  581. FtpContext *contexts[FD_SETSIZE];
  582. X
  583. void
  584. RegisterFtpFd(ftpc,fd,flags,func)
  585. FtpContext *ftpc;
  586. int fd,flags;
  587. void (*func)();
  588. {
  589. X    switch (flags) {
  590. X      case O_RDONLY:
  591. X    fprintf(stderr,"REGISTER fd %d, flags=RO\n",fd);
  592. X    FD_SET(fd,&readfds);
  593. X    FD_CLR(fd,&writefds);
  594. X    break;
  595. X      case O_WRONLY:
  596. X    fprintf(stderr,"REGISTER fd %d, flags=WO\n",fd);
  597. X    FD_CLR(fd,&readfds);
  598. X    FD_SET(fd,&writefds);
  599. X    break;
  600. X      case O_RDWR:
  601. X    fprintf(stderr,"REGISTER fd %d, flags=RW\n",fd);
  602. X    FD_SET(fd,&readfds);
  603. X    FD_SET(fd,&writefds);
  604. X    break;
  605. X    }
  606. X    funcs[fd] = func;
  607. X    contexts[fd] = ftpc;
  608. }
  609. X
  610. /*ARGSUSED*/
  611. void
  612. UnregisterFtpFd(ftpc,fd)
  613. FtpContext *ftpc;
  614. int fd;
  615. {
  616. X    fprintf(stderr,"UNREGISTER fd %d\n",fd);
  617. X    FD_CLR(fd,&readfds);
  618. X    FD_CLR(fd,&writefds);
  619. X    funcs[fd] = NULL;
  620. X    contexts[fd] = NULL;
  621. }
  622. X
  623. void
  624. done(ftpc)
  625. FtpContext *ftpc;
  626. {
  627. X    fprintf(stderr,"DONE!\n");
  628. X    ftpFreeContext(ftpc);
  629. X    exit(0);
  630. }
  631. X    
  632. void
  633. done1(ftpc)
  634. FtpContext *ftpc;
  635. {
  636. X    fprintf(stderr,"DONE1: \"%s\"\n",ftpc->files[ftpc->this_file]);
  637. }
  638. X    
  639. /*ARGSUSED*/
  640. void
  641. trace(ftpc,who,text)
  642. FtpContext *ftpc;
  643. int who;        /* 0 => recvd, non-0 => sent */
  644. char *text;
  645. {
  646. X    fprintf(stderr,"TRACE: ");
  647. X    if (who)    /* non-zero == us */
  648. X    fprintf(stderr,"ftp> ");
  649. X    fprintf(stderr,"%s",text);
  650. X    if (*(text+strlen(text)-1) != '\n')
  651. X    fprintf(stderr,"\n",text);
  652. }
  653. X    
  654. char *program;
  655. X
  656. main(argc,argv)
  657. int argc;
  658. char *argv[];
  659. {
  660. X    char *host,*cwd;
  661. X    FtpContext *ftpc;
  662. X    fd_set rfds,wfds;
  663. X    int fd;
  664. X
  665. X    if (argc < 3) {
  666. X    fprintf(stderr,"usage: %s host cwd files...\n",argv[0]);
  667. X    exit(1);
  668. X    }
  669. X    argc -= 1;
  670. X    program = *argv++;
  671. X    argc -= 1;
  672. X    host = *argv++;
  673. X    argc -= 1;
  674. X    cwd = *argv++;
  675. X    FD_ZERO(&rfds);
  676. X    FD_ZERO(&wfds);
  677. X    ftpc = ftpNewContext(host,"anonymous","ferguson@cs.rochester.edu",
  678. X             cwd,TYPE_I,1,1,FTP_GET,argv,argc,trace,done1,done);
  679. X    printf("Calling ftpStart...\n");
  680. X    ftpStart(ftpc);
  681. X    while (1) {
  682. X    bcopy((char *)&readfds,(char *)&rfds,sizeof(fd_set));
  683. X    bcopy((char *)&writefds,(char *)&wfds,sizeof(fd_set));
  684. X    fprintf(stderr,"select(): R=");
  685. X    for (fd=0; fd < FD_SETSIZE; fd++) {
  686. X        if (FD_ISSET(fd,&rfds))
  687. X        fprintf(stderr,"%d,",fd);
  688. X    }
  689. X    fprintf(stderr," W=");
  690. X    for (fd=0; fd < FD_SETSIZE; fd++) {
  691. X        if (FD_ISSET(fd,&wfds))
  692. X        fprintf(stderr,"%d,",fd);
  693. X    }
  694. X    fprintf(stderr,"\n");
  695. X    if (select(FD_SETSIZE,&rfds,&wfds,NULL,NULL) < 0) {
  696. X        perror(program);
  697. X        exit(1);
  698. X    }
  699. X    for (fd=0; fd < FD_SETSIZE; fd++) {
  700. X        if (FD_ISSET(fd,&rfds) || FD_ISSET(fd,&wfds)) {
  701. X        fprintf(stderr,"selected fd %d...\n",fd);
  702. X        (*(funcs[fd]))(contexts[fd]);
  703. X        }
  704. X    }
  705. X    }
  706. }
  707. X
  708. void
  709. sysError(s)
  710. char *s;
  711. {
  712. X    extern int errno;
  713. X    extern char *sys_errlist[];
  714. X    fprintf(stderr,"SYSERR: %s: %s\n",s,sys_errlist[errno]);
  715. }
  716. X
  717. void
  718. alert0(s)
  719. char *s;
  720. {
  721. X    fprintf(stderr,"ALERT: %s\n",s);
  722. }
  723. X
  724. void
  725. status0(s)
  726. char *s;
  727. {
  728. X    fprintf(stderr,"STATUS: %s\n",s);
  729. }
  730. X
  731. int
  732. ftpPrompt(ftpc)
  733. FtpContext *ftpc;
  734. {
  735. X    char c;
  736. X
  737. X    fprintf(stderr,"CONFIRM: %s %s [ynaq]",
  738. X        ftpfilecmdstr(ftpc->filecmd),ftpc->files[ftpc->this_file]);
  739. X    c = getchar();
  740. X    if (c != '\n')
  741. X    (void)getchar();
  742. X    switch (c) {
  743. X      case 'y': return(1);
  744. X      case 'n': return(0);
  745. X      case 'a': ftpc->prompt = 0;
  746. X            return(1);
  747. X      case 'q': ftpc->this_file = ftpc->num_files;
  748. X            return(0);
  749. X      default: return(1);
  750. X    }
  751. }
  752. #endif /*STANDALONE*/
  753. SHAR_EOF
  754. echo 'File xarchie-2.0.6/ftp.c is complete' &&
  755. chmod 0644 xarchie-2.0.6/ftp.c ||
  756. echo 'restore of xarchie-2.0.6/ftp.c failed'
  757. Wc_c="`wc -c < 'xarchie-2.0.6/ftp.c'`"
  758. test 46597 -eq "$Wc_c" ||
  759.     echo 'xarchie-2.0.6/ftp.c: original size 46597, current size' "$Wc_c"
  760. rm -f _shar_wnt_.tmp
  761. fi
  762. # ============= xarchie-2.0.6/ftp.h ==============
  763. if test -f 'xarchie-2.0.6/ftp.h' -a X"$1" != X"-c"; then
  764.     echo 'x - skipping xarchie-2.0.6/ftp.h (File already exists)'
  765.     rm -f _shar_wnt_.tmp
  766. else
  767. > _shar_wnt_.tmp
  768. echo 'x - extracting xarchie-2.0.6/ftp.h (Text)'
  769. sed 's/^X//' << 'SHAR_EOF' > 'xarchie-2.0.6/ftp.h' &&
  770. /*
  771. X * ftp.h : Definitions for the asynchronous FTP client
  772. X *
  773. X * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
  774. X * 28 Apr 1993: Changed constant from _FTP_H to _XA_FTP_H.
  775. X */
  776. X
  777. #ifndef _XA_FTP_H
  778. #define _XA_FTP_H_
  779. X
  780. #include <sys/types.h>
  781. #include <netinet/in.h>
  782. X
  783. #if NeedFunctionPrototypes
  784. struct _FtpContext;
  785. #endif
  786. X
  787. typedef void (*FtpCallbackProc)(
  788. #if NeedFunctionPrototypes
  789. X    struct _FtpContext* ftpc
  790. #endif
  791. );
  792. X
  793. typedef void (*FtpTraceProc)(
  794. #if NeedFunctionPrototypes
  795. X    struct _FtpContext* ftpc,
  796. X    int who,        /* 0 => recvd, non-0 => sent */
  797. X    char *text
  798. #endif
  799. );
  800. X
  801. typedef struct _FtpContext {
  802. X    /* Connection parameters */
  803. X    char *hostname;        /* hostname to contact */
  804. X    unsigned short servport;    /* port of ftp service */
  805. X    char **h_addr_list;        /* list of host addresses to try */
  806. X    char **this_addr;        /* which address are we trying */
  807. X    struct sockaddr_in saddr;    /* address of the control connection */
  808. X    /* Connection state */
  809. X    int state;            /* state of FTP process */
  810. X    int iostate;        /* connecting, reading, writing, or ready */
  811. X    int reply_state;        /* sub-state during reply parsing */
  812. X    int saved_state;        /* saved sub-state during IAC parsing */
  813. X    char *cmd;            /* pending part of cmd to send */
  814. X    /* Control connection */
  815. X    int    ctrl;            /* file descriptor of control connection */
  816. X    int    retcode;        /* code of last reply */
  817. X    int    tmpcode;        /* scratchpad for continuation lines */
  818. X    char reply[BUFSIZ<<4];     /* text of last reply */
  819. X    int reply_len;        /* length of reply (so far) */
  820. X    /* User transfer params */
  821. X    char *user;            /* usually anonymous */
  822. X    char *pass;            /* usually user@host.dom */
  823. X    char *cwd;            /* remote directory */
  824. X    char *wd;            /* the part of cwd remaining to do */
  825. X    char *local_dir;        /* directory for local files */
  826. X    int    type;            /* current transfer mode */
  827. X    int    stripcr;        /* 1 if want to remove CR from ASCII files */
  828. X    int prompt;            /* 1 to prompt during transfers */
  829. X    int filecmd;        /* FTP_GET or FTP_PUT */
  830. X    char **files;        /* array of files to GET or PUT */
  831. X    int num_files;        /* how many files */
  832. X    int this_file;        /* which file are we working on */
  833. X    int this_size;        /* how big is it (if we know) */
  834. X    FtpTraceProc trace;        /* called to trace transactions */
  835. X    FtpCallbackProc done;    /* called when connection finished */
  836. X    FtpCallbackProc done1;    /* called when each file transfer finished */
  837. X    /* Data connection */
  838. X    int    port;            /* the socket on which we will acccept(2) */
  839. X    int    data;            /* a data connection established */
  840. X    int local_fd;        /* fd for local copy of file (read or write) */
  841. X    int num_bytes;        /* bytes transferred this file */
  842. } FtpContext;
  843. X
  844. extern FtpContext *ftpNewContext(
  845. #if NeedFunctionPrototypes
  846. X    char *hostname, char *user, char *pass, char *cwd, char *local_dir,
  847. X    int type, int stripcr, int prompt,
  848. X    int filecmd, char **files, int num_files,
  849. X    FtpTraceProc trace, FtpCallbackProc done1, FtpCallbackProc done
  850. #endif
  851. );
  852. X
  853. extern void ftpStart(
  854. #if NeedFunctionPrototypes
  855. X    FtpContext *ftpc
  856. #endif
  857. );
  858. X
  859. extern void ftpAbort(
  860. #if NeedFunctionPrototypes
  861. X    FtpContext *ftpc
  862. #endif
  863. );
  864. X
  865. extern void ftpFreeContext(
  866. #if NeedFunctionPrototypes
  867. X    FtpContext *ftpc
  868. #endif
  869. );
  870. X
  871. /*
  872. X * Filecmd codes
  873. X */
  874. #define FTP_GET 1
  875. #define FTP_PUT 2
  876. X
  877. /* Values for state field of FtpContext */
  878. #define FTPS_OPEN        10
  879. #define FTPS_CONNECT        11
  880. #define FTPS_CONNECTED        12
  881. #define FTPS_USER        13
  882. #define FTPS_PASS        14
  883. #define FTPS_CWD        15
  884. #define FTPS_TYPE        16
  885. #define FTPS_READY        17
  886. #define FTPS_PORT        18
  887. #define FTPS_GETPUT        19
  888. #define FTPS_TRANSFER        20
  889. #define FTPS_EOF        21
  890. #define FTPS_QUIT        22
  891. #define FTPS_ABORT        23
  892. #define FTPS_ABORT2        24
  893. X
  894. /* Values for reply_state field of FtpContext */
  895. #define FTPS_REPLY_CODE        101
  896. #define FTPS_REPLY_CONT        102
  897. #define FTPS_REPLY_LAST        103
  898. #define FTPS_REPLY_MORE        104
  899. #define FTPS_REPLY_CHCK        105
  900. #define FTPS_REPLY_IAC1        106
  901. #define FTPS_REPLY_IAC2        107
  902. #define FTPS_REPLY_IAC3        108
  903. X
  904. /*
  905. X * Telnet codes
  906. X */
  907. #ifndef NO_ARPA_H
  908. # include <arpa/ftp.h>
  909. # include <arpa/telnet.h>
  910. #else
  911. X  /* <arpa/ftp.h>
  912. # define TYPE_A          1       /* ASCII */
  913. # define TYPE_E          2       /* EBCDIC */
  914. # define TYPE_I          3       /* image */
  915. # define TYPE_L          4       /* local byte size */
  916. X  /* <arpa/telnet.h> */
  917. # define IAC     255             /* interpret as command: */
  918. # define DONT    254             /* you are not to use option */
  919. # define DO      253             /* please, you use option */
  920. # define WONT    252             /* I won't use option */
  921. # define WILL    251             /* I will use option */
  922. # define IP      244             /* interrupt process--permanently */
  923. # define DM      242             /* data mark--for connect. cleaning */
  924. #endif /* !NO_ARPA_H */
  925. X
  926. /*
  927. X * FTP reply codes, per RFC 959
  928. X */
  929. X
  930. /* First digit */
  931. #define FTP_REPLY_TYPE(X)    (X/100)
  932. #define FTP_REPLY_PRELIM(X)    (FTP_REPLY_TYPE(X) == 1) /* +ve preliminary  */
  933. #define FTP_REPLY_COMPLETE(X)    (FTP_REPLY_TYPE(X) == 2) /* +ve complete     */
  934. #define FTP_REPLY_CONTINUE(X)    (FTP_REPLY_TYPE(X) == 3) /* +ve intermediate */
  935. #define FTP_REPLY_TRANSIENT(X)    (FTP_REPLY_TYPE(X) == 4) /* -ve transient    */
  936. #define FTP_REPLY_ERROR(X)    (FTP_REPLY_TYPE(X) == 5) /* -ve permanent    */
  937. #define FTP_REPLY_OK(X)        (X < 400)
  938. #define FTP_REPLY_ERR(X)    (X >= 400)
  939. X
  940. /* Second digit */
  941. #define FTP_REPLY_FUNCTION(X)    ((X%100)/10)
  942. #define FTP_REPLY_SYNTAX(X)    (FTP_REPLY_FUNCTION(X) == 0) /* syntax       */
  943. #define FTP_REPLY_INFO(X)    (FTP_REPLY_FUNCTION(X) == 1) /* information  */
  944. #define FTP_REPLY_CONN(X)    (FTP_REPLY_FUNCTION(X) == 2) /* connections  */
  945. #define FTP_REPLY_AUTH(X)    (FTP_REPLY_FUNCTION(X) == 3) /*authentication*/
  946. #define FTP_REPLY_UNSPEC(X)    (FTP_REPLY_FUNCTION(X) == 4) /* unspecified  */
  947. #define FTP_REPLY_FILE(X)    (FTP_REPLY_FUNCTION(X) == 5) /* file system  */
  948. X
  949. /* Third digit */
  950. #define FTP_REPLY_SPECIFIC(X)    (X%10)
  951. X
  952. /* Reply Codes by Function Groups (comment text from RFC959) */
  953. #define FTP_COMMAND_OK        200 /* Command okay. */
  954. #define FTP_SYNTAX_ERROR    500 /* Syntax error, command unrecognized.
  955. X                       This may include errors such as
  956. X                       command line too long. */
  957. #define FTP_PARM_SYNTAX_ERROR    501 /* Syntax error in parameters or
  958. X                       arguments. */
  959. #define FTP_CMD_NOT_NEEDED    202 /* Command not implemented, superfluous
  960. X                       at this site. */
  961. #define FTP_CMD_NOT_IMPL    502 /* Command not implemented. */
  962. #define FTP_BAD_CMD_SEQ        503 /* Bad sequence of commands. */
  963. #define FTP_CMD_PARM_NOT_IMPL    504 /* Command not implemented for that
  964. X                       parameter. */
  965. X
  966. #define FTP_RESTART_MARKER    110 /* Restart marker reply.
  967. X                       In this case, the text is exact and not
  968. X                       left to the particular implementation;
  969. X                       it must read:
  970. X                           MARK yyyy = mmmm
  971. X                       Where yyyy is User-process data stream
  972. X                       marker, and mmmm server's equivalent
  973. X                       marker (note the spaces between markers
  974. X                       and "="). */
  975. #define FTP_SYS_STATUS        211 /* System status, or system help reply. */
  976. #define FTP_DIR_STATUS        212 /* Directory status. */
  977. #define FTP_FILE_STATUS        213 /* File status. */
  978. #define FTP_HELP_MSG        214 /* Help message.
  979. X                       On how to use the server or the meaning
  980. X                       of a particular non-standard command.
  981. X                       This reply is useful only to the human
  982. X                       user. */
  983. #define FTP_SYS_NAME        215 /* NAME system type.
  984. X                       Where NAME is an official system name
  985. X                       from the list in the Assigned Numbers
  986. X                       document. */
  987. #define FTP_SERVICE_RDY_TIME    120 /* Service ready in nnn minutes. */
  988. #define FTP_SERVICE_RDY_USER    220 /* Service ready for new user. */
  989. #define FTP_SERVICE_CLOSING     221 /* Service closing control connection.
  990. X                       Logged out if appropriate. */
  991. #define FTP_SERVICE_UNAVAILABLE    421 /* Service not available, closing control
  992. X                       connection. This may be a reply to any
  993. X                       command if the service knows it must
  994. X                       shut down. */
  995. #define FTP_TRANSFER_STARTING    125 /* Data connection already open; transfer
  996. X                       starting. */
  997. #define FTP_DATA_OPEN        225 /* Data connection open; no transfer in
  998. X                       progress. */
  999. #define FTP_DATA_FAILED        425 /* Can't open data connection. */
  1000. #define FTP_DATA_CLOSE_OK    226 /* Closing data connection.
  1001. X                       Requested file action successful (for
  1002. X                       example, file transfer or file abort).*/
  1003. #define FTP_DATA_CLOSE_ABORT    426 /* Connection closed; transfer aborted. */
  1004. #define FTP_ENTERING_PASSIVE    227 /* Entering Passive Mode
  1005. X                       (h1,h2,h3,h4,p1,p2). */
  1006. X
  1007. #define FTP_LOGIN_OK        230 /* User logged in, proceed. */
  1008. #define FTP_LOGIN_ERR        530 /* Not logged in. */
  1009. #define FTP_LOGIN_NEED_PASSWD    331 /* User name okay, need password. */
  1010. #define FTP_LOGIN_NEED_ACCT    332 /* Need account for login. */
  1011. #define FTP_FILE_NEED_ACCT    532 /* Need account for storing files. */
  1012. X
  1013. #define FTP_DATACONN_OPEN    150 /* File status okay; about to open data
  1014. X                       connection. */
  1015. #define FTP_FILE_ACTION_OK    250 /* Requested file action okay, completed.*/
  1016. #define FTP_PATHNAME_CREATED    257 /* "PATHNAME" created. */
  1017. #define FTP_FILE_ACTION_PENDING    350 /* Requested file action pending further
  1018. X                       information. */
  1019. #define FTP_FILE_UNAVAILABLE    450 /* Requested file action not taken.
  1020. X                       File unavailable (e.g., file busy). */
  1021. #define FTP_ACTION_NOT_TAKEN    550 /* Requested action not taken.
  1022. X                       File unavailable (e.g., file not found,
  1023. X                       no access). */
  1024. #define FTP_ABORTED_LOCAL_ERR    451 /* Requested action aborted. Local error
  1025. X                       in processing. */
  1026. #define FTP_ABORTED_PAGE_TYPE    551 /* Requested action aborted. Page type
  1027. X                       unknown. */
  1028. #define FTP_INSUFFICIENT_SPACE    452 /* Requested action not taken.
  1029. X                       Insufficient storage space in system.*/
  1030. #define FTP_EXCEEDED_ALLOCATION    552 /* Requested file action aborted.
  1031. X                       Exceeded storage allocation (for
  1032. X                       current directory or dataset). */
  1033. #define FTP_BAD_FILENAME    553 /* Requested action not taken.
  1034. X                       File name not allowed. */
  1035. X
  1036. #endif /* !_XA_FTP_H */
  1037. SHAR_EOF
  1038. chmod 0644 xarchie-2.0.6/ftp.h ||
  1039. echo 'restore of xarchie-2.0.6/ftp.h failed'
  1040. Wc_c="`wc -c < 'xarchie-2.0.6/ftp.h'`"
  1041. test 10022 -eq "$Wc_c" ||
  1042.     echo 'xarchie-2.0.6/ftp.h: original size 10022, current size' "$Wc_c"
  1043. rm -f _shar_wnt_.tmp
  1044. fi
  1045. # ============= xarchie-2.0.6/get_pauth.c ==============
  1046. if test -f 'xarchie-2.0.6/get_pauth.c' -a X"$1" != X"-c"; then
  1047.     echo 'x - skipping xarchie-2.0.6/get_pauth.c (File already exists)'
  1048.     rm -f _shar_wnt_.tmp
  1049. else
  1050. > _shar_wnt_.tmp
  1051. echo 'x - extracting xarchie-2.0.6/get_pauth.c (Text)'
  1052. sed 's/^X//' << 'SHAR_EOF' > 'xarchie-2.0.6/get_pauth.c' &&
  1053. /*
  1054. X * Copyright (c) 1989, 1990 by the University of Washington
  1055. X *
  1056. X * For copying and distribution information, please see the file
  1057. X * <copyright.h>.
  1058. X *
  1059. X * gf: xarchie v2.0 - Sync with archie v1.4.1 - changes marked with "gf"
  1060. X */
  1061. X
  1062. #include <copyright.h>
  1063. #include <stdio.h>
  1064. #include "config.h"                /* gf */
  1065. #include "stringdefs.h"                /* gf */
  1066. X
  1067. #ifndef VMS
  1068. # if defined(MSDOS) && !defined(OS2) && !defined(PCNFS)
  1069. #  ifndef CUTCP
  1070. #   include <rwconf.h>
  1071. #  endif
  1072. # else
  1073. #  include <pwd.h>
  1074. # endif
  1075. #else
  1076. # include <jpidef.h>
  1077. # include <vms.h>
  1078. #endif
  1079. X
  1080. #include <pcompat.h>
  1081. #include <pauthent.h>
  1082. X
  1083. /*gf*/
  1084. /*ARGSUSED*/
  1085. PAUTH
  1086. get_pauth(type)
  1087. X    int        type;
  1088. X    {
  1089. X    static PAUTH_ST   no_auth_st;
  1090. X    static PAUTH          no_auth = NULL;
  1091. #if !defined(VMS) && !defined(MSDOS) || defined(OS2) || defined(PCNFS)
  1092. X    struct passwd *whoiampw;
  1093. #else
  1094. X    char username[13];
  1095. X    unsigned short usernamelen;
  1096. X    struct {
  1097. X        unsigned short buflen;
  1098. X        unsigned short itmcod;
  1099. X        char *bufadr;
  1100. X        unsigned short *retlenadr;
  1101. X        unsigned long null;
  1102. X    } jpi_itemlist;
  1103. #endif
  1104. X
  1105. X    if(no_auth == NULL) {
  1106. X        no_auth = &no_auth_st;
  1107. X        strcpy(no_auth->auth_type,"UNAUTHENTICATED");
  1108. X
  1109. X        /* find out who we are */
  1110. #ifndef VMS
  1111. #if defined(MSDOS) && !defined(OS2) && !defined(PCNFS)
  1112. #ifndef CUTCP
  1113. X        if (!getconf("general", "user", no_auth->authenticator, 250)
  1114. X        || (strlen (no_auth->authenticator) == 0))
  1115. #endif
  1116. X          strcpy(no_auth->authenticator,"nobody");
  1117. #else /* not MSDOS */
  1118. X        DISABLE_PFS(whoiampw = getpwuid(getuid()));
  1119. X        if (whoiampw == 0) strcpy(no_auth->authenticator,"nobody");
  1120. X        else strcpy(no_auth->authenticator, whoiampw->pw_name);
  1121. #endif /* not MSDOS */
  1122. #else
  1123. X        jpi_itemlist.buflen = sizeof(username);
  1124. X        jpi_itemlist.itmcod = JPI$_USERNAME;
  1125. X        jpi_itemlist.bufadr = &username;
  1126. X        jpi_itemlist.retlenadr = &usernamelen;
  1127. X        jpi_itemlist.null = 0;
  1128. X        if (SYS$GETJPI(0, 0, 0, &jpi_itemlist, 0, 0, 0) & 0x1)
  1129. X        {
  1130. X        username[usernamelen] = 0;
  1131. X        strcpy(no_auth->authenticator, username);
  1132. X        } else
  1133. X        strcpy(no_auth->authenticator, "nobody");
  1134. #endif
  1135. X    }
  1136. X    return(no_auth);
  1137. X    }
  1138. SHAR_EOF
  1139. chmod 0644 xarchie-2.0.6/get_pauth.c ||
  1140. echo 'restore of xarchie-2.0.6/get_pauth.c failed'
  1141. Wc_c="`wc -c < 'xarchie-2.0.6/get_pauth.c'`"
  1142. test 2068 -eq "$Wc_c" ||
  1143.     echo 'xarchie-2.0.6/get_pauth.c: original size 2068, current size' "$Wc_c"
  1144. rm -f _shar_wnt_.tmp
  1145. fi
  1146. # ============= xarchie-2.0.6/get_vdir.c ==============
  1147. if test -f 'xarchie-2.0.6/get_vdir.c' -a X"$1" != X"-c"; then
  1148.     echo 'x - skipping xarchie-2.0.6/get_vdir.c (File already exists)'
  1149.     rm -f _shar_wnt_.tmp
  1150. else
  1151. > _shar_wnt_.tmp
  1152. echo 'x - extracting xarchie-2.0.6/get_vdir.c (Text)'
  1153. sed 's/^X//' << 'SHAR_EOF' > 'xarchie-2.0.6/get_vdir.c' &&
  1154. /*
  1155. X * Copyright (c) 1989, 1990, 1991 by the University of Washington
  1156. X *
  1157. X * For copying and distribution information, please see the file
  1158. X * <copyright.h>.
  1159. X */
  1160. X
  1161. #include <copyright.h>
  1162. #include <stdio.h>
  1163. X
  1164. #include <pfs.h>
  1165. #include <pprot.h>
  1166. #include <perrno.h>
  1167. #include <pcompat.h>
  1168. #include <pauthent.h>
  1169. X
  1170. #include "config.h"                /* gf */
  1171. #include "stringdefs.h"                /* gf */
  1172. X
  1173. #ifdef DEBUG
  1174. extern int    pfs_debug;
  1175. #endif
  1176. X
  1177. extern int    pwarn;
  1178. extern char    p_warn_string[];
  1179. extern int    perrno;
  1180. extern char    p_err_string[];
  1181. X
  1182. /*
  1183. X * get_vdir - Get contents of a directory given its location
  1184. X *
  1185. X *          GET_VDIR takes a directory location, a list of desired
  1186. X *          components, a pointer to a directory structure to be 
  1187. X *          filled in, and flags.  It then queries the appropriate 
  1188. X *          directory server and retrieves the desired information.
  1189. X *
  1190. X *      ARGS:   dhost       - Host on which directory resides
  1191. X *              dfile       - Directory on that host
  1192. X *              components  - The names from the directory we want
  1193. X *        dir        - Structure to be filled in
  1194. X *            flags       - Options.  See FLAGS
  1195. X *        filters     - filters to be applied to result 
  1196. X *              acomp       - Pointer to remaining components
  1197. X *
  1198. X *     FLAGS:    GVD_UNION   - Do not expand union links
  1199. X *        GVD_EXPAND  - Expand union links locally
  1200. X *        GVD_REMEXP  - Request remote expansion (& local if refused)
  1201. X *        GVD_LREMEXP - Request remote expansion of local union links
  1202. X *        GVD_VERIFY  - Only verify that args are for a directory
  1203. X *              GVD_ATTRIB  - Request attributes from directory server
  1204. X *              GVD_NOSORT  - Do not sort links when adding to directory
  1205. X *
  1206. X *   RETURNS:   PSUCCESS (0) or error code
  1207. X *        On some codes addition information in p_err_string
  1208. X *
  1209. X *     NOTES:   If acomp is non-null the string it points to might be modified
  1210. X *
  1211. X *              If the directory passed as an argument already has
  1212. X *        links or union links, then those lists will be freed
  1213. X *              before the new contents are filled in.
  1214. X *
  1215. X *              If a filter is passed to the procedure, and application of
  1216. X *              the filter results in additional union link, then those links
  1217. X *              will (or will not) be expanded as specified in the FLAGS field.
  1218. X *
  1219. X *              If the list of components in NULL, or the null string, then
  1220. X *              get_vdir will return all links in the requested directory.
  1221. X *
  1222. X *      BUGS:   Doesn't process union links yet
  1223. X *              Doesn't process errors returned from server
  1224. X *        Doesn't expand union links if requested to
  1225. X */
  1226. int
  1227. get_vdir(dhost,dfile,components,dir,flags,filters,acomp)
  1228. X    char    *dhost;        /* Host on which directory resides           */
  1229. X    char    *dfile;        /* Name of file on that host                 */
  1230. X    char    *components;    /* Component name (wildcards allowed)        */
  1231. X    PVDIR    dir;        /* Structure to be filled in             */
  1232. X    long    flags;        /* Flags                         */
  1233. X    VLINK    filters;    /* Filters to be applied to result           */
  1234. X    char    *acomp;        /* Components left to be resolved            */
  1235. X    {
  1236. X        PTEXT    request;    /* Text of request to dir server             */
  1237. X    PTEXT    resp;            /* Response from dir server                 */
  1238. X
  1239. X    char    ulcomp[MAX_VPATH];/* Work space for new current component    */
  1240. X    char    *comp = components;
  1241. X
  1242. X    VLINK    cur_link = NULL;/* Current link being filled in              */
  1243. X    VLINK     exp = NULL;     /* The current ulink being expanded         */
  1244. X    VLINK    pul = NULL;     /* Prev union link (insert new one after it) */
  1245. X    VLINK    l;        /* Temp link pointer                  */
  1246. X    int    mcomp;        /* Flag - check multiple components          */
  1247. X    int    unresp;        /* Flag - received unresolved response       */
  1248. X    int    getattrib = 0;  /* Get attributes from server                */
  1249. X    int    vl_insert_flag; /* Flags to vl_insert                        */
  1250. X
  1251. X    int    fwdcnt = MAX_FWD_DEPTH;
  1252. X
  1253. X    int    no_links = 0;   /* Count of number of links found         */
  1254. X
  1255. X    char    options[40];    /* LIST option                               */
  1256. X    char    *opt;           /* After leading +                           */
  1257. X
  1258. X    PAUTH    authinfo;
  1259. X
  1260. X    /* Treat null string like NULL (return entire directory) */
  1261. X    if(!components || !*components) comp = NULL;
  1262. X
  1263. X    if(acomp && !filters) mcomp = 1;
  1264. X    else mcomp = 0;
  1265. X
  1266. X    if(flags&GVD_ATTRIB) {
  1267. X        getattrib++;
  1268. X        flags &= (~GVD_ATTRIB);
  1269. X    }
  1270. X
  1271. X    if(flags&GVD_NOSORT) vl_insert_flag = VLI_NOSORT;
  1272. X    else vl_insert_flag = VLI_ALLOW_CONF;
  1273. X    flags &= (~GVD_NOSORT);
  1274. X
  1275. X    if(filters) comp = NULL;
  1276. X
  1277. X    perrno = 0;
  1278. X
  1279. X    authinfo = get_pauth(PFSA_UNAUTHENTICATED);
  1280. X
  1281. X    *options = '\0';
  1282. X
  1283. X    if(getattrib) {
  1284. X        strcat(options,"+ATTRIBUTES");
  1285. X        flags &= (~GVD_ATTRIB);
  1286. X    }
  1287. X
  1288. X    if(!filters) { /* Can't do remote expansion if filters to be applied */
  1289. X        if(flags == GVD_REMEXP) strcat(options,"+EXPAND");
  1290. X        if(flags == GVD_LREMEXP) strcat(options,"+LEXPAND");
  1291. X    }
  1292. X
  1293. X    /* If all we are doing is verifying that dfile is a directory */
  1294. X    /* then we do not want a big response from the directory      */
  1295. X    /* server.  A NOT-FOUND is sufficient.                  */
  1296. X    if(flags == GVD_VERIFY)
  1297. #ifdef NEWVERIFYOPT
  1298. X        strcat(options,"+VERIFY");
  1299. #else
  1300. X    comp = "%#$PRobably_nOn_existaNT$#%";
  1301. #endif
  1302. X
  1303. X    if(*options) opt = options+1;
  1304. X    else opt = "''";
  1305. X
  1306. X    startover:
  1307. X    request = ptalloc();
  1308. X
  1309. X    sprintf(request->start,
  1310. X        "VERSION %d %s\nAUTHENTICATOR %s %s\nDIRECTORY ASCII %s\nLIST %s COMPONENTS %s%s%s\n",
  1311. X        VFPROT_VNO, PFS_SW_ID, authinfo->auth_type,
  1312. X        authinfo->authenticator, dfile, opt,
  1313. X        (comp ? comp : ""), (mcomp ? "/" : ""),
  1314. X        (mcomp ? acomp : ""));
  1315. X
  1316. X    request->length = strlen(request->start);
  1317. X
  1318. #ifdef DEBUG
  1319. X    if(pfs_debug > 2)
  1320. X        fprintf(stderr,"Sending message to dirsrv:\n%s",request->start);
  1321. #endif
  1322. X
  1323. #if defined(MSDOS)
  1324. X    resp = dirsend(request,dhost,0L);
  1325. #else
  1326. X    resp = dirsend(request,dhost,0);
  1327. #endif
  1328. X
  1329. #ifdef DEBUG
  1330. X    if(pfs_debug && (resp == NULL)) {
  1331. X        fprintf(stderr,"Dirsend failed: %d\n",perrno);
  1332. X    }
  1333. #endif
  1334. X
  1335. X    /* If we don't get a response, then if the requested       */
  1336. X    /* directory, return error, if a ulink, mark it unexpanded */
  1337. X    if(resp == NULL) {
  1338. X        if(exp) exp->expanded = FAILED;
  1339. X        else return(perrno);
  1340. X    }
  1341. X
  1342. X    unresp = 0;
  1343. X
  1344. X    /* Here we must parse reponse and put in directory */
  1345. X    /* While looking at each packet            */
  1346. X    while(resp) {
  1347. X        PTEXT        vtmp;
  1348. X        char        *line;
  1349. X
  1350. X        vtmp = resp;
  1351. #ifdef DEBUG
  1352. X        if(pfs_debug > 3) fprintf(stderr,"%s\n",resp->start);
  1353. #endif
  1354. X        /* Look at each line in packet */
  1355. X        for(line = resp->start;line != NULL;line = nxtline(line)) {
  1356. X        switch (*line) {
  1357. X            
  1358. X            /* Temporary variables to hold link info */
  1359. X            char    l_linktype;
  1360. X            char     l_name[MAX_DIR_LINESIZE];
  1361. X            char    l_type[MAX_DIR_LINESIZE];
  1362. X            char     l_htype[MAX_DIR_LINESIZE];
  1363. X            char     l_host[MAX_DIR_LINESIZE];
  1364. X            char     l_ntype[MAX_DIR_LINESIZE];
  1365. X            char     l_fname[MAX_DIR_LINESIZE];
  1366. X            int        l_version;
  1367. X            char     t_unresolved[MAX_DIR_LINESIZE];
  1368. X            int        l_magic;
  1369. X            int        tmp;
  1370. X
  1371. X        case 'L': /* LINK or LINK-INFO */
  1372. X            if(strncmp(line,"LINK-INFO",9) == 0) {
  1373. X            PATTRIB        at;
  1374. X            PATTRIB        last_at;
  1375. X            at = parse_attribute(line);
  1376. X            if(!at) break;
  1377. X
  1378. X            /* Cant have link info without a link */
  1379. X            if(!cur_link) {
  1380. X                perrno = DIRSRV_BAD_FORMAT;
  1381. X                atfree(at);
  1382. X                break;
  1383. X            }
  1384. X            
  1385. X            if(cur_link->lattrib) {
  1386. X                last_at = cur_link->lattrib;
  1387. X                while(last_at->next) last_at = last_at->next;
  1388. X                at->previous = last_at;
  1389. X                last_at->next = at;
  1390. X            }
  1391. X            else {
  1392. X                cur_link->lattrib = at;
  1393. X                at->previous = NULL;
  1394. X            }
  1395. X            break;
  1396. X            }
  1397. X
  1398. X            /* Not LINK-INFO, must be LINK - if not check for error */
  1399. X            if(strncmp(line,"LINK",4) != 0) goto scanerr;
  1400. X
  1401. X            /* If only verifying, don't want to change dir */
  1402. X            if(flags == GVD_VERIFY) {
  1403. X            break;
  1404. X            }
  1405. X            /* If first link and some links in dir, free them */
  1406. X            if(!no_links++) {
  1407. X            if(dir->links) vllfree(dir->links); dir->links=NULL;
  1408. X            if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
  1409. X            }
  1410. X            
  1411. X            cur_link = vlalloc();
  1412. X
  1413. X            /* parse and insert file info */
  1414. X            tmp = sscanf(line,"LINK %c %s %s %s %s %s %s %d %d", &l_linktype,
  1415. X                 l_type, l_name, l_htype, l_host, 
  1416. X                 l_ntype, l_fname, &(cur_link->version),
  1417. X                 &(cur_link->f_magic_no));
  1418. X
  1419. X            if(tmp != 9) {
  1420. X            perrno = DIRSRV_BAD_FORMAT;
  1421. X            vlfree(cur_link);
  1422. X            break;
  1423. X            }
  1424. X
  1425. X            cur_link->linktype = l_linktype;
  1426. X            cur_link->type = stcopyr(l_type,cur_link->type);
  1427. X            cur_link->name = stcopyr(unquote(l_name),cur_link->name);
  1428. X            cur_link->hosttype = stcopyr(l_htype,cur_link->hosttype);
  1429. X            cur_link->host = stcopyr(l_host,cur_link->host);
  1430. X            cur_link->nametype = stcopyr(l_ntype,cur_link->nametype);
  1431. X            cur_link->filename = stcopyr(l_fname,cur_link->filename);
  1432. X
  1433. X            /* Double check to make sure we don't get */
  1434. X            /* back unwanted components              */
  1435. X            /* OK to keep if special (URP) links      */
  1436. X            /* or if mcomp specified                  */
  1437. X            if(!mcomp && (cur_link->linktype == 'L') && 
  1438. X               (!wcmatch(cur_link->name,comp))) {
  1439. X            vlfree(cur_link);
  1440. X            break;
  1441. X            }
  1442. X
  1443. X            /* If other optional info was sent back, it must */
  1444. X            /* also be parsed before inserting link     ***  */
  1445. X            
  1446. X            
  1447. X            if(cur_link->linktype == 'L') 
  1448. X            vl_insert(cur_link,dir,vl_insert_flag);
  1449. X            else {
  1450. X            tmp = ul_insert(cur_link,dir,pul);
  1451. X
  1452. X            /* If inserted after pul, next one after cur_link */
  1453. X            if(pul && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
  1454. X                pul = cur_link;
  1455. X            }
  1456. X            
  1457. X            break;
  1458. X
  1459. X        case 'F': /* FILTER, FAILURE or FORWARDED */
  1460. X            /* FORWARDED */
  1461. X            if(strncmp(line,"FORWARDED",9) == 0) {
  1462. X            if(fwdcnt-- <= 0) {
  1463. X                ptlfree(resp);
  1464. X                perrno = PFS_MAX_FWD_DEPTH;
  1465. X                return(perrno);
  1466. X            }
  1467. X            /* parse and start over */
  1468. X
  1469. X            tmp = sscanf(line,"FORWARDED %s %s %s %s %d %d", 
  1470. X                     l_htype,l_host,l_ntype,l_fname,
  1471. X                     &l_version, &l_magic);
  1472. X
  1473. X            dhost = stcopy(l_host);
  1474. X            dfile = stcopy(l_fname);
  1475. X
  1476. X            if(tmp < 4) {
  1477. X                perrno = DIRSRV_BAD_FORMAT;
  1478. X                break;
  1479. X            }
  1480. X
  1481. X            ptlfree(resp);
  1482. X            goto startover;
  1483. X            }
  1484. X            if(strncmp(line,"FILTER",6) != 0) goto scanerr;
  1485. X            break;
  1486. X
  1487. X
  1488. X        case 'M': /* MULTI-PACKET (processed by dirsend) */
  1489. X        case 'P': /* PACKET (processed by dirsend) */
  1490. X            break;
  1491. X
  1492. X        case 'N': /* NOT-A-DIRECTORY or NONE-FOUND */
  1493. X            /* NONE-FOUND, we just have no links to insert */
  1494. X            /* It is not an error, but we must clear any   */
  1495. X            /* old links in the directory arg              */
  1496. X            if(strncmp(line,"NONE-FOUND",10) == 0) {
  1497. X            /* If only verifying, don't want to change dir */
  1498. X            if(flags == GVD_VERIFY) {
  1499. X                break;
  1500. X            }
  1501. X
  1502. X            /* If first link and some links in dir, free them */
  1503. X            if(!no_links++) {
  1504. X                if(dir->links) vllfree(dir->links);
  1505. X                if(dir->ulinks) vllfree(dir->ulinks);
  1506. X                dir->links = NULL;
  1507. X                dir->ulinks = NULL;
  1508. X            }
  1509. X            break;
  1510. X            }
  1511. X            /* If NOT-A-DIRECTORY or anything else, scan error */
  1512. X            goto scanerr;
  1513. X
  1514. X        case 'U': /* UNRESOLVED */
  1515. X            if(strncmp(line,"UNRESOLVED",10) != 0) {
  1516. X            goto scanerr;
  1517. X            }
  1518. X            tmp = sscanf(line,"UNRESOLVED %s", t_unresolved);
  1519. X            if(tmp < 1) {
  1520. X            perrno = DIRSRV_BAD_FORMAT;
  1521. X            break;
  1522. X            }
  1523. X            /* If multiple components were resolved */
  1524. X            if(strlen(t_unresolved) < strlen(acomp)) {
  1525. X            strcpy(ulcomp,acomp);
  1526. X            /* ulcomp is the components that were resolved */
  1527. X            *(ulcomp+strlen(acomp)-strlen(t_unresolved)-1) = '\0';
  1528. X            /* Comp gets the last component resolved */
  1529. X            comp = (char *) rindex(ulcomp,'/');
  1530. X            if(comp) comp++;
  1531. X            else comp = ulcomp;
  1532. X            /* Let rd_vdir know what remains */
  1533. X            strcpy(acomp,t_unresolved);
  1534. X            }
  1535. X            unresp = 1;
  1536. X            break;
  1537. X
  1538. X        case 'V': /* VERSION-NOT-SUPPORTED */
  1539. X            if(strncmp(line,"VERSION-NOT-SUPPORTED",21) == 0) {
  1540. X            perrno = DIRSRV_BAD_VERS;
  1541. X            return(perrno);
  1542. X            }
  1543. X            goto scanerr;
  1544. X
  1545. X        scanerr:
  1546. X        default:
  1547. X            if(*line && (tmp = scan_error(line))) {
  1548. X            ptlfree(resp);
  1549. X            return(tmp);
  1550. X            }
  1551. X            break;
  1552. X        }
  1553. X        }
  1554. X
  1555. X        resp = resp->next;
  1556. X
  1557. X        ptfree(vtmp);
  1558. X    }
  1559. X
  1560. X    /* We sent multiple components and weren't told any */
  1561. X    /* were unresolved                                  */
  1562. X    if(mcomp && !unresp) {
  1563. X        /* ulcomp is the components that were resolved */
  1564. X        strcpy(ulcomp,acomp);
  1565. X        /* Comp gets the last component resolved */
  1566. X        comp = (char *) rindex(ulcomp,'/');
  1567. X        if(comp) comp++;
  1568. X        else comp = ulcomp;
  1569. X        /* If we have union links to resolve, only one component remains */
  1570. X        mcomp = 0;
  1571. X        /* Let rd_vdir know what remains */
  1572. X        *acomp = '\0';
  1573. X    }
  1574. X
  1575. X    /* If only verifying, we already know it is a directory */
  1576. X    if(flags == GVD_VERIFY) return(PSUCCESS);
  1577. X
  1578. X    /* Don't return if matching was delayed by the need to filter    */
  1579. X    /* if FIND specified, and dir->links is non null, then we have   */
  1580. X    /* found a match, and should return.                             */
  1581. X    if((flags & GVD_FIND) && dir->links && (!filters))
  1582. X        return(PSUCCESS);
  1583. X
  1584. X    /* If expand specified, and ulinks must be expanded, making sure */
  1585. X        /* that the order of the links is maintained properly            */
  1586. X
  1587. expand_ulinks:
  1588. X
  1589. X    if((flags != GVD_UNION) && (flags != GVD_VERIFY)) {
  1590. X
  1591. X        l = dir->ulinks;
  1592. X
  1593. X        /* Find first unexpanded ulink */
  1594. X        while(l && l->expanded && (l->linktype == 'U')) l = l->next;
  1595. X        
  1596. X        /* Only expand if a FILE or DIRECTORY -  Mark as  */
  1597. X            /* failed otherwise                               */
  1598. X        /* We must still add support for symbolic ulinks */
  1599. X        if(l) {
  1600. X        if ((strcmp(l->type,"DIRECTORY") == 0) || 
  1601. X            (strcmp(l->type,"FILE") == 0)) {
  1602. X            l->expanded = TRUE;
  1603. X            exp = l;
  1604. X            pul = l;
  1605. X            dhost = l->host;
  1606. X            dfile = l->filename;
  1607. X            goto startover; /* was get_contents; */
  1608. X        }
  1609. X        else l->expanded = FAILED;
  1610. X        }
  1611. X    }
  1612. X
  1613. X    /* Double check to make sure we don't get */
  1614. X    /* back unwanted components          */
  1615. X    /* OK to keep if special (URP) links      */
  1616. X    if(components && *components) {
  1617. X        l = dir->links;
  1618. X        while(l) {
  1619. X        VLINK    ol;
  1620. X        if((l->linktype == 'L') && (!wcmatch(l->name,components))) {
  1621. X            if(l == dir->links)
  1622. X            dir->links = l->next;
  1623. X            else l->previous->next = l->next;
  1624. X            if(l->next) l->next->previous = l->previous;
  1625. X            ol = l;
  1626. X            l = l->next;
  1627. X            vlfree(ol);
  1628. X        }
  1629. X        else l = l->next;
  1630. X        }
  1631. X    }
  1632. X
  1633. X    return(PSUCCESS);
  1634. X    }
  1635. SHAR_EOF
  1636. chmod 0644 xarchie-2.0.6/get_vdir.c ||
  1637. echo 'restore of xarchie-2.0.6/get_vdir.c failed'
  1638. Wc_c="`wc -c < 'xarchie-2.0.6/get_vdir.c'`"
  1639. test 14086 -eq "$Wc_c" ||
  1640.     echo 'xarchie-2.0.6/get_vdir.c: original size 14086, current size' "$Wc_c"
  1641. rm -f _shar_wnt_.tmp
  1642. fi
  1643. # ============= xarchie-2.0.6/help-text1.h ==============
  1644. if test -f 'xarchie-2.0.6/help-text1.h' -a X"$1" != X"-c"; then
  1645.     echo 'x - skipping xarchie-2.0.6/help-text1.h (File already exists)'
  1646.     rm -f _shar_wnt_.tmp
  1647. else
  1648. > _shar_wnt_.tmp
  1649. echo 'x - extracting xarchie-2.0.6/help-text1.h (Text)'
  1650. sed 's/^X//' << 'SHAR_EOF' > 'xarchie-2.0.6/help-text1.h' &&
  1651. "\n",
  1652. NULL,
  1653. "NAME\n",
  1654. "     xarchie - X11 browser interface  to\n",
  1655. "     archie, version 2.0.6\n",
  1656. "\n",
  1657. NULL,
  1658. "SYNOPSIS\n",
  1659. "     xarchie [X Toolkit options]\n",
  1660. "             [-host host]\n",
  1661. "             [-search type|-e|-c|-s|-r|-ec|-es|-er]\n",
  1662. "             [-sort type|-t|-w]\n",
  1663. "             [-maxhits num]\n",
  1664. "             [-offset num] [-nice\n",
  1665. "             lev|-N lev] [-noscroll]\n",
  1666. "             [-mono|-gray|-color]\n",
  1667. "             [-debug num|-D num]\n",
  1668. "             [-help|-?]\n",
  1669. "\n",
  1670. NULL,
  1671. "DESCRIPTION\n",
  1672. "     Xarchie is an X11 browser interface\n",
  1673. "     to  the Archie Internet information\n",
  1674. "     system using the  Prospero  virtual\n",
  1675. "     filesystem  protocol.   Archie pro-\n",
  1676. "     vides   information   about   files\n",
  1677. "     available  for  ftp anywhere on the\n",
  1678. "     Internet;  Xarchie  displays   this\n",
  1679. "     information  using  an easy-to-use,\n",
  1680. "     point-and-click interface.  Xarchie\n",
  1681. "     allows  you  to further explore ftp\n",
  1682. "     sites  by   examining   directories\n",
  1683. "     returned   as  query  matches,  and\n",
  1684. "     allows  you   to   retrieve   files\n",
  1685. "     located   this   way.   Xarchie  is\n",
  1686. "     designed (like most X applications)\n",
  1687. "     to be highly customizable, allowing\n",
  1688. "     you to tailor the look-and-feel  of\n",
  1689. "     the tool to your own preferences.\n",
  1690. "\n",
  1691. "     This document is  broken  into  two\n",
  1692. "     parts.   First,  the  USER'S  GUIDE\n",
  1693. "     describes Archie and  Xarchie,  and\n",
  1694. "     covers both Basic and Advanced Xar-\n",
  1695. "     chie usage. Second,  the  REFERENCE\n",
  1696. "     MANUAL provides all the information\n",
  1697. "     needed to  customize  Xarchie.  You\n",
  1698. "     can also browse this document using\n",
  1699. "     the Xarchie Help facility.\n",
  1700. "\n",
  1701. "     To report problems or bugs,  please\n",
  1702. "     see the section \"Reporting Bugs\" in\n",
  1703. "     the REFERENCE MANUAL section.\n",
  1704. "\n",
  1705. NULL,
  1706. "USER'S GUIDE\n",
  1707. "     The User's Guide  section  of  this\n",
  1708. "     manual  describes  the  Archie ser-\n",
  1709. "     vice, the Xarchie client,  and  how\n",
  1710. "     to  use Xarchie to access resources\n",
  1711. SHAR_EOF
  1712. true || echo 'restore of xarchie-2.0.6/help-text1.h failed'
  1713. fi
  1714. echo 'End of xarchie-2.0.6 part 9'
  1715. echo 'File xarchie-2.0.6/help-text1.h is continued in part 10'
  1716. echo 10 > _shar_seq_.tmp
  1717. exit 0
  1718.  
  1719. exit 0 # Just in case...
  1720. -- 
  1721.   // chris@IMD.Sterling.COM       | Send comp.sources.x submissions to:
  1722. \X/  Amiga - The only way to fly! |    sources-x@imd.sterling.com
  1723.  "It's intuitively obvious to the |
  1724.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1725.