v13i019: ImageMagick - Graphics display programs, Part03/21

cristy at dupont.com cristy at dupont.com
Wed May 22 18:57:20 AEST 1991


Submitted-by: cristy at dupont.com
Posting-number: Volume 13, Issue 19
Archive-name: imagemagic/part03

#!/bin/sh
# this is img.03 (part 3 of ImageMagick)
# do not concatenate these parts, unpack them in order with /bin/sh
# file ImageMagick/xtp/regular.c continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 3; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping ImageMagick/xtp/regular.c'
else
echo 'x - continuing file ImageMagick/xtp/regular.c'
sed 's/^X//' << 'SHAR_EOF' >> 'ImageMagick/xtp/regular.c' &&
%                                                                             %
%                                                                             %
%   P i e c e                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
static char *Piece(flagp)
int
X  *flagp;
{
X  int
X    flags;
X
X  register char
X    *next_token,
X    op,
X    *status;
X
X  static void
X    Tail();
X
X  status=Atom(&flags);
X  if (status == NULL)
X    return(NULL);
X  op=(*token);
X  if (!MultipleMatches(op))
X    {
X      *flagp=flags;
X      return(status);
X    }
X  if (!(flags & NonNull) && op != '?')
X    Fail("*+ operand could be empty");
X  *flagp=(op != '+') ? (WorstCase | SpecialStart) : (WorstCase | NonNull);
X  if (op == '*' && (flags & Simple))
X    Insert(MatchZeroOrMore,status);
X  else
X    if (op == '*')
X      {
X        /*
X          Emit x* as (x&|), where & means "self".
X        */
X        Insert(MatchThisOrNext,status);  
X        OpTail(status,Node(Back)); 
X        OpTail(status,status); 
X        Tail(status,Node(MatchThisOrNext));  
X        Tail(status,Node(MatchEmptyString));
X      }
X    else
X      if ((op == '+') && (flags & Simple))
X        Insert(MatchOneOrMore,status);
X      else
X        if (op == '+')
X          {
X            /*
X              Emit x+ as x (&|), where & means "self".
X            */
X            next_token=Node(MatchThisOrNext);  
X            Tail(status,next_token);
X            Tail(Node(Back),status);
X            Tail(next_token,Node(MatchThisOrNext));
X            Tail(status,Node(MatchEmptyString));
X          }
X        else
X          if (op == '?')
X            {
X              /*
X                Emit x? as (x|)
X              */
X              Insert(MatchThisOrNext,status);  
X              Tail(status,Node(MatchThisOrNext));  
X              next_token=Node(MatchEmptyString);  
X              Tail(status,next_token);
X              OpTail(status,next_token);
X            }
X  token++;
X  if (MultipleMatches(*token))
X    Fail("nested *?+");
X  return(status);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e g u l a r                                                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
static char *Regular(parenthesized,flagp)
int
X  parenthesized;
X
int
X  *flagp;
{
X  int
X    flags;
X
X  register char
X    *br,
X    *ender,
X    *status;
X
X  register int
X    count;
X
X  static void
X    Tail();
X
X  count=0;
X  *flagp=NonNull;
X  if (!parenthesized)
X    status=NULL;
X  else
X    {
X      /*
X        Make an Open node.
X      */
X      if (number_parenthesis >= NumberSubExpressions)
X        Fail("too many ()");
X      count=number_parenthesis;
X      number_parenthesis++;
X      status=Node(Open+count);
X    }
X  /*
X    Pick up the branches, linking them together.
X  */
X  br=Branch(&flags);
X  if (br == NULL)
X    return(NULL);
X  if (status != NULL)
X    Tail(status,br);
X  else
X    status=br;
X  if (!(flags & NonNull))
X    *flagp&=(~NonNull);
X  *flagp|=flags & SpecialStart;
X  while (*token == '|')
X  {
X    token++;
X    br=Branch(&flags);
X    if (br == NULL)
X      return(NULL);
X    Tail(status,br);
X    if (!(flags & NonNull))
X      *flagp &= ~NonNull;
X    *flagp|=flags & SpecialStart;
X  }
X  /*
X    Make a closing node and hook it on the end.
X  */
X  ender=Node((parenthesized) ? Close+count : EndOfProgram);
X  Tail(status,ender);
X  /*
X    Hook the tails of the branches to the closing node.
X  */
X  for(br=status; br != NULL; br=NextToken(br))
X    OpTail(br,ender);
X  /*
X    Check for proper termination.
X  */
X  if (parenthesized && (*token++ != ')'))
X    Fail("unmatched()")
X  else
X    if (!parenthesized && (*token != '\0'))
X      {
X        if (*token == ')')
X          Fail("unmatched()")
X        else
X          Fail("junk on end")
X       }
X  return(status);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e p e a t                                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
static int Repeat(p)
char
X  *p;
{
X  register char
X    *operand,
X    *scan;
X
X  register int
X    count=0;
X
X  scan=p;
X  operand=Operand(p);
X  switch(OpCode(p))
X  {
X    case MatchAnyCharacter:
X    {
X      count=strlen(scan);
X      scan+=count;
X      break;
X    }
X    case MatchExactly:
X    {
X      while (*operand == *scan)
X      {
X        count++;
X        scan++;
X      }
X      break;
X    }
X    case MatchAnyCharacterOf:
X    {
X      while ((*scan != '\0') && (strchr(operand,*scan) != NULL))
X      {
X        count++;
X        scan++;
X      }
X      break;
X    }
X    case MatchAnyCharacterBut:
X    {
X      while ((*scan != '\0') && (strchr(operand,*scan) == NULL))
X      {
X        count++;
X        scan++;
X      }
X      break;
X    }
X    default:
X    {
X      (void) fprintf(stderr,"Regular(3): %s","internal foulup");
X      count=0;
X      break;
X    }
X  }
X  p=scan;
X  return(count);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   T a i l                                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
static void Tail(p,val)
char
X  *p;
X
char
X  *val;
{
X  register char
X    *scan,
X    *temp;
X
X  register int
X    offset;
X
X  if (p == &start_code)
X    return;
X  /*
X    Find last node.
X  */
X  scan=p;
X  for(;;)
X  {
X    temp=NextToken(scan);
X    if (temp == NULL)
X      break;
X    scan=temp;
X  }
X  if (OpCode(scan) == Back)
X    offset=scan-val;
X  else
X    offset=val-scan;
X  *(scan+1)=(offset >> 8) & 0377;
X  *(scan+2)=offset & 0377;
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   T r y                                                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
static int Try(regular_expression,pattern)
RegularExpression
X  *regular_expression;
X
char
X  *pattern;
{
X  register char
X    **ep,
X    **sp;
X
X  register int
X    i;
X
X  p=pattern;
X  subpattern=regular_expression->subpattern;
X  subpattern_end=regular_expression->subpattern_end;
X  sp=regular_expression->subpattern;
X  ep=regular_expression->subpattern_end;
X  for(i=NumberSubExpressions; i > 0; i--)
X  {
X    *sp++=NULL;
X    *ep++=NULL;
X  }
X  if (!Match(regular_expression->program+1))
X    return(0);
X  else
X    {
X      regular_expression->subpattern[0]=pattern;
X      regular_expression->subpattern_end[0]=p;
X      return(1);
X    }
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   C o m p i l e R e g u l a r E x p r e s s i o n                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function CompileRegularExpression compiles a regular expression into a 
%  structure of type RegularExpression and returns a pointer to it.  The space 
%  is allocated using function malloc and may be released by function free.
%
%
*/
RegularExpression *CompileRegularExpression(regular_expression)
char
X  *regular_expression;
{
X  int
X    flags;
X
X  register char
X    *longest,
X    *scan;
X
X  register RegularExpression
X    *r;
X
X  register int
X    length;
X
X  if (regular_expression == NULL)
X    Fail("NULL argument");
X  /*
X    First pass: determine size.
X  */
X  token=regular_expression;
X  number_parenthesis=1;
X  code_size=0L;
X  code=(&start_code);
X  EmitCode(Magick);
X  if (Regular(0,&flags) == NULL)
X    return(NULL);
X  /*
X    Allocate space.
X  */
X  r=(RegularExpression *)
X    malloc((unsigned int) (code_size+sizeof(RegularExpression)));
X  if (r == NULL)
X    Fail("out of space");
X  /*
X    Second pass: emit code.
X  */
X  token=regular_expression;
X  number_parenthesis=1;
X  code=r->program;
X  EmitCode(Magick);
X  if (Regular(0,&flags) == NULL)
X    return(NULL);
X  /*
X    Dig out information for optimizations.
X  */
X  r->start_character='\0';
X  r->anchor=0;
X  r->priority_pattern=NULL;
X  r->pattern_length=0;
X  scan=r->program+1;
X  if (OpCode(NextToken(scan)) == EndOfProgram)
X    {
X      scan=Operand(scan);
X      if (OpCode(scan) == MatchExactly)
X        r->start_character=(*Operand(scan));
X      else
X        if (OpCode(scan) == MatchBeginningOfLine)
X          r->anchor++;
X      /*
X        If there's something expensive in the regular expression, find the
X        longest literal pattern that must appear and make it the 
X        priority_pattern.
X      */
X      if (flags & SpecialStart)
X        {
X          longest=NULL;
X          length=0;
X          for(; scan != NULL; scan=NextToken(scan))
X            if ((OpCode(scan) == MatchExactly) && 
X                (strlen(Operand(scan)) >= length))
X              {
X                longest=Operand(scan);
X                length=strlen(Operand(scan));
X              }
X          r->priority_pattern=longest;
X          r->pattern_length=length;
X        }
X    }
X  return(r);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   E x e c u t e R e g u l a r E x p r e s s i o n                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function ExecuteRegularExpression matches a NULL-terminated pattern against 
%  the compiled regular expression in regular-expression.  It returns 1 for 
%  success and 0 for failure.
%
%
*/
int ExecuteRegularExpression(regular_expression,pattern)
register RegularExpression
X  *regular_expression;
X
register char
X  *pattern;
{
X  register char
X    *s;
X
X  if ((regular_expression == (RegularExpression *) NULL) || 
X      (pattern == (char *) NULL))
X    {
X      (void) fprintf(stderr,"Regular(3): %s","NULL parameter\n");
X      return(0);
X    }
X  /*
X    Check validity of program.
X  */
X  if (((int)*(unsigned char *)(regular_expression->program)) != Magick)
X    {
X      (void) fprintf(stderr,"Regular(3): %s","corrupted program");
X      return(0);
X    }
X  /*
X    If there is a "must appear" pattern, look for it.
X  */
X  if (regular_expression->priority_pattern != NULL)
X    {
X      s=pattern;
X      while ((s=strchr(s,regular_expression->priority_pattern[0])) != NULL)
X      {
X        if (strncmp(s,regular_expression->priority_pattern,
X            regular_expression->pattern_length) == 0)
X          break;
X        s++;
X       }
X       if (s == NULL)
X         return(0);
X    }
X  /*
X    Mark beginning of line for ^.
X  */
X  start_pattern=pattern;
X  /*
X    Simplest case:  anchored match need be tried only once.
X  */
X  if (regular_expression->anchor)
X    return(Try(regular_expression,pattern));
X  /*
X    Messy cases:  unanchored match.
X  */
X  s=pattern;
X  if (regular_expression->start_character != '\0')
X    while ((s=strchr(s,regular_expression->start_character)) != NULL)
X    {
X      if (Try(regular_expression,s))
X        return(1);
X      s++;
X    }
X  else
X    do
X    {
X      if (Try(regular_expression,s))
X        return(1);
X    } while (*s++ != '\0');
X  return(0);
}
SHAR_EOF
echo 'File ImageMagick/xtp/regular.c is complete' &&
chmod 0755 ImageMagick/xtp/regular.c ||
echo 'restore of ImageMagick/xtp/regular.c failed'
Wc_c="`wc -c < 'ImageMagick/xtp/regular.c'`"
test 33398 -eq "$Wc_c" ||
	echo 'ImageMagick/xtp/regular.c: original size 33398, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/xtp/regular.h ==============
if test -f 'ImageMagick/xtp/regular.h' -a X"$1" != X"-c"; then
	echo 'x - skipping ImageMagick/xtp/regular.h (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/xtp/regular.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/regular.h' &&
/*
X  Definitions etc. for RegularExpression(3) routines.
*/
#define EndOfProgram  0
#define MatchBeginningOfLine  1
#define MatchEndOfProgramOfLine  2
#define MatchAnyCharacter  3
#define MatchAnyCharacterOf  4
#define MatchAnyCharacterBut  5
#define MatchThisOrNext  6
#define Back  7
#define MatchExactly  8
#define MatchEmptyString  9
#define MatchZeroOrMore  10
#define MatchOneOrMore  11
#define Open  20
#define Close  30
X
#define WorstCase  0
#define NonNull  1
#define Simple  2
#define SpecialStart  4
X
#define Fail(m)  \
{  \
X  (void) fprintf(stderr,"RegularExpression: %s\n",m);  \
X  return(NULL);  \
}
#define Magick   0234
#define Meta  "^$.[()|?+*\\"
#define MultipleMatches(c) (((c) == '*') || ((c) == '+') || ((c) == '?'))
#define Next(p) (((*((p)+1) & 0377) << 8 )+(*((p)+2) & 0377))
#define NumberSubExpressions  10
#define OpCode(p) (*(p))
#define Operand(p) ((p)+3)
X
typedef struct _RegularExpression 
{
X  char 
X    *subpattern[NumberSubExpressions],
X    *subpattern_end[NumberSubExpressions],
X    start_character,
X    anchor,
X    *priority_pattern;
X
X  int 
X    pattern_length;
X
X  char 
X    program[1];
} RegularExpression;
X
extern RegularExpression 
X  *CompileRegularExpression();
X
extern int 
X  ExecuteRegularExpression();
SHAR_EOF
chmod 0755 ImageMagick/xtp/regular.h ||
echo 'restore of ImageMagick/xtp/regular.h failed'
Wc_c="`wc -c < 'ImageMagick/xtp/regular.h'`"
test 1245 -eq "$Wc_c" ||
	echo 'ImageMagick/xtp/regular.h: original size 1245, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/xtp/xtp.c ==============
if test -f 'ImageMagick/xtp/xtp.c' -a X"$1" != X"-c"; then
	echo 'x - skipping ImageMagick/xtp/xtp.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/xtp/xtp.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/xtp.c' &&
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%                            X   X  TTTTT PPPP                                %
%                             X X     T   P   P                               %
%                              X      T   PPPP                                %
%                             X X     T   P                                   %
%                            X   X    T   P                                   %
%                                                                             %
%                                                                             %
%                         File transfer program.                              %
%                                                                             %
%                                                                             %
%                                                                             %
%                           Software Design                                   %
%                             John Cristy                                     %
%                            January  1991                                    %
%                                                                             %
%                                                                             %
%  Copyright 1991 E. I. Dupont de Nemours & Company                           %
%                                                                             %
%  Permission to use, copy, modify, distribute, and sell this software and    %
%  its documentation for any purpose is hereby granted without fee,           %
%  provided that the above copyright notice appear in all copies and that     %
%  both that copyright notice and this permission notice appear in            %
%  supporting documentation, and that the name of E. I. Dupont de Nemours     %
%  & Company not be used in advertising or publicity pertaining to            %
%  distribution of the software without specific, written prior               %
%  permission.  E. I. Dupont de Nemours & Company makes no representations    %
%  about the suitability of this software for any purpose.  It is provided    %
%  "as is" without express or implied warranty.                               %
%                                                                             %
%  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
%  to this software, including all implied warranties of merchantability      %
%  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
%  liable for any special, indirect or consequential damages or any           %
%  damages whatsoever resulting from loss of use, data or profits, whether    %
%  in an action of contract, negligence or other tortious action, arising     %
%  out of or in connection with the use or performance of this software.      %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Xtp is a utility for retrieving, listing, or printing files from a
%  remote network site.  Xtp performs most of the same functions as the
%  ftp program, but does not require any interactive commands.  You simply
%  specify the file transfer task on the command line and xtp performs the
%  transfer automatically.
%
%  This program was adapted from a similiar program written by Steve Singles,
%  University of Delaware.
%
%  Command syntax:
%
%  Usage: xtp [-options ...] <host/ip address> [ <home directory> ]
%
%  Where options include:
%    -binary                retrieve files as binary
%    -exclude expression    exclude files that match the expression
%    -directory expression  list file names that match the expression
%    -ident password        specifies password
%    -print expression      print files that match the expression
%    -retrieve expression   retrieve files that match the expression
%    -send expression       send files that match the expression
%    -timeout seconds       specifies maximum seconds to logon host
%    -user name             identify yourself to the remote FTP server
%
%
*/
X
/*
X  Include declarations.
*/
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "regular.h"
/*
X  Define declarations.
*/
#define False  0
#define True  1
/*
X  Variable declarations.
*/
char
X  *program_name,
X  slave_tty[16],
X  *Wait();
X
int
X  master;
X
RegularExpression
X  *directory_expression,
X  *exclude_expression,
X  *print_expression,
X  *retrieve_expression;
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   D i r e c t o r y R e q u e s t                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function DirectoryRequest lists a file name and its attributes.
%
%  The format of the DirectoryRequest routine is:
%
%    DirectoryRequest(error)
%
%
*/
void DirectoryRequest(fileinfo,filename)
char
X  *fileinfo,
X  *filename;
{
X  (void) fprintf(stdout,"%s %s\n",fileinfo,filename);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   E r r o r                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function Error prints an error message then terminates the program.
%
%  The format of the Error routine is:
%
%    Error(error)
%
%  A description of each parameter follows:
%
%    o error:  Specifies a pointer to a character array that contains the
%      text of the error message.
%
%
*/
void Error(error)
char
X  *error;
{
X  char
X    message[80];
X
X  (void) sprintf(message,"%s: %s",program_name,error);
X  perror(message);
X  exit(1);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   E x e c u t e F t p                                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function ExecuteFtp executes the FTP program as a child process.
%
%  The format of the ExecuteFtp routine is:
%
%    ExecuteFtp(hostname)
%
%  A description of each parameter follows:
%
%    o hostname:  Specifies a pointer to a character array that contains the
%      name of the host to establish a connection to a FTP server.
%
%
*/
void ExecuteFtp(hostname)
char
X  *hostname;
{
#include <sys/ioctl.h>
X
X  int
X    slave;
X
X  struct ltchars
X    lc;
X
X  struct sgttyb
X    b;
X
X  struct tchars
X    tc;
X
X  (void) signal(SIGTSTP,SIG_IGN);
X  if (isatty(0))
X    {
X      int
X        tty;
X
X      /*
X        Disable controlling terminal.
X      */
X      tty=open("/dev/tty",O_RDWR);
X      if (tty >= 0)
X        {
X          (void) ioctl(tty,TIOCNOTTY,(char *) 0);
X          (void) close(tty);
X        }
X    }
X  slave=open(slave_tty,O_RDWR);
X  if (slave < 0)
X    Error(slave_tty);
X  /*
X    Fix tty line.
X  */
X  (void) ioctl(slave,TIOCGETP,&b);
X  b.sg_flags&=~(ECHO | CRMOD);
X  b.sg_erase=(-1);
X  b.sg_kill=(-1);
X  (void) ioctl(slave,TIOCSETP,&b);
X  tc.t_intrc=(-1);
X  tc.t_quitc=(-1);
X  tc.t_startc=(-1);
X  tc.t_stopc=(-1);
X  tc.t_eofc=(-1);
X  tc.t_brkc=(-1);
X  (void) ioctl(slave,TIOCSETC,&tc);
X  lc.t_suspc=(-1);
X  lc.t_dsuspc=(-1);
X  lc.t_rprntc=(-1);
X  lc.t_flushc=(-1);
X  lc.t_werasc=(-1);
X  lc.t_lnextc=(-1);
X  (void) ioctl(slave,TIOCSLTC,&lc);
X  /*
X    Execute FTP program as a child process.
X  */
X  (void) close(master);
X  (void) dup2(slave,0);
X  (void) dup2(slave,1);
X  (void) dup2(slave,2);
X  (void) close(slave);
X  (void) execlp("ftp","ftp","-n","-i","-g",hostname,(char *) 0);
X  perror("/usr/ucb/ftp");
X  (void) kill(0,SIGTERM);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   G e t H o s t I n f o                                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function GetHostInfo prints the hostname and IP address.
%
%  The format of the GetHostInfo routine is:
%
%    GetHostInfo(host)
%
%  A description of each parameter follows:
%
%    o host:  Specifies a pointer to a character array that contains either
%      a name of a host or an IP address.
%
%
*/
void GetHostInfo(host)
char
X  *host;
{
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
X
X  char
X    *address,
X    *inet_ntoa(),
X    *p;
X
X  struct in_addr
X    in;
X
X  struct hostent
X    *hp;
X
X  if (isdigit(*host))
X    {
X      /*
X        Internet address to name.
X      */
X      in.s_addr=inet_addr(host);
X      hp=gethostbyaddr((char *) &in.s_addr,sizeof(in.s_addr),AF_INET);
X      if (hp != (struct hostent *) NULL)
X        {
X          hp=gethostbyname(hp->h_name);
X          if (hp != (struct hostent *) NULL)
X            {
X              in.s_addr= *(int *) hp->h_addr;
X              address=inet_ntoa(in);
X            }
X        }
X    }
X  else
X    {
X      /*
X        Internet name to address.
X      */
X      hp=gethostbyname(host);
X      if (hp != (struct hostent *) NULL)
X        {
X          in.s_addr= *(int *) hp->h_addr;
X          address=inet_ntoa(in);
X          hp=gethostbyaddr((char *) &in.s_addr,sizeof(in.s_addr),AF_INET);
X        }
X    }
X  if (hp == (struct hostent *) NULL)
X    (void) fprintf(stdout,"%s: ",host);
X  else
X    {
X      /*
X        Convert hostname to lower-case characters and print.
X      */
X      p=hp->h_name;
X      while (*p)
X      {
X        if (isupper(*p))
X          *p=tolower(*p);
X        p++;
X      }
X      (void) fprintf(stdout,"%s [%s]: ",hp->h_name,address);
X    }
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   G e t P s e u d o T e r m i n a l                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function GetPseudoTerminal returns a master/slave pair of pseudo-terminals.
%
%  The format of the GetPseudoTerminal routine is:
%
%    GetPseudoTerminal()
%
%
*/
void GetPseudoTerminal()
{
X  char
X    master_tty[16];
X
X  register char
X    *bank,
X    *cp;
X
X  struct stat
X    info;
X
X  for (bank="pqrs"; *bank; bank++)
X  {
X    (void) sprintf(master_tty,"/dev/pty%c0",*bank);
X    if (stat(master_tty,&info) < 0)
X      break;
X    for (cp="0123456789abcdef"; *cp; cp++)
X    {
X      (void) sprintf((char *) master_tty,"/dev/pty%c%c",*bank,*cp);
X      master=open(master_tty,O_RDWR);
X      if (master >= 0)
X        {
X          /*
X            Verify slave side is usable.
X          */
X          (void) sprintf(slave_tty,"/dev/tty%c%c",*bank,*cp);
X          if (access(slave_tty,R_OK | W_OK) == 0)
X            return;
X          (void) close(master);
X        }
X    }
X  }
X  Error("All network ports in use.\n");
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   M a k e D i r e c t o r y                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function MakeDirectory checks each component of a directory path and if it
%  does not exist, creates it.
%
%  The format of the MakeDirectory routine is:
%
%    MakeDirectory(directory)
%
%  A description of each parameter follows:
%
%    o directory:  Specifies a pointer to a character array that contains
%      the name of the directory to create.
%
%
*/
int MakeDirectory(directory)
char
X  *directory;
{
#define IsDirectory(mode) (((mode) & S_IFMT) == S_IFDIR)
X
X  register char
X    *p;
X
X  struct stat
X    info;
X
X  /*
X    Determine first component of the directory.
X  */
X  p=strrchr(directory,'/');
X  if ((p == (char *) NULL) || (p == directory))
X    return(False);
X  *p=(char) NULL;
X  if (lstat(directory,&info) < 0)
X    {
X      /*
X        Path component does not exist;  create it.
X      */
X      if (MakeDirectory(directory) == 0)
X        if (mkdir(directory,0777) >= 0)
X          {
X            *p='/';
X            return(False);
X          }
X    }
X  else
X    if (IsDirectory(info.st_mode))
X      {
X        /*
X          Path component already exists.
X        */
X        *p='/';
X        return(False);
X      }
X  /*
X    Path component is a file not a directory.
X  */
X  *p='/';
X  return(True);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   P r i n t R e q u e s t                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function PrintRequest prints a file on the remote FTP server.
%
%  The format of the PrintRequest routine is:
%
%    PrintRequest(filename)
%
%  A description of each parameter follows:
%
%    o filename:  Specifies a pointer to a character array that contains
%      the name of the file to print.
%
%
*/
void PrintRequest(filename)
char
X  *filename;
{
X  char
X    command[256],
X    *response;
X
X  /*
X    get remote-file [ - | <| zcat> ].
X  */
X  (void) sprintf(command,"get %s",filename);
X  (void) write(master,command,(int) strlen(command));
X  if (strcmp(filename+strlen(filename)-2,".Z"))
X    (void) sprintf(command," -\n");
X  else
X    (void) sprintf(command," | zcat\n");
X  (void) write(master,command,(int) strlen(command));
X  (void) fprintf(stdout,"%s:\n",filename);
X  while (response=Wait())
X    (void) fprintf(stdout,"%s\n",response);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   P r o c e s s R e q u e s t                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function ProcessRequest first records any file in the current directory
%  of the remote FTP server or any of its subdirectories.  Next each filename
%  is either accepted or rejected based on a user specified regular
%  expresssion.  If any files match the regular expression, its filename is
%  listed, it is printed, or it is retrieved as specified on the command line.
%
%  The format of the ProcessRequest routine is:
%
%    ProcessRequest()
%
%
*/
void ProcessRequest()
{
X  typedef struct _DirectoryNode
X  {
X    char
X      *info,
X      *name;
X
X    struct _DirectoryNode
X      *next;
X  } DirectoryNode;
X
X  char
X    command[256],
X    directory[1024],
X    *info,
X    *name,
X    *response;
X
X  DirectoryNode
X    *next,
X    *root;
X
X  register char
X    *p;
X
X  register DirectoryNode
X    **last,
X    *node;
X
X  RegularExpression
X    *date_expression,
X    *mode_expression;
X
X  unsigned int
X    unix_filesystem;
X
X  void
X    DirectoryRequest(),
X    PrintRequest(),
X    RetrieveRequest();
X
X  /*
X    Initialize function variables.
X  */
X  root=(DirectoryNode *) NULL;
X  last=(&root);
X  *directory=(char) NULL;
X  /*
X    Unix-style filesystem if the first few characters is in mode format.
X  */
X  mode_expression=CompileRegularExpression("^[dbclps-][rwx-][rwx-][rwx-]");
X  unix_filesystem=False;
X  (void) strcpy(command,"dir\n");
X  (void) write(master,command,(int) strlen(command));
X  response=Wait();
X  if (response == (char *) NULL)
X    return;
X  while (response=Wait())
X    if (*response != (char) NULL)
X      if (!unix_filesystem)
X        unix_filesystem=ExecuteRegularExpression(mode_expression,response);
X  (void) free((char *) mode_expression);
X  /*
X    Issue directory command to remote FTP server.
X  */
X  if (unix_filesystem)
X    (void) strcpy(command,"dir -R\n");
X  else
X    (void) strcpy(command,"dir [...]\n");
X  (void) write(master,command,(int) strlen(command));
X  response=Wait();
X  if (response == (char *) NULL)
X    return;
X  response=Wait();
X  if (response == (char *) NULL)
X    {
X      /*
X        Directory command has limited functionality.
X      */
X      (void) strcpy(command,"dir\n");
X      (void) write(master,command,(int) strlen(command));
X      response=Wait();
X      if (response == (char *) NULL)
X        return;
X    }
X  if (!unix_filesystem)
X    do 
X    {
X      /*
X        Link non unix-style file into file list.
X      */
X      if (*response == (char) NULL)
X        continue;
X      while (*response == ' ')
X        response++;
X      /*
X        Extract file name & info.
X      */
X      name=response;
X      info=response;
X      while ((*info != ' ') && *info)
X        info++;
X      *info++=(char) NULL;
X      while (*info == ' ')
X        info++;
X      if (exclude_expression)
X        if (ExecuteRegularExpression(exclude_expression,name))
X          continue;
X      node=(DirectoryNode *) malloc(sizeof(DirectoryNode));
X      if (node == (DirectoryNode *) NULL)
X        Error("unable to allocate memory");
X      node->name=(char *) malloc((unsigned int) (strlen(name)+1));
X      node->info=(char *) malloc((unsigned int) (strlen(info)+1));
X      if ((node->name == (char *) NULL) || (node->info == (char *) NULL))
X        Error("unable to allocate memory");
X      (void) strcpy(node->name,name);
X      (void) strcpy(node->info,info);
X      node->next=(DirectoryNode *) NULL;
X      *last=node;
X      last=(&node->next);
X    }
X    while (response=Wait());
X  else
X    {
X      RegularExpression
X        *access_expression;
X
X      access_expression=
X        CompileRegularExpression("Permission denied|not found|cannot access");
X      date_expression=CompileRegularExpression("^[:9][0-9][0-9]");
X      do
X      {
X        /*
X           Link unix-style file into file list.
X        */
X        if (*response == (char) NULL)
X          continue;
X        while (*response == ' ')
X          response++;
X        p=response+strlen(response)-1;
X        if (*response == '-')
X          {
X            if (ExecuteRegularExpression(access_expression,response))
X              continue;
X            /*
X              Extract file info & name.
X            */
X            while (p-- > (response+3))
X            if (*p == ' ')
X              if (ExecuteRegularExpression(date_expression,p-3))
X                break;
X            *p++=(char) NULL;
X            while (*p == ' ')
X              p++;
X            name=p;
X            if (exclude_expression)
X              if (ExecuteRegularExpression(exclude_expression,name))
X                continue;
X            info=response;
X            node=(DirectoryNode *) malloc(sizeof(DirectoryNode));
X            if (node == (DirectoryNode *) NULL)
X              Error("unable to allocate memory");
X            node->name=(char *)
X              malloc((unsigned int) (strlen(directory)+strlen(name)+1));
X            node->info=(char *) malloc((unsigned int) (strlen(info)+1));
X            if ((node->name == (char *) NULL) || (node->info == (char *) NULL))
X              Error("unable to allocate memory");
X            (void) strcpy(node->name,directory);
X            (void) strcat(node->name,name);
X            (void) strcpy(node->info,info);
X            node->next=(DirectoryNode *) NULL;
X            *last=node;
X            last=(&node->next);
X          }
X        else
X          if (*p == ':')
X            {
X              /*
X                File is a directory.
X              */
X              do { p--; } while (*p == ' ');
X              *(++p)=(char) NULL;
X              (void) strcpy(directory,response);
X              (void) strcat(directory,"/");
X            }
X      }
X      while (response=Wait());
X      (void) free((char *) access_expression);
X      (void) free((char *) date_expression);
X    }
X  /*
X    Traverse the file list and act on a filename if it matches the regular
X    expression.
X  */
X  node=root;
X  while (node)
X  {
X    if (directory_expression)
X      if (ExecuteRegularExpression(directory_expression,node->name))
X        (void) DirectoryRequest(node->info,node->name);
X    if (retrieve_expression)
X      if (ExecuteRegularExpression(retrieve_expression,node->name))
X        (void) RetrieveRequest(node->name);
X    if (print_expression)
X      if (ExecuteRegularExpression(print_expression,node->name))
X        (void) PrintRequest(node->name);
X    /*
X      Free allocated memory for this node.
X    */
X    (void) free(node->info);
X    (void) free(node->name);
X    next=node->next;
X    (void) free((char *) node);
X    node=next;
X  }
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e t r i e v e R e q u e s t                                             %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function RetrieveRequest retrieves a file from the remote FTP server.
%
%  The format of the RetrieveRequest routine is:
%
%    RetrieveRequest(filename)
%
%  A description of each parameter follows:
%
%    o filename:  Specifies a pointer to a character array that contains
%      the name of the file to retrieve.
%
%
*/
void RetrieveRequest(filename)
char
X  *filename;
{
X  char
X    command[256],
X    *response;
X
X  /*
X    get remote-file
X  */
X  (void) MakeDirectory(filename);
X  (void) sprintf(command,"get %s\n",filename);
X  (void) write(master,command,(int) strlen(command));
X  (void) fprintf(stdout,"Retrieving %s...\n",filename);
X  while (response=Wait())
X    (void) fprintf(stdout,"%s\n",response);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   S i g n a l C h i l d                                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function SignalChild is called if the status of the child process changes.
%
%  The format of the SignalChild routine is:
%
%    SignalChild()
%
%
*/
void SignalChild()
{
X  char
X    message[256];
X
X  union wait
X    status;
X
X  while (wait3(&status,WNOHANG,(struct rusage *) NULL) > 0);
X  (void) sprintf(message,"child died, status %x",wait(&status));
X  Error(message);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   U s a g e                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Procedure Usage displays the program usage;
%
%  The format of the Usage routine is:
%
%      Usage(message)
%
%  A description of each parameter follows:
%
%    o message:  Specifies a specific message to display to the user.
%
%
*/
void Usage(message)
char
X  *message;
{
X  char
X    **p;
X
X  static char
X    *options[]=
X    {
X      "-binary                retrieve files as binary",
X      "-exclude expression    exclude files that match the expression",
X      "-directory expression  list file names that match the expression",
X      "-ident password        specifies password",
X      "-print expression      print files that match the expression",
X      "-retrieve expression   retrieve files that match the expression",
X      "-send expression       send files that match the expression",
X      "-timeout seconds       specifies maximum seconds to logon host",
X      "-user name             identify yourself to the remote FTP server",
X      "-verbose               show all responses from the remote server",
X      NULL
X    };
X  if (message)
X    (void) fprintf(stderr,"Can't continue, %s\n\n",message);
X  (void) fprintf(stderr,
X    "Usage: %s [-options ...] <host/ip address> [ <home directory> ]\n",
X    program_name);
X  (void) fprintf(stderr,"\nWhere options include:\n");
X  for (p=options; *p; p++)
X    (void) fprintf(stderr,"  %s\n",*p);
X  exit(1);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W a i t                                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function Wait reads a line of output from the remote FTP server.
%
%  The format of the Wait() routine is:
%
%    response=Wait()
%
%  A description of each parameter follows:
%
%    o response:  Function Wait returns this pointer to the output obtained
%      from the remote FTP server.
%
%
*/
char *Wait()
{
X  register char
X    *p;
X
X  static char
X    buffer[1024],
X    *q;
X
X  static char
X    line[1024];
X
X  static int
X    count=0;
X
X  p=line;
X  do
X  {
X    if (count <= 0)
X      {
X        /*
X          The buffer is empty;  read output from the remote FTP server.
X        */
X        count=read(master,buffer,sizeof(buffer));
X        q=buffer;
X        if (count <= 0)
X          {
X            if (p == line)
X              return((char *) NULL);
X            break;
X          }
X      }
X    count--;
X    *p=(*q++);
X    if (*p == '\n')
X      break;
X    p++;
X    if ((p-line) >= 5)
X      if (!strncmp(p-5,"ftp> ",5))
X        if (count == 0)
X          return((char *) NULL);
X  } while (p < (line+sizeof(line)));
X  *p=(char) NULL;
X  return(line);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   m a i n                                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
main(argc,argv)
int
X  argc;
X
register char
X  **argv;
{
#include <pwd.h>
X
X  char
X    command[256],
X    *ident,
X    *home_directory,
X    *hostname,
X    *send_expression,
X    *user;
X
X  extern char
X    *getpass();
X
X  int
X    binary,
X    child,
X    status;
X
X  register char
X    *p,
X    *response;
X
X  unsigned int
X    timeout,
X    verbose;
X
X  /*
X    Initialize program variables.
X  */
X  binary=False;
X  directory_expression=(RegularExpression *) NULL;
X  exclude_expression=(RegularExpression *) NULL;
X  ident=(char *) NULL;
X  print_expression=(RegularExpression *) NULL;
X  retrieve_expression=(RegularExpression *) NULL;
X  send_expression=(char *) NULL;
X  timeout=0;
X  user=(char *) NULL;
X  program_name=argv[0];
X  verbose=False;
X  /*
X    Parse command line arguments.
X  */
X  for (p=(*argv++); *argv && (**argv == '-'); argv++)
X    switch (argv[0][1])
X    {
X      case 'b':
X      {
X        binary=True;
X        break;
X      }
X      case 'd':
X      {
X        directory_expression=CompileRegularExpression(*++argv);
X        if (!directory_expression)
X          exit(1);
X        break;
X      }
X      case 'e':
X      {
X        exclude_expression=CompileRegularExpression(*++argv);
X        if (!exclude_expression)
X          exit(1);
X        break;
X      }
X      case 'i':
X      {
X        ident=(*++argv);
X        break;
X      }
X      case 'p':
X      {
X        print_expression=CompileRegularExpression(*++argv);
X        if (!print_expression)
X          exit(1);
X        break;
X      }
X      case 'r':
X      {
X        retrieve_expression=CompileRegularExpression(*++argv);
X        if (!retrieve_expression)
X          exit(1);
X        break;
X      }
X      case 's':
X      {
X        send_expression=(*++argv);
X        break;
X      }
X      case 't':
X      {
X        timeout=atoi(*++argv);
X        break;
X      }
X      case 'u':
X      {
X        user=(*++argv);
X        break;
X      }
X      case 'v':
X      {
X        verbose=True;
X        break;
X      }
X      default:
X      {
X        Usage((char *) NULL);
X        break;
X      }
X    }
X  if ((argc < 2) || (*argv == (char *) NULL))
X    Usage((char *) NULL);
X  hostname=argv[0];
X  home_directory=argv[1];
X  if ((directory_expression == (RegularExpression *) NULL) &&
X      (print_expression == (RegularExpression *) NULL) &&
X      (retrieve_expression == (RegularExpression *) NULL) &&
X      (send_expression == (char *) NULL))
X    directory_expression=CompileRegularExpression("");
X  if ((ident == (char *) NULL) && (user == (char *) NULL))
X    {
X      int
X        uid;
X
X      static char
X        name[256];
X
X      struct passwd
X        *user_info;
X
X      /*
X        Identify user as user at host.domain.
X      */
X      uid=geteuid();
X      user_info=getpwuid(uid);
X      if (user_info == (struct passwd *) NULL)
X        (void) strcpy(name,"anonymous");
X      else
X        (void) strcpy(name,user_info->pw_name);
X      p=name+strlen(name);
X      *p++='@';
X      (void) gethostname(p,64);
X      while (*p)
X        p++;
X      *p++='.';
X      (void) getdomainname(p,64);
X      user="anonymous";
X      ident=name;
X    }
X  else
X    if (ident == (char *) NULL)
X      ident=(char *) getpass("Password: ");
X    else
X      if (user == (char *) NULL)
X        user="anonymous";
X  (void) GetHostInfo(hostname);
X  if (!home_directory)
X    (void) fprintf(stdout,"\n");
X  else
X    (void) fprintf(stdout,"%s\n",home_directory);
X  (void) GetPseudoTerminal();
X  /*
X    Connect and logon to host.
X  */
X  (void) signal(SIGCHLD,SignalChild);
X  if (timeout > 0)
X    (void) alarm(timeout);  /* enable timer. */
X  child=fork();
X  if (child < 0)
X    Error("fork");
X  if (child == 0)
X    ExecuteFtp(hostname);
X  while (response=Wait())
X    (void) fprintf(stderr,"%s\n",response);
X  (void) sprintf(command,"user %s %s\n",user,ident);
X  (void) write(master,command,(int) strlen(command));
X  while (response=Wait())
X    (void) fprintf(stderr,"%s\n",response);
X  if (timeout > 0)
X    (void) alarm(timeout*100);
X  (void) fprintf(stderr,"\n");
X  if (!verbose)
X    {
X      (void) strcpy(command,"verbose off\n");
X      (void) write(master,command,(int) strlen(command));
X      while (response=Wait());
X    }
X  if (home_directory)
X    {
X      /*
X        Change remote working directory.
X      */
X      (void) sprintf(command,"cd %s\n",home_directory);
X      (void) write(master,command,(int) strlen(command));
X      while (response=Wait());
X      (void) strcpy(command,"pwd\n");
X      (void) write(master,command,(int) strlen(command));
X      while (response=Wait())
X        (void) fprintf(stderr,"%s\n",response);
X    }
X  if (binary)
X    {
X      /*
X        Set file transfer type.
X      */
X      (void) strcpy(command,"binary\n");
X      (void) write(master,command,(int) strlen(command));
X      while (Wait());
X      (void) strcpy(command,"type\n");
X      (void) write(master,command,(int) strlen(command));
X      while (response=Wait())
X        (void) fprintf(stderr,"%s\n",response);
X    }
X  (void) strcpy(command,"runique\n");
X  (void) write(master,command,(int) strlen(command));
X  while (Wait());
X  if (send_expression == (char *) NULL)
X    ProcessRequest();
X  else
X    {
X      /*
X        Process send request.
X      */
X      (void) strcpy(command,"glob on\n");
X      (void) write(master,command,(int) strlen(command));
X      while (Wait());
X      (void) sprintf(command,"mput %s\n",send_expression);
X      (void) write(master,command,(int) strlen(command));
X      while (response=Wait())
X        (void) fprintf(stderr,"%s\n",response);
X    }
X  (void) strcpy(command,"quit\n");
X  (void) write(master,command,(int) strlen(command));
X  /*
X    Wait for child to finish.
X  */
X  (void) signal(SIGCHLD,SIG_DFL);
X  while (child != wait((union wait *) &status));
X  (void) close(master);
X  (void) free((char *) directory_expression);
X  (void) free((char *) exclude_expression);
X  (void) free((char *) print_expression);
X  (void) free((char *) retrieve_expression);
X  return(False);
}
X
SHAR_EOF
chmod 0755 ImageMagick/xtp/xtp.c ||
echo 'restore of ImageMagick/xtp/xtp.c failed'
Wc_c="`wc -c < 'ImageMagick/xtp/xtp.c'`"
test 37231 -eq "$Wc_c" ||
	echo 'ImageMagick/xtp/xtp.c: original size 37231, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/xtp/xtp.man ==============
if test -f 'ImageMagick/xtp/xtp.man' -a X"$1" != X"-c"; then
	echo 'x - skipping ImageMagick/xtp/xtp.man (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/xtp/xtp.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/xtp/xtp.man' &&
.ad l
.nh
.TH XTP 1 "16 June 1990"
.SH NAME
xtp - file transfer program
.SH SYNOPSIS
.B "xtp"
[ \fI-options\fP ... ] \fI<host/ip address>\fP \fI<home directory>\fP
.SH DESCRIPTION
.PP
.I Xtp
is a utility for retrieving, listing, or printing files from a remote
network site, or sending files to a remote network site.
.I Xtp
performs most of the same functions as the \fIftp\fP program, but does
not require any interactive commands.  You simply specify the file transfer
task on the command line and \fIxtp\fP performs the task automatically.
.SH EXAMPLES
.PP
To retrieve file display.tar.Z from host wizard.dupont.com, use:
.PP
X     xtp -binary -retrieve display.tar.Z wizard.dupont.com
.PP
To retrieve all the files from directory \fIpublic/documents\fP from host 
wizard.dupont.com, use:
.PP
X     xtp -binary -retrieve documents/ wizard.dupont.com public
.PP
.SH OPTIONS
.TP
.B "-binary"
retrieve files as binary.
.TP
.B "-exclude \fIexpression\fP"
exclude files that match the \fIregular expression\fP.
.TP
.B "-directory \fIexpression\fP"
list the names of files and their attributes that match the 
\fIregular expression\fP.
.TP
.B "-ident \fIpassword\fP"
specifies password.
.TP
.B "-print \fIexpression\fP"
print files that match the \fIregular expression\fP.
.TP
.B "-retrieve \fIexpression\fP"
retrieve files that match the \fIregular expression\fP.
X
Retrieved files are stored on your local host directory as the full
name of the retrieved file.  For example, if the retrieved file is
named \fIdocuments/xtp.man\fP on the remote FTP server, it will appear
in your home directory as \fIdocuments/xtp.man\fP.
.TP
.B "-send \fIexpression\fP"
send files that match the \fIregular expression\fP.
.TP
.B "-timeout \fIseconds\fP"
specifies maximum seconds to logon to the remote FTP server.  If this time
expires, the program terminates.
.TP
.B "-user \fIname\fP"
identify yourself to the remote FTP server.
.PP
If \fB-user\fP is specified but not \fB-ident\fP, the password is obtained
from you interactively.
.PP
If neither \fB-print\fP, \fB-retrieve\fP, or \fB-send\fp are specified
on the command line, a directory of files is listed for the remote
network host.
.PP
Filename searching begins at the home directory.  Some remote hosts
may have thousands of files causing a significant delay satisfying
your request.  You can reduce the searching required by specifying
\fI<home directory>\fP on the command line.  This limits the filename
search to the specified directory and any of its subdirectories.
.PP
If only the program name is specified on the command line, the program command
syntax and options are listed.
.SH REGULAR EXPRESSIONS
A \fIregular expression\fP is zero or more branches, separated by
\fB|\fP.  It matches anything that matches one of the branches.
.PP
A branch is zero or more pieces, concatenated.  It matches a match for
the first, followed by a match for the second, etc.
.PP
A piece is an atom possibly followed by \fB*\fP, \fB+\fP, or \fB?\fP.
An atom followed by \fB*\fP matches a sequence of 0 or more matches of
the atom.  An atom followed by \fB+\fP matches a sequence of 1 or more
matches of the atom.  An atom followed by \fB?\fP matches a match of
the atom, or the null pattern.
.PP
An atom is a \fIregular expression\fP in parentheses (matching a match
for the \fIregular expression\fP), a range (see below), \fB.\fP
(matching any single character), \fB^\fP (matching the null pattern at
the beginning of the input pattern), \fB$\fP (matching the null pattern
at the end of the input pattern), a \fB\'\fP followed by a single
character (matching that character), or a single character with no
other significance (matching that character).
.PP
A range is a sequence of characters enclosed in \fB[]\fP.  It normally
matches any single character from the sequence.  If the sequence begins
with \fB^\fP, it matches any single character not from the rest of the
sequence.  If two characters in the sequence are separated by \fB-\fP,
this is shorthand for the full list of ASCII characters between them
(e.g.  \fB[0-9]\fP matches any decimal digit). To include a literal
\fB]\fP in the sequence, make it the first character (following a
possible \fB^\fP).  To include a literal \fB-\fP, make it the first or
last character.
.SH SEE ALSO
ftp(1C)
.SH COPYRIGHT
Copyright 1990 E. I. Dupont de Nemours & Company
.PP
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of E. I. Dupont de Nemours
& Company not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.  E. I. Dupont de Nemours & Company makes no representations
about the suitability of this software for any purpose.  It is provided
"as is" without express or implied warranty.
.PP
E. I. Dupont de Nemours & Company disclaims all warranties with regard
to this software, including all implied warranties of merchantability
and fitness, in no event shall E. I. Dupont de Nemours & Company be
liable for any special, indirect or consequential damages or any
damages whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action, arising
out of or in connection with the use or performance of this software.
.SH ACKNOWLEDGEMENTS
Steve Singles, University of Delaware, for the initial implementation of
this program.
.PP
Henry Spencer, University of Toronto, for the implementation of the
\fIregular expression\fP interpreter and the text in \fBREGULAR
EXPRESSIONS\fP.
.SH AUTHOR
John Cristy, E.I. DuPont De Nemours & Company Incorporated
X
X
SHAR_EOF
chmod 0755 ImageMagick/xtp/xtp.man ||
echo 'restore of ImageMagick/xtp/xtp.man failed'
Wc_c="`wc -c < 'ImageMagick/xtp/xtp.man'`"
test 5832 -eq "$Wc_c" ||
	echo 'ImageMagick/xtp/xtp.man: original size 5832, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/image.c ==============
if test -f 'ImageMagick/image.c' -a X"$1" != X"-c"; then
	echo 'x - skipping ImageMagick/image.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/image.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/image.c' &&
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%                     IIIII  M   M   AAA   GGGG  EEEEE                        %
%                       I    MM MM  A   A G      E                            %
%                       I    M M M  AAAAA G  GG  EEE                          %
%                       I    M   M  A   A G   G  E                            %
%                     IIIII  M   M  A   A  GGGG  EEEEE                        %
%                                                                             %
%                                                                             %
%                    Utiltity Image Routines for Display                      %
%                                                                             %
%                                                                             %
%                                                                             %
%                           Software Design                                   %
%                             John Cristy                                     %
%                            January  1991                                    %
%                                                                             %
%                                                                             %
%  Copyright 1991 E. I. Dupont de Nemours & Company                           %
%                                                                             %
%  Permission to use, copy, modify, distribute, and sell this software and    %
%  its documentation for any purpose is hereby granted without fee,           %
%  provided that the above Copyright notice appear in all copies and that     %
%  both that Copyright notice and this permission notice appear in            %
%  supporting documentation, and that the name of E. I. Dupont de Nemours     %
%  & Company not be used in advertising or publicity pertaining to            %
%  distribution of the software without specific, written prior               %
%  permission.  E. I. Dupont de Nemours & Company makes no representations    %
%  about the suitability of this software for any purpose.  It is provided    %
%  "as is" without express or implied warranty.                               %
%                                                                             %
%  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
%  to this software, including all implied warranties of merchantability      %
%  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
%  liable for any special, indirect or consequential damages or any           %
%  damages whatsoever resulting from loss of use, data or profits, whether    %
%  in an action of contract, negligence or other tortious action, arising     %
%  out of or in connection with the use or performance of this software.      %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%
*/
#include "display.h"
#include "image.h"
#include "X.h"
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   C l i p I m a g e                                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function ClipImage creates a new image that is a subregion of an existing
%  one.  It allocates the memory necessary for the new Image structure and
%  returns a pointer to the new image.  The pixels are copied from the source
%  image as defined by the region formed from x_offset, y_offset, width, and
%  height.
%
%  The format of the ClipImage routine is:
%
%      clipped_image=ClipImage(image,x_offset,y_offset,width,height)
%
%  A description of each parameter follows:
%
%    o clipped_image: Function ClipImage returns a pointer to the clipped
%      image.  A null image is returned if there is a a memory shortage or
%      if the image width or height is zero.
%
%    o image: The address of a structure of type Image.
%
%    o x_offset: An integer that specifies the column offset of the
%      clipped image.
%
%    o y_offset: An integer that specifies the row offset of the clipped
%      image.
%
%    o width: An integer that specifies the number of width in the clipped
%      image.
%
%    o height: An integer that specifies the number of height in the clipped
%      image.
%
%
*/
Image *ClipImage(image,x_offset,y_offset,width,height)
Image
X  *image;
X
int
X  x_offset,
X  y_offset;
X
unsigned int
X  width,
X  height;
{
X  Image
X    *clipped_image,
X    *CopyImage();
X
X  register int
X    x,
X    y;
X
X  register RunlengthPacket
X    *p,
X    *q;
X
X  void
X    DestroyImage();
X
X  /*
X    Check clip geometry.
X  */
X  if ((width*height) == 0)
X    {
X      Warning("unable to clip image","image size is zero");
X      return((Image *) NULL);
X    }
X  if (((x_offset+(int) width) < 0) || ((y_offset+(int) height) < 0) ||
X      (x_offset > (int) image->columns) || (y_offset > (int) image->rows))
X    {
X      Warning("unable to clip image","geometry does not contain image");
X      return((Image *) NULL);
X    }
X  if ((x_offset+(int) width) > (int) image->columns)
X    width=(unsigned int) ((int) image->columns-x_offset);
X  if ((y_offset+(int) height) > (int) image->rows)
X    height=(unsigned int) ((int) image->rows-y_offset);
X  if (x_offset < 0)
X    {
X      width-=(unsigned int) (-x_offset);
X      x_offset=0;
X    }
X  if (y_offset < 0)
X    {
X      height-=(unsigned int) (-y_offset);
X      y_offset=0;
X    }
X  /*
X    Initialize clipped image attributes.
X  */
X  clipped_image=CopyImage(image,width,height);
X  if (clipped_image == (Image *) NULL)
X    {
X      Warning("unable to clip image","memory allocation failed");
X      return((Image *) NULL);
X    }
X  /*
X    Skip pixels up to the clipped image.
X  */
X  p=image->pixels;
X  image->runlength=p->length+1;
X  for (x=0; x < (y_offset*(int) image->columns+x_offset); x++)
X    if (image->runlength > 0)
X      image->runlength--;
X    else
X      {
X        p++;
X        image->runlength=p->length;
X      }
X  /*
X    Extract clipped image.
X  */
X  clipped_image->packets=0;
X  q=clipped_image->pixels;
X  q->length=MaxRunlength;
X  for (y=0; y < clipped_image->rows; y++)
X  {
X    /*
X      Transfer scanline.
X    */
X    for (x=0; x < clipped_image->columns; x++)
X    {
X      if (image->runlength > 0)
X        image->runlength--;
X      else
X        {
X          p++;
X          image->runlength=p->length;
X        }
X      if ((p->red == q->red) && (p->green == q->green) &&
X          (p->blue == q->blue) && (q->length < MaxRunlength))
X        q->length++;
X      else
X        {
X          if (clipped_image->packets > 0)
X            q++;
X          clipped_image->packets++;
X          q->red=p->red;
X          q->green=p->green;
X          q->blue=p->blue;
X          q->index=p->index;
X          q->length=0;
X        }
X    }
X    /*
X      Skip to next scanline.
X    */
X    for (x=0; x < (image->columns-clipped_image->columns); x++)
X      if (image->runlength > 0)
X        image->runlength--;
X      else
X        {
X          p++;
X          image->runlength=p->length;
X        }
X  }
X  clipped_image->pixels=(RunlengthPacket *) realloc((char *)
X    clipped_image->pixels,clipped_image->packets*sizeof(RunlengthPacket));
X  return(clipped_image);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   C o p y I m a g e                                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Function CopyImage returns a copy of all fields of the input image.  The
%  the pixel memory is allocated but the pixel data is not copied.
%
%  The format of the CopyImage routine is:
%
%      copy_image=CopyImage(image,columns,rows)
%
%  A description of each parameter follows:
%
%    o copy_image: Function CopyImage returns a pointer to the image after
%      copying.  A null image is returned if there is a memory shortage.
%
%    o image: The address of a structure of type Image.
%
%    o columns: An integer that specifies the number of columns in the copied
%      image.
%
%    o rows: An integer that specifies the number of rows in the copied
%      image.
%
%
*/
Image *CopyImage(image,columns,rows)
Image
X  *image;
X
unsigned int
X  columns,
X  rows;
{
X  Image
X    *copy_image;
X
X  register int
X    i;
X
X  /*
X    Allocate image structure.
X  */
X  copy_image=(Image *) malloc(sizeof(Image));
X  if (copy_image == (Image *) NULL)
X    return((Image *) NULL);
X  *copy_image=(*image);
X  copy_image->compression=RunlengthEncodedCompression;
X  copy_image->columns=columns;
X  copy_image->rows=rows;
X  if (image->colormap != (ColorPacket *) NULL)
X    {
X      /*
X        Allocate and copy the image colormap.
X      */
X      copy_image->colormap=(ColorPacket *)
X        malloc(image->colors*sizeof(ColorPacket));
X      if (copy_image->colormap == (ColorPacket *) NULL)
X        return((Image *) NULL);
X      for (i=0; i < image->colors; i++)
X        copy_image->colormap[i]=image->colormap[i];
X    }
X  /*
X    Allocate but do not copy the image pixels.
X  */
X  copy_image->packets=copy_image->columns*copy_image->rows;
X  copy_image->pixels=(RunlengthPacket *)
X    malloc(copy_image->packets*sizeof(RunlengthPacket));
X  if (copy_image->pixels == (RunlengthPacket *) NULL)
X    return((Image *) NULL);
X  if (image->comments != (char *) NULL)
X    {
X      /*
X        Allocate and copy the image comments.
X      */
X      copy_image->comments=(char *)
X        malloc((unsigned int) ((strlen(image->comments)+1)*sizeof(char)));
X      if (copy_image->comments == (char *) NULL)
X        return((Image *) NULL);
X      (void) strcpy(copy_image->comments,image->comments);
X    }
X  return(copy_image);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SHAR_EOF
true || echo 'restore of ImageMagick/image.c failed'
fi
echo 'End of ImageMagick part 3'
echo 'File ImageMagick/image.c is continued in part 4'
echo 4 > _shar_seq_.tmp
exit 0
--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources-x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list