home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume39 / ncftp / part01 next >
Encoding:
Text File  |  1993-08-25  |  60.5 KB  |  2,488 lines

  1. Newsgroups: comp.sources.misc
  2. From: mgleason@cse.unl.edu (Mike Gleason)
  3. Subject: v39i053:  ncftp - Alternative User Interface for FTP, v1.5.0, Part01/05
  4. Message-ID: <csm-v39i053=ncftp.190257@sparky.Sterling.COM>
  5. X-Md4-Signature: 5cb695d03cf85312bdbf67b868043c0d
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: NCEMRSoft
  8. Date: Thu, 26 Aug 1993 00:03:44 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: mgleason@cse.unl.edu (Mike Gleason)
  12. Posting-number: Volume 39, Issue 53
  13. Archive-name: ncftp/part01
  14. Environment: UNIX, ANSI-C, !SVR4
  15. Supersedes: ncftp: Volume 35, Issue 4-7
  16.  
  17. NcFTP - Alternative user interface for FTP
  18. Version 1.5.0 by Mike Gleason, NCEMRSoft.
  19.  
  20. I used to list the features of ncftp in this blurb, but there are just
  21. too many to list.  Even if you only ftp occasionally, it is worth your
  22. time to install ncftp (or atleast bug your sysadmin to).  If you won't take
  23. my word for it, just ask around, or extract this archive and read the
  24. man page.
  25.  
  26. Note:  May not work correctly with System V R 4 (and Solaris 2.2).
  27. Note:  YOU WON'T FIND THIS in my ftp directory on cse.unl.edu.  I will
  28.   put it there in one week.
  29.  
  30. Major changes since 1.0.2:
  31.  
  32. * Supports the Getline (input-edit) and GNU Readline command-line
  33.   editing and history libraries.
  34.  
  35. * Supports the Socks firewall library, and another firewall gateway
  36.   implementation.
  37.  
  38. * Terrific new "recent-sites" file that automatically saves the
  39.   sites you call;  when you open a site in the recent-sites file
  40.   (of course you can abbreviate the names), you start in the
  41.   same directory you were in last time.
  42.  
  43. * Improved on-line help, and tips on how to use the program better
  44.   are printed each time you run the program.
  45.  
  46. * Rewritten man page.
  47.  
  48. * Faster ascii transfers.
  49.  
  50. * Typing 'open' by itself lists all the sites the program knows
  51.   about (the ones in your .netrc and the recent-sites list) so
  52.   you can just pick one.
  53.  
  54. * Enhanced colon-mode, that can dump a file to stdout (ftpcat mode)
  55.   or to a pager.  (i.e. ncftp -c wu:/README >/dev/null).
  56.  
  57. * You can choose whether an open is anonymous by default (like it
  58.   had always been) or a user login by default by setting a new
  59.   program variable.
  60.  
  61. * Bugs fixed.
  62.  
  63. Read the enclosed file, v2_Notes, which explains why I won't be
  64. able to work on the nearly finished, and much improved v2.0.
  65. -------
  66. #! /bin/sh
  67. # This is a shell archive.  Remove anything before this line, then feed it
  68. # into a shell via "sh file" or similar.  To overwrite existing files,
  69. # type "sh file -c".
  70. # Contents:  README cmds.c cmds.h open.h
  71. # Wrapped by kent@sparky on Wed Aug 25 18:59:16 1993
  72. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  73. echo If this archive is complete, you will see the following message:
  74. echo '          "shar: End of archive 1 (of 5)."'
  75. if test -f 'README' -a "${1}" != "-c" ; then 
  76.   echo shar: Will not clobber existing file \"'README'\"
  77. else
  78.   echo shar: Extracting \"'README'\" \(11962 characters\)
  79.   sed "s/^X//" >'README' <<'END_OF_FILE'
  80. XIf you are a novice user, and don't know how to compile things, try
  81. Xcontacting your local guru first (get them to do it for you :-).  Please
  82. Xunderstand that I don't have time to walk newbies through the whole
  83. Xinstallation procedure.
  84. X
  85. X1. READ this entire file.  Part A, below, tells what to do if you want to
  86. X   use NcFTP with a command-line editor.  Part B tells you how to configure
  87. X   the Makefile to compile the program for your system.  Part C tells you
  88. X   how to configure NcFTP's optional features.  Part D tells you how to
  89. X   contact me if you want to report a bug or submit new code to the
  90. X   program.
  91. X
  92. X2. EDIT the Makefile, making any necessary changes described in parts
  93. X   A, B, or C.  Don't forget to read the directions in the Makefile,
  94. X   so you don't forget any needed libraries, etcetera.
  95. X
  96. X3. You can also change the program's default behavior by editing defaults.h.
  97. X   99% of the time you don't need to do this, so you can skip this step.
  98. X
  99. XIf you have problems, you can mail me, but please try your best to install
  100. Xit without my help.  I'm quite tired of responding to lazy SunOS users
  101. Xbecause they didn't bother reading the directions so that they would have
  102. Xknown that they needed to use GCC.  
  103. X
  104. XI _do_ want to hear from you if you have comments or bug reports/fixes.  I
  105. Xwould also like to hear from you if you had a system that wasn't covered
  106. Xin sys.h, so I can add an entry for other users of your system.
  107. X
  108. XThe latest version of ncftp is available in the directory:
  109. X    cse.unl.edu:/pub/mgleason
  110. XThis machine is heavily used by students and faculty alike, so please
  111. Xdo not call during working hours (9AM - 5PM American Central time).  In fact,
  112. XI have a cron entry that changes all the file permissions to public
  113. Xunreadable during that period, so you won't be able to download anyway.
  114. X
  115. XI am grateful to Shari Deiana and the University of Nebraska for making this
  116. Xpossible!
  117. X
  118. X
  119. XPart A.  Installing with a command line editor:
  120. X----------------------------------------------
  121. X
  122. XAs of this release, GNU Readline and Chris Thewalt's Getline command-line
  123. Xediting and history facilities are supported.  Neither are included with the
  124. Xncftp sources.  You can find Getline at:
  125. X  ce.berkeley.edu:/pub/thewalt/getline.tar.Z  (note: use 'ls', not 'dir!')
  126. Xand Readline is in the directory:
  127. X  prep.ai.mit.edu:/pub/gnu
  128. X
  129. XTo install Readline, you will need to know where libreadline.a and the
  130. Xheader <readline/readline.h> are.  You will need to link libreadline.a and
  131. Xlibcurses.a (or libtermcap.a) with ncftp (see the Makefile).  Good luck on
  132. Xtrying to compile it.  It is not an easy thing to do!  In the Makefile, you
  133. Xwill need to add -DREADLINE to PDEFS, add -lreadline -lcurses to LIBS, and
  134. Xedit the HDRDIRS and LIBDIRS lines.  This stuff is already in the Makefile,
  135. Xso you can just uncomment it.
  136. X
  137. XTo install Getline, you need to know where libgetline.a and it's header
  138. X(getline.h) are.  In the Makefile, you'll need to add -lgetline to LIBS and
  139. Xedit the HDRDIRS and LIBDIRS lines.  This stuff is already in the Makefile,
  140. Xso you can just uncomment it.
  141. X
  142. XDO NOT bug me if you can't figure out how to compile Getline or Readline.
  143. XContact their respective authors instead.  It is not essential that you use
  144. Xthem.
  145. X
  146. X
  147. XPart B.  System Dependencies:
  148. X----------------------------
  149. X
  150. XNcFTP may need work-arounds for some things due to the differences
  151. Xin implementations of unix.  The following systems are taken care
  152. Xof automatically.  For these systems, you should just be able to type
  153. X'make' (but proceed to part C):
  154. X
  155. X   Silicon Graphics IRIX
  156. X   AIX
  157. X   SINIX
  158. X   Ultrix
  159. X   NeXT
  160. X   Pyramid OSx
  161. X
  162. XOtherwise you will have to configure ncftp manually.
  163. X
  164. XYou will need to add these things to the SDEFS line in the Makefile
  165. Xas applicable.  As an example, if I say 'add -DFoobar to SDEFS,' find
  166. Xthe line in the Makefile that reads 'SDEFS=' (or 'SDEFS=-DFoo2') and
  167. Xchange it to 'SDEFS=-DFoobar' (or 'SDEFS=-DFoo2 -DFoobar).  If your
  168. Xsystem is listed below, follow the directions and then you ready to
  169. Xgo to part C, below.
  170. X
  171. X    Sun Microsystems' SunOS/Solaris:  Use an ANSI compiler such as
  172. X      gcc (set CC=gcc in the Makefile), or acc (set CC=acc).
  173. X      The regular 'cc' is not an ANSI compiler.  You could also run
  174. X      something like 'ansi2knr' on the sources and hope it works.
  175. X
  176. X    Hewlett-Packard HP-UX:  If you have 7.0, you'll need to find
  177. X      a copy of <ftp.h> from somewhere (8.0 has it though). Then
  178. X      set CFLAGS= -Aa.  You may also need to use gcc if your
  179. X      compiler is non-ANSI.
  180. X
  181. X    SCO Unix:  Add -DSCO324 to SDEFS, and -lsocket to LIBS.
  182. X
  183. X    Bull DPX/2: Add -DBULL to SDEFS, add -linet to LIBS, and
  184. X      use gcc.
  185. X
  186. X    Sequent's DYNIX: Use gcc and add -DDYNIX (if necessary) to SDEFS.
  187. X      You may also be short several string functions which you will
  188. X      have to get elsewhere.
  189. X
  190. XIf your system doesn't fit any of those, things will be trickier.  Answer
  191. Xall these questions and add to the SDEFS line.  You may want to try
  192. Xeach option one at a time until everything works.
  193. X
  194. X*  Is your system closer to System V or BSD?  Your SDEFS line should have
  195. Xeither -DBSD or -DSYSV.  If you don't know, try leaving it blank first;
  196. Xsome compilers automatically define it for you.
  197. X
  198. X*  Add -DNO_CONST if your compiler chokes on the const directive.  You
  199. Xwill know if you need to add this if the compiler spits out errors saying
  200. Xit doesn't know what 'const' is.
  201. X
  202. X*  Add -DSYSSELECTH if you need <sys/select.h> included for definitions
  203. Xof fd_set, etc.
  204. X
  205. X*  Add -DNO_UNISTDH if you don't have <unistd.h>.  If the compiler complains
  206. Xabout not being able to open <unistd.h> add this.
  207. X
  208. X*  Add -DNO_STDLIBH if you don't have <stdlib.h>.  If the compiler complains
  209. Xabout not being able to open <stdlib.h> add this.
  210. X
  211. X*  Add -DNO_UTIMEH if you don't have <utime.h>.  If the compiler complains
  212. Xabout not being able to open <utime.h> add this.
  213. X
  214. X*  Add -DGETPASS if you would rather use the standard getpass() system
  215. Xcall, instead of our version, Getpass(), which takes more than 8
  216. Xcharacters.  You may want to define this if you are having problems
  217. Xcompiling getpass.c.
  218. X
  219. XIf you haven't given up on our Getpass(), you can try adding -DSGTTYB
  220. Xif you want to use a struct sgttyb instead of a struct termio.  By default,
  221. XBSD systems define SGTTYB automatically.  You can also try adding -DTERMIOS
  222. Xto use a POSIX compliant struct termios instead.  Don't pull your hair out
  223. Xtrying to get the Getpass code to compile;  if it gives you problems just
  224. Xdefine -DGETPASS and hope your system's getpass can handle passwords
  225. Xlonger than 8 characters.
  226. X
  227. X*  Add -DBAD_INETADDR if your inet_addr() function returns a struct in_addr
  228. Xinstead of a u_long, as it should (in DG/UX 5.4.1).
  229. X
  230. X*  Add -DBROKEN_MEMCPY if ncftp mysteriously dumps core when trying to open
  231. Xa remote host.  I'm told that this happens because of some problem in System
  232. XV's sockets don't like fprintf (and memcpy).
  233. X
  234. X*  (Optional) Add -DGETCWDSIZET if your system's getcwd() takes a size_t
  235. Xas the second parameter instead of an int.
  236. X
  237. X*  (Optional) Add -DHERROR if you know you have the herror() system
  238. Xcall.
  239. X
  240. X*  (Optional) Add -DU_WAIT if you know your wait system call takes
  241. Xa pointer to a 'union wait.'  Defined automatically if you define
  242. XBSD.
  243. X
  244. X*  (Optional) Add -DHOSTNAME=\"machine.domain.nam\" if your system
  245. Xdoesn't generate it's own hostname.  To check this, compile ncftp
  246. Xthen run it and type 'set.'  Look at the variable anon-password.
  247. XIf the hostname is wrong, or if it is in the form of 'yourlogin' or
  248. X'yourlogin@machine' instead of 'yourlogin@machine.xxx.yyy,'
  249. Xre-compile it with HOSTNAME set to your machine's address, in the
  250. Xform of 'machine.xxx.yyy.'
  251. X
  252. X*  (Optional) Add -DSTRICT_PROTOS if your compiler wants function prototypes
  253. Xfor all functions, not just non-int-returning ones.
  254. X
  255. X
  256. XPart C.  Program Options:
  257. X------------------------
  258. X
  259. XAdd these as applicable to the PDEFS line in the Makefile.
  260. X
  261. X*   -DCURSES:  Uses curses library to display boldface, underline, etc.
  262. X    By default ncftp uses hard-coded ANSI escapes (^[[1m etc.) to
  263. X    save the 100k or so the curses library adds.  You will also need
  264. X    to edit the LIBS line in the Makefile to add -lcurses.
  265. X
  266. X*   -DSYSLOG:  Define this to have ncftp log connections and transfers
  267. X    to the syslog.
  268. X
  269. X*   -DNO_TIPS:  Define if you want to cut a little fat at the expense of
  270. X     novice users.
  271. X
  272. X*   -DGETLINE: If you want to use Chris Thewalt's getline input line editor
  273. X    and history facility, add this (and see below).
  274. X
  275. X*   -DREADLINE:  If you want to use GNU's readline input line editor and
  276. X    history facility, add this (and see the Makefile). If you do this, you
  277. X    also need to add -DCURSES (see above).
  278. X
  279. X*    -DSOCKS: NcFTP is now compatible with the Socks library by David Koblas,
  280. X    at koblas@sgi.com.  This lets you use NcFTP with a "firewall" gateway
  281. X    for enhanced site security.  You can get the latest version from
  282. X    netcom.com:/pub/koblas.  After you have compiled it, compile NcFTP
  283. X    with -DSOCKS added to PDEFS, and the pathname of the Rconnect.o file
  284. X    added to LIBS.
  285. X    
  286. X*   -DDB_ERRS:  Define this if you want my Perror() function to be more
  287. X    verbose.  You may want to do this if you are a programmer examining this
  288. X    code, and want to know where in the source the Perror's are coming
  289. X    from.
  290. X
  291. XPart D.  Sending me patches:
  292. X---------------------------
  293. X
  294. XI apologize in advance for problems that my coding style may cause.  The code
  295. Xitself is formatted such that each indent-level is a tab (intended to be
  296. Xequivalent to 4 spaces), and not spaces nor a combination of tabs and spaces.
  297. XThe reason for this, besides being more logical to me, is that I use a
  298. XMacintosh editor to compose the code and I prefer it's indenting method.
  299. XAnother problem in my coding-style is that I write C-code intended for ANSI
  300. XC compilers.  This means that I will use the new-style function declarations
  301. Xand function prototypes, like:
  302. X
  303. X
  304. X   long Foobar(long, long, char *);
  305. X   long Foobar(long t0, long t1, char *str)
  306. X   {
  307. X   }
  308. X
  309. Xas opposed to:
  310. X
  311. X   long Foobar();
  312. X   long Foobar(t0, t1, str)
  313. X       long t0, t1;
  314. X       char *str;
  315. X   {
  316. X   }
  317. X
  318. XAnother thing may annoy you is that I always use function prototypes for any
  319. Xfunction I call, including functions that return an int.  This is a good
  320. Xpractice that I learned from the Macintosh programming world.  
  321. X
  322. XSo if you send me patches, please conform to my coding style so that 'patch'
  323. Xwon't screw up, and also that some continuity will be preserved.
  324. X
  325. XBefore you make your patch, you should be sure that you are using the most
  326. Xcurrent version of the program.  This is especially important if you are
  327. Xreporting a bug; I may have already fixed it!  See the above info to get it
  328. Xvia ftp.  Major versions are always posted to comp.sources.misc.  Bug reports
  329. Xare posted to comp.sources.bugs.  Patches that need to be posted ASAP are
  330. Xposted to this group first, so it is advisable that you check this group.
  331. X
  332. XIf you make changes to the code, surround your code in #ifdef/#endif blocks.
  333. XInstead of doing things like #ifdef SunOS, use a name that describes the
  334. Xbug fix or feature, and not your system type, like #ifdef NO_UNISTDH,
  335. Xor #ifdef GETLINE.  That way in case another system has the same problem,
  336. Xit can be added to sys.h without cluttering up the source code.  Then, add
  337. Xthe symbol you used to the end of cmds.c, in the 'CPP Hell' part of the
  338. Xversion() command.  You'll see a list of CPP symbols, so just add yours in
  339. Xa similar fashion, like #ifdef GETLINE/DStrs[nDStrs++] = "GETLINE";/#endif.
  340. X
  341. XIf you don't know how to make a patch, here's how to do it.  Things are easy
  342. Xif you've only changed one file.  Then all you need to do pipe the output of
  343. Xdiff -c into a file and send it to me, i.e. "diff -c cmds.c cmds.c.hack >pch."
  344. XIf you've hacked several files, the way I do it is to keep the originals in
  345. Xone directory (you did make a copy of everything first didn't you?) and the
  346. Xrevisions in another directory.  Then you change directory to the one with the
  347. Xoriginals and do "diff -c . ../revisions > ../pch."
  348. X
  349. X--mg (mgleason@cse.unl.edu)
  350. END_OF_FILE
  351.   if test 11962 -ne `wc -c <'README'`; then
  352.     echo shar: \"'README'\" unpacked with wrong size!
  353.   fi
  354.   # end of 'README'
  355. fi
  356. if test -f 'cmds.c' -a "${1}" != "-c" ; then 
  357.   echo shar: Will not clobber existing file \"'cmds.c'\"
  358. else
  359.   echo shar: Extracting \"'cmds.c'\" \(38637 characters\)
  360.   sed "s/^X//" >'cmds.c' <<'END_OF_FILE'
  361. X/* cmds.c */
  362. X
  363. X/*  $RCSfile: cmds.c,v $
  364. X *  $Revision: 14020.14 $
  365. X *  $Date: 93/07/09 11:31:53 $
  366. X */
  367. X
  368. X#include "sys.h"
  369. X#include <sys/types.h>
  370. X#include <sys/param.h>
  371. X
  372. X#include <sys/wait.h>
  373. X
  374. X#include <sys/stat.h>
  375. X#include <sys/socket.h>
  376. X#include <arpa/ftp.h>
  377. X#include <setjmp.h>
  378. X#include <signal.h>
  379. X#include <string.h>
  380. X#include <errno.h>
  381. X#include <netdb.h>
  382. X#include <netinet/in.h>
  383. X#include <arpa/inet.h>
  384. X#include <ctype.h>
  385. X#include <sys/time.h>
  386. X#include <time.h>
  387. X
  388. X#ifdef SYSLOG
  389. X#    include <syslog.h>
  390. X#endif
  391. X
  392. X#ifndef NO_UNISTDH
  393. X#    include <unistd.h>
  394. X#endif
  395. X
  396. X#include "util.h"
  397. X#include "cmds.h"
  398. X#include "main.h"
  399. X#include "ftp.h"
  400. X#include "ftprc.h"
  401. X#include "getpass.h"
  402. X#include "glob.h"
  403. X#include "set.h"
  404. X#include "defaults.h"
  405. X#include "copyright.h"
  406. X
  407. X/* cmds.c globals */
  408. Xint                    curtype;            /* file transfer type */
  409. Xchar                *typeabbrs = "abiet";
  410. Xstr32                curtypename;        /* name of file transfer type */
  411. Xint                    verbose;             /* verbosity level of output */
  412. Xint                    mprompt;            /* interactively prompt on m* cmds */
  413. Xint                    debug;                /* debugging level */
  414. Xint                    options;            /* used during socket creation */
  415. Xint                    macnum;                /* number of defined macros */
  416. Xint                    paging = 0;
  417. Xint                    creating = 0;
  418. Xstruct macel        macros[MAXMACROS];
  419. Xchar                *macbuf;            /* holds ALL macros */
  420. Xjmp_buf                jabort;
  421. Xchar                *mname;                /* name of current m* command */
  422. Xint                    activemcmd;            /* flag: if != 0, then active multi command */
  423. Xint                    warnNoLSFlagsWithWildcards = 0;
  424. X                                        /* Tells whether the user has been
  425. X                                         * warned about not being able to use
  426. X                                         * flags with ls when using wildcards.
  427. X                                         */
  428. Xlongstring            cwd;                /* current remote directory */
  429. Xlongstring            lcwd;                /* current local directory */
  430. XHostname            lasthostname;        /* name of last host w/ lookup(). */
  431. Xint                    logged_in = 0;        /* TRUE if connected and user/pw OK. */
  432. Xint                    is_ls = 0;            /* are we doing an ls?  if so, then
  433. X                                           read input into a line buffer
  434. X                                           for re-use. */
  435. Xextern int                    buffer_only;
  436. Xstruct lslist               *lshead = NULL;    /* hold last output from host */
  437. Xstruct lslist               *lstail = NULL;
  438. X
  439. X/* cmds.c externs */
  440. Xextern char                    *globerr, *home, *reply_string;
  441. Xextern int                    margc, connected, ansi_escapes;
  442. Xextern int                    code, connected;
  443. Xextern int                    toatty, fromatty;
  444. Xextern int                    data, progress_meter, remote_is_unix;
  445. Xextern int                    parsing_rc, keep_recent;
  446. Xextern char                    *altarg, *line, *margv[];
  447. Xextern char                    *globchars;
  448. Xextern Hostname                hostname;
  449. Xextern string                progname, pager, anon_password;
  450. Xextern string                prompt, version, indataline;
  451. Xextern longstring            logfname;
  452. Xextern long                    logsize;
  453. Xextern size_t                xferbufsize;
  454. Xextern struct servent        serv;
  455. Xextern struct cmd            cmdtab[];
  456. Xextern struct userinfo        uinfo;
  457. Xextern FILE                    *cin, *cout, *logf;
  458. Xextern int                    Optind;
  459. Xextern char                    *Optarg;
  460. Xextern int                    Optind;
  461. Xextern char                    *Optarg;
  462. X
  463. X#ifdef STRICT_PROTOS
  464. Xextern int gethostname(char *, int), getdomainname(char *, int);
  465. X#endif
  466. X
  467. X
  468. Xstruct types types[] = {
  469. X    { "ascii",  "A",    TYPE_A, 0 },
  470. X    { "binary", "I",    TYPE_I, 0 },
  471. X    { "image",  "I",    TYPE_I, 0 },
  472. X    { "ebcdic", "E",    TYPE_E, 0 },
  473. X    { "tenex",  "L",    TYPE_L, "8" },
  474. X    0
  475. X};
  476. X
  477. X
  478. X
  479. Xlong GetDateAndSize(char *fName, unsigned long *mod_time)
  480. X{
  481. X    char *cp, *np;
  482. X    string lsline;
  483. X    long size = 0L;
  484. X    int n, v;
  485. X    struct lslist *saved;
  486. X    
  487. X    *mod_time = 0;
  488. X    v = verbose; verbose = V_QUIET;
  489. X    is_ls = 1;
  490. X    buffer_only = 1;
  491. X    saved = lshead;
  492. X    lshead = NULL;
  493. X    (void) recvrequest("LIST", "-", fName, "w");
  494. X    is_ls = 0;
  495. X    buffer_only = 0;
  496. X    verbose = v;
  497. X    if (lshead == NULL) {
  498. X        PurgeLineBuffer();
  499. X        lshead = saved;
  500. X        goto aa;
  501. X    }
  502. X    (void) Strncpy(lsline, lshead->string);
  503. X    PurgeLineBuffer();
  504. X    lshead = saved;
  505. X
  506. X    if (code >= 400 && code < 500)
  507. X        goto aa;
  508. X
  509. X    /* See if this line looks like a unix-style ls line. 
  510. X     * If so, we can grab the date and size from it.
  511. X     */    
  512. X    if (strpbrk(lsline, "-dlsbcp") == lsline) {
  513. X        /* See if it looks like a typical '-rwxrwxrwx' line. */
  514. X        cp = lsline + 1;
  515. X        if (*cp != 'r' && *cp != '-')
  516. X            goto aa;
  517. X        ++cp;
  518. X        if (*cp != 'w' && *cp != '-')
  519. X            goto aa;
  520. X        cp += 2;
  521. X        if (*cp != 'r' && *cp != '-')
  522. X            goto aa;
  523. X         /* skip mode, links, owner (and possibly group) */
  524. X         for (n = 0; n < 4; n++) {
  525. X             np = cp;
  526. X             while (*cp != '\0' && !isspace(*cp))
  527. X                 cp++;
  528. X             while (*cp != '\0' &&  isspace(*cp))
  529. X                 cp++;
  530. X         }
  531. X         if (!isdigit(*cp))
  532. X             cp = np;    /* back up (no group) */
  533. X         (void) sscanf(cp, "%ld%n", &size, &n);
  534. X         *mod_time = UnLSDate(cp + n + 1);
  535. X
  536. X        if (size < 100) {
  537. X            /* May be the size of a link to the file, instead of the file. */
  538. X            if ((cp = strstr(lsline, " -> ")) != NULL) {
  539. X                /* Yes, it was a link. */
  540. X                size = GetDateAndSize(cp + 4, mod_time); /* Try the file. */
  541. X            }
  542. X        }
  543. X    }    
  544. Xaa:
  545. X    return (size);
  546. X}    /* GetDateAndSize */
  547. X
  548. X
  549. X
  550. X
  551. Xint _settype(char *typename)
  552. X{
  553. X    register struct types    *p;
  554. X    int                        comret, c;
  555. X    string                    cmd;
  556. X    char                    *cp;
  557. X    c = isupper(*typename) ? tolower(*typename) : (*typename);
  558. X    if ((cp = index(typeabbrs, c)) != NULL)
  559. X        p = &types[(int) (cp - typeabbrs)];
  560. X    else {
  561. X        (void) printf("%s: unknown type\n", typename);
  562. X        return USAGE;
  563. X    }
  564. X    if (c == 't')
  565. X        (void) strcpy(cmd, "TYPE L 8");
  566. X    else    
  567. X        (void) sprintf(cmd, "TYPE %s", p->t_mode);
  568. X    comret = command(cmd);
  569. X    if (comret == COMPLETE) {
  570. X        (void) Strncpy(curtypename, p->t_name);
  571. X        curtype = p->t_type;
  572. X    }
  573. X    return NOERR;
  574. X}    /* _settype */
  575. X
  576. X
  577. X
  578. X
  579. Xint SetTypeByNumber(int i)
  580. X{
  581. X    char tstr[4], *tp = tstr, c;
  582. X
  583. X    tp[1] = c = 0;
  584. X    switch (i) {
  585. X        case TYPE_A: c = 'a'; break;
  586. X        case TYPE_I: c = 'b'; break;
  587. X        case TYPE_E: c = 'e'; break;
  588. X        case TYPE_L: c = 't';
  589. X    }
  590. X    *tp = c;
  591. X    return (_settype(tp));
  592. X}    /* SetTypeByNumber */
  593. X
  594. X
  595. X
  596. X
  597. X/*
  598. X * Set transfer type.
  599. X */
  600. Xint settype(int argc, char **argv)
  601. X{
  602. X    int result = NOERR;
  603. X
  604. X    if (argc > 2) {
  605. X        result = USAGE;
  606. X    } else {
  607. X        if (argc < 2)
  608. X            goto xx;
  609. X        result = _settype(argv[1]);
  610. X        if (IS_VVERBOSE)
  611. Xxx:            (void) printf("Using %s mode to transfer files.\n", curtypename);
  612. X    }
  613. X    return result;
  614. X}    /* settype */
  615. X
  616. X
  617. X
  618. X
  619. X/*ARGSUSED*/
  620. Xint setbinary(int argc, char **argv) {    return (_settype("binary")); }
  621. X/*ARGSUSED*/
  622. Xint setascii(int argc, char **argv) {    return (_settype("ascii")); }
  623. X
  624. X
  625. X
  626. X/*
  627. X * Send a single file.
  628. X */
  629. Xint put(int argc, char **argv)
  630. X{
  631. X    char *cmd;
  632. X
  633. X    if (argc == 2) {
  634. X        argc++;
  635. X        argv[2] = argv[1];
  636. X    }
  637. X    if (argc < 2)
  638. X        argv = re_makeargv("(local-file) ", &argc);
  639. X    if (argc < 2) {
  640. Xusage:
  641. X        return USAGE;
  642. X    }
  643. X    if (argc < 3)
  644. X        argv = re_makeargv("(remote-file) ", &argc);
  645. X    if (argc < 3) 
  646. X        goto usage;
  647. X    cmd = (argv[0][0] == 'a') ? "APPE" : "STOR";
  648. X    (void) sendrequest(cmd, argv[1], argv[2]);
  649. X    return NOERR;
  650. X}    /* put */
  651. X
  652. X
  653. X
  654. X
  655. X/*
  656. X * Send multiple files.
  657. X */
  658. Xint mput(int argc, char **argv)
  659. X{
  660. X    register int i;
  661. X    sig_t oldintr;
  662. X    char *tp;
  663. X
  664. X    if (argc < 2)
  665. X        argv = re_makeargv("(local-files) ", &argc);
  666. X    if (argc < 2) {
  667. X        return USAGE;
  668. X    }
  669. X    mname = argv[0];
  670. X    activemcmd = 1;
  671. X    oldintr = Signal(SIGINT, mabort);
  672. X    (void) setjmp(jabort);
  673. X    for (i = 1; i < argc; i++) {
  674. X        register char **cpp, **gargs;
  675. X
  676. X        gargs = glob(argv[i]);
  677. X        if (globerr != NULL) {
  678. X            (void) printf("%s\n", globerr);
  679. X            if (gargs) {
  680. X                blkfree(gargs);
  681. X                free(gargs);
  682. X            }
  683. X            continue;
  684. X        }
  685. X        for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
  686. X            if (activemcmd && confirm(argv[0], *cpp)) {
  687. X                tp = *cpp;
  688. X                (void) sendrequest("STOR", *cpp, tp);
  689. X                if (!activemcmd && fromatty) {
  690. X                    if (confirm("Continue with","mput")) {
  691. X                        activemcmd++;
  692. X                    }
  693. X                }
  694. X            }
  695. X        }
  696. X        if (gargs != NULL) {
  697. X            blkfree(gargs);
  698. X            free(gargs);
  699. X        }
  700. X    }
  701. X    (void) Signal(SIGINT, oldintr);
  702. X    activemcmd = 0;
  703. X    return NOERR;
  704. X}    /* mput */
  705. X
  706. X
  707. X
  708. X
  709. Xint rem_glob_one(char *pattern)
  710. X{
  711. X    int            oldverbose, result = 0;
  712. X    char        *cp;
  713. X    string        str, tname;
  714. X    FILE        *ftemp;
  715. X
  716. X    /* Check for wildcard characters. */
  717. X    if (*pattern == '|' || strpbrk(pattern, globchars) == NULL)
  718. X        return 0;
  719. X
  720. X    (void) tmp_name(tname);
  721. X    oldverbose = verbose;
  722. X    verbose = V_QUIET;
  723. X    (void) recvrequest ("NLST", tname, pattern, "w");
  724. X    verbose = oldverbose;
  725. X    ftemp = fopen(tname, "r");
  726. X    if (ftemp == NULL || FGets(str, ftemp) == NULL) {
  727. X        if (NOT_VQUIET)
  728. X            (void) printf("%s: no match.\n", pattern);
  729. X        result = -1;
  730. X        goto done;
  731. X    }
  732. X    if ((cp = index(str, '\n')) != NULL)
  733. X        *cp = '\0';
  734. X    (void) strcpy(pattern, str);
  735. X    cp = FGets(str, ftemp);
  736. X    /* It is an error if the pattern matched more than one file. */
  737. X    if (cp != NULL) {
  738. X        if (NOT_VQUIET)
  739. X            (void) printf("?Ambiguous remote file name.\n");
  740. X        result = -2;
  741. X    }
  742. Xdone:
  743. X    if (ftemp != NULL)
  744. X        (void) fclose(ftemp);
  745. X    (void) unlink(tname);
  746. X    return (result);
  747. X}    /* rem_glob_one */
  748. X
  749. X
  750. X
  751. X
  752. X/*
  753. X * Receive (and maybe page) one file.
  754. X */
  755. Xint get(int argc, char **argv)
  756. X{
  757. X    string local_file;
  758. X    char remote_file[256];
  759. X    char *cp;
  760. X    int oldtype = curtype;
  761. X
  762. X    /* paging mode is set if the command name is 'page' or 'more.' */
  763. X    paging = (**argv != 'g');
  764. X
  765. X    if (argc < 2)
  766. X        argv = re_makeargv("(remote-file) ", &argc);
  767. X
  768. X    if (argc < 2) {
  769. X        return USAGE;
  770. X    }
  771. X    cp = Strncpy(remote_file, argv[1]);
  772. X    argv[1] = cp;
  773. X    if (rem_glob_one(argv[1]) < 0)
  774. X        return CMDERR;
  775. X
  776. X    if (paging) {
  777. X        size_t len = strlen(remote_file);
  778. X
  779. X        /* Run compressed remote files through zcat, then the pager. */
  780. X        if (strlen(remote_file) > 2 && (remote_file[len - 1] == 'Z' || remote_file[len - 1] == 'z') && remote_file[len - 2] == '.') {
  781. X            (void) _settype("b");
  782. X            (void) sprintf(local_file, "|%s ", ZCAT);
  783. X            argv[2] = Strncat(local_file, pager);
  784. X        } else {
  785. X            /* Try to use text mode for paging, so newlines get converted. */
  786. X            (void) _settype("a");
  787. X            argv[2] = pager;
  788. X        }
  789. X    } else {
  790. X        /* normal get */
  791. X        if (argc == 2) {
  792. X            (void) Strncpy(local_file, argv[1]);
  793. X            argv[2] = local_file;
  794. X        } else {
  795. X            if (argc < 3)
  796. X                argv = re_makeargv("(local-file) ", &argc);
  797. X            if (argc < 3) 
  798. X                return USAGE;
  799. X            if (!globulize(&argv[2])) {
  800. X                return CMDERR;
  801. X            }
  802. X        }
  803. X    }
  804. X    (void) recvrequest("RETR", argv[2], argv[1], "w");
  805. X    if (paging) {
  806. X        (void) SetTypeByNumber(oldtype);    /* Restore it to what it was. */
  807. X        paging = 0;
  808. X    }
  809. X    return NOERR;
  810. X}    /* get */
  811. X
  812. X
  813. X
  814. X/*ARGSUSED*/
  815. Xvoid mabort SIG_PARAMS
  816. X{
  817. X    (void) printf("\n");
  818. X    (void) fflush(stdout);
  819. X    if (activemcmd && fromatty) {
  820. X        if (confirm("Continue with", mname)) {
  821. X            longjmp(jabort,0);
  822. X        }
  823. X    }
  824. X    activemcmd = 0;
  825. X    longjmp(jabort,0);
  826. X}    /* mabort */
  827. X
  828. X
  829. X
  830. X
  831. X/*
  832. X * Get multiple files.
  833. X */
  834. Xint mget(int argc, char **argv)
  835. X{
  836. X    char *cp;
  837. X    longstring local;
  838. X    sig_t oldintr;
  839. X
  840. X    if (argc < 2)
  841. X        argv = re_makeargv("(remote-files) ", &argc);
  842. X    if (argc < 2) {
  843. X        return USAGE;
  844. X    }
  845. X    mname = argv[0];
  846. X    activemcmd = 1;
  847. X    oldintr = Signal(SIGINT, mabort);
  848. X    (void) setjmp(jabort);
  849. X    while ((cp = remglob(argv)) != NULL) {
  850. X        if (*cp == '\0') {
  851. X            activemcmd = 0;
  852. X            continue;
  853. X        }
  854. X        if (activemcmd && confirm(argv[0], cp)) {
  855. X            (void) Strncpy(local, cp);
  856. X            (void) recvrequest("RETR", local, cp, "w");
  857. X            if (!activemcmd && fromatty) {
  858. X                if (confirm("Continue with","mget")) {
  859. X                    activemcmd++;
  860. X                }
  861. X            }
  862. X        }
  863. X    }
  864. X    (void) Signal(SIGINT,oldintr);
  865. X    activemcmd = 0;
  866. X    return NOERR;
  867. X}    /* mget */
  868. X
  869. X
  870. X
  871. X
  872. Xchar *remglob(char *argv[])
  873. X{
  874. X    static FILE            *ftemp = NULL;
  875. X    int                    oldverbose, i;
  876. X    char                *cp, *mode;
  877. X    static string        tmpname, str;
  878. X
  879. X    if (!activemcmd) {
  880. Xxx:
  881. X        if (ftemp) {
  882. X            (void) fclose(ftemp);
  883. X            ftemp = NULL;
  884. X            (void) unlink(tmpname);
  885. X        }
  886. X        return(NULL);
  887. X    }
  888. X    if (ftemp == NULL) {
  889. X        (void) tmp_name(tmpname);
  890. X        oldverbose = verbose, verbose = V_QUIET;
  891. X        for (mode = "w", i=1; argv[i] != NULL; i++, mode = "a")
  892. X            (void) recvrequest ("NLST", tmpname, argv[i], mode);
  893. X        verbose = oldverbose;
  894. X        ftemp = fopen(tmpname, "r");
  895. X        if (ftemp == NULL) {
  896. X            (void) printf("Can't find list of remote files (%s), oops.\n", tmpname);
  897. X            return (NULL);
  898. X        }
  899. X    }
  900. X    if (FGets(str, ftemp) == NULL) 
  901. X        goto xx;
  902. X    if ((cp = index(str, '\n')) != NULL)
  903. X        *cp = '\0';
  904. X    return (str);
  905. X}    /* remglob */
  906. X
  907. X
  908. X/*
  909. X * Turn on/off printing of server echo's, messages, and statistics.
  910. X */
  911. Xint setverbose(int argc, char **argv)
  912. X{
  913. X    if (argc > 1)
  914. X        set_verbose(argv[1], 0);
  915. X    else set_verbose(argv[1], -1);
  916. X    return NOERR;
  917. X}    /* setverbose */
  918. X
  919. X
  920. X
  921. X/*
  922. X * Toggle interactive prompting
  923. X * during mget, mput, and mdelete.
  924. X */
  925. Xint setprompt(int argc, char **argv)
  926. X{
  927. X    if (argc > 1)
  928. X        mprompt = StrToBool(argv[1]);
  929. X    else mprompt = !mprompt;
  930. X    if (IS_VVERBOSE)
  931. X        (void) printf("Interactive prompting for m* commmands %s.\n", onoff(mprompt));
  932. X    return NOERR;
  933. X}    /* setprompt */
  934. X
  935. X
  936. X
  937. X
  938. Xvoid fix_options(void)
  939. X{
  940. X    if (debug)
  941. X        options |= SO_DEBUG;
  942. X    else
  943. X    options &= ~SO_DEBUG;
  944. X}   /* fix_options */
  945. X
  946. X
  947. X/*
  948. X * Set debugging mode on/off and/or
  949. X * set level of debugging.
  950. X */
  951. Xint setdebug(int argc, char **argv)
  952. X{
  953. X    int val;
  954. X
  955. X    if (argc > 1) {
  956. X        val = StrToBool(argv[1]);
  957. X        if (val < 0) {
  958. X            (void) printf("%s: bad debugging value.\n", argv[1]);
  959. X            return USAGE;
  960. X        }
  961. X    } else
  962. X        val = !debug;
  963. X    debug = val;
  964. X    fix_options();
  965. X    if (IS_VVERBOSE)
  966. X        (void) printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
  967. X    return NOERR;
  968. X}    /* debug */
  969. X
  970. X
  971. X
  972. X/*
  973. X * Set current working directory
  974. X * on remote machine.
  975. X */
  976. Xint cd(int argc, char **argv)
  977. X{
  978. X    if (argc < 2)
  979. X        argv = re_makeargv("(remote-directory) ", &argc);
  980. X    if (argc < 2) {
  981. X        return USAGE;
  982. X    }
  983. X    (void) _cd(argv[1]);
  984. X    return NOERR;
  985. X}    /* cd */
  986. X
  987. X
  988. X
  989. X
  990. Xint implicit_cd(char *dir)
  991. X{
  992. X    int i, j = 0;
  993. X    
  994. X    if (connected) {
  995. X        i = verbose;
  996. X        /* Special verbosity level that ignores errors and prints other stuff,
  997. X         * so you will get just the unknown command message and not an error
  998. X         * message from cd.
  999. X         */
  1000. X        verbose = V_IMPLICITCD;
  1001. X        j = _cd(dir);
  1002. X        verbose = i;
  1003. X    }
  1004. X    return j;
  1005. X}    /* implicit_cd */
  1006. X
  1007. X
  1008. X
  1009. X
  1010. Xint _cd(char *dir)
  1011. X{
  1012. X    register char *cp;
  1013. X    int result = 0;
  1014. X    string str;
  1015. X
  1016. X    if (dir == NULL)
  1017. X        goto getrwd;
  1018. X    /* Won't work because glob really is a ls, so 'cd pu*' will match
  1019. X     * pub/README, pub/file2, etc.
  1020. X     *    if (result = rem_glob_one(dir) < 0)
  1021. X     *    return result;
  1022. X     */
  1023. X    if (strncmp(dir, "CDUP", (size_t) 4) == 0)
  1024. X        (void) Strncpy(str, dir);
  1025. X    else
  1026. X        (void) sprintf(str, "CWD %s", dir);
  1027. X    if (command(str) != 5) {
  1028. Xgetrwd:
  1029. X        (void) quiet_command("PWD");
  1030. X        cp = rindex(reply_string, '\"');
  1031. X        if (cp != NULL) {
  1032. X            result = 1;
  1033. X            *cp = '\0';
  1034. X            cp = index(reply_string, '\"');
  1035. X            if (cp != NULL)
  1036. X                (void) Strncpy(cwd, ++cp);
  1037. X        }
  1038. X    }
  1039. X    dbprintf("Current remote directory is \"%s\"\n", cwd);
  1040. X    return (result);
  1041. X}    /* _cd */
  1042. X
  1043. X
  1044. X
  1045. X
  1046. X/*
  1047. X * Set current working directory
  1048. X * on local machine.
  1049. X */
  1050. Xint lcd(int argc, char **argv)
  1051. X{
  1052. X    if (argc < 2)
  1053. X        argc++, argv[1] = home;
  1054. X    if (argc != 2) {
  1055. X        return USAGE;
  1056. X    }
  1057. X    if (!globulize(&argv[1])) {
  1058. X        return CMDERR;
  1059. X    }
  1060. X    if (chdir(argv[1]) < 0) {
  1061. X        PERROR("lcd", argv[1]);
  1062. X        return CMDERR;
  1063. X    }
  1064. X    (void) get_cwd(lcwd, (int) sizeof(lcwd));
  1065. X    if (IS_VVERBOSE) 
  1066. X        (void) printf("Local directory now %s\n", lcwd);
  1067. X    return NOERR;
  1068. X}    /* lcd */
  1069. X
  1070. X
  1071. X
  1072. X
  1073. X/*
  1074. X * Delete a single file.
  1075. X */
  1076. Xint do_delete(int argc, char **argv)
  1077. X{
  1078. X    string str;
  1079. X
  1080. X    if (argc < 2)
  1081. X        argv = re_makeargv("(remote file to delete) ", &argc);
  1082. X    if (argc < 2) {
  1083. X        return USAGE;
  1084. X    }
  1085. X    if (rem_glob_one(argv[1]) == 0) {
  1086. X        (void) sprintf(str, "DELE %s", argv[1]);
  1087. X        (void) command(str);
  1088. X    }
  1089. X    return NOERR;
  1090. X}    /* do_delete */
  1091. X
  1092. X
  1093. X
  1094. X
  1095. X/*
  1096. X * Delete multiple files.
  1097. X */
  1098. Xint mdelete(int argc, char **argv)
  1099. X{
  1100. X    char *cp;
  1101. X    sig_t oldintr;
  1102. X    string str;
  1103. X
  1104. X    if (argc < 2)
  1105. X        argv = re_makeargv("(remote-files) ", &argc);
  1106. X    if (argc < 2) {
  1107. X        return USAGE;
  1108. X    }
  1109. X    mname = argv[0];
  1110. X    activemcmd = 1;
  1111. X    oldintr = Signal(SIGINT, mabort);
  1112. X    (void) setjmp(jabort);
  1113. X    while ((cp = remglob(argv)) != NULL) {
  1114. X        if (*cp == '\0') {
  1115. X            activemcmd = 0;
  1116. X            continue;
  1117. X        }
  1118. X        if (activemcmd && confirm(argv[0], cp)) {
  1119. X            (void) sprintf(str, "DELE %s", cp);
  1120. X            (void) command(str);
  1121. X            if (!activemcmd && fromatty) {
  1122. X                if (confirm("Continue with", "mdelete")) {
  1123. X                    activemcmd++;
  1124. X                }
  1125. X            }
  1126. X        }
  1127. X    }
  1128. X    (void) Signal(SIGINT, oldintr);
  1129. X    activemcmd = 0;
  1130. X    return NOERR;
  1131. X}    /* mdelete */
  1132. X
  1133. X
  1134. X
  1135. X
  1136. X/*
  1137. X * Rename a remote file.
  1138. X */
  1139. Xint renamefile(int argc, char **argv)
  1140. X{
  1141. X    string str;
  1142. X
  1143. X    if (argc < 2)
  1144. X        argv = re_makeargv("(from-name) ", &argc);
  1145. X    if (argc < 2) {
  1146. Xusage:
  1147. X        return USAGE;
  1148. X    }
  1149. X    if (argc < 3)
  1150. X        argv = re_makeargv("(to-name) ", &argc);
  1151. X    if (argc < 3)
  1152. X        goto usage;
  1153. X    if (rem_glob_one(argv[1]) < 0)
  1154. X        return CMDERR;
  1155. X    (void) sprintf(str, "RNFR %s", argv[1]);
  1156. X    if (command(str) == CONTINUE) {
  1157. X        (void) sprintf(str, "RNTO %s", argv[2]);
  1158. X        (void) command(str);
  1159. X    }
  1160. X    return NOERR;
  1161. X}    /* renamefile */
  1162. X
  1163. X
  1164. X
  1165. X/*
  1166. X * Get a directory listing
  1167. X * of remote files.
  1168. X */
  1169. Xint ls(int argc, char **argv)
  1170. X{
  1171. X    char        *whichcmd, *cp;
  1172. X    str32        lsflags;
  1173. X    string        remote, local, str;
  1174. X    int            listmode, pagemode, i;
  1175. X
  1176. X    PurgeLineBuffer();
  1177. X    pagemode = 0;
  1178. X    switch (**argv) {
  1179. X        case 'p':                            /* pls, pdir, pnlist */
  1180. X            pagemode = 1;
  1181. X            listmode = argv[0][1] == 'd';
  1182. X            break;
  1183. X        case 'd':                            /* dir */
  1184. X            listmode = 1;
  1185. X            break;
  1186. X        default:                            /* ls, nlist */
  1187. X            listmode = 0;
  1188. X    }
  1189. X    whichcmd = listmode ? "LIST" : "NLST";
  1190. X
  1191. X    (void) strncpy(local, (pagemode ? pager : "-"), sizeof(local));
  1192. X    remote[0] = lsflags[0] = 0;
  1193. X    
  1194. X    /* Possible scenarios:
  1195. X     *  1.    ls
  1196. X     *  2.    ls -flags
  1197. X     *  3.    ls directory
  1198. X     *  4.  ls -flags >outfile
  1199. X     *  5.  ls directory >outfile
  1200. X     *  6.  ls -flags directory
  1201. X     *  7.  ls -flags directory >outfile
  1202. X     *
  1203. X     * Note that using a wildcard will choke with flags.  I.e., don't do
  1204. X     * "ls -CF *.tar," but instead do "ls *.tar."
  1205. X     */
  1206. X
  1207. X    for (i=1; i<argc; i++) {
  1208. X        switch (argv[i][0]) {
  1209. X            case '-': 
  1210. X                /*
  1211. X                 * If you give more than one set of flags, concat the each
  1212. X                 * additional set to the first one (without the dash).
  1213. X                 */
  1214. X                (void) strncat(lsflags, (argv[i] + (lsflags[0] == '-')), sizeof(lsflags));
  1215. X                break;
  1216. X            case '|':
  1217. X            case '>': (void) Strncpy(local, argv[i] + (argv[i][0] == '>')); break;
  1218. X            default:  
  1219. X                cp = argv[i];
  1220. X                /*
  1221. X                 * In case you want to get a remote file called '--README--'
  1222. X                 * or '>README,' you can use '\--README--' and '\>README.'
  1223. X                 */
  1224. X                if ((cp[1] != 0) && (*cp == '\\'))
  1225. X                    ++cp;
  1226. X                if (remote[0] != 0) {
  1227. X                    (void) Strncat(remote, " ");
  1228. X                    (void) Strncat(remote, cp);
  1229. X                } else {
  1230. X                    (void) Strncpy(remote, cp);
  1231. X                }
  1232. X        }    /* end switch */    
  1233. X    }        /* end loop */
  1234. X
  1235. X    /*
  1236. X     *    If we are given an ls with some flags, make sure we use 
  1237. X     *    columnized output (-C) unless one column output (-1) is
  1238. X     *    specified.
  1239. X     */
  1240. X    if (!listmode) {
  1241. X        if (lsflags[0] != 0) {
  1242. X            (void) Strncpy(str, lsflags);
  1243. X            for (cp = str + 1; *cp; cp++)
  1244. X                if (*cp == '1')
  1245. X                    goto aa;
  1246. X            (void) sprintf(lsflags, "-FC%s", str + 1);
  1247. X        } else {
  1248. X            if (remote_is_unix)
  1249. X                (void) strcpy(lsflags, "-FC");
  1250. X        }
  1251. X        /* As noted above, we can't use -flags if the user gave a
  1252. X         * wildcard expr.
  1253. X         */
  1254. X        if (remote_is_unix && (strpbrk(remote, globchars) != NULL)) {
  1255. X            lsflags[0] = 0;
  1256. X            /* Warn the user what's going on. */
  1257. X            if ((warnNoLSFlagsWithWildcards == 0) && NOT_VQUIET) {
  1258. X                (void) fprintf(stderr, "Warning: ls flags disabled with wildcard expressions.\n");
  1259. X                warnNoLSFlagsWithWildcards++;
  1260. X            }
  1261. X        }
  1262. X    }
  1263. X
  1264. Xaa:    if (strcmp(local, "-") != 0) {
  1265. X        char *lp = local;
  1266. X
  1267. X        if ((!globulize(&lp)) || ((local[0] != '|') && (!confirm("Output to local-file: ", local)))) {
  1268. X            return CMDERR;
  1269. X        } 
  1270. X        if (lp != local) {
  1271. X            (void) Strncpy(str, lp);
  1272. X            (void) Strncpy(local, str);
  1273. X        }
  1274. X    }
  1275. X    is_ls = 1; /* tells getreply() to start saving input to a buffer. */
  1276. X    (void) Strncpy(str, remote);
  1277. X    if (lsflags[0] && remote[0])
  1278. X        (void) sprintf(remote, "%s%c%s", lsflags, LS_FLAGS_AND_FILE, str);
  1279. X    else
  1280. X        (void) strncpy(remote, lsflags[0] ? lsflags : str, sizeof(remote));
  1281. X    (void) recvrequest(whichcmd, local, (remote[0] == 0 ? NULL : remote), "w");
  1282. X    is_ls=0;
  1283. X    return NOERR;
  1284. X}    /* ls */
  1285. X
  1286. X
  1287. X
  1288. X/*
  1289. X * Do a shell escape
  1290. X */
  1291. X/*ARGSUSED*/
  1292. Xint shell(int argc, char **argv)
  1293. X{
  1294. X    int                pid;
  1295. X    sig_t            old1, old2;
  1296. X    char            *theShell, *namep;
  1297. X#ifndef U_WAIT
  1298. X    int                Status;
  1299. X#else
  1300. X    union wait        Status;
  1301. X#endif
  1302. X    string            str;
  1303. X
  1304. X    old1 = signal (SIGINT, SIG_IGN);
  1305. X    old2 = signal (SIGQUIT, SIG_IGN);
  1306. X    if ((pid = fork()) == 0) {
  1307. X        for (pid = 3; pid < 20; pid++)
  1308. X            (void) close(pid);
  1309. X        (void) Signal(SIGINT, SIG_DFL);
  1310. X        (void) Signal(SIGQUIT, SIG_DFL);
  1311. X        if ((theShell = getenv("SHELL")) == NULL)
  1312. X            theShell = uinfo.shell;
  1313. X        if (theShell == NULL)
  1314. X            theShell = "/bin/sh";
  1315. X        namep = rindex(theShell, '/');
  1316. X        if (namep == NULL)
  1317. X            namep = theShell;
  1318. X        (void) strcpy(str, "-");
  1319. X        (void) strcat(str, ++namep);
  1320. X        if (strcmp(namep, "sh") != 0)
  1321. X            str[0] = '+';
  1322. X        dbprintf ("%s\n", theShell);
  1323. X        if (argc > 1)
  1324. X            (void) execl(theShell, str, "-c", altarg, (char *)0);
  1325. X        else
  1326. X            (void) execl(theShell, str, (char *)0);
  1327. X        PERROR("shell", theShell);
  1328. X        exit(1);
  1329. X        }
  1330. X    if (pid > 0)
  1331. X        while (wait((void *) &Status) != pid)
  1332. X            ;
  1333. X    (void) Signal(SIGINT, old1);
  1334. X    (void) Signal(SIGQUIT, old2);
  1335. X    if (pid == -1) {
  1336. X        PERROR("shell", "Try again later");
  1337. X    }
  1338. X    return NOERR;
  1339. X}    /* shell */
  1340. X
  1341. X
  1342. X
  1343. X
  1344. X/*
  1345. X * Send new user information (re-login)
  1346. X */
  1347. Xint do_user(int argc, char **argv)
  1348. X{
  1349. X    char            acct[80];
  1350. X    int                n, aflag = 0;
  1351. X    string            str;
  1352. X
  1353. X    if (argc < 2)
  1354. X        argv = re_makeargv("(username) ", &argc);
  1355. X    if (argc > 4) {
  1356. X        return USAGE;
  1357. X    }
  1358. X    (void) sprintf(str, "USER %s", argv[1]);
  1359. X    n = command(str);
  1360. X    if (n == CONTINUE) {
  1361. X        if (argc < 3 )
  1362. X            argv[2] = Getpass("Password: "), argc++;
  1363. X        (void) sprintf(str, "PASS %s", argv[2]);
  1364. X        n = command(str);
  1365. X    }
  1366. X    if (n == CONTINUE) {
  1367. X        if (argc < 4) {
  1368. X            (void) printf("Account: "); (void) fflush(stdout);
  1369. X            (void) FGets(acct, stdin);
  1370. X            acct[strlen(acct) - 1] = '\0';
  1371. X            argv[3] = acct; argc++;
  1372. X        }
  1373. X        (void) sprintf(str, "ACCT %s", argv[3]);
  1374. X        n = command(str);
  1375. X        aflag++;
  1376. X    }
  1377. X    if (n != COMPLETE) {
  1378. X        (void) fprintf(stdout, "Login failed.\n");
  1379. X        logged_in = 0;
  1380. X        return (0);
  1381. X    }
  1382. X    if (!aflag && argc == 4) {
  1383. X        (void) sprintf(str, "ACCT %s", argv[3]);
  1384. X        (void) command(str);
  1385. X    }
  1386. X    logged_in = 1;
  1387. X    return NOERR;
  1388. X}    /* do_user */
  1389. X
  1390. X
  1391. X
  1392. X
  1393. X/*
  1394. X * Print working directory.
  1395. X */
  1396. X/*ARGSUSED*/
  1397. Xint pwd(int argc, char **argv)
  1398. X{
  1399. X    (void) quiet_command("PWD");
  1400. X    return NOERR;
  1401. X}    /* pwd */
  1402. X
  1403. X
  1404. X
  1405. X
  1406. X/*
  1407. X * Make a directory.
  1408. X */
  1409. Xint makedir(int argc, char **argv)
  1410. X{
  1411. X    string str;
  1412. X
  1413. X    if (argc < 2)
  1414. X        argv = re_makeargv("(directory-name) ", &argc);
  1415. X    if (argc < 2) {
  1416. X        return USAGE;
  1417. X    }
  1418. X    (void) sprintf(str, "MKD %s", argv[1]);
  1419. X    (void) command(str);
  1420. X    return NOERR;
  1421. X}    /* makedir */
  1422. X
  1423. X
  1424. X
  1425. X
  1426. X/*
  1427. X * Remove a directory.
  1428. X */
  1429. Xint removedir(int argc, char **argv)
  1430. X{
  1431. X    string str;
  1432. X    if (argc < 2)
  1433. X        argv = re_makeargv("(directory-name) ", &argc);
  1434. X    if (argc < 2) {
  1435. X        return USAGE;
  1436. X    }
  1437. X    if (rem_glob_one(argv[1]) == 0) {
  1438. X        (void) sprintf(str, "RMD %s", argv[1]);
  1439. X        (void) command(str);
  1440. X    }
  1441. X    return NOERR;
  1442. X}    /* removedir */
  1443. X
  1444. X
  1445. X
  1446. X
  1447. X/*
  1448. X * Send a line, verbatim, to the remote machine.
  1449. X */
  1450. Xint quote(int argc, char **argv)
  1451. X{
  1452. X    int i, tmpverbose;
  1453. X    string str;
  1454. X
  1455. X    if (argc < 2)
  1456. X        argv = re_makeargv("(command line to send) ", &argc);
  1457. X    if (argc < 2) {
  1458. X        return USAGE;
  1459. X    }
  1460. X    str[0] = 0;
  1461. X    if (*argv[0] == 's')    /* Command was 'site' instead of 'quote.' */
  1462. X        (void) Strncpy(str, "site ");
  1463. X    (void) Strncat(str, argv[1]);
  1464. X    for (i = 2; i < argc; i++) {
  1465. X        (void) Strncat(str, " ");
  1466. X        (void) Strncat(str, argv[i]);
  1467. X    }
  1468. X    tmpverbose = verbose;
  1469. X    verbose = V_VERBOSE;
  1470. X    if (command(str) == PRELIM) {
  1471. X        while (getreply(0) == PRELIM);
  1472. X    }
  1473. X    verbose = tmpverbose;
  1474. X    return NOERR;
  1475. X}    /* quote */
  1476. X
  1477. X
  1478. X
  1479. X
  1480. X/*
  1481. X * Ask the other side for help.
  1482. X */
  1483. Xint rmthelp(int argc, char **argv)
  1484. X{
  1485. X    string str;
  1486. X
  1487. X    if (argc == 1) (void) verbose_command("HELP");
  1488. X    else {
  1489. X        (void) sprintf(str, "HELP %s", argv[1]);
  1490. X        (void) verbose_command(str);
  1491. X    }
  1492. X    return NOERR;
  1493. X}    /* rmthelp */
  1494. X
  1495. X
  1496. X
  1497. X
  1498. X/*
  1499. X * Terminate session and exit.
  1500. X */
  1501. X/*ARGSUSED*/
  1502. Xint quit(int argc, char **argv)
  1503. X{
  1504. X    close_up_shop();
  1505. X    trim_log();
  1506. X    exit(0);
  1507. X}    /* quit */
  1508. X
  1509. X
  1510. X
  1511. Xvoid close_streams(int wantShutDown)
  1512. X{
  1513. X    if (cout != NULL) {
  1514. X        if (wantShutDown)
  1515. X            (void) shutdown(fileno(cout), 1+1);
  1516. X        (void) fclose(cout);
  1517. X        cout = NULL;
  1518. X    }
  1519. X    if (cin != NULL) {
  1520. X        if (wantShutDown)
  1521. X            (void) shutdown(fileno(cin), 1+1);
  1522. X        (void) fclose(cin);
  1523. X        cin = NULL;
  1524. X    }
  1525. X}    /* close_streams */
  1526. X
  1527. X
  1528. X
  1529. X
  1530. X/*
  1531. X * Terminate session, but don't exit.
  1532. X */
  1533. X/*ARGSUSED*/
  1534. Xint disconnect(int argc, char **argv)
  1535. X{
  1536. X#ifdef SYSLOG
  1537. X    syslog (LOG_INFO, "%s disconnected from %s.", uinfo.username, hostname);
  1538. X#endif
  1539. X
  1540. X    (void) command("QUIT");
  1541. X    close_streams(0);
  1542. X    UpdateRecentSitesList(hostname, cwd);
  1543. X    hostname[0] = cwd[0] = 0;
  1544. X    logged_in = connected = 0;
  1545. X    data = -1;
  1546. X    macnum = 0;
  1547. X    return NOERR;
  1548. X}    /* disconnect */
  1549. X
  1550. X
  1551. X
  1552. Xvoid
  1553. Xclose_up_shop(void)
  1554. X{
  1555. X    static int only_once = 0;
  1556. X    if (only_once++ > 0)
  1557. X        return;
  1558. X    if (connected)
  1559. X        (void) disconnect(0, NULL);
  1560. X    WriteRecentSitesFile();
  1561. X    if (logf != NULL) {
  1562. X        (void) fclose(logf);
  1563. X        logf = NULL;
  1564. X    }
  1565. X}    /* close_up_shop */
  1566. X
  1567. X
  1568. X
  1569. X
  1570. X/*
  1571. X * Glob a local file name specification with
  1572. X * the expectation of a single return value.
  1573. X * Can't control multiple values being expanded
  1574. X * from the expression, we return only the first.
  1575. X */
  1576. Xint globulize(char **cpp)
  1577. X{
  1578. X    char **globbed;
  1579. X
  1580. X    (void) LocalPath(*cpp);
  1581. X    globbed = glob(*cpp);
  1582. X    if (globerr != NULL) {
  1583. X        (void) printf("%s: %s\n", *cpp, globerr);
  1584. X        if (globbed) {
  1585. X            blkfree(globbed);
  1586. X            free(globbed);
  1587. X        }
  1588. X        return (0);
  1589. X    }
  1590. X    if (globbed) {
  1591. X        *cpp = *globbed++;
  1592. X        /* don't waste too much memory */
  1593. X        if (*globbed) {
  1594. X            blkfree(globbed);
  1595. X            free(globbed);
  1596. X        }
  1597. X    }
  1598. X    return (1);
  1599. X}    /* globulize */
  1600. X
  1601. X
  1602. X
  1603. X/* change directory to perent directory */
  1604. X/*ARGSUSED*/
  1605. Xint cdup(int argc, char **argv)
  1606. X{
  1607. X    (void) _cd("CDUP");
  1608. X    return NOERR;
  1609. X}    /* cdup */
  1610. X
  1611. X
  1612. X/* show remote system type */
  1613. X/*ARGSUSED*/
  1614. Xint syst(int argc, char **argv)
  1615. X{
  1616. X    (void) verbose_command("SYST");
  1617. X    return NOERR;
  1618. X}    /* syst */
  1619. X
  1620. X
  1621. X
  1622. X
  1623. Xint make_macro(char *name, FILE *fp)
  1624. X{
  1625. X    char            *tmp;
  1626. X    char            *cp;
  1627. X    string            str;
  1628. X    size_t            len;
  1629. X    int                i;
  1630. X
  1631. X    if (macnum == MAXMACROS) {
  1632. X        (void) fprintf(stderr, "Limit of %d macros have already been defined.\n", MAXMACROS);
  1633. X        return -1;
  1634. X    }
  1635. X
  1636. X    /* Make sure macros have unique names.  If 'init' was attempted to be
  1637. X     * redefined, just return, since it was probably cmdOpen() in a redial
  1638. X     * mode which tried to define it again.
  1639. X     */
  1640. X    for (i = 0; i<macnum; i++) {
  1641. X        if (strncmp(name, macros[i].mac_name, (size_t)8) == 0) {
  1642. X            if (parsing_rc) {
  1643. X                /* Just shut up and read in the macro, but don't save it,
  1644. X                 * because we already have it.
  1645. X                 */
  1646. X                while ((cp = FGets(str, fp)) != NULL) {
  1647. X                    /* See if we have a 'blank' line: just whitespace. */
  1648. X                    while (*cp && isspace(*cp)) ++cp;
  1649. X                    if (!*cp)
  1650. X                        break;
  1651. X                }
  1652. X            } else
  1653. X                (void) fprintf(stderr,
  1654. X                    "There is already a macro named '%s.'\n", name);
  1655. X            return -1;
  1656. X        }
  1657. X    }
  1658. X    (void) strncpy(macros[macnum].mac_name, name, (size_t)8);
  1659. X    if (macnum == 0)
  1660. X        macros[macnum].mac_start = macbuf;
  1661. X    else
  1662. X        macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
  1663. X    tmp = macros[macnum].mac_start;
  1664. X    while (1) {
  1665. X        cp = FGets(str, fp);
  1666. X        if (cp == NULL) {
  1667. X            /*
  1668. X             * If we had started a macro, we will say it is
  1669. X             * okay to skip the blank line delimiter if we
  1670. X             * are at the EOF.
  1671. X             */
  1672. X            if (tmp > macros[macnum].mac_start)
  1673. X                goto endmac;
  1674. X            (void) fprintf(stderr, "No text supplied for macro \"%s.\"\n", name);
  1675. X        }
  1676. X        /* see if we have a 'blank' line: just whitespace. */
  1677. X        while (*cp && isspace(*cp)) ++cp;
  1678. X        if (*cp == '\0') {
  1679. X            /* Blank line; end this macro. */
  1680. Xendmac:
  1681. X            macros[macnum++].mac_end = tmp;
  1682. X            return 0;
  1683. X        }
  1684. X        /* Add the text of this line to the macro. */
  1685. X        len = strlen(cp) + 1;    /* we need the \0 too. */
  1686. X        if (tmp + len >= macbuf + MACBUFLEN) {
  1687. X            (void) fprintf(stderr, "Macro \"%s\" not defined -- %d byte buffer exceeded.\n", name, MACBUFLEN);
  1688. X            return -1;
  1689. X        }
  1690. X        (void) strcpy(tmp, cp);
  1691. X        tmp += len;
  1692. X    }
  1693. X}    /* make_macro */
  1694. X
  1695. X
  1696. X
  1697. X
  1698. Xint macdef(int argc, char **argv)
  1699. X{
  1700. X    if (argc < 2)
  1701. X        argv = re_makeargv("(macro name) ", &argc);
  1702. X    if (argc != 2) {
  1703. X        (void) domacro(0, NULL);
  1704. X        return USAGE;
  1705. X    }
  1706. X    (void) printf("Enter macro line by line, terminating it with a blank line\n");
  1707. X    (void) make_macro(argv[1], stdin);
  1708. X    return NOERR;
  1709. X}    /* macdef */
  1710. X
  1711. X
  1712. X
  1713. X
  1714. Xint domacro(int argc, char **argv)
  1715. X{
  1716. X    register int            i, j;
  1717. X    register char            *cp1, *cp2;
  1718. X    int                        count = 2, loopflg = 0;
  1719. X    string                    str;
  1720. X    struct cmd                *c;
  1721. X
  1722. X    if (argc < 2) {
  1723. X        /* print macros. */
  1724. X        if (macnum == 0)
  1725. X            (void) printf("No macros defined.\n");
  1726. X        else {
  1727. X            (void) printf("Current macro definitions:\n");
  1728. X            for (i = 0; i < macnum; ++i) {
  1729. X                (void) printf("%s:\n", macros[i].mac_name);
  1730. X                cp1 = macros[i].mac_start;
  1731. X                cp2 = macros[i].mac_end;
  1732. X                while (cp1 < cp2) {
  1733. X                    (void) printf("   > ");
  1734. X                    while (cp1 < cp2 && *cp1)
  1735. X                        putchar(*cp1++);
  1736. X                    ++cp1;
  1737. X                }
  1738. X            }
  1739. X        }
  1740. X        if (argc == 0) return (NOERR);    /* called from macdef(), above. */
  1741. X        argv = re_makeargv("(macro to run) ", &argc);
  1742. X    }            
  1743. X    if (argc < 2) {
  1744. X        return USAGE;
  1745. X    }
  1746. X    for (i = 0; i < macnum; ++i) {
  1747. X        if (!strncmp(argv[1], macros[i].mac_name, (size_t) 9)) {
  1748. X            break;
  1749. X        }
  1750. X    }
  1751. X    if (i == macnum) {
  1752. X        (void) printf("'%s' macro not found.\n", argv[1]);
  1753. X        return USAGE;
  1754. X    }
  1755. X    (void) Strncpy(str, line);
  1756. XTOP:
  1757. X    cp1 = macros[i].mac_start;
  1758. X    while (cp1 != macros[i].mac_end) {
  1759. X        while (isspace(*cp1)) {
  1760. X            cp1++;
  1761. X        }
  1762. X        cp2 = line;
  1763. X        while (*cp1 != '\0') {
  1764. X              switch(*cp1) {
  1765. X                   case '\\':
  1766. X                 *cp2++ = *++cp1;
  1767. X                 break;
  1768. X                case '$':
  1769. X                 if (isdigit(*(cp1+1))) {
  1770. X                    j = 0;
  1771. X                    while (isdigit(*++cp1)) {
  1772. X                      j = 10*j +  *cp1 - '0';
  1773. X                    }
  1774. X                    cp1--;
  1775. X                    if (argc - 2 >= j) {
  1776. X                    (void) strcpy(cp2, argv[j+1]);
  1777. X                    cp2 += strlen(argv[j+1]);
  1778. X                    }
  1779. X                    break;
  1780. X                 }
  1781. X                 if (*(cp1+1) == 'i') {
  1782. X                    loopflg = 1;
  1783. X                    cp1++;
  1784. X                    if (count < argc) {
  1785. X                       (void) strcpy(cp2, argv[count]);
  1786. X                       cp2 += strlen(argv[count]);
  1787. X                    }
  1788. X                    break;
  1789. X                }
  1790. X                /* intentional drop through */
  1791. X                default:
  1792. X                *cp2++ = *cp1;
  1793. X                break;
  1794. X              }
  1795. X              if (*cp1 != '\0') {
  1796. X                    cp1++;
  1797. X              }
  1798. X        }
  1799. X        *cp2 = '\0';
  1800. X        makeargv();
  1801. X        c = getcmd(margv[0]);
  1802. X        if ((c == (struct cmd *) -1) && !parsing_rc) {
  1803. X            (void) printf("?Ambiguous command\n");
  1804. X        } else if (c == NULL && !parsing_rc) {
  1805. X            (void) printf("?Invalid command\n");
  1806. X        } else if (c->c_conn && !connected) {
  1807. X            (void) printf("Not connected.\n");
  1808. X        } else {
  1809. X            if (IS_VVERBOSE)
  1810. X                (void) printf("%s\n",line);
  1811. X            if ((*c->c_handler)(margc, margv) == USAGE)
  1812. X                cmd_usage(c);
  1813. X            (void) strcpy(line, str);
  1814. X            makeargv();
  1815. X            argc = margc;
  1816. X            argv = margv;
  1817. X        }
  1818. X        if (cp1 != macros[i].mac_end) {
  1819. X            cp1++;
  1820. X        }
  1821. X    }
  1822. X    if (loopflg && ++count < argc) {
  1823. X        goto TOP;
  1824. X    }
  1825. X    return NOERR;
  1826. X}    /* domacro */
  1827. X
  1828. X
  1829. X
  1830. X/*
  1831. X * get size of file on remote machine
  1832. X */
  1833. Xint sizecmd(int argc, char **argv)
  1834. X{
  1835. X    string str;
  1836. X
  1837. X    if (argc < 2)
  1838. X        argv = re_makeargv("(remote-file) ", &argc);
  1839. X    if (argc < 2) {
  1840. X        return USAGE;
  1841. X    }
  1842. X    if (rem_glob_one(argv[1]) == 0) {
  1843. X        (void) sprintf(str, "SIZE %s", argv[1]);
  1844. X        (void) verbose_command(str);
  1845. X    }
  1846. X    return NOERR;
  1847. X}    /* sizecmd */
  1848. X
  1849. X
  1850. X
  1851. X
  1852. X/*
  1853. X * get last modification time of file on remote machine
  1854. X */
  1855. Xint modtime(int argc, char **argv)
  1856. X{
  1857. X    int overbose;
  1858. X    string str;
  1859. X
  1860. X    if (argc < 2)
  1861. X        argv = re_makeargv("(remote-file) ", &argc);
  1862. X    if (argc < 2) {
  1863. X        return USAGE;
  1864. X    }
  1865. X    if (rem_glob_one(argv[1]) == 0) {
  1866. X        overbose = verbose;
  1867. X        if (debug == 0)
  1868. X            verbose = V_QUIET;
  1869. X        (void) sprintf(str, "MDTM %s", argv[1]);
  1870. X        if (command(str) == COMPLETE) {
  1871. X            int yy, mo, day, hour, min, sec;
  1872. X            (void) sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
  1873. X                &day, &hour, &min, &sec);
  1874. X            /* might want to print this in local time */
  1875. X            (void) printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
  1876. X                mo, day, yy, hour, min, sec);
  1877. X        } else
  1878. X            (void) fputs(reply_string, stdout);
  1879. X        verbose = overbose;
  1880. X    }
  1881. X    return NOERR;
  1882. X}    /* modtime */
  1883. X
  1884. X
  1885. X
  1886. Xint lookup(int argc, char **argv)
  1887. X{
  1888. X    int i, j, by_name, result = NOERR;
  1889. X    struct hostent *host;        /* structure returned by gethostbyaddr() */
  1890. X    extern int h_errno;
  1891. X#ifdef BAD_INETADDR
  1892. X    struct in_addr addr;        /* address in host order */
  1893. X# define ADDR    addr.s_addr
  1894. X#else
  1895. X    unsigned long addr;            /* address in host order */
  1896. X# define ADDR    addr
  1897. X#endif
  1898. X
  1899. X    if (argc < 2)
  1900. X        argv = re_makeargv("(sitename) ", &argc);
  1901. X    if (argc < 2) {
  1902. X        return USAGE;
  1903. X    }
  1904. X
  1905. X     lasthostname[0] = 0;
  1906. X    for (i=1; i<argc; i++) {
  1907. X        /* does the argument look like an address? */
  1908. X        if (4 == sscanf (argv[i], "%d.%d.%d.%d", &j, &j, &j, &j)) {
  1909. X            /* ip */
  1910. X              addr = inet_addr (argv[i]);
  1911. X              if (ADDR == 0xffffffff) {
  1912. X                 (void) fprintf(stderr, "## could not convert \"%s\" into a valid IP address.\n", argv[i]);
  1913. X                 continue;
  1914. X             }
  1915. X            host = gethostbyaddr ((char *) &ADDR, 4, AF_INET);
  1916. X            by_name = 0;
  1917. X        } else {
  1918. X            /* name */
  1919. X            host = gethostbyname (argv[i]);
  1920. X            by_name = 1;
  1921. X        }
  1922. X        if (host == NULL) {
  1923. X            if (NOT_VQUIET) {
  1924. X                /* gethostxxx error */                
  1925. X                if (h_errno == HOST_NOT_FOUND) {
  1926. X                     (void) printf("%s: lookup error (%d).\n",
  1927. X                         argv[i], h_errno);
  1928. X                     result = h_errno;
  1929. X                 } else {
  1930. X                     (void) printf("%s \"%s\"\n",
  1931. X                         (by_name==0 ? "unknown address" : "unknown host"),
  1932. X                         argv[i]);
  1933. X                     result = 
  1934. X                         h_errno != 0 ? h_errno :
  1935. X                         -1;
  1936. X                }
  1937. X            }
  1938. X         } else {
  1939. X             if (*host->h_name)
  1940. X                 (void) Strncpy(lasthostname, host->h_name);
  1941. X            if (NOT_VQUIET) {
  1942. X                (void) printf("%-32s  ", *host->h_name ? host->h_name : "???");
  1943. X                if (*host->h_addr_list) {
  1944. X                    unsigned long horder;
  1945. X    
  1946. X                    horder = ntohl (*(unsigned long *) *(char **)host->h_addr_list);
  1947. X                    (void) printf ("%lu.%lu.%lu.%lu\n",
  1948. X                        (horder >> 24),
  1949. X                        (horder >> 16) & 0xff,
  1950. X                        (horder >> 8) & 0xff,
  1951. X                        horder & 0xff);
  1952. X                }
  1953. X                else (void) printf("???\n");
  1954. X            }
  1955. X        }
  1956. X    }    /* loop thru all sites */
  1957. X    return result;
  1958. X}    /* lookup */
  1959. X
  1960. X
  1961. X
  1962. X
  1963. Xint getlocalhostname(char *host, size_t size)
  1964. X{
  1965. X    int oldv, r;
  1966. X    char *argv[2];
  1967. X    char domain[64];
  1968. X
  1969. X#ifdef HOSTNAME
  1970. X    (void) strncpy(host, HOSTNAME, size);
  1971. X    return NOERR;
  1972. X#else
  1973. X    *host = 0;
  1974. X    if ((r = gethostname(host, size)) == 0) {
  1975. X        oldv = verbose;
  1976. X        verbose = V_QUIET;
  1977. X        argv[0] = "lookup";
  1978. X        (void) sprintf(line, "lookup %s", host);
  1979. X        (void) makeargv();
  1980. X        if (lookup(margc, margv) == 0 && lasthostname[0]) {
  1981. X            (void) _Strncpy(host, lasthostname, size);
  1982. X#ifdef HAS_DOMAINNAME
  1983. X            if (index(host, '.') == NULL) {
  1984. X                if (getdomainname(domain + 1, sizeof(domain) - 1) == 0) {
  1985. X                    domain[0] = '.';
  1986. X                    (void) _Strncat(host, domain, size);
  1987. X                }
  1988. X            }
  1989. X#endif
  1990. X        }
  1991. X        verbose = oldv;
  1992. X    }
  1993. X    return r;
  1994. X#endif
  1995. X}    /* getlocalhostname */
  1996. X
  1997. X
  1998. X
  1999. X
  2000. X/*
  2001. X * show status on remote machine
  2002. X */
  2003. Xint rmtstatus(int argc, char **argv)
  2004. X{
  2005. X    string str;
  2006. X
  2007. X    if (argc > 1) {
  2008. X        (void) sprintf(str, "STAT %s" , argv[1]);
  2009. X        (void) verbose_command(str);
  2010. X    } else (void) verbose_command("STAT");
  2011. X    return NOERR;
  2012. X}    /* rmtstatus */
  2013. X
  2014. X
  2015. X
  2016. X
  2017. X/*
  2018. X * create an empty file on remote machine.
  2019. X */
  2020. Xint create(int argc, char **argv)
  2021. X{
  2022. X    string            str;
  2023. X    FILE            *ftemp;
  2024. X
  2025. X    if (argc < 2)
  2026. X        argv = re_makeargv("(remote-file) ", &argc);
  2027. X    if (argc < 2) {
  2028. X        return USAGE;
  2029. X    }
  2030. X    (void) tmp_name(str);
  2031. X    ftemp = fopen(str, "w");
  2032. X    /* (void) fputc('x', ftemp); */
  2033. X    (void) fclose(ftemp);
  2034. X    creating = 1;
  2035. X    (void) sendrequest("STOR", str, argv[1]);
  2036. X    creating = 0;
  2037. X    (void) unlink(str);
  2038. X    return NOERR;
  2039. X}    /* create */
  2040. X
  2041. X
  2042. X
  2043. X
  2044. X/* show version info */
  2045. X/*ARGSUSED*/
  2046. Xint show_version(int argc, char **argv)
  2047. X{
  2048. X    char    *DStrs[40];
  2049. X    int        nDStrs = 0, i, j;
  2050. X
  2051. X    (void) printf("%s\n%-30s %s\n", version, "Author:",
  2052. X        "Mike Gleason, NCEMRSoft (mgleason@cse.unl.edu).");
  2053. X
  2054. X/* Now entering CPP hell... */
  2055. X#ifdef __DATE__
  2056. X    (void) printf("%-30s %s\n", "Compile Date:", __DATE__);
  2057. X#endif
  2058. X    (void) printf("%-30s %s (%s)\n", "Operating System:",
  2059. X#ifdef System
  2060. X    System,
  2061. X#else
  2062. X#    ifdef unix
  2063. X    "UNIX",
  2064. X#    else
  2065. X    "??",
  2066. X#    endif
  2067. X#endif
  2068. X#ifdef SYSV
  2069. X        "SYSV");
  2070. X#else
  2071. X#    ifdef BSD
  2072. X            "BSD");
  2073. X#    else
  2074. X            "neither BSD nor SYSV?");
  2075. X#    endif
  2076. X#endif
  2077. X
  2078. X    /* Show which CPP symbols were used in compilation. */
  2079. X#ifdef __GNUC__
  2080. X    DStrs[nDStrs++] = "__GNUC__";
  2081. X#endif
  2082. X#ifdef RINDEX
  2083. X    DStrs[nDStrs++] = "RINDEX";
  2084. X#endif
  2085. X#ifdef CURSES
  2086. X    DStrs[nDStrs++] = "CURSES";
  2087. X#endif
  2088. X#ifdef HERROR
  2089. X    DStrs[nDStrs++] = "HERROR";
  2090. X#endif
  2091. X#ifdef U_WAIT
  2092. X    DStrs[nDStrs++] = "U_WAIT";
  2093. X#endif
  2094. X#if defined(NO_CONST) || defined(const)
  2095. X    DStrs[nDStrs++] = "NO_CONST";
  2096. X#endif
  2097. X#ifdef GETPASS
  2098. X    DStrs[nDStrs++] = "GETPASS";
  2099. X#endif
  2100. X#ifdef GETCWDSIZET
  2101. X    DStrs[nDStrs++] = "GETCWDSIZET";
  2102. X#endif
  2103. X#ifdef HOSTNAME
  2104. X    DStrs[nDStrs++] = "HOSTNAME";
  2105. X#endif
  2106. X#ifdef SYSDIRH
  2107. X    DStrs[nDStrs++] = "SYSDIRH";
  2108. X#endif
  2109. X#ifdef SYSSELECTH
  2110. X    DStrs[nDStrs++] = "SYSSELECTH";
  2111. X#endif
  2112. X#ifdef NO_UNISTDH 
  2113. X    DStrs[nDStrs++] = "NO_UNISTDH";
  2114. X#endif
  2115. X#ifdef NO_STDLIBH
  2116. X    DStrs[nDStrs++] = "NO_STDLIBH";
  2117. X#endif
  2118. X#ifdef SYSLOG 
  2119. X    DStrs[nDStrs++] = "SYSLOG";
  2120. X#endif
  2121. X#ifdef BAD_INETADDR
  2122. X    DStrs[nDStrs++] = "BAD_INETADDR";
  2123. X#endif
  2124. X#ifdef SGTTYB
  2125. X    DStrs[nDStrs++] = "SGTTYB";
  2126. X#endif
  2127. X#ifdef TERMIOS
  2128. X    DStrs[nDStrs++] = "TERMIOS";
  2129. X#endif
  2130. X#ifdef STRICT_PROTOS
  2131. X    DStrs[nDStrs++] = "STRICT_PROTOS";
  2132. X#endif
  2133. X#ifdef dFTP_PORT
  2134. X    DStrs[nDStrs++] = "dFTP_PORT";
  2135. X#endif
  2136. X#ifdef BROKEN_MEMCPY
  2137. X    DStrs[nDStrs++] = "BROKEN_MEMCPY";
  2138. X#endif
  2139. X#ifdef READLINE
  2140. X    DStrs[nDStrs++] = "READLINE";
  2141. X#endif
  2142. X#ifdef GETLINE 
  2143. X    DStrs[nDStrs++] = "GETLINE";
  2144. X#endif
  2145. X#ifdef _POSIX_SOURCE
  2146. X    DStrs[nDStrs++] = "_POSIX_SOURCE";
  2147. X#endif
  2148. X#ifdef NO_TIPS
  2149. X    DStrs[nDStrs++] = "NO_TIPS";
  2150. X#endif
  2151. X#ifdef NO_UTIMEH 
  2152. X    DStrs[nDStrs++] = "NO_UTIMEH";
  2153. X#endif
  2154. X#ifdef DB_ERRS
  2155. X    DStrs[nDStrs++] = "DB_ERRS";
  2156. X#endif
  2157. X#ifdef NO_VARARGS 
  2158. X    DStrs[nDStrs++] = "NO_VARARGS";
  2159. X#endif
  2160. X#ifdef GATEWAY
  2161. X    DStrs[nDStrs++] = "GATEWAY";
  2162. X#endif
  2163. X#ifdef SOCKS
  2164. X    DStrs[nDStrs++] = "SOCKS";
  2165. X#endif
  2166. X
  2167. X/* DONE with #ifdefs for now! */
  2168. X
  2169. X    (void) printf ("\nCompile Options:\n");
  2170. X    for (i=j=0; i<nDStrs; i++) {
  2171. X        if (j == 0)
  2172. X            (void) printf("    ");
  2173. X        (void) printf("%-15s", DStrs[i]);
  2174. X        if (++j == 4) {
  2175. X            j = 0;
  2176. X            (void) putchar('\n');
  2177. X        }
  2178. X    }
  2179. X    if (j != 0)
  2180. X        (void) putchar('\n');
  2181. X
  2182. X#ifdef MK
  2183. X    (void) printf("\nMK: %s\n", MK);
  2184. X#endif /* MK */
  2185. X
  2186. X    (void) printf("\nDefaults:\n");
  2187. X    (void) printf("\
  2188. X    Xfer Buf Size: %8d   Debug: %d   MPrompt: %d   Verbosity: %d\n\
  2189. X    Prompt: %s   Pager: %s  ZCat: %s\n\
  2190. X    Logname: %s   Logging: %d   Type: %s   Cmd Len: %d\n\
  2191. X    Recv Line Len: %d   #Macros: %d   Macbuf: %d  Auto-Binary: %d\n\
  2192. X    Recent File: %s   Recent On: %d   nRecents: %d\n\
  2193. X    Redial Delay: %d  Anon Open: %d  New Mail Message: \"%s\"\n",
  2194. X        MAX_XFER_BUFSIZE, dDEBUG, dMPROMPT, dVERBOSE,
  2195. X        dPROMPT, dPAGER, ZCAT,
  2196. X        dLOGNAME, dLOGGING, dTYPESTR, CMDLINELEN,
  2197. X        RECEIVEDLINELEN, MAXMACROS, MACBUFLEN, dAUTOBINARY,
  2198. X        dRECENTF, dRECENT_ON, dMAXRECENTS,
  2199. X        dREDIALDELAY, dANONOPEN, NEWMAILMESSAGE
  2200. X    );
  2201. X#ifdef GATEWAY
  2202. X    (void) printf("\
  2203. X    Gateway Login: %s\n", dGATEWAY_LOGIN);
  2204. X#endif
  2205. X    return NOERR;
  2206. X}    /* show_version */
  2207. X
  2208. X
  2209. X
  2210. Xvoid PurgeLineBuffer(void)
  2211. X{
  2212. X    register struct lslist *a, *b;
  2213. X         
  2214. X    for (a = lshead; a != NULL; ) {
  2215. X        b = a->next;
  2216. X        if (a->string)
  2217. X            free(a->string);    /* free string */
  2218. X        free(a);                /* free node */
  2219. X        a = b;
  2220. X    }
  2221. X    lshead = lstail = NULL;
  2222. X}    /* PurgeLineBuffer */
  2223. X
  2224. X
  2225. X
  2226. X
  2227. X/*ARGSUSED*/
  2228. Xint ShowLineBuffer(int argc, char **argv)
  2229. X{
  2230. X    register struct lslist *a = lshead;
  2231. X    int pagemode;
  2232. X    FILE *fp;
  2233. X    sig_t oldintp;
  2234. X
  2235. X    if (a == NULL)
  2236. X        return CMDERR;
  2237. X    pagemode= (**argv) == 'p' && pager[0] == '|';
  2238. X    if (pagemode) {
  2239. X        fp = popen(pager + 1, "w");
  2240. X        if (!fp) {
  2241. X            PERROR("ShowLineBuffer", pager + 1);
  2242. X            return CMDERR;
  2243. X        }
  2244. X    } else
  2245. X        fp = stdout;
  2246. X    oldintp = Signal(SIGPIPE, SIG_IGN);
  2247. X    while (a) {
  2248. X        if (a->string)
  2249. X            (void) fprintf(fp, "%s\n", a->string);
  2250. X        a = a->next;
  2251. X    }
  2252. X    if (pagemode)
  2253. X        (void) pclose(fp);
  2254. X    if (oldintp)
  2255. X        (void) Signal(SIGPIPE, oldintp);
  2256. X    return NOERR;
  2257. X}    /* ShowLineBuffer */
  2258. X
  2259. X
  2260. X
  2261. X
  2262. X/*ARGSUSED*/
  2263. Xint unimpl(int argc, char **argv)
  2264. X{
  2265. X    if (!parsing_rc)
  2266. X        (void) printf("%s: command not supported. (and probably won't ever be).\n", argv[0]);
  2267. X    return (NOERR);
  2268. X}    /* unimpl */
  2269. X
  2270. X/* eof cmds.c */
  2271. END_OF_FILE
  2272.   if test 38637 -ne `wc -c <'cmds.c'`; then
  2273.     echo shar: \"'cmds.c'\" unpacked with wrong size!
  2274.   fi
  2275.   # end of 'cmds.c'
  2276. fi
  2277. if test -f 'cmds.h' -a "${1}" != "-c" ; then 
  2278.   echo shar: Will not clobber existing file \"'cmds.h'\"
  2279. else
  2280.   echo shar: Extracting \"'cmds.h'\" \(3287 characters\)
  2281.   sed "s/^X//" >'cmds.h' <<'END_OF_FILE'
  2282. X/* cmds.h */
  2283. X
  2284. X#ifndef _cmd_h_
  2285. X#define _cmd_h_
  2286. X
  2287. X/*  $RCSfile: cmds.h,v $
  2288. X *  $Revision: 14020.11 $
  2289. X *  $Date: 93/07/09 10:58:19 $
  2290. X */
  2291. X
  2292. X/* Verbosity levels. */
  2293. X#define V_QUIET        -1
  2294. X#define V_ERRS        0
  2295. X#define V_TERSE        1
  2296. X#define V_VERBOSE    2
  2297. X#define V_IMPLICITCD 4
  2298. X#define IS_VQUIET    (verbose <= V_QUIET)
  2299. X#define IS_VERRS    (verbose == V_ERRS)
  2300. X#define IS_VTERSE    (verbose == V_TERSE)
  2301. X#define IS_VVERBOSE    (verbose == V_VERBOSE)
  2302. X#define NOT_VQUIET    (verbose > V_QUIET)
  2303. X
  2304. X/* Open modes. */
  2305. X#define OPEN_A 1
  2306. X#define OPEN_U 0
  2307. X
  2308. X#define LS_FLAGS_AND_FILE '\1'
  2309. X
  2310. X/* Command result codes. */
  2311. X#define USAGE (88)
  2312. X#define NOERR (0)
  2313. X#define CMDERR (-1)
  2314. X
  2315. X/*
  2316. X * Format of command table.
  2317. X */
  2318. Xstruct cmd {
  2319. X    char    *c_name;    /* name of command */
  2320. X    char    c_conn;        /* must be connected to use command */
  2321. X    char    c_hidden;    /* a hidden command or alias (won't show up in help) */
  2322. X    int        (*c_handler)(int, char **);    /* function to call */
  2323. X    char    *c_help;    /* help string */
  2324. X    char    *c_usage;    /* usage string or NULL, to ask the function itself. */
  2325. X};
  2326. X
  2327. X#define NCMDS ((int) ((sizeof (cmdtab) / sizeof (struct cmd)) - 1))
  2328. X
  2329. Xstruct macel {
  2330. X    char mac_name[9];    /* macro name */
  2331. X    char *mac_start;    /* start of macro in macbuf */
  2332. X    char *mac_end;        /* end of macro in macbuf */
  2333. X};
  2334. X
  2335. Xstruct types {
  2336. X    char    *t_name;
  2337. X    char    *t_mode;
  2338. X    int        t_type;
  2339. X    char    *t_arg;
  2340. X};
  2341. X
  2342. Xstruct lslist {
  2343. X    char            *string;
  2344. X    struct lslist    *next;
  2345. X};
  2346. X
  2347. Xint settype(int argc, char **argv);
  2348. Xint _settype(char *typename);
  2349. Xint setbinary(int argc, char **argv);
  2350. Xint setascii(int argc, char **argv);
  2351. Xint put(int argc, char **argv);
  2352. Xint mput(int argc, char **argv);
  2353. Xint rem_glob_one(char *pattern);
  2354. Xint get(int argc, char **argv);
  2355. Xvoid mabort SIG_PARAMS;
  2356. Xint mget(int argc, char **argv);
  2357. Xchar *remglob(char *argv[]);
  2358. Xint setverbose(int argc, char **argv);
  2359. Xint setprompt(int argc, char **argv);
  2360. Xint setdebug(int argc, char **argv);
  2361. Xvoid fix_options(void);
  2362. Xint cd(int argc, char **argv);
  2363. Xint implicit_cd(char *dir);
  2364. Xint _cd(char *dir);
  2365. Xint lcd(int argc, char **argv);
  2366. Xint do_delete(int argc, char **argv);
  2367. Xint mdelete(int argc, char **argv);
  2368. Xint renamefile(int argc, char **argv);
  2369. Xint ls(int argc, char **argv);
  2370. Xint shell(int argc, char **argv);
  2371. Xint do_user(int argc, char **argv);
  2372. Xint pwd(int argc, char **argv);
  2373. Xint makedir(int argc, char **argv);
  2374. Xint removedir(int argc, char **argv);
  2375. Xint quote(int argc, char **argv);
  2376. Xint rmthelp(int argc, char **argv);
  2377. Xint quit(int argc, char **argv);
  2378. Xvoid close_streams(int wantShutDown);
  2379. Xint disconnect(int argc, char **argv);
  2380. Xvoid close_up_shop(void);
  2381. Xint globulize(char **cpp);
  2382. Xint cdup(int argc, char **argv);
  2383. Xint syst(int argc, char **argv);
  2384. Xint make_macro(char *name, FILE *fp);
  2385. Xint macdef(int argc, char **argv);
  2386. Xint domacro(int argc, char **argv);
  2387. Xint sizecmd(int argc, char **argv);
  2388. Xint modtime(int argc, char **argv);
  2389. Xint lookup(int argc, char **argv);
  2390. Xint rmtstatus(int argc, char **argv);
  2391. Xint create(int argc, char **argv);
  2392. Xint getlocalhostname(char *host, size_t size);
  2393. Xint show_version(int argc, char **argv);
  2394. Xvoid PurgeLineBuffer(void);
  2395. Xint ShowLineBuffer(int argc, char **argv);
  2396. Xint unimpl(int argc, char **argv);
  2397. Xlong GetDateAndSize(char *fName, unsigned long *mod_time);
  2398. Xint SetTypeByNumber(int i);
  2399. X
  2400. X/* In util.c: */
  2401. Xvoid cmd_help(struct cmd *c);
  2402. Xvoid cmd_usage(struct cmd *c);
  2403. Xstruct cmd *getcmd(char *name);
  2404. X
  2405. X#endif    /* _cmd_h_ */
  2406. END_OF_FILE
  2407.   if test 3287 -ne `wc -c <'cmds.h'`; then
  2408.     echo shar: \"'cmds.h'\" unpacked with wrong size!
  2409.   fi
  2410.   # end of 'cmds.h'
  2411. fi
  2412. if test -f 'open.h' -a "${1}" != "-c" ; then 
  2413.   echo shar: Will not clobber existing file \"'open.h'\"
  2414. else
  2415.   echo shar: Extracting \"'open.h'\" \(1194 characters\)
  2416.   sed "s/^X//" >'open.h' <<'END_OF_FILE'
  2417. X/* open.h */
  2418. X
  2419. X#ifndef _open_h_
  2420. X#define _open_h_ 1
  2421. X
  2422. X/* Variables for Open() that can be changed from the command line. */
  2423. Xtypedef struct OpenOptions {
  2424. X    int                openmode;
  2425. X    int                ignore_rc;
  2426. X    unsigned int    port;
  2427. X    int                redial_delay;
  2428. X    int                max_dials;
  2429. X    int                ftpcat;
  2430. X    Hostname        hostname;
  2431. X    longstring        cdpath;
  2432. X    longstring        colonmodepath;
  2433. X} OpenOptions;
  2434. X
  2435. X/* Open modes. */
  2436. X#define openImplicitAnon 1
  2437. X#define openImplicitUser 4
  2438. X#define openExplicitAnon 3
  2439. X#define openExplicitUser 2
  2440. X
  2441. X#define ISUSEROPEN(a) ((a==openImplicitUser)||(a==openExplicitUser))
  2442. X#define ISANONOPEN(a) (!ISUSEROPEN(a))
  2443. X#define ISEXPLICITOPEN(a) ((a==openExplicitAnon)||(a==openExplicitUser))
  2444. X#define ISIMPLICITOPEN(a) (!ISEXPLICITOPEN(a))
  2445. X
  2446. X/* ftpcat modes. */
  2447. X#define NO_FTPCAT    0
  2448. X#define FTPCAT        1
  2449. X#define FTPMORE        2
  2450. X
  2451. X/* Protos: */
  2452. Xint InitOpenOptions(OpenOptions *openopt);
  2453. Xint GetOpenOptions(int argc, char **argv, OpenOptions *openopt);
  2454. Xint CheckForColonMode(OpenOptions *openopt, int *login_verbosity);
  2455. Xint HookupToRemote(OpenOptions *openopt);
  2456. Xvoid CheckRemoteSystemType(OpenOptions *openopt);
  2457. Xvoid ColonMode(OpenOptions *openopt);
  2458. Xint Open(OpenOptions *openopt);
  2459. Xint cmdOpen(int argc, char **argv);
  2460. X
  2461. X#endif    /* _open_h_ */
  2462. END_OF_FILE
  2463.   if test 1194 -ne `wc -c <'open.h'`; then
  2464.     echo shar: \"'open.h'\" unpacked with wrong size!
  2465.   fi
  2466.   # end of 'open.h'
  2467. fi
  2468. echo shar: End of archive 1 \(of 5\).
  2469. cp /dev/null ark1isdone
  2470. MISSING=""
  2471. for I in 1 2 3 4 5 ; do
  2472.     if test ! -f ark${I}isdone ; then
  2473.     MISSING="${MISSING} ${I}"
  2474.     fi
  2475. done
  2476. if test "${MISSING}" = "" ; then
  2477.     echo You have unpacked all 5 archives.
  2478.     rm -f ark[1-9]isdone
  2479. else
  2480.     echo You still must unpack the following archives:
  2481.     echo "        " ${MISSING}
  2482. fi
  2483. exit 0
  2484. exit 0 # Just in case...
  2485.