home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume20 / imagemgc / part06 < prev    next >
Encoding:
Text File  |  1993-07-13  |  50.3 KB  |  1,646 lines

  1. Newsgroups: comp.sources.x
  2. From: cristy@eplrx7.es.duPont.com (Cristy)
  3. Subject: v20i062:  imagemagic - X11 image processing and display, Part06/38
  4. Message-ID: <1993Jul14.175355.924@sparky.sterling.com>
  5. X-Md4-Signature: 876c13a522ed2d602a8f0f4218ca8470
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Wed, 14 Jul 1993 17:53:55 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: cristy@eplrx7.es.duPont.com (Cristy)
  12. Posting-number: Volume 20, Issue 62
  13. Archive-name: imagemagic/part06
  14. Environment: X11
  15. Supersedes: imagemagic: Volume 13, Issue 17-37
  16.  
  17. #!/bin/sh
  18. # this is magick.06 (part 6 of ImageMagick)
  19. # do not concatenate these parts, unpack them in order with /bin/sh
  20. # file ImageMagick/xtp/regular.c continued
  21. #
  22. if test ! -r _shar_seq_.tmp; then
  23.     echo 'Please unpack part 1 first!'
  24.     exit 1
  25. fi
  26. (read Scheck
  27.  if test "$Scheck" != 6; then
  28.     echo Please unpack part "$Scheck" next!
  29.     exit 1
  30.  else
  31.     exit 0
  32.  fi
  33. ) < _shar_seq_.tmp || exit 1
  34. if test ! -f _shar_wnt_.tmp; then
  35.     echo 'x - still skipping ImageMagick/xtp/regular.c'
  36. else
  37. echo 'x - continuing file ImageMagick/xtp/regular.c'
  38. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/xtp/regular.c' &&
  39. %                                                                             %
  40. %                                                                             %
  41. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  42. %
  43. %
  44. */
  45. static char *NextToken(p)
  46. register char
  47. X  *p;
  48. {
  49. X  register int
  50. X    offset;
  51. X
  52. X  if (p == &start_code)
  53. X    return(NULL);
  54. X  offset=Next(p);
  55. X  if (offset == 0)
  56. X    return(NULL);
  57. X  if (OpCode(p) == Back)
  58. X    return(p-offset);
  59. X  else
  60. X    return(p+offset);
  61. }
  62. X
  63. /*
  64. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  65. %                                                                             %
  66. %                                                                             %
  67. %                                                                             %
  68. %   N o d e                                                                   %
  69. %                                                                             %
  70. %                                                                             %
  71. %                                                                             %
  72. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  73. %
  74. %
  75. */
  76. static char *Node(opcode)
  77. int
  78. X  opcode;
  79. {
  80. X  register char
  81. X    *ptr,
  82. X    *status;
  83. X
  84. X  status=code;
  85. X  if (status == &start_code)
  86. X    {
  87. X      code_size+=3;
  88. X      return(status);
  89. X    }
  90. X  ptr=status;
  91. X  *ptr++=(char) opcode;
  92. X  *ptr++='\0';
  93. X  *ptr++='\0';
  94. X  code=ptr;
  95. X  return(status);
  96. }
  97. X
  98. /*
  99. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  100. %                                                                             %
  101. %                                                                             %
  102. %                                                                             %
  103. %   O p T a i l                                                               %
  104. %                                                                             %
  105. %                                                                             %
  106. %                                                                             %
  107. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  108. %
  109. %
  110. */
  111. static void OpTail(p,value)
  112. char
  113. X  *p;
  114. X
  115. char
  116. X  *value;
  117. {
  118. X  /*
  119. X    "Operandless" and "op != MatchThisOrNext" are synonymous in practice.
  120. X  */
  121. X  if ((p == NULL) || (p == &start_code) || (OpCode(p) != MatchThisOrNext))
  122. X    return;
  123. X  Tail(Operand(p),value);
  124. }
  125. X
  126. /*
  127. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  128. %                                                                             %
  129. %                                                                             %
  130. %                                                                             %
  131. %   P i e c e                                                                 %
  132. %                                                                             %
  133. %                                                                             %
  134. %                                                                             %
  135. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  136. %
  137. %
  138. */
  139. static char *Piece(flagp)
  140. int
  141. X  *flagp;
  142. {
  143. X  int
  144. X    flags;
  145. X
  146. X  register char
  147. X    *next_token,
  148. X    op,
  149. X    *status;
  150. X
  151. X  status=Atom(&flags);
  152. X  if (status == NULL)
  153. X    return(NULL);
  154. X  op=(*token);
  155. X  if (!MultipleMatches(op))
  156. X    {
  157. X      *flagp=flags;
  158. X      return(status);
  159. X    }
  160. X  if (!(flags & NonNull) && op != '?')
  161. X    Fail("*+ operand could be empty");
  162. X  *flagp=(op != '+') ? (WorstCase | SpecialStart) : (WorstCase | NonNull);
  163. X  if (op == '*' && (flags & Simple))
  164. X    Insert(MatchZeroOrMore,status);
  165. X  else
  166. X    if (op == '*')
  167. X      {
  168. X        /*
  169. X          Emit x* as (x&|), where & means "self".
  170. X        */
  171. X        Insert(MatchThisOrNext,status);
  172. X        OpTail(status,Node(Back));
  173. X        OpTail(status,status);
  174. X        Tail(status,Node(MatchThisOrNext));
  175. X        Tail(status,Node(MatchEmptyString));
  176. X      }
  177. X    else
  178. X      if ((op == '+') && (flags & Simple))
  179. X        Insert(MatchOneOrMore,status);
  180. X      else
  181. X        if (op == '+')
  182. X          {
  183. X            /*
  184. X              Emit x+ as x (&|), where & means "self".
  185. X            */
  186. X            next_token=Node(MatchThisOrNext);
  187. X            Tail(status,next_token);
  188. X            Tail(Node(Back),status);
  189. X            Tail(next_token,Node(MatchThisOrNext));
  190. X            Tail(status,Node(MatchEmptyString));
  191. X          }
  192. X        else
  193. X          if (op == '?')
  194. X            {
  195. X              /*
  196. X                Emit x? as (x|)
  197. X              */
  198. X              Insert(MatchThisOrNext,status);
  199. X              Tail(status,Node(MatchThisOrNext));
  200. X              next_token=Node(MatchEmptyString);
  201. X              Tail(status,next_token);
  202. X              OpTail(status,next_token);
  203. X            }
  204. X  token++;
  205. X  if (MultipleMatches(*token))
  206. X    Fail("nested *?+");
  207. X  return(status);
  208. }
  209. X
  210. /*
  211. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  212. %                                                                             %
  213. %                                                                             %
  214. %                                                                             %
  215. %   R e g u l a r                                                             %
  216. %                                                                             %
  217. %                                                                             %
  218. %                                                                             %
  219. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  220. %
  221. %
  222. */
  223. static char *Regular(parenthesized,flagp)
  224. int
  225. X  parenthesized;
  226. X
  227. int
  228. X  *flagp;
  229. {
  230. X  int
  231. X    flags;
  232. X
  233. X  register char
  234. X    *br,
  235. X    *ender,
  236. X    *status;
  237. X
  238. X  register int
  239. X    count;
  240. X
  241. X  count=0;
  242. X  *flagp=NonNull;
  243. X  if (!parenthesized)
  244. X    status=NULL;
  245. X  else
  246. X    {
  247. X      /*
  248. X        Make an Open node.
  249. X      */
  250. X      if (number_parenthesis >= NumberSubExpressions)
  251. X        Fail("too many ()");
  252. X      count=number_parenthesis;
  253. X      number_parenthesis++;
  254. X      status=Node(Open+count);
  255. X    }
  256. X  /*
  257. X    Pick up the branches, linking them together.
  258. X  */
  259. X  br=Branch(&flags);
  260. X  if (br == NULL)
  261. X    return(NULL);
  262. X  if (status != NULL)
  263. X    Tail(status,br);
  264. X  else
  265. X    status=br;
  266. X  if (!(flags & NonNull))
  267. X    *flagp&=(~NonNull);
  268. X  *flagp|=flags & SpecialStart;
  269. X  while (*token == '|')
  270. X  {
  271. X    token++;
  272. X    br=Branch(&flags);
  273. X    if (br == NULL)
  274. X      return(NULL);
  275. X    Tail(status,br);
  276. X    if (!(flags & NonNull))
  277. X      *flagp &= ~NonNull;
  278. X    *flagp|=flags & SpecialStart;
  279. X  }
  280. X  /*
  281. X    Make a closing node and hook it on the end.
  282. X  */
  283. X  ender=Node((parenthesized) ? Close+count : EndOfProgram);
  284. X  Tail(status,ender);
  285. X  /*
  286. X    Hook the tails of the branches to the closing node.
  287. X  */
  288. X  for(br=status; br != NULL; br=NextToken(br))
  289. X    OpTail(br,ender);
  290. X  /*
  291. X    Check for proper termination.
  292. X  */
  293. X  if (parenthesized && (*token++ != ')'))
  294. X    Fail("unmatched()")
  295. X  else
  296. X    if (!parenthesized && (*token != '\0'))
  297. X      {
  298. X        if (*token == ')')
  299. X          Fail("unmatched()")
  300. X        else
  301. X          Fail("junk on end")
  302. X       }
  303. X  return(status);
  304. }
  305. X
  306. /*
  307. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  308. %                                                                             %
  309. %                                                                             %
  310. %                                                                             %
  311. %   R e p e a t                                                               %
  312. %                                                                             %
  313. %                                                                             %
  314. %                                                                             %
  315. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  316. %
  317. %
  318. */
  319. static int Repeat(p)
  320. char
  321. X  *p;
  322. {
  323. X  register char
  324. X    *operand,
  325. X    *scan;
  326. X
  327. X  register int
  328. X    count=0;
  329. X
  330. X  scan=p;
  331. X  operand=Operand(p);
  332. X  switch(OpCode(p))
  333. X  {
  334. X    case MatchAnyCharacter:
  335. X    {
  336. X      count=strlen(scan);
  337. X      scan+=count;
  338. X      break;
  339. X    }
  340. X    case MatchExactly:
  341. X    {
  342. X      while (*operand == *scan)
  343. X      {
  344. X        count++;
  345. X        scan++;
  346. X      }
  347. X      break;
  348. X    }
  349. X    case MatchAnyCharacterOf:
  350. X    {
  351. X      while ((*scan != '\0') && (strchr(operand,*scan) != NULL))
  352. X      {
  353. X        count++;
  354. X        scan++;
  355. X      }
  356. X      break;
  357. X    }
  358. X    case MatchAnyCharacterBut:
  359. X    {
  360. X      while ((*scan != '\0') && (strchr(operand,*scan) == NULL))
  361. X      {
  362. X        count++;
  363. X        scan++;
  364. X      }
  365. X      break;
  366. X    }
  367. X    default:
  368. X    {
  369. X      (void) fprintf(stderr,"Regular(3): %s","internal foulup");
  370. X      count=0;
  371. X      break;
  372. X    }
  373. X  }
  374. X  p=scan;
  375. X  return(count);
  376. }
  377. X
  378. /*
  379. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  380. %                                                                             %
  381. %                                                                             %
  382. %                                                                             %
  383. %   T a i l                                                                   %
  384. %                                                                             %
  385. %                                                                             %
  386. %                                                                             %
  387. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  388. %
  389. %
  390. */
  391. static void Tail(p,val)
  392. char
  393. X  *p;
  394. X
  395. char
  396. X  *val;
  397. {
  398. X  register char
  399. X    *scan,
  400. X    *temp;
  401. X
  402. X  register int
  403. X    offset;
  404. X
  405. X  if (p == &start_code)
  406. X    return;
  407. X  /*
  408. X    Find last node.
  409. X  */
  410. X  scan=p;
  411. X  for(;;)
  412. X  {
  413. X    temp=NextToken(scan);
  414. X    if (temp == NULL)
  415. X      break;
  416. X    scan=temp;
  417. X  }
  418. X  if (OpCode(scan) == Back)
  419. X    offset=scan-val;
  420. X  else
  421. X    offset=val-scan;
  422. X  *(scan+1)=(offset >> 8) & 0377;
  423. X  *(scan+2)=offset & 0377;
  424. }
  425. X
  426. /*
  427. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  428. %                                                                             %
  429. %                                                                             %
  430. %                                                                             %
  431. %   T r y                                                                     %
  432. %                                                                             %
  433. %                                                                             %
  434. %                                                                             %
  435. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  436. %
  437. %
  438. */
  439. static int Try(regular_expression,pattern)
  440. RegularExpression
  441. X  *regular_expression;
  442. X
  443. char
  444. X  *pattern;
  445. {
  446. X  register char
  447. X    **ep,
  448. X    **sp;
  449. X
  450. X  register int
  451. X    i;
  452. X
  453. X  p=pattern;
  454. X  subpattern=regular_expression->subpattern;
  455. X  subpattern_end=regular_expression->subpattern_end;
  456. X  sp=regular_expression->subpattern;
  457. X  ep=regular_expression->subpattern_end;
  458. X  for(i=NumberSubExpressions; i > 0; i--)
  459. X  {
  460. X    *sp++=NULL;
  461. X    *ep++=NULL;
  462. X  }
  463. X  if (!Match(regular_expression->program+1))
  464. X    return(0);
  465. X  else
  466. X    {
  467. X      regular_expression->subpattern[0]=pattern;
  468. X      regular_expression->subpattern_end[0]=p;
  469. X      return(1);
  470. X    }
  471. }
  472. X
  473. /*
  474. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  475. %                                                                             %
  476. %                                                                             %
  477. %                                                                             %
  478. %   C o m p i l e R e g u l a r E x p r e s s i o n                           %
  479. %                                                                             %
  480. %                                                                             %
  481. %                                                                             %
  482. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  483. %
  484. %  Function CompileRegularExpression compiles a regular expression into a
  485. %  structure of type RegularExpression and returns a pointer to it.  The space
  486. %  is allocated using function malloc and may be released by function free.
  487. %
  488. %
  489. */
  490. RegularExpression *CompileRegularExpression(regular_expression)
  491. char
  492. X  *regular_expression;
  493. {
  494. X  int
  495. X    flags;
  496. X
  497. X  register char
  498. X    *longest,
  499. X    *scan;
  500. X
  501. X  register RegularExpression
  502. X    *r;
  503. X
  504. X  register int
  505. X    length;
  506. X
  507. X  if (regular_expression == NULL)
  508. X    Fail("NULL argument");
  509. X  /*
  510. X    First pass: determine size.
  511. X  */
  512. X  token=regular_expression;
  513. X  number_parenthesis=1;
  514. X  code_size=0L;
  515. X  code=(&start_code);
  516. X  EmitCode(Magick);
  517. X  if (Regular(0,&flags) == NULL)
  518. X    return(NULL);
  519. X  /*
  520. X    Allocate space.
  521. X  */
  522. X  r=(RegularExpression *) malloc((code_size+sizeof(RegularExpression)));
  523. X  if (r == (RegularExpression *) NULL)
  524. X    Fail("out of space");
  525. X  /*
  526. X    Second pass: emit code.
  527. X  */
  528. X  token=regular_expression;
  529. X  number_parenthesis=1;
  530. X  code=r->program;
  531. X  EmitCode(Magick);
  532. X  if (Regular(0,&flags) == NULL)
  533. X    return(NULL);
  534. X  /*
  535. X    Dig out information for optimizations.
  536. X  */
  537. X  r->start_character='\0';
  538. X  r->anchor=0;
  539. X  r->priority_pattern=NULL;
  540. X  r->pattern_length=0;
  541. X  scan=r->program+1;
  542. X  if (OpCode(NextToken(scan)) == EndOfProgram)
  543. X    {
  544. X      scan=Operand(scan);
  545. X      if (OpCode(scan) == MatchExactly)
  546. X        r->start_character=(*Operand(scan));
  547. X      else
  548. X        if (OpCode(scan) == MatchBeginningOfLine)
  549. X          r->anchor++;
  550. X      /*
  551. X        If there's something expensive in the regular expression, find the
  552. X        longest literal pattern that must appear and make it the
  553. X        priority_pattern.
  554. X      */
  555. X      if (flags & SpecialStart)
  556. X        {
  557. X          longest=NULL;
  558. X          length=0;
  559. X          for(; scan != NULL; scan=NextToken(scan))
  560. X            if ((OpCode(scan) == MatchExactly) &&
  561. X                ((int) strlen(Operand(scan)) >= length))
  562. X              {
  563. X                longest=Operand(scan);
  564. X                length=strlen(Operand(scan));
  565. X              }
  566. X          r->priority_pattern=longest;
  567. X          r->pattern_length=length;
  568. X        }
  569. X    }
  570. X  return(r);
  571. }
  572. X
  573. /*
  574. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  575. %                                                                             %
  576. %                                                                             %
  577. %                                                                             %
  578. %   E x e c u t e R e g u l a r E x p r e s s i o n                           %
  579. %                                                                             %
  580. %                                                                             %
  581. %                                                                             %
  582. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  583. %
  584. %  Function ExecuteRegularExpression matches a NULL-terminated pattern against
  585. %  the compiled regular expression in regular-expression.  It returns 1 for
  586. %  success and 0 for failure.
  587. %
  588. %
  589. */
  590. int ExecuteRegularExpression(regular_expression,pattern)
  591. register RegularExpression
  592. X  *regular_expression;
  593. X
  594. register char
  595. X  *pattern;
  596. {
  597. X  register char
  598. X    *s;
  599. X
  600. X  if ((regular_expression == (RegularExpression *) NULL) ||
  601. X      (pattern == (char *) NULL))
  602. X    {
  603. X      (void) fprintf(stderr,"Regular(3): %s","NULL parameter\n");
  604. X      return(0);
  605. X    }
  606. X  /*
  607. X    Check validity of program.
  608. X  */
  609. X  if (((int)*(unsigned char *)(regular_expression->program)) != Magick)
  610. X    {
  611. X      (void) fprintf(stderr,"Regular(3): %s","corrupted program");
  612. X      return(0);
  613. X    }
  614. X  /*
  615. X    If there is a "must appear" pattern, look for it.
  616. X  */
  617. X  if (regular_expression->priority_pattern != NULL)
  618. X    {
  619. X      s=pattern;
  620. X      while ((s=strchr(s,regular_expression->priority_pattern[0])) != NULL)
  621. X      {
  622. X        if (strncmp(s,regular_expression->priority_pattern,
  623. X            regular_expression->pattern_length) == 0)
  624. X          break;
  625. X        s++;
  626. X       }
  627. X       if (s == NULL)
  628. X         return(0);
  629. X    }
  630. X  /*
  631. X    Mark beginning of line for ^.
  632. X  */
  633. X  start_pattern=pattern;
  634. X  /*
  635. X    Simplest case:  anchored match need be tried only once.
  636. X  */
  637. X  if (regular_expression->anchor)
  638. X    return(Try(regular_expression,pattern));
  639. X  /*
  640. X    Messy cases:  unanchored match.
  641. X  */
  642. X  s=pattern;
  643. X  if (regular_expression->start_character != '\0')
  644. X    while ((s=strchr(s,regular_expression->start_character)) != NULL)
  645. X    {
  646. X      if (Try(regular_expression,s))
  647. X        return(1);
  648. X      s++;
  649. X    }
  650. X  else
  651. X    do
  652. X    {
  653. X      if (Try(regular_expression,s))
  654. X        return(1);
  655. X    } while (*s++ != '\0');
  656. X  return(0);
  657. }
  658. SHAR_EOF
  659. echo 'File ImageMagick/xtp/regular.c is complete' &&
  660. chmod 0644 ImageMagick/xtp/regular.c ||
  661. echo 'restore of ImageMagick/xtp/regular.c failed'
  662. Wc_c="`wc -c < 'ImageMagick/xtp/regular.c'`"
  663. test 36662 -eq "$Wc_c" ||
  664.     echo 'ImageMagick/xtp/regular.c: original size 36662, current size' "$Wc_c"
  665. rm -f _shar_wnt_.tmp
  666. fi
  667. # ============= ImageMagick/xtp/regular.h ==============
  668. if test -f 'ImageMagick/xtp/regular.h' -a X"$1" != X"-c"; then
  669.     echo 'x - skipping ImageMagick/xtp/regular.h (File already exists)'
  670.     rm -f _shar_wnt_.tmp
  671. else
  672. > _shar_wnt_.tmp
  673. echo 'x - extracting ImageMagick/xtp/regular.h (Text)'
  674. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/regular.h' &&
  675. /*
  676. X  Definitions etc. for RegularExpression(3) routines.
  677. */
  678. #define EndOfProgram  0
  679. #define MatchBeginningOfLine  1
  680. #define MatchEndOfProgramOfLine  2
  681. #define MatchAnyCharacter  3
  682. #define MatchAnyCharacterOf  4
  683. #define MatchAnyCharacterBut  5
  684. #define MatchThisOrNext  6
  685. #define Back  7
  686. #define MatchExactly  8
  687. #define MatchEmptyString  9
  688. #define MatchZeroOrMore  10
  689. #define MatchOneOrMore  11
  690. #define Open  20
  691. #define Close  30
  692. X
  693. #define WorstCase  0
  694. #define NonNull  1
  695. #define Simple  2
  696. #define SpecialStart  4
  697. X
  698. #define Fail(m)  \
  699. {  \
  700. X  (void) fprintf(stderr,"RegularExpression: %s\n",m);  \
  701. X  return(NULL);  \
  702. }
  703. #define Magick   0234
  704. #define Meta  "^$.[()|?+*\\"
  705. #define MultipleMatches(c) (((c) == '*') || ((c) == '+') || ((c) == '?'))
  706. #define Next(p) (((*((p)+1) & 0377) << 8 )+(*((p)+2) & 0377))
  707. #define NumberSubExpressions  10
  708. #define OpCode(p) (*(p))
  709. #define Operand(p) ((p)+3)
  710. X
  711. typedef struct _RegularExpression 
  712. {
  713. X  char 
  714. X    *subpattern[NumberSubExpressions],
  715. X    *subpattern_end[NumberSubExpressions],
  716. X    start_character,
  717. X    anchor,
  718. X    *priority_pattern;
  719. X
  720. X  int 
  721. X    pattern_length;
  722. X
  723. X  char 
  724. X    program[1];
  725. } RegularExpression;
  726. X
  727. extern RegularExpression 
  728. X  *CompileRegularExpression _Declare((char *));
  729. X
  730. extern int 
  731. X  ExecuteRegularExpression _Declare((RegularExpression *,char *));
  732. SHAR_EOF
  733. chmod 0644 ImageMagick/xtp/regular.h ||
  734. echo 'restore of ImageMagick/xtp/regular.h failed'
  735. Wc_c="`wc -c < 'ImageMagick/xtp/regular.h'`"
  736. test 1299 -eq "$Wc_c" ||
  737.     echo 'ImageMagick/xtp/regular.h: original size 1299, current size' "$Wc_c"
  738. rm -f _shar_wnt_.tmp
  739. fi
  740. # ============= ImageMagick/xtp/xtp.c ==============
  741. if test -f 'ImageMagick/xtp/xtp.c' -a X"$1" != X"-c"; then
  742.     echo 'x - skipping ImageMagick/xtp/xtp.c (File already exists)'
  743.     rm -f _shar_wnt_.tmp
  744. else
  745. > _shar_wnt_.tmp
  746. echo 'x - extracting ImageMagick/xtp/xtp.c (Text)'
  747. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/xtp.c' &&
  748. /*
  749. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  750. %                                                                             %
  751. %                                                                             %
  752. %                                                                             %
  753. %                            X   X  TTTTT PPPP                                %
  754. %                             X X     T   P   P                               %
  755. %                              X      T   PPPP                                %
  756. %                             X X     T   P                                   %
  757. %                            X   X    T   P                                   %
  758. %                                                                             %
  759. %                                                                             %
  760. %                         File transfer program.                              %
  761. %                                                                             %
  762. %                                                                             %
  763. %                                                                             %
  764. %                           Software Design                                   %
  765. %                             John Cristy                                     %
  766. %                             October 1992                                    %
  767. %                                                                             %
  768. %                                                                             %
  769. %  Copyright 1993 E. I. Dupont de Nemours & Company                           %
  770. %                                                                             %
  771. %  Permission to use, copy, modify, distribute, and sell this software and    %
  772. %  its documentation for any purpose is hereby granted without fee,           %
  773. %  provided that the above copyright notice appear in all copies and that     %
  774. %  both that copyright notice and this permission notice appear in            %
  775. %  supporting documentation, and that the name of E. I. Dupont de Nemours     %
  776. %  & Company not be used in advertising or publicity pertaining to            %
  777. %  distribution of the software without specific, written prior               %
  778. %  permission.  E. I. Dupont de Nemours & Company makes no representations    %
  779. %  about the suitability of this software for any purpose.  It is provided    %
  780. %  "as is" without express or implied warranty.                               %
  781. %                                                                             %
  782. %  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
  783. %  to this software, including all implied warranties of merchantability      %
  784. %  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
  785. %  liable for any special, indirect or consequential damages or any           %
  786. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  787. %  in an action of contract, negligence or other tortious action, arising     %
  788. %  out of or in connection with the use or performance of this software.      %
  789. %                                                                             %
  790. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  791. %
  792. %  Xtp is a utility for retrieving, listing, or printing files from a
  793. %  remote network site.  Xtp performs most of the same functions as the
  794. %  FTP program, but does not require any interactive commands.  You simply
  795. %  specify the file transfer task on the command line and xtp performs the
  796. %  transfer automatically.
  797. %
  798. %  This program was adapted from a similiar program written by Steve Singles,
  799. %  University of Delaware.
  800. %
  801. %  Command syntax:
  802. %
  803. %  Usage: xtp [-options ...] <host/ip address> [ <home directory> ]
  804. %
  805. %  Where options include:
  806. %    -binary                retrieve files as binary
  807. %    -exclude expression    exclude files that match the expression
  808. %    -directory expression  list file names that match the expression
  809. %    -ident password        specifies password
  810. %    -port number           port number of FTP server
  811. %    -print expression      print files that match the expression
  812. %    -prune                 do not recursively search for files
  813. %    -retrieve expression   retrieve files that match the expression
  814. %    -send expression       send files that match the expression
  815. %    -timeout seconds       specifies maximum seconds of XTP session
  816. %    -user name             identify yourself to the remote FTP server
  817. %
  818. %
  819. */
  820. X
  821. /*
  822. X  Include declarations.
  823. */
  824. #define _POSIX_SOURCE  1
  825. #include "xtp.h"
  826. #include "regular.h"
  827. #include <unistd.h>
  828. #include <sys/types.h>
  829. #include <signal.h>
  830. #include <termios.h>
  831. #include <fcntl.h>
  832. #include <sys/stat.h>
  833. #include <sys/wait.h>
  834. /*
  835. X  Variable declarations.
  836. */
  837. static char
  838. X  *client_name,
  839. X  slave_tty[16];
  840. X
  841. static int
  842. X  master,
  843. X  status;
  844. X
  845. static RegularExpression
  846. X  *directory_expression,
  847. X  *exclude_expression,
  848. X  *print_expression,
  849. X  *retrieve_expression;
  850. X
  851. /*
  852. X  External declarations.
  853. */
  854. extern char
  855. X  *GetHostInfo _Declare((char *));
  856. X
  857. /*
  858. X  Forward declarations.
  859. */
  860. static char
  861. X  *Wait _Declare((void));
  862. X
  863. static void
  864. X  DirectoryRequest _Declare((char *, char *)),
  865. X  PrintRequest _Declare((char *,unsigned int)),
  866. X  RetrieveRequest _Declare((char *,unsigned int));
  867. X
  868. /*
  869. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  870. %                                                                             %
  871. %                                                                             %
  872. %                                                                             %
  873. %   D i r e c t o r y R e q u e s t                                           %
  874. %                                                                             %
  875. %                                                                             %
  876. %                                                                             %
  877. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  878. %
  879. %  Function DirectoryRequest lists a file name and its attributes.
  880. %
  881. %  The format of the DirectoryRequest routine is:
  882. %
  883. %    DirectoryRequest(fileinfo,filename)
  884. %
  885. %  A description of each parameter follows:
  886. %
  887. %    o filename:  Specifies a pointer to a character array that contains
  888. %      information about the file.
  889. %
  890. %    o filename:  Specifies a pointer to a character array that contains
  891. %      the name of the file.
  892. %
  893. */
  894. static void DirectoryRequest(fileinfo,filename)
  895. char
  896. X  *fileinfo,
  897. X  *filename;
  898. {
  899. X  status=0;
  900. X  if (*fileinfo == '\0')
  901. X    (void) fprintf(stdout,"%s\n",filename);
  902. X  else
  903. X    (void) fprintf(stdout,"%s %s\n",fileinfo,filename);
  904. }
  905. X
  906. /*
  907. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  908. %                                                                             %
  909. %                                                                             %
  910. %                                                                             %
  911. %   E r r o r                                                                 %
  912. %                                                                             %
  913. %                                                                             %
  914. %                                                                             %
  915. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  916. %
  917. %  Function Error displays an error message and then terminates the program.
  918. %
  919. %  The format of the Error routine is:
  920. %
  921. %      Error(message,qualifier)
  922. %
  923. %  A description of each parameter follows:
  924. %
  925. %    o message: Specifies the message to display before terminating the
  926. %      program.
  927. %
  928. %    o qualifier: Specifies any qualifier to the message.
  929. %
  930. %
  931. */
  932. void Error(message,qualifier)
  933. char
  934. X  *message,
  935. X  *qualifier;
  936. {
  937. X  (void) fprintf(stderr,"%s: %s",client_name,message);
  938. X  if (qualifier != (char *) NULL)
  939. X    (void) fprintf(stderr," (%s)",qualifier);
  940. X  (void) fprintf(stderr,".\n");
  941. X  exit(1);
  942. }
  943. X
  944. /*
  945. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  946. %                                                                             %
  947. %                                                                             %
  948. %                                                                             %
  949. %   E x e c u t e F t p                                                       %
  950. %                                                                             %
  951. %                                                                             %
  952. %                                                                             %
  953. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  954. %
  955. %  Function ExecuteFtp executes the FTP program as a child process.
  956. %
  957. %  The format of the ExecuteFtp routine is:
  958. %
  959. %    ExecuteFtp(host_name,port)
  960. %
  961. %  A description of each parameter follows:
  962. %
  963. %    o host_name:  Specifies a pointer to a character array that contains the
  964. %      name of the host to establish a connection to a FTP server.
  965. %
  966. %    o port:  Specifies a port number.  If the port number is NULL, xtp
  967. %      attempts to contact a FTP server at the default port.
  968. %
  969. %
  970. %
  971. */
  972. static void ExecuteFtp(host_name,port)
  973. char
  974. X  *host_name,
  975. X  *port;
  976. {
  977. X  int
  978. X    slave;
  979. X
  980. X  struct sigaction
  981. X    action;
  982. X
  983. X  struct termios
  984. X    attributes;
  985. X
  986. X  /*
  987. X    Get slave tty line.
  988. X  */
  989. X  action.sa_handler=SIG_IGN;
  990. X  (void) sigemptyset(&action.sa_mask);
  991. X  action.sa_flags=0;
  992. X  (void) sigaction(SIGTSTP,&action,(struct sigaction *) NULL);
  993. X  if (isatty(STDIN_FILENO))
  994. X    (void) setsid();
  995. X  slave=open(slave_tty,O_RDWR | O_NOCTTY);
  996. X  if (slave < 0)
  997. X    Error("unable to open slave pseudo-terminal",slave_tty);
  998. X  /*
  999. X    Condition slave tty line.
  1000. X  */
  1001. X  (void) tcgetattr(slave,&attributes);
  1002. X  attributes.c_iflag&=(~(BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR |
  1003. X    IGNCR | ICRNL | IXON));
  1004. X  attributes.c_iflag|=IGNBRK | IXOFF;
  1005. X  attributes.c_oflag&=(~OPOST);
  1006. X  attributes.c_lflag&=
  1007. X    (~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | ISIG | NOFLSH | TOSTOP));
  1008. X  attributes.c_cflag&=(~(CSIZE | CSTOPB | HUPCL | PARENB));
  1009. X  attributes.c_cflag|=CLOCAL | CREAD | CS8;
  1010. X  (void) tcflush(slave,TCIFLUSH);
  1011. X  (void) tcsetattr(slave,TCSANOW,&attributes);
  1012. X  /*
  1013. X    Execute FTP program as a child process.
  1014. X  */
  1015. X  (void) close(master);
  1016. X  (void) dup2(slave,STDIN_FILENO);
  1017. X  (void) dup2(slave,STDOUT_FILENO);
  1018. X  (void) dup2(slave,STDERR_FILENO);
  1019. X  (void) close(slave);
  1020. X  (void) execlp("ftp","ftp","-n","-i","-g","-v",host_name,port,(char *) 0);
  1021. X  perror("ftp");
  1022. X  (void) kill(0,SIGTERM);
  1023. }
  1024. X
  1025. /*
  1026. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1027. %                                                                             %
  1028. %                                                                             %
  1029. %                                                                             %
  1030. %   G e t P a s s w o r d                                                     %
  1031. %                                                                             %
  1032. %                                                                             %
  1033. %                                                                             %
  1034. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1035. %
  1036. %  Function GetPassword prompts the user for a password.  The password is
  1037. %  not echoed on the terminal.
  1038. %
  1039. %  The format of the GetPassword routine is:
  1040. %
  1041. %    password=GetPassword(prompt)
  1042. %
  1043. %  A description of each parameter follows:
  1044. %
  1045. %    o password:  Specifies a pointer to a character array that contains
  1046. %      accepted from the user.
  1047. %
  1048. %    o prompt:  Specifies a pointer to a character array that contains
  1049. %      a message to display to the user.
  1050. %
  1051. %
  1052. */
  1053. static char *GetPassword(prompt)
  1054. char
  1055. X  *prompt;
  1056. {
  1057. X  static char
  1058. X    password[2048];
  1059. X
  1060. X  struct termios
  1061. X    attributes;
  1062. X
  1063. X  (void) fprintf(stdout,"%s",prompt);
  1064. X  (void) fflush(stdout);
  1065. X  (void) tcgetattr(STDIN_FILENO,&attributes);
  1066. X  attributes.c_lflag&=(~ECHO);
  1067. X  (void) tcsetattr(STDIN_FILENO,TCSANOW,&attributes);
  1068. X  (void) gets(password);
  1069. X  attributes.c_lflag|=ECHO;
  1070. X  (void) tcsetattr(STDIN_FILENO,TCSANOW,&attributes);
  1071. X  (void) fprintf(stdout,"\n");
  1072. X  return(password);
  1073. }
  1074. X
  1075. /*
  1076. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1077. %                                                                             %
  1078. %                                                                             %
  1079. %                                                                             %
  1080. %   G e t P s e u d o T e r m i n a l                                         %
  1081. %                                                                             %
  1082. %                                                                             %
  1083. %                                                                             %
  1084. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1085. %
  1086. %  Function GetPseudoTerminal returns a master/slave pair of pseudo-terminals.
  1087. %
  1088. %  The format of the GetPseudoTerminal routine is:
  1089. %
  1090. %    GetPseudoTerminal()
  1091. %
  1092. %
  1093. */
  1094. static void GetPseudoTerminal()
  1095. {
  1096. X  char
  1097. X    master_tty[16];
  1098. X
  1099. X  register char
  1100. X    *bank,
  1101. X    *cp;
  1102. X
  1103. X  struct stat
  1104. X    info;
  1105. X
  1106. X  for (bank="pqrs"; *bank; bank++)
  1107. X  {
  1108. X    (void) sprintf(master_tty,"/dev/pty%c0",*bank);
  1109. X    if (stat(master_tty,&info) < 0)
  1110. X      break;
  1111. X    for (cp="0123456789abcdef"; *cp; cp++)
  1112. X    {
  1113. X      (void) sprintf((char *) master_tty,"/dev/pty%c%c",*bank,*cp);
  1114. X      master=open(master_tty,O_RDWR);
  1115. X      if (master >= 0)
  1116. X        {
  1117. X          /*
  1118. X            Verify slave side is usable.
  1119. X          */
  1120. X          (void) sprintf(slave_tty,"/dev/tty%c%c",*bank,*cp);
  1121. X          if (access(slave_tty,R_OK | W_OK) == 0)
  1122. X            {
  1123. X              struct termios
  1124. X                attributes;
  1125. X
  1126. X              /*
  1127. X                Condition master tty line.
  1128. X              */
  1129. X              (void) tcgetattr(master,&attributes);
  1130. X              attributes.c_lflag&=(~(ICANON | ECHO));
  1131. X              (void) tcflush(master,TCIFLUSH);
  1132. X              (void) tcsetattr(master,TCSANOW,&attributes);
  1133. X              return;
  1134. X            }
  1135. X          (void) close(master);
  1136. X        }
  1137. X    }
  1138. X  }
  1139. X  Error("All network ports in use",(char *) NULL);
  1140. }
  1141. X
  1142. /*
  1143. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1144. %                                                                             %
  1145. %                                                                             %
  1146. %                                                                             %
  1147. %   M a k e D i r e c t o r y                                                 %
  1148. %                                                                             %
  1149. %                                                                             %
  1150. %                                                                             %
  1151. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1152. %
  1153. %  Function MakeDirectory checks each component of a directory path and if it
  1154. %  does not exist, creates it.
  1155. %
  1156. %  The format of the MakeDirectory routine is:
  1157. %
  1158. %    MakeDirectory(directory)
  1159. %
  1160. %  A description of each parameter follows:
  1161. %
  1162. %    o directory:  Specifies a pointer to a character array that contains
  1163. %      the name of the directory to create.
  1164. %
  1165. %
  1166. */
  1167. static int MakeDirectory(directory)
  1168. char
  1169. X  *directory;
  1170. {
  1171. X  register char
  1172. X    *p;
  1173. X
  1174. X  struct stat
  1175. X    info;
  1176. X
  1177. X  /*
  1178. X    Determine first component of the directory.
  1179. X  */
  1180. X  p=strrchr(directory,'/');
  1181. X  if ((p == (char *) NULL) || (p == directory))
  1182. X    return(False);
  1183. X  *p='\0';
  1184. X  if (lstat(directory,&info) < 0)
  1185. X    {
  1186. X      /*
  1187. X        Path component does not exist;  create it.
  1188. X      */
  1189. X      if (MakeDirectory(directory) == 0)
  1190. X        if (mkdir(directory,(mode_t) 0777) >= 0)
  1191. X          {
  1192. X            *p='/';
  1193. X            return(False);
  1194. X          }
  1195. X    }
  1196. X  else
  1197. X    if (S_ISDIR(info.st_mode))
  1198. X      {
  1199. X        /*
  1200. X          Path component already exists.
  1201. X        */
  1202. X        *p='/';
  1203. X        return(False);
  1204. X      }
  1205. X  /*
  1206. X    Path component is a file not a directory.
  1207. X  */
  1208. X  *p='/';
  1209. X  return(True);
  1210. }
  1211. X
  1212. /*
  1213. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1214. %                                                                             %
  1215. %                                                                             %
  1216. %                                                                             %
  1217. %   P r i n t R e q u e s t                                                   %
  1218. %                                                                             %
  1219. %                                                                             %
  1220. %                                                                             %
  1221. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1222. %
  1223. %  Function PrintRequest prints a file on the remote FTP server.
  1224. %
  1225. %  The format of the PrintRequest routine is:
  1226. %
  1227. %    PrintRequest(filename,verbose)
  1228. %
  1229. %  A description of each parameter follows:
  1230. %
  1231. %    o filename:  Specifies a pointer to a character array that contains
  1232. %      the name of the file to print.
  1233. %
  1234. %    o verbose: An unsigned integer.  A value other than zero dhows all
  1235. %      responses from the remote server.
  1236. %
  1237. %
  1238. */
  1239. static void PrintRequest(filename,verbose)
  1240. char
  1241. X  *filename;
  1242. X
  1243. unsigned int
  1244. X  verbose;
  1245. {
  1246. X  char
  1247. X    command[2048],
  1248. X    *response;
  1249. X
  1250. X  /*
  1251. X    get remote-file [ - | < |zcat > ].
  1252. X  */
  1253. X  (void) sprintf(command,"get %s",filename);
  1254. X  if (strcmp(filename+strlen(filename)-2,".Z"))
  1255. X    (void) strcat(command," -\n");
  1256. X  else
  1257. X    (void) strcat(command," |zcat\n");
  1258. X  (void) write(master,command,strlen(command));
  1259. X  (void) fprintf(stdout,"%s:\n",filename);
  1260. X  while ((response=Wait()))
  1261. X    if (status == 0)
  1262. X      (void) fprintf(stdout,"%s\n",response);
  1263. X    else
  1264. X      if ((status == 5) || verbose)
  1265. X        (void) fprintf(stderr,"%s\n",response);
  1266. }
  1267. X
  1268. /*
  1269. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1270. %                                                                             %
  1271. %                                                                             %
  1272. %                                                                             %
  1273. %   P r o c e s s R e q u e s t                                               %
  1274. %                                                                             %
  1275. %                                                                             %
  1276. %                                                                             %
  1277. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1278. %
  1279. %  Function ProcessRequest first records any file in the current directory
  1280. %  of the remote FTP server or any of its subdirectories.  Next each filename
  1281. %  is either accepted or rejected based on a user specified regular
  1282. %  expresssion.  If any files match the regular expression, its filename is
  1283. %  listed, it is printed, or it is retrieved as specified on the command line.
  1284. %
  1285. %  The format of the ProcessRequest routine is:
  1286. %
  1287. %    ProcessRequest(prune,verbose)
  1288. %
  1289. %  A description of each parameter follows:
  1290. %
  1291. %    o prune:  Specifies whether to recusively search for files.
  1292. %
  1293. %    o verbose: An unsigned integer.  A value other than zero dhows all
  1294. %      responses from the remote server.
  1295. %
  1296. %
  1297. */
  1298. static void ProcessRequest(prune,verbose)
  1299. unsigned int
  1300. X  prune,
  1301. X  verbose;
  1302. {
  1303. X  typedef struct _DirectoryNode
  1304. X  {
  1305. X    char
  1306. X      *info,
  1307. X      *name;
  1308. X
  1309. X    struct _DirectoryNode
  1310. X      *next;
  1311. X  } DirectoryNode;
  1312. X
  1313. X  char
  1314. X    command[2048],
  1315. X    directory[2048],
  1316. X    *info,
  1317. X    *name,
  1318. X    *response;
  1319. X
  1320. X  DirectoryNode
  1321. X    *next,
  1322. X    *root;
  1323. X
  1324. X  register char
  1325. X    *p;
  1326. X
  1327. X  register DirectoryNode
  1328. X    **last,
  1329. X    *node;
  1330. X
  1331. X  RegularExpression
  1332. X    *date_expression,
  1333. X    *mode_expression;
  1334. X
  1335. X  unsigned int
  1336. X    unix_filesystem;
  1337. X
  1338. X  /*
  1339. X    Initialize function variables.
  1340. X  */
  1341. X  root=(DirectoryNode *) NULL;
  1342. X  last=(&root);
  1343. X  *directory='\0';
  1344. X  response=(char *) NULL;
  1345. X  unix_filesystem=False;
  1346. X  if (!prune)
  1347. X    {
  1348. X      /*
  1349. X        Obtain a time sorted recursive directory if available.
  1350. X      */
  1351. X      (void) strcpy(command,"get ls-ltR.Z |zcat\n");
  1352. X      (void) write(master,command,strlen(command));
  1353. X      while ((response=Wait()))
  1354. X        if ((status == 0) || (status == 5))
  1355. X          break;
  1356. X      if (status == 5)
  1357. X        {
  1358. X          /*
  1359. X            Obtain a recursive directory if available.
  1360. X          */
  1361. X          while (Wait());
  1362. X          (void) strcpy(command,"get ls-lR.Z |zcat\n");
  1363. X          (void) write(master,command,strlen(command));
  1364. X          while ((response=Wait()))
  1365. X            if ((status == 0) || (status == 5))
  1366. X              break;
  1367. X        }
  1368. X      if (status == 5)
  1369. X        while (Wait());
  1370. X      else
  1371. X        {
  1372. X          (void) fprintf(stderr,"Using existing directory listing...\n");
  1373. X          unix_filesystem=True;
  1374. X        }
  1375. X    }
  1376. X  if (prune || !unix_filesystem)
  1377. X    {
  1378. X      /*
  1379. X        Determine if the FTP server has unix-style filenames.
  1380. X      */
  1381. X      mode_expression=CompileRegularExpression("^.[rwx-][rwx-][rwx-]");
  1382. X      (void) strcpy(command,"dir\n");
  1383. X      (void) write(master,command,strlen(command));
  1384. X      while ((response=Wait()))
  1385. X        if (!unix_filesystem)
  1386. X          if (*response != '\0')
  1387. X            unix_filesystem=ExecuteRegularExpression(mode_expression,response);
  1388. X      (void) free((char *) mode_expression);
  1389. X      /*
  1390. X        Obtain recursive directory listing with the FTP directory command.
  1391. X      */
  1392. X      if (prune)
  1393. X        (void) strcpy(command,"dir\n");
  1394. X      else
  1395. X        if (unix_filesystem)
  1396. X          (void) strcpy(command,"ls -ltR\n");
  1397. X        else
  1398. X          (void) strcpy(command,"ls [...]\n");
  1399. X      (void) write(master,command,strlen(command));
  1400. X      while ((response=Wait()))
  1401. X        if ((status == 0) || (status == 5))
  1402. X          break;
  1403. X      if (status == 5)
  1404. X        {
  1405. X          /*
  1406. X            Directory command has limited functionality.
  1407. X          */
  1408. X          while (Wait());
  1409. X          (void) strcpy(command,"dir\n");
  1410. X          (void) write(master,command,strlen(command));
  1411. X          while ((response=Wait()))
  1412. X            if (status == 0)
  1413. X              break;
  1414. X        }
  1415. X    }
  1416. X  status=(-1);
  1417. X  if (response == (char *) NULL)
  1418. X    return;
  1419. X  if (!unix_filesystem)
  1420. X    do
  1421. X    {
  1422. X      /*
  1423. X        Link non unix-style file into file list.
  1424. X      */
  1425. X      if ((status > 0) || (*response == '\0'))
  1426. X        continue;
  1427. X      while (*response == ' ')
  1428. X        response++;
  1429. X      /*
  1430. X        Extract file name & info.
  1431. X      */
  1432. X      name=response;
  1433. X      info=response;
  1434. X      while ((*info != ' ') && *info)
  1435. X        info++;
  1436. X      *info='\0';
  1437. X      node=(DirectoryNode *) malloc(sizeof(DirectoryNode));
  1438. X      if (node == (DirectoryNode *) NULL)
  1439. X        Error("unable to allocate memory",(char *) NULL);
  1440. X      node->name=(char *) malloc((strlen(name)+1)*sizeof(char));
  1441. X      node->info=(char *) malloc((strlen(info)+1)*sizeof(char));
  1442. X      if ((node->name == (char *) NULL) || (node->info == (char *) NULL))
  1443. X        Error("unable to allocate memory",(char *) NULL);
  1444. X      (void) strcpy(node->name,name);
  1445. X      (void) strcpy(node->info,info);
  1446. X      node->next=(DirectoryNode *) NULL;
  1447. X      if (exclude_expression)
  1448. X        if (ExecuteRegularExpression(exclude_expression,node->name))
  1449. X          {
  1450. X            /*
  1451. X              Free allocated memory for this node.
  1452. X            */
  1453. X            (void) free((char *) node->info);
  1454. X            (void) free((char *) node->name);
  1455. X            (void) free((char *) node);
  1456. X            continue;
  1457. X          }
  1458. X      *last=node;
  1459. X      last=(&node->next);
  1460. X    }
  1461. X    while ((response=Wait()));
  1462. X  else
  1463. X    {
  1464. X      RegularExpression
  1465. X        *access_expression;
  1466. X
  1467. X      access_expression=
  1468. X        CompileRegularExpression("Permission denied|not found|cannot access");
  1469. X      date_expression=
  1470. X        CompileRegularExpression(" [0-9][0-9][0-9][0-9]|[0-9][0-9]:[0-9][0-9]");
  1471. X      do
  1472. X      {
  1473. X        /*
  1474. X           Link unix-style file into file list.
  1475. X        */
  1476. X        if ((status > 0) || (*response == '\0'))
  1477. X          continue;
  1478. X        while (*response == ' ')
  1479. X          response++;
  1480. X        p=response+strlen(response)-1;
  1481. X        if ((*response == '-') || (*response == 'F'))
  1482. X          {
  1483. X            if (ExecuteRegularExpression(access_expression,response))
  1484. X              continue;
  1485. X            /*
  1486. X              Extract file info & name.
  1487. X            */
  1488. X            while (p-- > (response+5))
  1489. X              if (*p == ' ')
  1490. X                if (!ExecuteRegularExpression(date_expression,p-5))
  1491. X                  *p='_';
  1492. X                else
  1493. X                  break;
  1494. X            *p++='\0';
  1495. X            while (*p == ' ')
  1496. X              p++;
  1497. X            name=p;
  1498. X            info=response;
  1499. X            node=(DirectoryNode *) malloc(sizeof(DirectoryNode));
  1500. X            if (node == (DirectoryNode *) NULL)
  1501. X              Error("unable to allocate memory",(char *) NULL);
  1502. X            node->name=(char *) malloc(strlen(directory)+strlen(name)+1);
  1503. X            node->info=(char *) malloc(strlen(info)+1);
  1504. X            if ((node->name == (char *) NULL) || (node->info == (char *) NULL))
  1505. X              Error("unable to allocate memory",(char *) NULL);
  1506. X            (void) strcpy(node->name,directory);
  1507. X            (void) strcat(node->name,name);
  1508. X            (void) strcpy(node->info,info);
  1509. X            node->next=(DirectoryNode *) NULL;
  1510. X            if (exclude_expression)
  1511. X              if (ExecuteRegularExpression(exclude_expression,node->name))
  1512. X                {
  1513. X                  /*
  1514. X                    Free allocated memory for this node.
  1515. X                  */
  1516. X                  (void) free((char *) node->info);
  1517. X                  (void) free((char *) node->name);
  1518. X                  (void) free((char *) node);
  1519. X                  continue;
  1520. X                }
  1521. X            *last=node;
  1522. X            last=(&node->next);
  1523. X          }
  1524. X        else
  1525. X          if (*p == ':')
  1526. X            {
  1527. X              /*
  1528. X                File is a directory.
  1529. X              */
  1530. X              do { p--; } while (*p == ' ');
  1531. X              *(++p)='\0';
  1532. X              (void) strcpy(directory,response);
  1533. X              (void) strcat(directory,"/");
  1534. X            }
  1535. X      }
  1536. X      while ((response=Wait()));
  1537. X      (void) free((char *) access_expression);
  1538. X      (void) free((char *) date_expression);
  1539. X    }
  1540. X  /*
  1541. X    Traverse the file list and act on a filename if it matches the regular
  1542. X    expression.
  1543. X  */
  1544. X  status=(-1);
  1545. X  node=root;
  1546. X  while (node)
  1547. X  {
  1548. X    if (directory_expression)
  1549. X      if (ExecuteRegularExpression(directory_expression,node->name))
  1550. X        (void) DirectoryRequest(node->info,node->name);
  1551. X    if (print_expression)
  1552. X      if (ExecuteRegularExpression(print_expression,node->name))
  1553. X        (void) PrintRequest(node->name,verbose);
  1554. X    if (retrieve_expression)
  1555. X      if (ExecuteRegularExpression(retrieve_expression,node->name))
  1556. X        (void) RetrieveRequest(node->name,verbose);
  1557. X    /*
  1558. X      Free allocated memory for this node.
  1559. X    */
  1560. X    (void) free((char *) node->info);
  1561. X    (void) free((char *) node->name);
  1562. X    next=node->next;
  1563. X    (void) free((char *) node);
  1564. X    node=next;
  1565. X  }
  1566. X  if (status < 0)
  1567. X    Warning("no files matched your expression",(char *) NULL);
  1568. }
  1569. X
  1570. /*
  1571. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1572. %                                                                             %
  1573. %                                                                             %
  1574. %                                                                             %
  1575. %   R e t r i e v e R e q u e s t                                             %
  1576. %                                                                             %
  1577. %                                                                             %
  1578. %                                                                             %
  1579. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1580. %
  1581. %  Function RetrieveRequest retrieves a file from the remote FTP server.
  1582. %
  1583. %  The format of the RetrieveRequest routine is:
  1584. %
  1585. %    RetrieveRequest(filename,verbose)
  1586. %
  1587. %  A description of each parameter follows:
  1588. %
  1589. %    o filename:  Specifies a pointer to a character array that contains
  1590. %      the name of the file to retrieve.
  1591. %
  1592. %    o verbose: An unsigned integer.  A value other than zero dhows all
  1593. %      responses from the remote server.
  1594. %
  1595. %
  1596. */
  1597. static void RetrieveRequest(filename,verbose)
  1598. char
  1599. X  *filename;
  1600. X
  1601. unsigned int
  1602. X  verbose;
  1603. {
  1604. X  char
  1605. X    command[2048],
  1606. X    *response;
  1607. X
  1608. X  /*
  1609. X    get remote-file
  1610. X  */
  1611. X  (void) MakeDirectory(filename);
  1612. X  (void) sprintf(command,"get %s\n",filename);
  1613. X  (void) write(master,command,strlen(command));
  1614. X  while ((response=Wait()))
  1615. X    if (status == 0)
  1616. X      (void) fprintf(stdout,"%s\n",response);
  1617. X    else
  1618. X      if ((status == 5) || verbose)
  1619. X        (void) fprintf(stderr,"%s\n",response);
  1620. }
  1621. X
  1622. /*
  1623. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1624. %                                                                             %
  1625. %                                                                             %
  1626. %                                                                             %
  1627. %   S i g n a l C h i l d                                                     %
  1628. %                                                                             %
  1629. %                                                                             %
  1630. %                                                                             %
  1631. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1632. SHAR_EOF
  1633. true || echo 'restore of ImageMagick/xtp/xtp.c failed'
  1634. fi
  1635. echo 'End of ImageMagick part 6'
  1636. echo 'File ImageMagick/xtp/xtp.c is continued in part 7'
  1637. echo 7 > _shar_seq_.tmp
  1638. exit 0
  1639.  
  1640. exit 0 # Just in case...
  1641. -- 
  1642.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1643. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  1644.  "It's intuitively obvious to the |
  1645.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1646.