home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume13 / imagemagic / part03 < prev    next >
Internet Message Format  |  1991-05-22  |  75KB

  1. Path: uunet!cs.utexas.edu!sun-barr!newstop!exodus!dupont.com!cristy
  2. From: cristy@dupont.com
  3. Newsgroups: comp.sources.x
  4. Subject: v13i019: ImageMagick - Graphics display programs, Part03/21
  5. Message-ID: <13789@exodus.Eng.Sun.COM>
  6. Date: 22 May 91 08:57:20 GMT
  7. References: <csx-13i017:imagemagic@uunet.UU.NET>
  8. Sender: news@exodus.Eng.Sun.COM
  9. Lines: 2396
  10. Approved: argv@sun.com
  11.  
  12. Submitted-by: cristy@dupont.com
  13. Posting-number: Volume 13, Issue 19
  14. Archive-name: imagemagic/part03
  15.  
  16. #!/bin/sh
  17. # this is img.03 (part 3 of ImageMagick)
  18. # do not concatenate these parts, unpack them in order with /bin/sh
  19. # file ImageMagick/xtp/regular.c continued
  20. #
  21. if test ! -r _shar_seq_.tmp; then
  22.     echo 'Please unpack part 1 first!'
  23.     exit 1
  24. fi
  25. (read Scheck
  26.  if test "$Scheck" != 3; then
  27.     echo Please unpack part "$Scheck" next!
  28.     exit 1
  29.  else
  30.     exit 0
  31.  fi
  32. ) < _shar_seq_.tmp || exit 1
  33. if test ! -f _shar_wnt_.tmp; then
  34.     echo 'x - still skipping ImageMagick/xtp/regular.c'
  35. else
  36. echo 'x - continuing file ImageMagick/xtp/regular.c'
  37. sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/xtp/regular.c' &&
  38. %                                                                             %
  39. %                                                                             %
  40. %   P i e c e                                                                 %
  41. %                                                                             %
  42. %                                                                             %
  43. %                                                                             %
  44. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  45. %
  46. %
  47. */
  48. static char *Piece(flagp)
  49. int
  50. X  *flagp;
  51. {
  52. X  int
  53. X    flags;
  54. X
  55. X  register char
  56. X    *next_token,
  57. X    op,
  58. X    *status;
  59. X
  60. X  static void
  61. X    Tail();
  62. X
  63. X  status=Atom(&flags);
  64. X  if (status == NULL)
  65. X    return(NULL);
  66. X  op=(*token);
  67. X  if (!MultipleMatches(op))
  68. X    {
  69. X      *flagp=flags;
  70. X      return(status);
  71. X    }
  72. X  if (!(flags & NonNull) && op != '?')
  73. X    Fail("*+ operand could be empty");
  74. X  *flagp=(op != '+') ? (WorstCase | SpecialStart) : (WorstCase | NonNull);
  75. X  if (op == '*' && (flags & Simple))
  76. X    Insert(MatchZeroOrMore,status);
  77. X  else
  78. X    if (op == '*')
  79. X      {
  80. X        /*
  81. X          Emit x* as (x&|), where & means "self".
  82. X        */
  83. X        Insert(MatchThisOrNext,status);  
  84. X        OpTail(status,Node(Back)); 
  85. X        OpTail(status,status); 
  86. X        Tail(status,Node(MatchThisOrNext));  
  87. X        Tail(status,Node(MatchEmptyString));
  88. X      }
  89. X    else
  90. X      if ((op == '+') && (flags & Simple))
  91. X        Insert(MatchOneOrMore,status);
  92. X      else
  93. X        if (op == '+')
  94. X          {
  95. X            /*
  96. X              Emit x+ as x (&|), where & means "self".
  97. X            */
  98. X            next_token=Node(MatchThisOrNext);  
  99. X            Tail(status,next_token);
  100. X            Tail(Node(Back),status);
  101. X            Tail(next_token,Node(MatchThisOrNext));
  102. X            Tail(status,Node(MatchEmptyString));
  103. X          }
  104. X        else
  105. X          if (op == '?')
  106. X            {
  107. X              /*
  108. X                Emit x? as (x|)
  109. X              */
  110. X              Insert(MatchThisOrNext,status);  
  111. X              Tail(status,Node(MatchThisOrNext));  
  112. X              next_token=Node(MatchEmptyString);  
  113. X              Tail(status,next_token);
  114. X              OpTail(status,next_token);
  115. X            }
  116. X  token++;
  117. X  if (MultipleMatches(*token))
  118. X    Fail("nested *?+");
  119. X  return(status);
  120. }
  121. X
  122. /*
  123. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  124. %                                                                             %
  125. %                                                                             %
  126. %                                                                             %
  127. %   R e g u l a r                                                             %
  128. %                                                                             %
  129. %                                                                             %
  130. %                                                                             %
  131. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  132. %
  133. %
  134. */
  135. static char *Regular(parenthesized,flagp)
  136. int
  137. X  parenthesized;
  138. X
  139. int
  140. X  *flagp;
  141. {
  142. X  int
  143. X    flags;
  144. X
  145. X  register char
  146. X    *br,
  147. X    *ender,
  148. X    *status;
  149. X
  150. X  register int
  151. X    count;
  152. X
  153. X  static void
  154. X    Tail();
  155. X
  156. X  count=0;
  157. X  *flagp=NonNull;
  158. X  if (!parenthesized)
  159. X    status=NULL;
  160. X  else
  161. X    {
  162. X      /*
  163. X        Make an Open node.
  164. X      */
  165. X      if (number_parenthesis >= NumberSubExpressions)
  166. X        Fail("too many ()");
  167. X      count=number_parenthesis;
  168. X      number_parenthesis++;
  169. X      status=Node(Open+count);
  170. X    }
  171. X  /*
  172. X    Pick up the branches, linking them together.
  173. X  */
  174. X  br=Branch(&flags);
  175. X  if (br == NULL)
  176. X    return(NULL);
  177. X  if (status != NULL)
  178. X    Tail(status,br);
  179. X  else
  180. X    status=br;
  181. X  if (!(flags & NonNull))
  182. X    *flagp&=(~NonNull);
  183. X  *flagp|=flags & SpecialStart;
  184. X  while (*token == '|')
  185. X  {
  186. X    token++;
  187. X    br=Branch(&flags);
  188. X    if (br == NULL)
  189. X      return(NULL);
  190. X    Tail(status,br);
  191. X    if (!(flags & NonNull))
  192. X      *flagp &= ~NonNull;
  193. X    *flagp|=flags & SpecialStart;
  194. X  }
  195. X  /*
  196. X    Make a closing node and hook it on the end.
  197. X  */
  198. X  ender=Node((parenthesized) ? Close+count : EndOfProgram);
  199. X  Tail(status,ender);
  200. X  /*
  201. X    Hook the tails of the branches to the closing node.
  202. X  */
  203. X  for(br=status; br != NULL; br=NextToken(br))
  204. X    OpTail(br,ender);
  205. X  /*
  206. X    Check for proper termination.
  207. X  */
  208. X  if (parenthesized && (*token++ != ')'))
  209. X    Fail("unmatched()")
  210. X  else
  211. X    if (!parenthesized && (*token != '\0'))
  212. X      {
  213. X        if (*token == ')')
  214. X          Fail("unmatched()")
  215. X        else
  216. X          Fail("junk on end")
  217. X       }
  218. X  return(status);
  219. }
  220. X
  221. /*
  222. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  223. %                                                                             %
  224. %                                                                             %
  225. %                                                                             %
  226. %   R e p e a t                                                               %
  227. %                                                                             %
  228. %                                                                             %
  229. %                                                                             %
  230. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  231. %
  232. %
  233. */
  234. static int Repeat(p)
  235. char
  236. X  *p;
  237. {
  238. X  register char
  239. X    *operand,
  240. X    *scan;
  241. X
  242. X  register int
  243. X    count=0;
  244. X
  245. X  scan=p;
  246. X  operand=Operand(p);
  247. X  switch(OpCode(p))
  248. X  {
  249. X    case MatchAnyCharacter:
  250. X    {
  251. X      count=strlen(scan);
  252. X      scan+=count;
  253. X      break;
  254. X    }
  255. X    case MatchExactly:
  256. X    {
  257. X      while (*operand == *scan)
  258. X      {
  259. X        count++;
  260. X        scan++;
  261. X      }
  262. X      break;
  263. X    }
  264. X    case MatchAnyCharacterOf:
  265. X    {
  266. X      while ((*scan != '\0') && (strchr(operand,*scan) != NULL))
  267. X      {
  268. X        count++;
  269. X        scan++;
  270. X      }
  271. X      break;
  272. X    }
  273. X    case MatchAnyCharacterBut:
  274. X    {
  275. X      while ((*scan != '\0') && (strchr(operand,*scan) == NULL))
  276. X      {
  277. X        count++;
  278. X        scan++;
  279. X      }
  280. X      break;
  281. X    }
  282. X    default:
  283. X    {
  284. X      (void) fprintf(stderr,"Regular(3): %s","internal foulup");
  285. X      count=0;
  286. X      break;
  287. X    }
  288. X  }
  289. X  p=scan;
  290. X  return(count);
  291. }
  292. X
  293. /*
  294. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  295. %                                                                             %
  296. %                                                                             %
  297. %                                                                             %
  298. %   T a i l                                                                   %
  299. %                                                                             %
  300. %                                                                             %
  301. %                                                                             %
  302. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  303. %
  304. %
  305. */
  306. static void Tail(p,val)
  307. char
  308. X  *p;
  309. X
  310. char
  311. X  *val;
  312. {
  313. X  register char
  314. X    *scan,
  315. X    *temp;
  316. X
  317. X  register int
  318. X    offset;
  319. X
  320. X  if (p == &start_code)
  321. X    return;
  322. X  /*
  323. X    Find last node.
  324. X  */
  325. X  scan=p;
  326. X  for(;;)
  327. X  {
  328. X    temp=NextToken(scan);
  329. X    if (temp == NULL)
  330. X      break;
  331. X    scan=temp;
  332. X  }
  333. X  if (OpCode(scan) == Back)
  334. X    offset=scan-val;
  335. X  else
  336. X    offset=val-scan;
  337. X  *(scan+1)=(offset >> 8) & 0377;
  338. X  *(scan+2)=offset & 0377;
  339. }
  340. X
  341. /*
  342. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  343. %                                                                             %
  344. %                                                                             %
  345. %                                                                             %
  346. %   T r y                                                                     %
  347. %                                                                             %
  348. %                                                                             %
  349. %                                                                             %
  350. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  351. %
  352. %
  353. */
  354. static int Try(regular_expression,pattern)
  355. RegularExpression
  356. X  *regular_expression;
  357. X
  358. char
  359. X  *pattern;
  360. {
  361. X  register char
  362. X    **ep,
  363. X    **sp;
  364. X
  365. X  register int
  366. X    i;
  367. X
  368. X  p=pattern;
  369. X  subpattern=regular_expression->subpattern;
  370. X  subpattern_end=regular_expression->subpattern_end;
  371. X  sp=regular_expression->subpattern;
  372. X  ep=regular_expression->subpattern_end;
  373. X  for(i=NumberSubExpressions; i > 0; i--)
  374. X  {
  375. X    *sp++=NULL;
  376. X    *ep++=NULL;
  377. X  }
  378. X  if (!Match(regular_expression->program+1))
  379. X    return(0);
  380. X  else
  381. X    {
  382. X      regular_expression->subpattern[0]=pattern;
  383. X      regular_expression->subpattern_end[0]=p;
  384. X      return(1);
  385. X    }
  386. }
  387. X
  388. /*
  389. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  390. %                                                                             %
  391. %                                                                             %
  392. %                                                                             %
  393. %   C o m p i l e R e g u l a r E x p r e s s i o n                           %
  394. %                                                                             %
  395. %                                                                             %
  396. %                                                                             %
  397. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  398. %
  399. %  Function CompileRegularExpression compiles a regular expression into a 
  400. %  structure of type RegularExpression and returns a pointer to it.  The space 
  401. %  is allocated using function malloc and may be released by function free.
  402. %
  403. %
  404. */
  405. RegularExpression *CompileRegularExpression(regular_expression)
  406. char
  407. X  *regular_expression;
  408. {
  409. X  int
  410. X    flags;
  411. X
  412. X  register char
  413. X    *longest,
  414. X    *scan;
  415. X
  416. X  register RegularExpression
  417. X    *r;
  418. X
  419. X  register int
  420. X    length;
  421. X
  422. X  if (regular_expression == NULL)
  423. X    Fail("NULL argument");
  424. X  /*
  425. X    First pass: determine size.
  426. X  */
  427. X  token=regular_expression;
  428. X  number_parenthesis=1;
  429. X  code_size=0L;
  430. X  code=(&start_code);
  431. X  EmitCode(Magick);
  432. X  if (Regular(0,&flags) == NULL)
  433. X    return(NULL);
  434. X  /*
  435. X    Allocate space.
  436. X  */
  437. X  r=(RegularExpression *)
  438. X    malloc((unsigned int) (code_size+sizeof(RegularExpression)));
  439. X  if (r == NULL)
  440. X    Fail("out of space");
  441. X  /*
  442. X    Second pass: emit code.
  443. X  */
  444. X  token=regular_expression;
  445. X  number_parenthesis=1;
  446. X  code=r->program;
  447. X  EmitCode(Magick);
  448. X  if (Regular(0,&flags) == NULL)
  449. X    return(NULL);
  450. X  /*
  451. X    Dig out information for optimizations.
  452. X  */
  453. X  r->start_character='\0';
  454. X  r->anchor=0;
  455. X  r->priority_pattern=NULL;
  456. X  r->pattern_length=0;
  457. X  scan=r->program+1;
  458. X  if (OpCode(NextToken(scan)) == EndOfProgram)
  459. X    {
  460. X      scan=Operand(scan);
  461. X      if (OpCode(scan) == MatchExactly)
  462. X        r->start_character=(*Operand(scan));
  463. X      else
  464. X        if (OpCode(scan) == MatchBeginningOfLine)
  465. X          r->anchor++;
  466. X      /*
  467. X        If there's something expensive in the regular expression, find the
  468. X        longest literal pattern that must appear and make it the 
  469. X        priority_pattern.
  470. X      */
  471. X      if (flags & SpecialStart)
  472. X        {
  473. X          longest=NULL;
  474. X          length=0;
  475. X          for(; scan != NULL; scan=NextToken(scan))
  476. X            if ((OpCode(scan) == MatchExactly) && 
  477. X                (strlen(Operand(scan)) >= length))
  478. X              {
  479. X                longest=Operand(scan);
  480. X                length=strlen(Operand(scan));
  481. X              }
  482. X          r->priority_pattern=longest;
  483. X          r->pattern_length=length;
  484. X        }
  485. X    }
  486. X  return(r);
  487. }
  488. X
  489. /*
  490. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  491. %                                                                             %
  492. %                                                                             %
  493. %                                                                             %
  494. %   E x e c u t e R e g u l a r E x p r e s s i o n                           %
  495. %                                                                             %
  496. %                                                                             %
  497. %                                                                             %
  498. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  499. %
  500. %  Function ExecuteRegularExpression matches a NULL-terminated pattern against 
  501. %  the compiled regular expression in regular-expression.  It returns 1 for 
  502. %  success and 0 for failure.
  503. %
  504. %
  505. */
  506. int ExecuteRegularExpression(regular_expression,pattern)
  507. register RegularExpression
  508. X  *regular_expression;
  509. X
  510. register char
  511. X  *pattern;
  512. {
  513. X  register char
  514. X    *s;
  515. X
  516. X  if ((regular_expression == (RegularExpression *) NULL) || 
  517. X      (pattern == (char *) NULL))
  518. X    {
  519. X      (void) fprintf(stderr,"Regular(3): %s","NULL parameter\n");
  520. X      return(0);
  521. X    }
  522. X  /*
  523. X    Check validity of program.
  524. X  */
  525. X  if (((int)*(unsigned char *)(regular_expression->program)) != Magick)
  526. X    {
  527. X      (void) fprintf(stderr,"Regular(3): %s","corrupted program");
  528. X      return(0);
  529. X    }
  530. X  /*
  531. X    If there is a "must appear" pattern, look for it.
  532. X  */
  533. X  if (regular_expression->priority_pattern != NULL)
  534. X    {
  535. X      s=pattern;
  536. X      while ((s=strchr(s,regular_expression->priority_pattern[0])) != NULL)
  537. X      {
  538. X        if (strncmp(s,regular_expression->priority_pattern,
  539. X            regular_expression->pattern_length) == 0)
  540. X          break;
  541. X        s++;
  542. X       }
  543. X       if (s == NULL)
  544. X         return(0);
  545. X    }
  546. X  /*
  547. X    Mark beginning of line for ^.
  548. X  */
  549. X  start_pattern=pattern;
  550. X  /*
  551. X    Simplest case:  anchored match need be tried only once.
  552. X  */
  553. X  if (regular_expression->anchor)
  554. X    return(Try(regular_expression,pattern));
  555. X  /*
  556. X    Messy cases:  unanchored match.
  557. X  */
  558. X  s=pattern;
  559. X  if (regular_expression->start_character != '\0')
  560. X    while ((s=strchr(s,regular_expression->start_character)) != NULL)
  561. X    {
  562. X      if (Try(regular_expression,s))
  563. X        return(1);
  564. X      s++;
  565. X    }
  566. X  else
  567. X    do
  568. X    {
  569. X      if (Try(regular_expression,s))
  570. X        return(1);
  571. X    } while (*s++ != '\0');
  572. X  return(0);
  573. }
  574. SHAR_EOF
  575. echo 'File ImageMagick/xtp/regular.c is complete' &&
  576. chmod 0755 ImageMagick/xtp/regular.c ||
  577. echo 'restore of ImageMagick/xtp/regular.c failed'
  578. Wc_c="`wc -c < 'ImageMagick/xtp/regular.c'`"
  579. test 33398 -eq "$Wc_c" ||
  580.     echo 'ImageMagick/xtp/regular.c: original size 33398, current size' "$Wc_c"
  581. rm -f _shar_wnt_.tmp
  582. fi
  583. # ============= ImageMagick/xtp/regular.h ==============
  584. if test -f 'ImageMagick/xtp/regular.h' -a X"$1" != X"-c"; then
  585.     echo 'x - skipping ImageMagick/xtp/regular.h (File already exists)'
  586.     rm -f _shar_wnt_.tmp
  587. else
  588. > _shar_wnt_.tmp
  589. echo 'x - extracting ImageMagick/xtp/regular.h (Text)'
  590. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/regular.h' &&
  591. /*
  592. X  Definitions etc. for RegularExpression(3) routines.
  593. */
  594. #define EndOfProgram  0
  595. #define MatchBeginningOfLine  1
  596. #define MatchEndOfProgramOfLine  2
  597. #define MatchAnyCharacter  3
  598. #define MatchAnyCharacterOf  4
  599. #define MatchAnyCharacterBut  5
  600. #define MatchThisOrNext  6
  601. #define Back  7
  602. #define MatchExactly  8
  603. #define MatchEmptyString  9
  604. #define MatchZeroOrMore  10
  605. #define MatchOneOrMore  11
  606. #define Open  20
  607. #define Close  30
  608. X
  609. #define WorstCase  0
  610. #define NonNull  1
  611. #define Simple  2
  612. #define SpecialStart  4
  613. X
  614. #define Fail(m)  \
  615. {  \
  616. X  (void) fprintf(stderr,"RegularExpression: %s\n",m);  \
  617. X  return(NULL);  \
  618. }
  619. #define Magick   0234
  620. #define Meta  "^$.[()|?+*\\"
  621. #define MultipleMatches(c) (((c) == '*') || ((c) == '+') || ((c) == '?'))
  622. #define Next(p) (((*((p)+1) & 0377) << 8 )+(*((p)+2) & 0377))
  623. #define NumberSubExpressions  10
  624. #define OpCode(p) (*(p))
  625. #define Operand(p) ((p)+3)
  626. X
  627. typedef struct _RegularExpression 
  628. {
  629. X  char 
  630. X    *subpattern[NumberSubExpressions],
  631. X    *subpattern_end[NumberSubExpressions],
  632. X    start_character,
  633. X    anchor,
  634. X    *priority_pattern;
  635. X
  636. X  int 
  637. X    pattern_length;
  638. X
  639. X  char 
  640. X    program[1];
  641. } RegularExpression;
  642. X
  643. extern RegularExpression 
  644. X  *CompileRegularExpression();
  645. X
  646. extern int 
  647. X  ExecuteRegularExpression();
  648. SHAR_EOF
  649. chmod 0755 ImageMagick/xtp/regular.h ||
  650. echo 'restore of ImageMagick/xtp/regular.h failed'
  651. Wc_c="`wc -c < 'ImageMagick/xtp/regular.h'`"
  652. test 1245 -eq "$Wc_c" ||
  653.     echo 'ImageMagick/xtp/regular.h: original size 1245, current size' "$Wc_c"
  654. rm -f _shar_wnt_.tmp
  655. fi
  656. # ============= ImageMagick/xtp/xtp.c ==============
  657. if test -f 'ImageMagick/xtp/xtp.c' -a X"$1" != X"-c"; then
  658.     echo 'x - skipping ImageMagick/xtp/xtp.c (File already exists)'
  659.     rm -f _shar_wnt_.tmp
  660. else
  661. > _shar_wnt_.tmp
  662. echo 'x - extracting ImageMagick/xtp/xtp.c (Text)'
  663. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/xtp.c' &&
  664. /*
  665. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  666. %                                                                             %
  667. %                                                                             %
  668. %                                                                             %
  669. %                            X   X  TTTTT PPPP                                %
  670. %                             X X     T   P   P                               %
  671. %                              X      T   PPPP                                %
  672. %                             X X     T   P                                   %
  673. %                            X   X    T   P                                   %
  674. %                                                                             %
  675. %                                                                             %
  676. %                         File transfer program.                              %
  677. %                                                                             %
  678. %                                                                             %
  679. %                                                                             %
  680. %                           Software Design                                   %
  681. %                             John Cristy                                     %
  682. %                            January  1991                                    %
  683. %                                                                             %
  684. %                                                                             %
  685. %  Copyright 1991 E. I. Dupont de Nemours & Company                           %
  686. %                                                                             %
  687. %  Permission to use, copy, modify, distribute, and sell this software and    %
  688. %  its documentation for any purpose is hereby granted without fee,           %
  689. %  provided that the above copyright notice appear in all copies and that     %
  690. %  both that copyright notice and this permission notice appear in            %
  691. %  supporting documentation, and that the name of E. I. Dupont de Nemours     %
  692. %  & Company not be used in advertising or publicity pertaining to            %
  693. %  distribution of the software without specific, written prior               %
  694. %  permission.  E. I. Dupont de Nemours & Company makes no representations    %
  695. %  about the suitability of this software for any purpose.  It is provided    %
  696. %  "as is" without express or implied warranty.                               %
  697. %                                                                             %
  698. %  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
  699. %  to this software, including all implied warranties of merchantability      %
  700. %  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
  701. %  liable for any special, indirect or consequential damages or any           %
  702. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  703. %  in an action of contract, negligence or other tortious action, arising     %
  704. %  out of or in connection with the use or performance of this software.      %
  705. %                                                                             %
  706. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  707. %
  708. %  Xtp is a utility for retrieving, listing, or printing files from a
  709. %  remote network site.  Xtp performs most of the same functions as the
  710. %  ftp program, but does not require any interactive commands.  You simply
  711. %  specify the file transfer task on the command line and xtp performs the
  712. %  transfer automatically.
  713. %
  714. %  This program was adapted from a similiar program written by Steve Singles,
  715. %  University of Delaware.
  716. %
  717. %  Command syntax:
  718. %
  719. %  Usage: xtp [-options ...] <host/ip address> [ <home directory> ]
  720. %
  721. %  Where options include:
  722. %    -binary                retrieve files as binary
  723. %    -exclude expression    exclude files that match the expression
  724. %    -directory expression  list file names that match the expression
  725. %    -ident password        specifies password
  726. %    -print expression      print files that match the expression
  727. %    -retrieve expression   retrieve files that match the expression
  728. %    -send expression       send files that match the expression
  729. %    -timeout seconds       specifies maximum seconds to logon host
  730. %    -user name             identify yourself to the remote FTP server
  731. %
  732. %
  733. */
  734. X
  735. /*
  736. X  Include declarations.
  737. */
  738. #include <stdio.h>
  739. #include <ctype.h>
  740. #include <malloc.h>
  741. #include <signal.h>
  742. #include <string.h>
  743. #include <sys/types.h>
  744. #include <sys/file.h>
  745. #include <sys/stat.h>
  746. #include <sys/socket.h>
  747. #include <sys/wait.h>
  748. #include <sys/time.h>
  749. #include <sys/resource.h>
  750. #include "regular.h"
  751. /*
  752. X  Define declarations.
  753. */
  754. #define False  0
  755. #define True  1
  756. /*
  757. X  Variable declarations.
  758. */
  759. char
  760. X  *program_name,
  761. X  slave_tty[16],
  762. X  *Wait();
  763. X
  764. int
  765. X  master;
  766. X
  767. RegularExpression
  768. X  *directory_expression,
  769. X  *exclude_expression,
  770. X  *print_expression,
  771. X  *retrieve_expression;
  772. X
  773. /*
  774. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  775. %                                                                             %
  776. %                                                                             %
  777. %                                                                             %
  778. %   D i r e c t o r y R e q u e s t                                           %
  779. %                                                                             %
  780. %                                                                             %
  781. %                                                                             %
  782. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  783. %
  784. %  Function DirectoryRequest lists a file name and its attributes.
  785. %
  786. %  The format of the DirectoryRequest routine is:
  787. %
  788. %    DirectoryRequest(error)
  789. %
  790. %
  791. */
  792. void DirectoryRequest(fileinfo,filename)
  793. char
  794. X  *fileinfo,
  795. X  *filename;
  796. {
  797. X  (void) fprintf(stdout,"%s %s\n",fileinfo,filename);
  798. }
  799. X
  800. /*
  801. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  802. %                                                                             %
  803. %                                                                             %
  804. %                                                                             %
  805. %   E r r o r                                                                 %
  806. %                                                                             %
  807. %                                                                             %
  808. %                                                                             %
  809. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  810. %
  811. %  Function Error prints an error message then terminates the program.
  812. %
  813. %  The format of the Error routine is:
  814. %
  815. %    Error(error)
  816. %
  817. %  A description of each parameter follows:
  818. %
  819. %    o error:  Specifies a pointer to a character array that contains the
  820. %      text of the error message.
  821. %
  822. %
  823. */
  824. void Error(error)
  825. char
  826. X  *error;
  827. {
  828. X  char
  829. X    message[80];
  830. X
  831. X  (void) sprintf(message,"%s: %s",program_name,error);
  832. X  perror(message);
  833. X  exit(1);
  834. }
  835. X
  836. /*
  837. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  838. %                                                                             %
  839. %                                                                             %
  840. %                                                                             %
  841. %   E x e c u t e F t p                                                       %
  842. %                                                                             %
  843. %                                                                             %
  844. %                                                                             %
  845. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  846. %
  847. %  Function ExecuteFtp executes the FTP program as a child process.
  848. %
  849. %  The format of the ExecuteFtp routine is:
  850. %
  851. %    ExecuteFtp(hostname)
  852. %
  853. %  A description of each parameter follows:
  854. %
  855. %    o hostname:  Specifies a pointer to a character array that contains the
  856. %      name of the host to establish a connection to a FTP server.
  857. %
  858. %
  859. */
  860. void ExecuteFtp(hostname)
  861. char
  862. X  *hostname;
  863. {
  864. #include <sys/ioctl.h>
  865. X
  866. X  int
  867. X    slave;
  868. X
  869. X  struct ltchars
  870. X    lc;
  871. X
  872. X  struct sgttyb
  873. X    b;
  874. X
  875. X  struct tchars
  876. X    tc;
  877. X
  878. X  (void) signal(SIGTSTP,SIG_IGN);
  879. X  if (isatty(0))
  880. X    {
  881. X      int
  882. X        tty;
  883. X
  884. X      /*
  885. X        Disable controlling terminal.
  886. X      */
  887. X      tty=open("/dev/tty",O_RDWR);
  888. X      if (tty >= 0)
  889. X        {
  890. X          (void) ioctl(tty,TIOCNOTTY,(char *) 0);
  891. X          (void) close(tty);
  892. X        }
  893. X    }
  894. X  slave=open(slave_tty,O_RDWR);
  895. X  if (slave < 0)
  896. X    Error(slave_tty);
  897. X  /*
  898. X    Fix tty line.
  899. X  */
  900. X  (void) ioctl(slave,TIOCGETP,&b);
  901. X  b.sg_flags&=~(ECHO | CRMOD);
  902. X  b.sg_erase=(-1);
  903. X  b.sg_kill=(-1);
  904. X  (void) ioctl(slave,TIOCSETP,&b);
  905. X  tc.t_intrc=(-1);
  906. X  tc.t_quitc=(-1);
  907. X  tc.t_startc=(-1);
  908. X  tc.t_stopc=(-1);
  909. X  tc.t_eofc=(-1);
  910. X  tc.t_brkc=(-1);
  911. X  (void) ioctl(slave,TIOCSETC,&tc);
  912. X  lc.t_suspc=(-1);
  913. X  lc.t_dsuspc=(-1);
  914. X  lc.t_rprntc=(-1);
  915. X  lc.t_flushc=(-1);
  916. X  lc.t_werasc=(-1);
  917. X  lc.t_lnextc=(-1);
  918. X  (void) ioctl(slave,TIOCSLTC,&lc);
  919. X  /*
  920. X    Execute FTP program as a child process.
  921. X  */
  922. X  (void) close(master);
  923. X  (void) dup2(slave,0);
  924. X  (void) dup2(slave,1);
  925. X  (void) dup2(slave,2);
  926. X  (void) close(slave);
  927. X  (void) execlp("ftp","ftp","-n","-i","-g",hostname,(char *) 0);
  928. X  perror("/usr/ucb/ftp");
  929. X  (void) kill(0,SIGTERM);
  930. }
  931. X
  932. /*
  933. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  934. %                                                                             %
  935. %                                                                             %
  936. %                                                                             %
  937. %   G e t H o s t I n f o                                                     %
  938. %                                                                             %
  939. %                                                                             %
  940. %                                                                             %
  941. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  942. %
  943. %  Function GetHostInfo prints the hostname and IP address.
  944. %
  945. %  The format of the GetHostInfo routine is:
  946. %
  947. %    GetHostInfo(host)
  948. %
  949. %  A description of each parameter follows:
  950. %
  951. %    o host:  Specifies a pointer to a character array that contains either
  952. %      a name of a host or an IP address.
  953. %
  954. %
  955. */
  956. void GetHostInfo(host)
  957. char
  958. X  *host;
  959. {
  960. #include <netinet/in.h>
  961. #include <netdb.h>
  962. #include <arpa/inet.h>
  963. X
  964. X  char
  965. X    *address,
  966. X    *inet_ntoa(),
  967. X    *p;
  968. X
  969. X  struct in_addr
  970. X    in;
  971. X
  972. X  struct hostent
  973. X    *hp;
  974. X
  975. X  if (isdigit(*host))
  976. X    {
  977. X      /*
  978. X        Internet address to name.
  979. X      */
  980. X      in.s_addr=inet_addr(host);
  981. X      hp=gethostbyaddr((char *) &in.s_addr,sizeof(in.s_addr),AF_INET);
  982. X      if (hp != (struct hostent *) NULL)
  983. X        {
  984. X          hp=gethostbyname(hp->h_name);
  985. X          if (hp != (struct hostent *) NULL)
  986. X            {
  987. X              in.s_addr= *(int *) hp->h_addr;
  988. X              address=inet_ntoa(in);
  989. X            }
  990. X        }
  991. X    }
  992. X  else
  993. X    {
  994. X      /*
  995. X        Internet name to address.
  996. X      */
  997. X      hp=gethostbyname(host);
  998. X      if (hp != (struct hostent *) NULL)
  999. X        {
  1000. X          in.s_addr= *(int *) hp->h_addr;
  1001. X          address=inet_ntoa(in);
  1002. X          hp=gethostbyaddr((char *) &in.s_addr,sizeof(in.s_addr),AF_INET);
  1003. X        }
  1004. X    }
  1005. X  if (hp == (struct hostent *) NULL)
  1006. X    (void) fprintf(stdout,"%s: ",host);
  1007. X  else
  1008. X    {
  1009. X      /*
  1010. X        Convert hostname to lower-case characters and print.
  1011. X      */
  1012. X      p=hp->h_name;
  1013. X      while (*p)
  1014. X      {
  1015. X        if (isupper(*p))
  1016. X          *p=tolower(*p);
  1017. X        p++;
  1018. X      }
  1019. X      (void) fprintf(stdout,"%s [%s]: ",hp->h_name,address);
  1020. X    }
  1021. }
  1022. X
  1023. /*
  1024. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1025. %                                                                             %
  1026. %                                                                             %
  1027. %                                                                             %
  1028. %   G e t P s e u d o T e r m i n a l                                         %
  1029. %                                                                             %
  1030. %                                                                             %
  1031. %                                                                             %
  1032. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1033. %
  1034. %  Function GetPseudoTerminal returns a master/slave pair of pseudo-terminals.
  1035. %
  1036. %  The format of the GetPseudoTerminal routine is:
  1037. %
  1038. %    GetPseudoTerminal()
  1039. %
  1040. %
  1041. */
  1042. void GetPseudoTerminal()
  1043. {
  1044. X  char
  1045. X    master_tty[16];
  1046. X
  1047. X  register char
  1048. X    *bank,
  1049. X    *cp;
  1050. X
  1051. X  struct stat
  1052. X    info;
  1053. X
  1054. X  for (bank="pqrs"; *bank; bank++)
  1055. X  {
  1056. X    (void) sprintf(master_tty,"/dev/pty%c0",*bank);
  1057. X    if (stat(master_tty,&info) < 0)
  1058. X      break;
  1059. X    for (cp="0123456789abcdef"; *cp; cp++)
  1060. X    {
  1061. X      (void) sprintf((char *) master_tty,"/dev/pty%c%c",*bank,*cp);
  1062. X      master=open(master_tty,O_RDWR);
  1063. X      if (master >= 0)
  1064. X        {
  1065. X          /*
  1066. X            Verify slave side is usable.
  1067. X          */
  1068. X          (void) sprintf(slave_tty,"/dev/tty%c%c",*bank,*cp);
  1069. X          if (access(slave_tty,R_OK | W_OK) == 0)
  1070. X            return;
  1071. X          (void) close(master);
  1072. X        }
  1073. X    }
  1074. X  }
  1075. X  Error("All network ports in use.\n");
  1076. }
  1077. X
  1078. /*
  1079. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1080. %                                                                             %
  1081. %                                                                             %
  1082. %                                                                             %
  1083. %   M a k e D i r e c t o r y                                                 %
  1084. %                                                                             %
  1085. %                                                                             %
  1086. %                                                                             %
  1087. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1088. %
  1089. %  Function MakeDirectory checks each component of a directory path and if it
  1090. %  does not exist, creates it.
  1091. %
  1092. %  The format of the MakeDirectory routine is:
  1093. %
  1094. %    MakeDirectory(directory)
  1095. %
  1096. %  A description of each parameter follows:
  1097. %
  1098. %    o directory:  Specifies a pointer to a character array that contains
  1099. %      the name of the directory to create.
  1100. %
  1101. %
  1102. */
  1103. int MakeDirectory(directory)
  1104. char
  1105. X  *directory;
  1106. {
  1107. #define IsDirectory(mode) (((mode) & S_IFMT) == S_IFDIR)
  1108. X
  1109. X  register char
  1110. X    *p;
  1111. X
  1112. X  struct stat
  1113. X    info;
  1114. X
  1115. X  /*
  1116. X    Determine first component of the directory.
  1117. X  */
  1118. X  p=strrchr(directory,'/');
  1119. X  if ((p == (char *) NULL) || (p == directory))
  1120. X    return(False);
  1121. X  *p=(char) NULL;
  1122. X  if (lstat(directory,&info) < 0)
  1123. X    {
  1124. X      /*
  1125. X        Path component does not exist;  create it.
  1126. X      */
  1127. X      if (MakeDirectory(directory) == 0)
  1128. X        if (mkdir(directory,0777) >= 0)
  1129. X          {
  1130. X            *p='/';
  1131. X            return(False);
  1132. X          }
  1133. X    }
  1134. X  else
  1135. X    if (IsDirectory(info.st_mode))
  1136. X      {
  1137. X        /*
  1138. X          Path component already exists.
  1139. X        */
  1140. X        *p='/';
  1141. X        return(False);
  1142. X      }
  1143. X  /*
  1144. X    Path component is a file not a directory.
  1145. X  */
  1146. X  *p='/';
  1147. X  return(True);
  1148. }
  1149. X
  1150. /*
  1151. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1152. %                                                                             %
  1153. %                                                                             %
  1154. %                                                                             %
  1155. %   P r i n t R e q u e s t                                                   %
  1156. %                                                                             %
  1157. %                                                                             %
  1158. %                                                                             %
  1159. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1160. %
  1161. %  Function PrintRequest prints a file on the remote FTP server.
  1162. %
  1163. %  The format of the PrintRequest routine is:
  1164. %
  1165. %    PrintRequest(filename)
  1166. %
  1167. %  A description of each parameter follows:
  1168. %
  1169. %    o filename:  Specifies a pointer to a character array that contains
  1170. %      the name of the file to print.
  1171. %
  1172. %
  1173. */
  1174. void PrintRequest(filename)
  1175. char
  1176. X  *filename;
  1177. {
  1178. X  char
  1179. X    command[256],
  1180. X    *response;
  1181. X
  1182. X  /*
  1183. X    get remote-file [ - | <| zcat> ].
  1184. X  */
  1185. X  (void) sprintf(command,"get %s",filename);
  1186. X  (void) write(master,command,(int) strlen(command));
  1187. X  if (strcmp(filename+strlen(filename)-2,".Z"))
  1188. X    (void) sprintf(command," -\n");
  1189. X  else
  1190. X    (void) sprintf(command," | zcat\n");
  1191. X  (void) write(master,command,(int) strlen(command));
  1192. X  (void) fprintf(stdout,"%s:\n",filename);
  1193. X  while (response=Wait())
  1194. X    (void) fprintf(stdout,"%s\n",response);
  1195. }
  1196. X
  1197. /*
  1198. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1199. %                                                                             %
  1200. %                                                                             %
  1201. %                                                                             %
  1202. %   P r o c e s s R e q u e s t                                               %
  1203. %                                                                             %
  1204. %                                                                             %
  1205. %                                                                             %
  1206. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1207. %
  1208. %  Function ProcessRequest first records any file in the current directory
  1209. %  of the remote FTP server or any of its subdirectories.  Next each filename
  1210. %  is either accepted or rejected based on a user specified regular
  1211. %  expresssion.  If any files match the regular expression, its filename is
  1212. %  listed, it is printed, or it is retrieved as specified on the command line.
  1213. %
  1214. %  The format of the ProcessRequest routine is:
  1215. %
  1216. %    ProcessRequest()
  1217. %
  1218. %
  1219. */
  1220. void ProcessRequest()
  1221. {
  1222. X  typedef struct _DirectoryNode
  1223. X  {
  1224. X    char
  1225. X      *info,
  1226. X      *name;
  1227. X
  1228. X    struct _DirectoryNode
  1229. X      *next;
  1230. X  } DirectoryNode;
  1231. X
  1232. X  char
  1233. X    command[256],
  1234. X    directory[1024],
  1235. X    *info,
  1236. X    *name,
  1237. X    *response;
  1238. X
  1239. X  DirectoryNode
  1240. X    *next,
  1241. X    *root;
  1242. X
  1243. X  register char
  1244. X    *p;
  1245. X
  1246. X  register DirectoryNode
  1247. X    **last,
  1248. X    *node;
  1249. X
  1250. X  RegularExpression
  1251. X    *date_expression,
  1252. X    *mode_expression;
  1253. X
  1254. X  unsigned int
  1255. X    unix_filesystem;
  1256. X
  1257. X  void
  1258. X    DirectoryRequest(),
  1259. X    PrintRequest(),
  1260. X    RetrieveRequest();
  1261. X
  1262. X  /*
  1263. X    Initialize function variables.
  1264. X  */
  1265. X  root=(DirectoryNode *) NULL;
  1266. X  last=(&root);
  1267. X  *directory=(char) NULL;
  1268. X  /*
  1269. X    Unix-style filesystem if the first few characters is in mode format.
  1270. X  */
  1271. X  mode_expression=CompileRegularExpression("^[dbclps-][rwx-][rwx-][rwx-]");
  1272. X  unix_filesystem=False;
  1273. X  (void) strcpy(command,"dir\n");
  1274. X  (void) write(master,command,(int) strlen(command));
  1275. X  response=Wait();
  1276. X  if (response == (char *) NULL)
  1277. X    return;
  1278. X  while (response=Wait())
  1279. X    if (*response != (char) NULL)
  1280. X      if (!unix_filesystem)
  1281. X        unix_filesystem=ExecuteRegularExpression(mode_expression,response);
  1282. X  (void) free((char *) mode_expression);
  1283. X  /*
  1284. X    Issue directory command to remote FTP server.
  1285. X  */
  1286. X  if (unix_filesystem)
  1287. X    (void) strcpy(command,"dir -R\n");
  1288. X  else
  1289. X    (void) strcpy(command,"dir [...]\n");
  1290. X  (void) write(master,command,(int) strlen(command));
  1291. X  response=Wait();
  1292. X  if (response == (char *) NULL)
  1293. X    return;
  1294. X  response=Wait();
  1295. X  if (response == (char *) NULL)
  1296. X    {
  1297. X      /*
  1298. X        Directory command has limited functionality.
  1299. X      */
  1300. X      (void) strcpy(command,"dir\n");
  1301. X      (void) write(master,command,(int) strlen(command));
  1302. X      response=Wait();
  1303. X      if (response == (char *) NULL)
  1304. X        return;
  1305. X    }
  1306. X  if (!unix_filesystem)
  1307. X    do 
  1308. X    {
  1309. X      /*
  1310. X        Link non unix-style file into file list.
  1311. X      */
  1312. X      if (*response == (char) NULL)
  1313. X        continue;
  1314. X      while (*response == ' ')
  1315. X        response++;
  1316. X      /*
  1317. X        Extract file name & info.
  1318. X      */
  1319. X      name=response;
  1320. X      info=response;
  1321. X      while ((*info != ' ') && *info)
  1322. X        info++;
  1323. X      *info++=(char) NULL;
  1324. X      while (*info == ' ')
  1325. X        info++;
  1326. X      if (exclude_expression)
  1327. X        if (ExecuteRegularExpression(exclude_expression,name))
  1328. X          continue;
  1329. X      node=(DirectoryNode *) malloc(sizeof(DirectoryNode));
  1330. X      if (node == (DirectoryNode *) NULL)
  1331. X        Error("unable to allocate memory");
  1332. X      node->name=(char *) malloc((unsigned int) (strlen(name)+1));
  1333. X      node->info=(char *) malloc((unsigned int) (strlen(info)+1));
  1334. X      if ((node->name == (char *) NULL) || (node->info == (char *) NULL))
  1335. X        Error("unable to allocate memory");
  1336. X      (void) strcpy(node->name,name);
  1337. X      (void) strcpy(node->info,info);
  1338. X      node->next=(DirectoryNode *) NULL;
  1339. X      *last=node;
  1340. X      last=(&node->next);
  1341. X    }
  1342. X    while (response=Wait());
  1343. X  else
  1344. X    {
  1345. X      RegularExpression
  1346. X        *access_expression;
  1347. X
  1348. X      access_expression=
  1349. X        CompileRegularExpression("Permission denied|not found|cannot access");
  1350. X      date_expression=CompileRegularExpression("^[:9][0-9][0-9]");
  1351. X      do
  1352. X      {
  1353. X        /*
  1354. X           Link unix-style file into file list.
  1355. X        */
  1356. X        if (*response == (char) NULL)
  1357. X          continue;
  1358. X        while (*response == ' ')
  1359. X          response++;
  1360. X        p=response+strlen(response)-1;
  1361. X        if (*response == '-')
  1362. X          {
  1363. X            if (ExecuteRegularExpression(access_expression,response))
  1364. X              continue;
  1365. X            /*
  1366. X              Extract file info & name.
  1367. X            */
  1368. X            while (p-- > (response+3))
  1369. X            if (*p == ' ')
  1370. X              if (ExecuteRegularExpression(date_expression,p-3))
  1371. X                break;
  1372. X            *p++=(char) NULL;
  1373. X            while (*p == ' ')
  1374. X              p++;
  1375. X            name=p;
  1376. X            if (exclude_expression)
  1377. X              if (ExecuteRegularExpression(exclude_expression,name))
  1378. X                continue;
  1379. X            info=response;
  1380. X            node=(DirectoryNode *) malloc(sizeof(DirectoryNode));
  1381. X            if (node == (DirectoryNode *) NULL)
  1382. X              Error("unable to allocate memory");
  1383. X            node->name=(char *)
  1384. X              malloc((unsigned int) (strlen(directory)+strlen(name)+1));
  1385. X            node->info=(char *) malloc((unsigned int) (strlen(info)+1));
  1386. X            if ((node->name == (char *) NULL) || (node->info == (char *) NULL))
  1387. X              Error("unable to allocate memory");
  1388. X            (void) strcpy(node->name,directory);
  1389. X            (void) strcat(node->name,name);
  1390. X            (void) strcpy(node->info,info);
  1391. X            node->next=(DirectoryNode *) NULL;
  1392. X            *last=node;
  1393. X            last=(&node->next);
  1394. X          }
  1395. X        else
  1396. X          if (*p == ':')
  1397. X            {
  1398. X              /*
  1399. X                File is a directory.
  1400. X              */
  1401. X              do { p--; } while (*p == ' ');
  1402. X              *(++p)=(char) NULL;
  1403. X              (void) strcpy(directory,response);
  1404. X              (void) strcat(directory,"/");
  1405. X            }
  1406. X      }
  1407. X      while (response=Wait());
  1408. X      (void) free((char *) access_expression);
  1409. X      (void) free((char *) date_expression);
  1410. X    }
  1411. X  /*
  1412. X    Traverse the file list and act on a filename if it matches the regular
  1413. X    expression.
  1414. X  */
  1415. X  node=root;
  1416. X  while (node)
  1417. X  {
  1418. X    if (directory_expression)
  1419. X      if (ExecuteRegularExpression(directory_expression,node->name))
  1420. X        (void) DirectoryRequest(node->info,node->name);
  1421. X    if (retrieve_expression)
  1422. X      if (ExecuteRegularExpression(retrieve_expression,node->name))
  1423. X        (void) RetrieveRequest(node->name);
  1424. X    if (print_expression)
  1425. X      if (ExecuteRegularExpression(print_expression,node->name))
  1426. X        (void) PrintRequest(node->name);
  1427. X    /*
  1428. X      Free allocated memory for this node.
  1429. X    */
  1430. X    (void) free(node->info);
  1431. X    (void) free(node->name);
  1432. X    next=node->next;
  1433. X    (void) free((char *) node);
  1434. X    node=next;
  1435. X  }
  1436. }
  1437. X
  1438. /*
  1439. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1440. %                                                                             %
  1441. %                                                                             %
  1442. %                                                                             %
  1443. %   R e t r i e v e R e q u e s t                                             %
  1444. %                                                                             %
  1445. %                                                                             %
  1446. %                                                                             %
  1447. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1448. %
  1449. %  Function RetrieveRequest retrieves a file from the remote FTP server.
  1450. %
  1451. %  The format of the RetrieveRequest routine is:
  1452. %
  1453. %    RetrieveRequest(filename)
  1454. %
  1455. %  A description of each parameter follows:
  1456. %
  1457. %    o filename:  Specifies a pointer to a character array that contains
  1458. %      the name of the file to retrieve.
  1459. %
  1460. %
  1461. */
  1462. void RetrieveRequest(filename)
  1463. char
  1464. X  *filename;
  1465. {
  1466. X  char
  1467. X    command[256],
  1468. X    *response;
  1469. X
  1470. X  /*
  1471. X    get remote-file
  1472. X  */
  1473. X  (void) MakeDirectory(filename);
  1474. X  (void) sprintf(command,"get %s\n",filename);
  1475. X  (void) write(master,command,(int) strlen(command));
  1476. X  (void) fprintf(stdout,"Retrieving %s...\n",filename);
  1477. X  while (response=Wait())
  1478. X    (void) fprintf(stdout,"%s\n",response);
  1479. }
  1480. X
  1481. /*
  1482. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1483. %                                                                             %
  1484. %                                                                             %
  1485. %                                                                             %
  1486. %   S i g n a l C h i l d                                                     %
  1487. %                                                                             %
  1488. %                                                                             %
  1489. %                                                                             %
  1490. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1491. %
  1492. %  Function SignalChild is called if the status of the child process changes.
  1493. %
  1494. %  The format of the SignalChild routine is:
  1495. %
  1496. %    SignalChild()
  1497. %
  1498. %
  1499. */
  1500. void SignalChild()
  1501. {
  1502. X  char
  1503. X    message[256];
  1504. X
  1505. X  union wait
  1506. X    status;
  1507. X
  1508. X  while (wait3(&status,WNOHANG,(struct rusage *) NULL) > 0);
  1509. X  (void) sprintf(message,"child died, status %x",wait(&status));
  1510. X  Error(message);
  1511. }
  1512. X
  1513. /*
  1514. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1515. %                                                                             %
  1516. %                                                                             %
  1517. %                                                                             %
  1518. %   U s a g e                                                                 %
  1519. %                                                                             %
  1520. %                                                                             %
  1521. %                                                                             %
  1522. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1523. %
  1524. %  Procedure Usage displays the program usage;
  1525. %
  1526. %  The format of the Usage routine is:
  1527. %
  1528. %      Usage(message)
  1529. %
  1530. %  A description of each parameter follows:
  1531. %
  1532. %    o message:  Specifies a specific message to display to the user.
  1533. %
  1534. %
  1535. */
  1536. void Usage(message)
  1537. char
  1538. X  *message;
  1539. {
  1540. X  char
  1541. X    **p;
  1542. X
  1543. X  static char
  1544. X    *options[]=
  1545. X    {
  1546. X      "-binary                retrieve files as binary",
  1547. X      "-exclude expression    exclude files that match the expression",
  1548. X      "-directory expression  list file names that match the expression",
  1549. X      "-ident password        specifies password",
  1550. X      "-print expression      print files that match the expression",
  1551. X      "-retrieve expression   retrieve files that match the expression",
  1552. X      "-send expression       send files that match the expression",
  1553. X      "-timeout seconds       specifies maximum seconds to logon host",
  1554. X      "-user name             identify yourself to the remote FTP server",
  1555. X      "-verbose               show all responses from the remote server",
  1556. X      NULL
  1557. X    };
  1558. X  if (message)
  1559. X    (void) fprintf(stderr,"Can't continue, %s\n\n",message);
  1560. X  (void) fprintf(stderr,
  1561. X    "Usage: %s [-options ...] <host/ip address> [ <home directory> ]\n",
  1562. X    program_name);
  1563. X  (void) fprintf(stderr,"\nWhere options include:\n");
  1564. X  for (p=options; *p; p++)
  1565. X    (void) fprintf(stderr,"  %s\n",*p);
  1566. X  exit(1);
  1567. }
  1568. X
  1569. /*
  1570. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1571. %                                                                             %
  1572. %                                                                             %
  1573. %                                                                             %
  1574. %   W a i t                                                                   %
  1575. %                                                                             %
  1576. %                                                                             %
  1577. %                                                                             %
  1578. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1579. %
  1580. %  Function Wait reads a line of output from the remote FTP server.
  1581. %
  1582. %  The format of the Wait() routine is:
  1583. %
  1584. %    response=Wait()
  1585. %
  1586. %  A description of each parameter follows:
  1587. %
  1588. %    o response:  Function Wait returns this pointer to the output obtained
  1589. %      from the remote FTP server.
  1590. %
  1591. %
  1592. */
  1593. char *Wait()
  1594. {
  1595. X  register char
  1596. X    *p;
  1597. X
  1598. X  static char
  1599. X    buffer[1024],
  1600. X    *q;
  1601. X
  1602. X  static char
  1603. X    line[1024];
  1604. X
  1605. X  static int
  1606. X    count=0;
  1607. X
  1608. X  p=line;
  1609. X  do
  1610. X  {
  1611. X    if (count <= 0)
  1612. X      {
  1613. X        /*
  1614. X          The buffer is empty;  read output from the remote FTP server.
  1615. X        */
  1616. X        count=read(master,buffer,sizeof(buffer));
  1617. X        q=buffer;
  1618. X        if (count <= 0)
  1619. X          {
  1620. X            if (p == line)
  1621. X              return((char *) NULL);
  1622. X            break;
  1623. X          }
  1624. X      }
  1625. X    count--;
  1626. X    *p=(*q++);
  1627. X    if (*p == '\n')
  1628. X      break;
  1629. X    p++;
  1630. X    if ((p-line) >= 5)
  1631. X      if (!strncmp(p-5,"ftp> ",5))
  1632. X        if (count == 0)
  1633. X          return((char *) NULL);
  1634. X  } while (p < (line+sizeof(line)));
  1635. X  *p=(char) NULL;
  1636. X  return(line);
  1637. }
  1638. X
  1639. /*
  1640. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1641. %                                                                             %
  1642. %                                                                             %
  1643. %                                                                             %
  1644. %   m a i n                                                                   %
  1645. %                                                                             %
  1646. %                                                                             %
  1647. %                                                                             %
  1648. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1649. %
  1650. %
  1651. */
  1652. main(argc,argv)
  1653. int
  1654. X  argc;
  1655. X
  1656. register char
  1657. X  **argv;
  1658. {
  1659. #include <pwd.h>
  1660. X
  1661. X  char
  1662. X    command[256],
  1663. X    *ident,
  1664. X    *home_directory,
  1665. X    *hostname,
  1666. X    *send_expression,
  1667. X    *user;
  1668. X
  1669. X  extern char
  1670. X    *getpass();
  1671. X
  1672. X  int
  1673. X    binary,
  1674. X    child,
  1675. X    status;
  1676. X
  1677. X  register char
  1678. X    *p,
  1679. X    *response;
  1680. X
  1681. X  unsigned int
  1682. X    timeout,
  1683. X    verbose;
  1684. X
  1685. X  /*
  1686. X    Initialize program variables.
  1687. X  */
  1688. X  binary=False;
  1689. X  directory_expression=(RegularExpression *) NULL;
  1690. X  exclude_expression=(RegularExpression *) NULL;
  1691. X  ident=(char *) NULL;
  1692. X  print_expression=(RegularExpression *) NULL;
  1693. X  retrieve_expression=(RegularExpression *) NULL;
  1694. X  send_expression=(char *) NULL;
  1695. X  timeout=0;
  1696. X  user=(char *) NULL;
  1697. X  program_name=argv[0];
  1698. X  verbose=False;
  1699. X  /*
  1700. X    Parse command line arguments.
  1701. X  */
  1702. X  for (p=(*argv++); *argv && (**argv == '-'); argv++)
  1703. X    switch (argv[0][1])
  1704. X    {
  1705. X      case 'b':
  1706. X      {
  1707. X        binary=True;
  1708. X        break;
  1709. X      }
  1710. X      case 'd':
  1711. X      {
  1712. X        directory_expression=CompileRegularExpression(*++argv);
  1713. X        if (!directory_expression)
  1714. X          exit(1);
  1715. X        break;
  1716. X      }
  1717. X      case 'e':
  1718. X      {
  1719. X        exclude_expression=CompileRegularExpression(*++argv);
  1720. X        if (!exclude_expression)
  1721. X          exit(1);
  1722. X        break;
  1723. X      }
  1724. X      case 'i':
  1725. X      {
  1726. X        ident=(*++argv);
  1727. X        break;
  1728. X      }
  1729. X      case 'p':
  1730. X      {
  1731. X        print_expression=CompileRegularExpression(*++argv);
  1732. X        if (!print_expression)
  1733. X          exit(1);
  1734. X        break;
  1735. X      }
  1736. X      case 'r':
  1737. X      {
  1738. X        retrieve_expression=CompileRegularExpression(*++argv);
  1739. X        if (!retrieve_expression)
  1740. X          exit(1);
  1741. X        break;
  1742. X      }
  1743. X      case 's':
  1744. X      {
  1745. X        send_expression=(*++argv);
  1746. X        break;
  1747. X      }
  1748. X      case 't':
  1749. X      {
  1750. X        timeout=atoi(*++argv);
  1751. X        break;
  1752. X      }
  1753. X      case 'u':
  1754. X      {
  1755. X        user=(*++argv);
  1756. X        break;
  1757. X      }
  1758. X      case 'v':
  1759. X      {
  1760. X        verbose=True;
  1761. X        break;
  1762. X      }
  1763. X      default:
  1764. X      {
  1765. X        Usage((char *) NULL);
  1766. X        break;
  1767. X      }
  1768. X    }
  1769. X  if ((argc < 2) || (*argv == (char *) NULL))
  1770. X    Usage((char *) NULL);
  1771. X  hostname=argv[0];
  1772. X  home_directory=argv[1];
  1773. X  if ((directory_expression == (RegularExpression *) NULL) &&
  1774. X      (print_expression == (RegularExpression *) NULL) &&
  1775. X      (retrieve_expression == (RegularExpression *) NULL) &&
  1776. X      (send_expression == (char *) NULL))
  1777. X    directory_expression=CompileRegularExpression("");
  1778. X  if ((ident == (char *) NULL) && (user == (char *) NULL))
  1779. X    {
  1780. X      int
  1781. X        uid;
  1782. X
  1783. X      static char
  1784. X        name[256];
  1785. X
  1786. X      struct passwd
  1787. X        *user_info;
  1788. X
  1789. X      /*
  1790. X        Identify user as user@host.domain.
  1791. X      */
  1792. X      uid=geteuid();
  1793. X      user_info=getpwuid(uid);
  1794. X      if (user_info == (struct passwd *) NULL)
  1795. X        (void) strcpy(name,"anonymous");
  1796. X      else
  1797. X        (void) strcpy(name,user_info->pw_name);
  1798. X      p=name+strlen(name);
  1799. X      *p++='@';
  1800. X      (void) gethostname(p,64);
  1801. X      while (*p)
  1802. X        p++;
  1803. X      *p++='.';
  1804. X      (void) getdomainname(p,64);
  1805. X      user="anonymous";
  1806. X      ident=name;
  1807. X    }
  1808. X  else
  1809. X    if (ident == (char *) NULL)
  1810. X      ident=(char *) getpass("Password: ");
  1811. X    else
  1812. X      if (user == (char *) NULL)
  1813. X        user="anonymous";
  1814. X  (void) GetHostInfo(hostname);
  1815. X  if (!home_directory)
  1816. X    (void) fprintf(stdout,"\n");
  1817. X  else
  1818. X    (void) fprintf(stdout,"%s\n",home_directory);
  1819. X  (void) GetPseudoTerminal();
  1820. X  /*
  1821. X    Connect and logon to host.
  1822. X  */
  1823. X  (void) signal(SIGCHLD,SignalChild);
  1824. X  if (timeout > 0)
  1825. X    (void) alarm(timeout);  /* enable timer. */
  1826. X  child=fork();
  1827. X  if (child < 0)
  1828. X    Error("fork");
  1829. X  if (child == 0)
  1830. X    ExecuteFtp(hostname);
  1831. X  while (response=Wait())
  1832. X    (void) fprintf(stderr,"%s\n",response);
  1833. X  (void) sprintf(command,"user %s %s\n",user,ident);
  1834. X  (void) write(master,command,(int) strlen(command));
  1835. X  while (response=Wait())
  1836. X    (void) fprintf(stderr,"%s\n",response);
  1837. X  if (timeout > 0)
  1838. X    (void) alarm(timeout*100);
  1839. X  (void) fprintf(stderr,"\n");
  1840. X  if (!verbose)
  1841. X    {
  1842. X      (void) strcpy(command,"verbose off\n");
  1843. X      (void) write(master,command,(int) strlen(command));
  1844. X      while (response=Wait());
  1845. X    }
  1846. X  if (home_directory)
  1847. X    {
  1848. X      /*
  1849. X        Change remote working directory.
  1850. X      */
  1851. X      (void) sprintf(command,"cd %s\n",home_directory);
  1852. X      (void) write(master,command,(int) strlen(command));
  1853. X      while (response=Wait());
  1854. X      (void) strcpy(command,"pwd\n");
  1855. X      (void) write(master,command,(int) strlen(command));
  1856. X      while (response=Wait())
  1857. X        (void) fprintf(stderr,"%s\n",response);
  1858. X    }
  1859. X  if (binary)
  1860. X    {
  1861. X      /*
  1862. X        Set file transfer type.
  1863. X      */
  1864. X      (void) strcpy(command,"binary\n");
  1865. X      (void) write(master,command,(int) strlen(command));
  1866. X      while (Wait());
  1867. X      (void) strcpy(command,"type\n");
  1868. X      (void) write(master,command,(int) strlen(command));
  1869. X      while (response=Wait())
  1870. X        (void) fprintf(stderr,"%s\n",response);
  1871. X    }
  1872. X  (void) strcpy(command,"runique\n");
  1873. X  (void) write(master,command,(int) strlen(command));
  1874. X  while (Wait());
  1875. X  if (send_expression == (char *) NULL)
  1876. X    ProcessRequest();
  1877. X  else
  1878. X    {
  1879. X      /*
  1880. X        Process send request.
  1881. X      */
  1882. X      (void) strcpy(command,"glob on\n");
  1883. X      (void) write(master,command,(int) strlen(command));
  1884. X      while (Wait());
  1885. X      (void) sprintf(command,"mput %s\n",send_expression);
  1886. X      (void) write(master,command,(int) strlen(command));
  1887. X      while (response=Wait())
  1888. X        (void) fprintf(stderr,"%s\n",response);
  1889. X    }
  1890. X  (void) strcpy(command,"quit\n");
  1891. X  (void) write(master,command,(int) strlen(command));
  1892. X  /*
  1893. X    Wait for child to finish.
  1894. X  */
  1895. X  (void) signal(SIGCHLD,SIG_DFL);
  1896. X  while (child != wait((union wait *) &status));
  1897. X  (void) close(master);
  1898. X  (void) free((char *) directory_expression);
  1899. X  (void) free((char *) exclude_expression);
  1900. X  (void) free((char *) print_expression);
  1901. X  (void) free((char *) retrieve_expression);
  1902. X  return(False);
  1903. }
  1904. X
  1905. SHAR_EOF
  1906. chmod 0755 ImageMagick/xtp/xtp.c ||
  1907. echo 'restore of ImageMagick/xtp/xtp.c failed'
  1908. Wc_c="`wc -c < 'ImageMagick/xtp/xtp.c'`"
  1909. test 37231 -eq "$Wc_c" ||
  1910.     echo 'ImageMagick/xtp/xtp.c: original size 37231, current size' "$Wc_c"
  1911. rm -f _shar_wnt_.tmp
  1912. fi
  1913. # ============= ImageMagick/xtp/xtp.man ==============
  1914. if test -f 'ImageMagick/xtp/xtp.man' -a X"$1" != X"-c"; then
  1915.     echo 'x - skipping ImageMagick/xtp/xtp.man (File already exists)'
  1916.     rm -f _shar_wnt_.tmp
  1917. else
  1918. > _shar_wnt_.tmp
  1919. echo 'x - extracting ImageMagick/xtp/xtp.man (Text)'
  1920. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/xtp.man' &&
  1921. .ad l
  1922. .nh
  1923. .TH XTP 1 "16 June 1990"
  1924. .SH NAME
  1925. xtp - file transfer program
  1926. .SH SYNOPSIS
  1927. .B "xtp"
  1928. [ \fI-options\fP ... ] \fI<host/ip address>\fP \fI<home directory>\fP
  1929. .SH DESCRIPTION
  1930. .PP
  1931. .I Xtp
  1932. is a utility for retrieving, listing, or printing files from a remote
  1933. network site, or sending files to a remote network site.
  1934. .I Xtp
  1935. performs most of the same functions as the \fIftp\fP program, but does
  1936. not require any interactive commands.  You simply specify the file transfer
  1937. task on the command line and \fIxtp\fP performs the task automatically.
  1938. .SH EXAMPLES
  1939. .PP
  1940. To retrieve file display.tar.Z from host wizard.dupont.com, use:
  1941. .PP
  1942. X     xtp -binary -retrieve display.tar.Z wizard.dupont.com
  1943. .PP
  1944. To retrieve all the files from directory \fIpublic/documents\fP from host 
  1945. wizard.dupont.com, use:
  1946. .PP
  1947. X     xtp -binary -retrieve documents/ wizard.dupont.com public
  1948. .PP
  1949. .SH OPTIONS
  1950. .TP
  1951. .B "-binary"
  1952. retrieve files as binary.
  1953. .TP
  1954. .B "-exclude \fIexpression\fP"
  1955. exclude files that match the \fIregular expression\fP.
  1956. .TP
  1957. .B "-directory \fIexpression\fP"
  1958. list the names of files and their attributes that match the 
  1959. \fIregular expression\fP.
  1960. .TP
  1961. .B "-ident \fIpassword\fP"
  1962. specifies password.
  1963. .TP
  1964. .B "-print \fIexpression\fP"
  1965. print files that match the \fIregular expression\fP.
  1966. .TP
  1967. .B "-retrieve \fIexpression\fP"
  1968. retrieve files that match the \fIregular expression\fP.
  1969. X
  1970. Retrieved files are stored on your local host directory as the full
  1971. name of the retrieved file.  For example, if the retrieved file is
  1972. named \fIdocuments/xtp.man\fP on the remote FTP server, it will appear
  1973. in your home directory as \fIdocuments/xtp.man\fP.
  1974. .TP
  1975. .B "-send \fIexpression\fP"
  1976. send files that match the \fIregular expression\fP.
  1977. .TP
  1978. .B "-timeout \fIseconds\fP"
  1979. specifies maximum seconds to logon to the remote FTP server.  If this time
  1980. expires, the program terminates.
  1981. .TP
  1982. .B "-user \fIname\fP"
  1983. identify yourself to the remote FTP server.
  1984. .PP
  1985. If \fB-user\fP is specified but not \fB-ident\fP, the password is obtained
  1986. from you interactively.
  1987. .PP
  1988. If neither \fB-print\fP, \fB-retrieve\fP, or \fB-send\fp are specified
  1989. on the command line, a directory of files is listed for the remote
  1990. network host.
  1991. .PP
  1992. Filename searching begins at the home directory.  Some remote hosts
  1993. may have thousands of files causing a significant delay satisfying
  1994. your request.  You can reduce the searching required by specifying
  1995. \fI<home directory>\fP on the command line.  This limits the filename
  1996. search to the specified directory and any of its subdirectories.
  1997. .PP
  1998. If only the program name is specified on the command line, the program command
  1999. syntax and options are listed.
  2000. .SH REGULAR EXPRESSIONS
  2001. A \fIregular expression\fP is zero or more branches, separated by
  2002. \fB|\fP.  It matches anything that matches one of the branches.
  2003. .PP
  2004. A branch is zero or more pieces, concatenated.  It matches a match for
  2005. the first, followed by a match for the second, etc.
  2006. .PP
  2007. A piece is an atom possibly followed by \fB*\fP, \fB+\fP, or \fB?\fP.
  2008. An atom followed by \fB*\fP matches a sequence of 0 or more matches of
  2009. the atom.  An atom followed by \fB+\fP matches a sequence of 1 or more
  2010. matches of the atom.  An atom followed by \fB?\fP matches a match of
  2011. the atom, or the null pattern.
  2012. .PP
  2013. An atom is a \fIregular expression\fP in parentheses (matching a match
  2014. for the \fIregular expression\fP), a range (see below), \fB.\fP
  2015. (matching any single character), \fB^\fP (matching the null pattern at
  2016. the beginning of the input pattern), \fB$\fP (matching the null pattern
  2017. at the end of the input pattern), a \fB\'\fP followed by a single
  2018. character (matching that character), or a single character with no
  2019. other significance (matching that character).
  2020. .PP
  2021. A range is a sequence of characters enclosed in \fB[]\fP.  It normally
  2022. matches any single character from the sequence.  If the sequence begins
  2023. with \fB^\fP, it matches any single character not from the rest of the
  2024. sequence.  If two characters in the sequence are separated by \fB-\fP,
  2025. this is shorthand for the full list of ASCII characters between them
  2026. (e.g.  \fB[0-9]\fP matches any decimal digit). To include a literal
  2027. \fB]\fP in the sequence, make it the first character (following a
  2028. possible \fB^\fP).  To include a literal \fB-\fP, make it the first or
  2029. last character.
  2030. .SH SEE ALSO
  2031. ftp(1C)
  2032. .SH COPYRIGHT
  2033. Copyright 1990 E. I. Dupont de Nemours & Company
  2034. .PP
  2035. Permission to use, copy, modify, distribute, and sell this software and
  2036. its documentation for any purpose is hereby granted without fee,
  2037. provided that the above copyright notice appear in all copies and that
  2038. both that copyright notice and this permission notice appear in
  2039. supporting documentation, and that the name of E. I. Dupont de Nemours
  2040. & Company not be used in advertising or publicity pertaining to
  2041. distribution of the software without specific, written prior
  2042. permission.  E. I. Dupont de Nemours & Company makes no representations
  2043. about the suitability of this software for any purpose.  It is provided
  2044. "as is" without express or implied warranty.
  2045. .PP
  2046. E. I. Dupont de Nemours & Company disclaims all warranties with regard
  2047. to this software, including all implied warranties of merchantability
  2048. and fitness, in no event shall E. I. Dupont de Nemours & Company be
  2049. liable for any special, indirect or consequential damages or any
  2050. damages whatsoever resulting from loss of use, data or profits, whether
  2051. in an action of contract, negligence or other tortious action, arising
  2052. out of or in connection with the use or performance of this software.
  2053. .SH ACKNOWLEDGEMENTS
  2054. Steve Singles, University of Delaware, for the initial implementation of
  2055. this program.
  2056. .PP
  2057. Henry Spencer, University of Toronto, for the implementation of the
  2058. \fIregular expression\fP interpreter and the text in \fBREGULAR
  2059. EXPRESSIONS\fP.
  2060. .SH AUTHOR
  2061. John Cristy, E.I. DuPont De Nemours & Company Incorporated
  2062. X
  2063. X
  2064. SHAR_EOF
  2065. chmod 0755 ImageMagick/xtp/xtp.man ||
  2066. echo 'restore of ImageMagick/xtp/xtp.man failed'
  2067. Wc_c="`wc -c < 'ImageMagick/xtp/xtp.man'`"
  2068. test 5832 -eq "$Wc_c" ||
  2069.     echo 'ImageMagick/xtp/xtp.man: original size 5832, current size' "$Wc_c"
  2070. rm -f _shar_wnt_.tmp
  2071. fi
  2072. # ============= ImageMagick/image.c ==============
  2073. if test -f 'ImageMagick/image.c' -a X"$1" != X"-c"; then
  2074.     echo 'x - skipping ImageMagick/image.c (File already exists)'
  2075.     rm -f _shar_wnt_.tmp
  2076. else
  2077. > _shar_wnt_.tmp
  2078. echo 'x - extracting ImageMagick/image.c (Text)'
  2079. sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/image.c' &&
  2080. /*
  2081. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2082. %                                                                             %
  2083. %                                                                             %
  2084. %                                                                             %
  2085. %                     IIIII  M   M   AAA   GGGG  EEEEE                        %
  2086. %                       I    MM MM  A   A G      E                            %
  2087. %                       I    M M M  AAAAA G  GG  EEE                          %
  2088. %                       I    M   M  A   A G   G  E                            %
  2089. %                     IIIII  M   M  A   A  GGGG  EEEEE                        %
  2090. %                                                                             %
  2091. %                                                                             %
  2092. %                    Utiltity Image Routines for Display                      %
  2093. %                                                                             %
  2094. %                                                                             %
  2095. %                                                                             %
  2096. %                           Software Design                                   %
  2097. %                             John Cristy                                     %
  2098. %                            January  1991                                    %
  2099. %                                                                             %
  2100. %                                                                             %
  2101. %  Copyright 1991 E. I. Dupont de Nemours & Company                           %
  2102. %                                                                             %
  2103. %  Permission to use, copy, modify, distribute, and sell this software and    %
  2104. %  its documentation for any purpose is hereby granted without fee,           %
  2105. %  provided that the above Copyright notice appear in all copies and that     %
  2106. %  both that Copyright notice and this permission notice appear in            %
  2107. %  supporting documentation, and that the name of E. I. Dupont de Nemours     %
  2108. %  & Company not be used in advertising or publicity pertaining to            %
  2109. %  distribution of the software without specific, written prior               %
  2110. %  permission.  E. I. Dupont de Nemours & Company makes no representations    %
  2111. %  about the suitability of this software for any purpose.  It is provided    %
  2112. %  "as is" without express or implied warranty.                               %
  2113. %                                                                             %
  2114. %  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
  2115. %  to this software, including all implied warranties of merchantability      %
  2116. %  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
  2117. %  liable for any special, indirect or consequential damages or any           %
  2118. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  2119. %  in an action of contract, negligence or other tortious action, arising     %
  2120. %  out of or in connection with the use or performance of this software.      %
  2121. %                                                                             %
  2122. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2123. %
  2124. %
  2125. %
  2126. */
  2127. #include "display.h"
  2128. #include "image.h"
  2129. #include "X.h"
  2130. X
  2131. /*
  2132. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2133. %                                                                             %
  2134. %                                                                             %
  2135. %                                                                             %
  2136. %   C l i p I m a g e                                                         %
  2137. %                                                                             %
  2138. %                                                                             %
  2139. %                                                                             %
  2140. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2141. %
  2142. %  Function ClipImage creates a new image that is a subregion of an existing
  2143. %  one.  It allocates the memory necessary for the new Image structure and
  2144. %  returns a pointer to the new image.  The pixels are copied from the source
  2145. %  image as defined by the region formed from x_offset, y_offset, width, and
  2146. %  height.
  2147. %
  2148. %  The format of the ClipImage routine is:
  2149. %
  2150. %      clipped_image=ClipImage(image,x_offset,y_offset,width,height)
  2151. %
  2152. %  A description of each parameter follows:
  2153. %
  2154. %    o clipped_image: Function ClipImage returns a pointer to the clipped
  2155. %      image.  A null image is returned if there is a a memory shortage or
  2156. %      if the image width or height is zero.
  2157. %
  2158. %    o image: The address of a structure of type Image.
  2159. %
  2160. %    o x_offset: An integer that specifies the column offset of the
  2161. %      clipped image.
  2162. %
  2163. %    o y_offset: An integer that specifies the row offset of the clipped
  2164. %      image.
  2165. %
  2166. %    o width: An integer that specifies the number of width in the clipped
  2167. %      image.
  2168. %
  2169. %    o height: An integer that specifies the number of height in the clipped
  2170. %      image.
  2171. %
  2172. %
  2173. */
  2174. Image *ClipImage(image,x_offset,y_offset,width,height)
  2175. Image
  2176. X  *image;
  2177. X
  2178. int
  2179. X  x_offset,
  2180. X  y_offset;
  2181. X
  2182. unsigned int
  2183. X  width,
  2184. X  height;
  2185. {
  2186. X  Image
  2187. X    *clipped_image,
  2188. X    *CopyImage();
  2189. X
  2190. X  register int
  2191. X    x,
  2192. X    y;
  2193. X
  2194. X  register RunlengthPacket
  2195. X    *p,
  2196. X    *q;
  2197. X
  2198. X  void
  2199. X    DestroyImage();
  2200. X
  2201. X  /*
  2202. X    Check clip geometry.
  2203. X  */
  2204. X  if ((width*height) == 0)
  2205. X    {
  2206. X      Warning("unable to clip image","image size is zero");
  2207. X      return((Image *) NULL);
  2208. X    }
  2209. X  if (((x_offset+(int) width) < 0) || ((y_offset+(int) height) < 0) ||
  2210. X      (x_offset > (int) image->columns) || (y_offset > (int) image->rows))
  2211. X    {
  2212. X      Warning("unable to clip image","geometry does not contain image");
  2213. X      return((Image *) NULL);
  2214. X    }
  2215. X  if ((x_offset+(int) width) > (int) image->columns)
  2216. X    width=(unsigned int) ((int) image->columns-x_offset);
  2217. X  if ((y_offset+(int) height) > (int) image->rows)
  2218. X    height=(unsigned int) ((int) image->rows-y_offset);
  2219. X  if (x_offset < 0)
  2220. X    {
  2221. X      width-=(unsigned int) (-x_offset);
  2222. X      x_offset=0;
  2223. X    }
  2224. X  if (y_offset < 0)
  2225. X    {
  2226. X      height-=(unsigned int) (-y_offset);
  2227. X      y_offset=0;
  2228. X    }
  2229. X  /*
  2230. X    Initialize clipped image attributes.
  2231. X  */
  2232. X  clipped_image=CopyImage(image,width,height);
  2233. X  if (clipped_image == (Image *) NULL)
  2234. X    {
  2235. X      Warning("unable to clip image","memory allocation failed");
  2236. X      return((Image *) NULL);
  2237. X    }
  2238. X  /*
  2239. X    Skip pixels up to the clipped image.
  2240. X  */
  2241. X  p=image->pixels;
  2242. X  image->runlength=p->length+1;
  2243. X  for (x=0; x < (y_offset*(int) image->columns+x_offset); x++)
  2244. X    if (image->runlength > 0)
  2245. X      image->runlength--;
  2246. X    else
  2247. X      {
  2248. X        p++;
  2249. X        image->runlength=p->length;
  2250. X      }
  2251. X  /*
  2252. X    Extract clipped image.
  2253. X  */
  2254. X  clipped_image->packets=0;
  2255. X  q=clipped_image->pixels;
  2256. X  q->length=MaxRunlength;
  2257. X  for (y=0; y < clipped_image->rows; y++)
  2258. X  {
  2259. X    /*
  2260. X      Transfer scanline.
  2261. X    */
  2262. X    for (x=0; x < clipped_image->columns; x++)
  2263. X    {
  2264. X      if (image->runlength > 0)
  2265. X        image->runlength--;
  2266. X      else
  2267. X        {
  2268. X          p++;
  2269. X          image->runlength=p->length;
  2270. X        }
  2271. X      if ((p->red == q->red) && (p->green == q->green) &&
  2272. X          (p->blue == q->blue) && (q->length < MaxRunlength))
  2273. X        q->length++;
  2274. X      else
  2275. X        {
  2276. X          if (clipped_image->packets > 0)
  2277. X            q++;
  2278. X          clipped_image->packets++;
  2279. X          q->red=p->red;
  2280. X          q->green=p->green;
  2281. X          q->blue=p->blue;
  2282. X          q->index=p->index;
  2283. X          q->length=0;
  2284. X        }
  2285. X    }
  2286. X    /*
  2287. X      Skip to next scanline.
  2288. X    */
  2289. X    for (x=0; x < (image->columns-clipped_image->columns); x++)
  2290. X      if (image->runlength > 0)
  2291. X        image->runlength--;
  2292. X      else
  2293. X        {
  2294. X          p++;
  2295. X          image->runlength=p->length;
  2296. X        }
  2297. X  }
  2298. X  clipped_image->pixels=(RunlengthPacket *) realloc((char *)
  2299. X    clipped_image->pixels,clipped_image->packets*sizeof(RunlengthPacket));
  2300. X  return(clipped_image);
  2301. }
  2302. X
  2303. /*
  2304. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2305. %                                                                             %
  2306. %                                                                             %
  2307. %                                                                             %
  2308. %   C o p y I m a g e                                                         %
  2309. %                                                                             %
  2310. %                                                                             %
  2311. %                                                                             %
  2312. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2313. %
  2314. %  Function CopyImage returns a copy of all fields of the input image.  The
  2315. %  the pixel memory is allocated but the pixel data is not copied.
  2316. %
  2317. %  The format of the CopyImage routine is:
  2318. %
  2319. %      copy_image=CopyImage(image,columns,rows)
  2320. %
  2321. %  A description of each parameter follows:
  2322. %
  2323. %    o copy_image: Function CopyImage returns a pointer to the image after
  2324. %      copying.  A null image is returned if there is a memory shortage.
  2325. %
  2326. %    o image: The address of a structure of type Image.
  2327. %
  2328. %    o columns: An integer that specifies the number of columns in the copied
  2329. %      image.
  2330. %
  2331. %    o rows: An integer that specifies the number of rows in the copied
  2332. %      image.
  2333. %
  2334. %
  2335. */
  2336. Image *CopyImage(image,columns,rows)
  2337. Image
  2338. X  *image;
  2339. X
  2340. unsigned int
  2341. X  columns,
  2342. X  rows;
  2343. {
  2344. X  Image
  2345. X    *copy_image;
  2346. X
  2347. X  register int
  2348. X    i;
  2349. X
  2350. X  /*
  2351. X    Allocate image structure.
  2352. X  */
  2353. X  copy_image=(Image *) malloc(sizeof(Image));
  2354. X  if (copy_image == (Image *) NULL)
  2355. X    return((Image *) NULL);
  2356. X  *copy_image=(*image);
  2357. X  copy_image->compression=RunlengthEncodedCompression;
  2358. X  copy_image->columns=columns;
  2359. X  copy_image->rows=rows;
  2360. X  if (image->colormap != (ColorPacket *) NULL)
  2361. X    {
  2362. X      /*
  2363. X        Allocate and copy the image colormap.
  2364. X      */
  2365. X      copy_image->colormap=(ColorPacket *)
  2366. X        malloc(image->colors*sizeof(ColorPacket));
  2367. X      if (copy_image->colormap == (ColorPacket *) NULL)
  2368. X        return((Image *) NULL);
  2369. X      for (i=0; i < image->colors; i++)
  2370. X        copy_image->colormap[i]=image->colormap[i];
  2371. X    }
  2372. X  /*
  2373. X    Allocate but do not copy the image pixels.
  2374. X  */
  2375. X  copy_image->packets=copy_image->columns*copy_image->rows;
  2376. X  copy_image->pixels=(RunlengthPacket *)
  2377. X    malloc(copy_image->packets*sizeof(RunlengthPacket));
  2378. X  if (copy_image->pixels == (RunlengthPacket *) NULL)
  2379. X    return((Image *) NULL);
  2380. X  if (image->comments != (char *) NULL)
  2381. X    {
  2382. X      /*
  2383. X        Allocate and copy the image comments.
  2384. X      */
  2385. X      copy_image->comments=(char *)
  2386. X        malloc((unsigned int) ((strlen(image->comments)+1)*sizeof(char)));
  2387. X      if (copy_image->comments == (char *) NULL)
  2388. X        return((Image *) NULL);
  2389. X      (void) strcpy(copy_image->comments,image->comments);
  2390. X    }
  2391. X  return(copy_image);
  2392. }
  2393. X
  2394. /*
  2395. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2396. SHAR_EOF
  2397. true || echo 'restore of ImageMagick/image.c failed'
  2398. fi
  2399. echo 'End of ImageMagick part 3'
  2400. echo 'File ImageMagick/image.c is continued in part 4'
  2401. echo 4 > _shar_seq_.tmp
  2402. exit 0
  2403. --
  2404. Dan Heller
  2405. O'Reilly && Associates       Z-Code Software    Comp-sources-x:
  2406. Senior Writer                President          comp-sources-x@uunet.uu.net
  2407. argv@ora.com                 argv@zipcode.com
  2408.