home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume39 / ncftp / part04 < prev    next >
Encoding:
Text File  |  1993-08-25  |  60.6 KB  |  2,714 lines

  1. Newsgroups: comp.sources.misc
  2. From: mgleason@cse.unl.edu (Mike Gleason)
  3. Subject: v39i056:  ncftp - Alternative User Interface for FTP, v1.5.0, Part04/05
  4. Message-ID: <1993Aug26.000638.24466@sparky.sterling.com>
  5. X-Md4-Signature: fee606c92f461f0d8a67e46bcb065356
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: NCEMRSoft
  8. Date: Thu, 26 Aug 1993 00:06:38 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: mgleason@cse.unl.edu (Mike Gleason)
  12. Posting-number: Volume 39, Issue 56
  13. Archive-name: ncftp/part04
  14. Environment: UNIX, ANSI-C, !SVR4
  15. Supersedes: ncftp: Volume 35, Issue 4-7
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  cmdtab.c ftprc.c getpass.h glob.c set.c util.c
  22. # Wrapped by kent@sparky on Wed Aug 25 18:59:17 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 4 (of 5)."'
  26. if test -f 'cmdtab.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'cmdtab.c'\"
  28. else
  29.   echo shar: Extracting \"'cmdtab.c'\" \(10938 characters\)
  30.   sed "s/^X//" >'cmdtab.c' <<'END_OF_FILE'
  31. X/* cmdtab.c */
  32. X
  33. X/*  $RCSfile: cmdtab.c,v $
  34. X *  $Revision: 14020.11 $
  35. X *  $Date: 93/07/09 11:04:56 $
  36. X */
  37. X
  38. X#include "sys.h"
  39. X#include <sys/types.h>
  40. X#include <sys/time.h>
  41. X#include "util.h"
  42. X#include "cmds.h"
  43. X#include "main.h"
  44. X#include "ftp.h"
  45. X#include "ftprc.h"
  46. X#include "glob.h"
  47. X#include "open.h"
  48. X#include "set.h"
  49. X#include "copyright.h"
  50. X
  51. X#define REMOTEFILE " remote-file-name"
  52. X#define REMOTEFILES " remote-file-names and/or UNIX-style-wildcards"
  53. X#define LOCALFILE " local-file-name"
  54. X#define LOCALFILES " local-file-names and/or UNIX-style-wildcards"
  55. X#define LDIRNAME " local-directory-name"
  56. X#define RMTDIRNAME " remote-directory-name"
  57. X#define EMPTYSTR ""
  58. X#define TOGGLE " [on | off] (no argument toggles the switch)"
  59. X
  60. X#define BINARYHELP "transfer files as binary files, without CR/LF translation"
  61. X#define BINARYUSAGE EMPTYSTR
  62. X
  63. X#define CHDIRHELP "changes the current remote working directory"
  64. X#define CHDIRUSAGE RMTDIRNAME
  65. X
  66. X#define CLOSEHELP "closes FTP connection to current remote host"
  67. X#define CLOSEUSAGE EMPTYSTR
  68. X
  69. X#define DELETEHELP "deletes the specified file on the remote host"
  70. X#define DELETEUSAGE REMOTEFILE
  71. X
  72. X#define DIRUSAGE " \
  73. X[flags] [remote-items] [>outfile or \"|pipecmd [cmd-args]\"]\n\
  74. X    Note that there must be no whitespace between > and outfile, or | and\n\
  75. X    pipecmd, and if the pipe-command needs arguments, you must enclose the\n\
  76. X    whole thing with double quotes.\n\
  77. XExamples:\n\
  78. X    dir -s\n\
  79. X    dir remoteFile\n\
  80. X    dir /pub/mac \"|head -20\"\n\
  81. X    dir -rtR file1 file2 dir1 >contents.txt"
  82. X
  83. X#define GETUSAGE " remote-file-name [local-file-name or |pipecommand]\n\
  84. XExamples:\n\
  85. X    get myfile.txt\n\
  86. X    get MYFILE.ZIP myfile.zip\n\
  87. X    get myfile.txt |head\n\
  88. X    get myfile.txt \"|head -20\"\n\
  89. X    get ./help/newuser.txt    (./newuser.txt will be local-file-name)\n\
  90. X    get ./help/newuser.txt ./docs/newbie.help\n\
  91. X    get my*.txt  (pseudo-filename-completion if match is unique, i.e. myfile.txt)"
  92. X
  93. X#define    HELPHELP "shows commands, and optionally tell you how to use a specific one"
  94. X#define    HELPUSAGE " [command-name | showall (shows hidden commands) | helpall"
  95. X
  96. X#define LSHELP "prints remote directory contents (short-mode)"
  97. X#define LSUSAGE " \
  98. X[flags] [remote-items] [>outfile or \"|pipecmd [cmd-args]\"]\n\
  99. X    Note that there must be no whitespace between > and outfile, or | and\n\
  100. X    pipecmd, and if the pipe-command needs arguments, you must enclose the\n\
  101. X    whole thing with double quotes.\n\
  102. XExamples:\n\
  103. X    ls -s\n\
  104. X    ls remoteFile\n\
  105. X    ls /pub/mac \"|head -20\"\n\
  106. X    ls -lrtR file1 file2 dir1 >contents.txt"
  107. X
  108. X#define OPENHELP "connects to a new remote host, and optionally fetches a file\n\
  109. X    or sets the current remote working directory"
  110. X#define OPENUSAGE " \
  111. X[-a | -u] [-i] [-p N] [-r [-d N] [-g N]] hostname[:pathname]\n\
  112. X    -a     : Open anonymously (this is the default).\n\
  113. X    -u     : Open, specify user/password.\n\
  114. X    -i     : Ignore machine entry in your .netrc.\n\
  115. X    -p N   : Use port #N for connection.\n\
  116. X    -r     : \"Redial\" until connected.\n\
  117. X    -d N   : Redial, pausing N seconds between tries.\n\
  118. X    -g N   : Redial, giving up after N tries.\n\
  119. X    :path  : Open site, then retrieve file \"path.\""
  120. X
  121. X#define PAGEHELP "view a file on the remote host with your $PAGER"
  122. X#define PAGEUSAGE REMOTEFILE
  123. X
  124. X#define PDIRUSAGE " [flags] [remote-files]"
  125. X
  126. X#define PUTHELP "sends a local file to the current remote host"
  127. X#define PUTUSAGE " local-file-name [remote-file-name]"
  128. X
  129. X#define QUITHELP "quits the program"
  130. X#define QUITUSAGE EMPTYSTR
  131. X
  132. X#define RHELPHELP "asks the remote-server for help"
  133. X#define RHELPUSAGE " [help-topic (i.e. FTP command)]"
  134. X
  135. X#define UNIMPLHELP "this command is not supported"
  136. X#define UNIMPLUSAGE (NULL)
  137. X
  138. Xstruct cmd cmdtab[] = {
  139. X    /* name ; must-be-connected ; hidden ; help-string ; usage-string */
  140. X    { "!",                0,  0,  shell,
  141. X        "spawns a shell for you to run other commands",
  142. X        " [single-command-and-arguments]" },
  143. X    { "$",                0,  0,  domacro,
  144. X        "runs a macro previously defined in your NETRC, or with the macdef cmd",
  145. X        "macro-number" },
  146. X    { "account",       0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  147. X    { "append",        0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  148. X    { "ascii",            1,  1,  setascii,
  149. X        "transfer files as text files, with proper CR/LF translation",
  150. X        "" },
  151. X    { "bell",          0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  152. X    { "binary",           1,  1,  setbinary, BINARYHELP, BINARYUSAGE },
  153. X    { "bye",              0,  1,  quit, QUITHELP, QUITUSAGE },
  154. X    { "case",          0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  155. X    { "cd",               1,  0,  cd, CHDIRHELP, CHDIRUSAGE },
  156. X    { "cdup",             1,  0,  cdup,
  157. X        "changes the current remote working directory to it's parent",
  158. X        "" },
  159. X    { "chdir",            1,  1,  cd, CHDIRHELP, CHDIRUSAGE },
  160. X    { "close",            1,  1,  disconnect, CLOSEHELP, CLOSEUSAGE },
  161. X    { "connect",          0,  1,  cmdOpen, OPENHELP, OPENUSAGE },
  162. X    { "cr",            0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  163. X    { "create",           1,  0,  create,
  164. X        "create an empty file on the remote host",
  165. X        REMOTEFILE },
  166. X    { "delete",           1,  0,  do_delete, DELETEHELP, DELETEUSAGE },
  167. X    { "debug",            0,  1,  setdebug,
  168. X        "to print debugging messages during execution of the program",
  169. X        TOGGLE },
  170. X    { "dir",              1,  0,  ls,
  171. X        "prints remote directory contents (long-mode)",
  172. X        DIRUSAGE },
  173. X    { "erase",            1,  1,  do_delete, DELETEHELP, DELETEUSAGE },
  174. X    { "exit",             0,  1,  quit, QUITHELP, QUITUSAGE },
  175. X    { "form",          0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  176. X    { "get",              1,  0,  get,
  177. X        "fetches a file from the current remote host", GETUSAGE },
  178. X    { "glob",          0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  179. X    { "hash",             0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  180. X    { "help",             0,  0,  help, HELPHELP, HELPUSAGE },
  181. X    { "idle",             0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  182. X    { "image",            1,  1,  setbinary, BINARYHELP, BINARYUSAGE },
  183. X    { "lcd",              0,  0,  lcd,
  184. X        "changes the current local directory", LDIRNAME },
  185. X    { "lookup",           0,  0,  lookup,
  186. X        "uses the name-server to tell you a host's IP number given it's\n\
  187. X    name, or it's name given it's IP number",
  188. X        " hostname | host-IP-number" },
  189. X    { "ls",               1,  0,  ls, LSHELP, LSUSAGE },
  190. X    { "macdef",           0,  0,  macdef,
  191. X        "defines a macro which is expanded when you use the $ command",
  192. X        " new-macro-name" },
  193. X    { "mdelete",          1,  0,  mdelete,
  194. X        "deletes multiple files on the remote host", REMOTEFILES  },
  195. X    { "mdir",             1,  1,  ls, LSHELP, LSUSAGE },
  196. X    { "mget",             1,  0,  mget,
  197. X        "fetches multiple files from the remote host", REMOTEFILES },
  198. X    { "mkdir",            1,  0,  makedir,
  199. X        "creates a new sub-directory on the current remote host",
  200. X        RMTDIRNAME },
  201. X    { "mls",              1,  0,  ls, LSHELP, LSUSAGE },
  202. X    { "mode",          0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  203. X    { "modtime",          1,  0,  modtime,
  204. X        "shows the last modification date for a remote file",
  205. X        REMOTEFILE },
  206. X    { "more",             1,  1,  get, PAGEHELP, PAGEUSAGE },
  207. X    { "mput",             1,  0,  mput,
  208. X        "sends multiple local files to the current remote host",
  209. X        LOCALFILES },
  210. X    { "newer",         0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  211. X    { "nlist",            1,  1,  ls, LSHELP, LSUSAGE },
  212. X    { "nmap",          0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  213. X    { "ntrans",        0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  214. X    { "open",             0,  0,  cmdOpen, OPENHELP, OPENUSAGE },
  215. X    { "p",             1,  1,  get, PAGEHELP, PAGEUSAGE },
  216. X    { "page",             1,  0,  get, PAGEHELP, PAGEUSAGE },
  217. X    { "pdir",             1,  0,  ls,
  218. X        "view a remote directory listing (long mode) with your $PAGER",
  219. X        PDIRUSAGE },
  220. X    { "pls",              1,  0,  ls,
  221. X        "view a remote directory listing (short mode) with your $PAGER",
  222. X        PDIRUSAGE },
  223. X    { "predir",           1,  0,  ShowLineBuffer,
  224. X        "view the last remote directory listing with your $PAGER",
  225. X        EMPTYSTR },
  226. X    { "prompt",           0,  1,  setprompt,
  227. X        "toggle interactive prompting on multiple commands",
  228. X        TOGGLE },
  229. X    { "proxy",         0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  230. X    { "put",              1,  0,  put, PUTHELP, PUTUSAGE },
  231. X    { "pwd",              1,  0,  pwd,
  232. X        "prints the name of the current remote directory",
  233. X        EMPTYSTR },
  234. X    { "quit",             0,  0,  quit, QUITHELP, QUITUSAGE },
  235. X    { "quote",            1,  0,  quote,
  236. X        "allows advanced users to directly enter FTP commands verbatim",
  237. X        " FTP-commands" },
  238. X    { "redir",            1,  0,  ShowLineBuffer,
  239. X        "re-prints the last directory listing",
  240. X        EMPTYSTR },
  241. X    { "reget",         0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  242. X    { "remotehelp",       1,  0,  rmthelp, RHELPHELP, RHELPUSAGE },
  243. X    { "reset",         0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  244. X    { "restart",       0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  245. X    { "rm",               1,  1,  do_delete, DELETEHELP, DELETEUSAGE },
  246. X    { "rstatus",          1,  0,  rmtstatus,
  247. X        "asks the remote-server for it's status",
  248. X        EMPTYSTR },
  249. X    { "rhelp",            1,  1,  rmthelp, RHELPHELP, RHELPUSAGE },
  250. X    { "rename",           1,  0,  renamefile,
  251. X        "changes the name of a file on the current remote host",
  252. X        " old-name new-name" },
  253. X    { "rmdir",            1,  0,  removedir,
  254. X        "deletes a directory on the current remote host",
  255. X        RMTDIRNAME },
  256. X    { "runique",       0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  257. X    { "send",             1,  1,  put, PUTHELP, PUTUSAGE },
  258. X    { "sendport",      0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  259. X    { "show",             0,  0,  do_show,
  260. X        "prints the value of some or all program variables",
  261. X        " all | variable-names" },
  262. X    { "set",              0,  0,  set,
  263. X        "changes the value of a program variable; for numeric/boolean\n\
  264. X    variables sets them to 1/true",
  265. X        " variable-name [= new-value]" },
  266. X    { "site",            1,  0,  quote,
  267. X        "allows advanced users to send site-specific commands to the host",
  268. X        " site-specific-commands\n\
  269. XExample (to try on wuarchive.wustl.edu):\n\
  270. X    site locate emacs" },
  271. X    { "size",             1,  0,  sizecmd,
  272. X        "shows the size of a remote file",
  273. X        REMOTEFILE },
  274. X    { "struct",        0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  275. X    { "sunique",       0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  276. X    { "system",           1,  0,  syst,
  277. X        "tells you what type of machine the current remote host is",
  278. X        EMPTYSTR },
  279. X    { "tenex",         0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  280. X    { "umask",         0,  1,  unimpl, UNIMPLHELP, UNIMPLUSAGE },
  281. X    { "unset",            0,  0,  set,
  282. X        "resets the value of a program variable to it's default state, or for\n\
  283. X    numeric/boolean variables, sets them to 0/false",
  284. X        " variable-name" },
  285. X    { "user",             1,  0,  do_user,
  286. X        "lets you login as a new user (with appropriate password)",
  287. X        " new-user-name [new-password]" },
  288. X    { "type",             1,  0,  settype,
  289. X        "changes the current file transfer method",
  290. X        " ascii | binary | ebcdic | tenex" },
  291. X    { "verbose",          0,  0,  setverbose,
  292. X        "controls how many message the program prints in response to commands",
  293. X        " -1 (quiet) | 0 (errs) | 1 (terse) | 2 (verbose)" },
  294. X    { "version",          0,  0,  show_version,
  295. X        "prints information about the program",
  296. X        EMPTYSTR },
  297. X    { "?",                0,  1,  help, HELPHELP, HELPUSAGE },
  298. X    { NULL,               0,  0,  NULL, NULL, NULL }
  299. X};
  300. X
  301. X/* eof cmdtab.c */
  302. END_OF_FILE
  303.   if test 10938 -ne `wc -c <'cmdtab.c'`; then
  304.     echo shar: \"'cmdtab.c'\" unpacked with wrong size!
  305.   fi
  306.   # end of 'cmdtab.c'
  307. fi
  308. if test -f 'ftprc.c' -a "${1}" != "-c" ; then 
  309.   echo shar: Will not clobber existing file \"'ftprc.c'\"
  310. else
  311.   echo shar: Extracting \"'ftprc.c'\" \(11194 characters\)
  312.   sed "s/^X//" >'ftprc.c' <<'END_OF_FILE'
  313. X/* ftprc.c */
  314. X
  315. X/*  $RCSfile: ftprc.c,v $
  316. X *  $Revision: 14020.11 $
  317. X *  $Date: 93/07/09 10:58:37 $
  318. X */
  319. X
  320. X#include "sys.h"
  321. X#include <sys/types.h>
  322. X#include <sys/param.h>
  323. X#include <sys/stat.h>
  324. X
  325. X#include <string.h>
  326. X#include <ctype.h>
  327. X#include <time.h>
  328. X
  329. X#include "util.h"
  330. X#include "ftprc.h"
  331. X#include "main.h"
  332. X#include "cmds.h"
  333. X#include "set.h"
  334. X#include "defaults.h"
  335. X#include "copyright.h"
  336. X
  337. X/* ftprc.c global variables */
  338. Xsiteptr                    firstsite = NULL, lastsite = NULL;
  339. Xrecentsite                recents[dMAXRECENTS];
  340. Xint                        nRecents = 0;
  341. Xint                        nSites = 0;
  342. Xint                        keep_recent = dRECENT_ON;
  343. Xlongstring                rcname;
  344. Xlongstring                recent_file;
  345. Xint                        parsing_rc = 0;
  346. X
  347. Xextern char                *line, *margv[];
  348. Xextern int                margc, fromatty;
  349. Xextern string            anon_password;        /* most likely your email address */
  350. Xextern struct userinfo    uinfo;
  351. X
  352. Xint thrash_rc(void)
  353. X{
  354. X    struct stat            st;
  355. X    string                word, str;
  356. X    longstring            cwd;
  357. X    char                *cp, *dp, *rc;
  358. X    FILE                *fp;
  359. X    int                    i;
  360. X
  361. X    (void) get_cwd(cwd, sizeof(cwd));
  362. X    if (cwd[strlen(cwd) - 1] != '/')
  363. X        (void) Strncat(cwd, "/");
  364. X
  365. X    /* Because some versions of regular ftp complain about ncftp's
  366. X     * #set commands, FTPRC takes precedence over NETRC.
  367. X     */
  368. X    cp = getenv("DOTDIR");
  369. X    for (i=0; i<2; i++) {
  370. X        rc = (i == 0) ? FTPRC : NETRC;
  371. X
  372. X        (void) sprintf(rcname, "%s%s", cwd, rc);
  373. X        if (stat(rcname, &st) == 0)
  374. X            goto foundrc;
  375. X        
  376. X        (void) sprintf(rcname, "%s.%s", cwd, rc);
  377. X        if (stat(rcname, &st) == 0)
  378. X            goto foundrc;
  379. X
  380. X        if (cp != NULL) {
  381. X            (void) sprintf(rcname, "%s/.%s", cp, rc);
  382. X            if (stat(rcname, &st) == 0)
  383. X                goto foundrc;
  384. X        }
  385. X
  386. X        (void) sprintf(rcname, "%s/.%s", uinfo.homedir, rc);
  387. X        if (stat(rcname, &st) == 0)
  388. X            goto foundrc;
  389. X    }
  390. X
  391. X    return (0);    /* it's OK not to have an rc. */
  392. X    
  393. Xfoundrc:    
  394. X    if ((st.st_mode & 077) != 0)                /* rc must be unreadable by others. */
  395. X        (void) chmod(rcname, 0600);
  396. X
  397. X    if ((fp = fopen(rcname, "r")) == NULL) {
  398. X        PERROR("thrash_rc", rcname);
  399. X        return -1;
  400. X    }
  401. X    
  402. X    parsing_rc = 1;
  403. X    while (cp = FGets(str, fp)) {
  404. X        while (isspace(*cp)) ++cp;        /* skip leading space. */
  405. X        if (*cp == '#') {
  406. X            if ((strncmp("set", ++cp, (size_t)3) == 0) || (strncmp("unset", cp, (size_t)5) == 0)) {
  407. X                (void) strcpy(line, cp);
  408. X                makeargv();
  409. X                (void) set(margc, margv);            
  410. X                /* setting or unsetting a variable. */
  411. X            } /* else a comment. */
  412. X        } else {
  413. X            if (strncmp(cp, "machine", (size_t) 7) == 0) {
  414. X                /* We have a new machine record. */
  415. X                cp += 7;
  416. X                while (isspace(*cp)) ++cp;    /* skip delimiting space. */
  417. X                dp = word;
  418. X                while (*cp && !isspace(*cp)) *dp++ = *cp++;    /* copy the name. */
  419. X                *dp = 0;
  420. X                AddNewSitePtr(word);
  421. X            }
  422. X        }
  423. X    }
  424. X    (void) fclose(fp);
  425. X    parsing_rc = 0;
  426. X    return 1;
  427. X}    /* thrash_rc */
  428. X
  429. X
  430. X
  431. X
  432. Xvoid AddNewSitePtr(char *word)
  433. X{
  434. X    siteptr            s;
  435. X
  436. X    if (s = (siteptr) malloc(sizeof(site))) {
  437. X        s->next = NULL;
  438. X        if (s->name = malloc(strlen(word) + 1)) {
  439. X            (void) strcpy(s->name, word);
  440. X            if (firstsite == NULL)
  441. X                firstsite = lastsite = s;
  442. X            else {
  443. X                lastsite->next = s;
  444. X                lastsite = s;
  445. X            }
  446. X            ++nSites;
  447. X        } else {
  448. X            free(s);
  449. X        }
  450. X    }
  451. X}    /* AddNewSitePtr */
  452. X
  453. X
  454. X
  455. X
  456. Xstatic int RecentCmp(recentsite *a, recentsite *b)
  457. X{
  458. X    int i = 1;
  459. X    
  460. X    if (a->lastcall > b->lastcall)
  461. X        i = -1;
  462. X    else if (a->lastcall == b->lastcall)
  463. X        i = 0;
  464. X    return i;
  465. X}    /* RecentCmp */
  466. X
  467. X
  468. X
  469. X
  470. Xstatic siteptr FindNetrcSite(char *host)
  471. X{
  472. X    register siteptr s, s2;
  473. X
  474. X    /* see if 'host' is in our list of favorite sites (in NETRC). */
  475. X    for (s = firstsite; s != NULL; s2=s->next, s=s2) {
  476. X        if (strstr(s->name, host) != NULL) {
  477. X            return s;
  478. X        }
  479. X    }
  480. X    return NULL;
  481. X}    /* FindNetrcSite */
  482. X
  483. X
  484. X
  485. X
  486. Xstatic recentsite *FindRecentSite(char *host)
  487. X{
  488. X    register recentsite        *r;
  489. X    register int            i;
  490. X
  491. X    /* see if 'host' is in our list of favorite sites (in recent-log). */
  492. X    for (i=0; i<nRecents; i++) {
  493. X        r = &recents[i];
  494. X        if (strstr(r->name, host) != NULL) {
  495. X            return r;
  496. X        }
  497. X    }
  498. X    return NULL;
  499. X}    /* FindRecentSite */
  500. X
  501. X
  502. X
  503. X
  504. Xvoid ReadRecentSitesFile(void)
  505. X{
  506. X    FILE *rfp;
  507. X    recentsite *r;
  508. X    char name[64], dir[256];
  509. X    string str;
  510. X
  511. X    nRecents = 0;
  512. X    if (recent_file[0] != 0 && keep_recent) {
  513. X        rfp = fopen(recent_file, "r");
  514. X        if (rfp != NULL) {
  515. X            for (; nRecents < dMAXRECENTS; ) {
  516. X                r = &recents[nRecents];
  517. X                if (FGets(str, rfp) == NULL)
  518. X                    break;
  519. X                if (sscanf(str, "%s %lu %s", name, (unsigned long *) &r->lastcall, dir) == 3) {
  520. X                    if ((r->name = NewString(name)) != NULL) {
  521. X                        r->dir = NewString(dir);
  522. X                        if (r->dir != NULL)
  523. X                            nRecents++;
  524. X                        else free(r->name);
  525. X                    }
  526. X                }
  527. X            }
  528. X            (void) fclose(rfp);
  529. X        }
  530. X    }
  531. X}    /* ReadRecentSitesFile */
  532. X
  533. X
  534. X
  535. Xstatic void SortRecentList(void)
  536. X{
  537. X    QSort(recents, nRecents, sizeof(recentsite), RecentCmp);
  538. X}    /* SortRecentList */
  539. X
  540. X
  541. X
  542. X
  543. Xvoid WriteRecentSitesFile(void)
  544. X{
  545. X    FILE            *rfp;
  546. X    recentsite        *r;
  547. X    int                i;
  548. X
  549. X    if ((recent_file[0] != 0) && (nRecents > 0) && (keep_recent)) {
  550. X        rfp = fopen(recent_file, "w");
  551. X        SortRecentList();
  552. X        if (rfp != NULL) {
  553. X            for (i=0; i<nRecents; i++) {
  554. X                r = &recents[i];
  555. X                (void) fprintf(rfp, "%-32s %11lu %s\n", r->name,
  556. X                    (unsigned long) r->lastcall, r->dir);
  557. X            }
  558. X            (void) fclose(rfp);
  559. X            (void) chmod(recent_file, 0600);
  560. X        }
  561. X    }
  562. X}    /* WriteRecentSitesFile */
  563. X
  564. X
  565. X
  566. X
  567. Xvoid AddRecentSite(char *host, char *lastdir)
  568. X{
  569. X    char            *nhost, *ndir;
  570. X    recentsite        *r;
  571. X    
  572. X    if (keep_recent) {
  573. X        nhost = NewString(host);
  574. X        /* Use '/' to denote that the current directory wasn't known,
  575. X         * because we won't try to cd to the root directory.
  576. X         */
  577. X        ndir = NewString(*lastdir ? lastdir : "/");
  578. X        
  579. X        /* Don't bother if we don't have the memory, or if it is already
  580. X         * in our NETRC.
  581. X         */
  582. X        if ((ndir != NULL) && (nhost != NULL) && (FindNetrcSite(host) == NULL)) {
  583. X            if (nRecents == dMAXRECENTS) {
  584. X                SortRecentList();
  585. X                r = &recents[dMAXRECENTS - 1];
  586. X                if (r->name != NULL)
  587. X                    free(r->name);
  588. X                if (r->dir != NULL)
  589. X                    free(r->dir);
  590. X            } else {
  591. X                r = &recents[nRecents];
  592. X                nRecents++;
  593. X            }
  594. X            r->name = nhost;            
  595. X            r->dir = ndir;
  596. X            (void) time(&r->lastcall);
  597. X            SortRecentList();
  598. X        }
  599. X    }
  600. X}    /* AddRecentSite */
  601. X
  602. X
  603. X
  604. X
  605. X/*
  606. X * After you are done with a site (by closing it or quitting), we
  607. X * need to update the list of recent sites called.
  608. X */
  609. Xvoid UpdateRecentSitesList(char *host, char *lastdir)
  610. X{
  611. X    recentsite *r;
  612. X    char *ndir;
  613. X
  614. X    if (keep_recent) {    
  615. X        r = FindRecentSite(host);
  616. X        if (r == NULL)
  617. X            AddRecentSite(host, lastdir);
  618. X        else {
  619. X            /* Update the last time connected, and the directory we left in. */
  620. X            if ((ndir = NewString(*lastdir ? lastdir : "/")) != NULL) {
  621. X                free(r->dir);
  622. X                r->dir = ndir;
  623. X            }
  624. X            (void) time(&r->lastcall);
  625. X        }
  626. X    }
  627. X}    /* UpdateRecentSitesList */
  628. X
  629. X
  630. X
  631. X/*
  632. X * Prints out the number of sites we know about, so the user can figure out
  633. X * an abbreviation or type it's number to open (setpeer).
  634. X */
  635. Xvoid PrintSiteList(void)
  636. X{
  637. X    int                        i, j;
  638. X    siteptr                    s, s2;
  639. X
  640. X    if (fromatty) {
  641. X        j = 0;
  642. X        i = 1;
  643. X        if (nRecents > 0) {
  644. X            j++;
  645. X            (void) printf("Recently called sites:\n");
  646. X            for (; i<=nRecents; i++) {
  647. X                (void) printf("%4d. %-32s", i, recents[i-1].name);
  648. X                i++;
  649. X                if (i <= nRecents) {
  650. X                    (void) printf("%5d. %-32s", i, recents[i-1].name);
  651. X                } else {
  652. X                    (void) printf("\n");
  653. X                    break;
  654. X                }
  655. X                (void) printf("\n");
  656. X            }
  657. X        }
  658. X        if (nSites > 0) {
  659. X            j++;
  660. X            (void) printf("Sites in your netrc (%s):\n", rcname);
  661. X            for (s = firstsite; s != NULL; s2=s->next, s=s2, ++i) {
  662. X                (void) printf("%4d. %-32s", i, s->name);
  663. X                s2=s->next;
  664. X                s=s2;
  665. X                i++;
  666. X                if (s != NULL) {
  667. X                    (void) printf("%5d. %-32s", i, s->name);
  668. X                } else {
  669. X                    (void) printf("\n");
  670. X                    break;
  671. X                }
  672. X                (void) printf("\n");
  673. X            }
  674. X        }
  675. X        if (j > 0) {
  676. X            (void) printf("\
  677. XNote that you can specify an abbreviation of any name, or #x, where x is the\n\
  678. Xnumber of the site you want to connect to.\n\n");
  679. X        }
  680. X    }
  681. X}    /* PrintRecentSiteList */
  682. X
  683. X
  684. X
  685. X
  686. X/*
  687. X * Given a sitename, check to see if the name was really an abbreviation
  688. X * of a site in the NETRC, or a site in our list of recently connected
  689. X * sites.  Also check if the name was in the format #x, where x which
  690. X * would mean to use recents[x].name as the site; if x was greater than
  691. X * the number of sites in the recent list, then index into the netrc
  692. X * site list.
  693. X */
  694. Xvoid GetFullSiteName(char *host, char *lastdir)
  695. X{
  696. X    register siteptr        s, s2;
  697. X    register recentsite        *r;
  698. X    char                    *ndir, *nhost;
  699. X    int                        x, i;
  700. X
  701. X    ndir = nhost = NULL;
  702. X    x = 0;
  703. X
  704. X    /* see if 'host' is in our list of favorite sites (in NETRC). */
  705. X    if ((s = FindNetrcSite(host)) != NULL) {
  706. X        nhost = s->name;
  707. X    } else if ((r = FindRecentSite(host)) != NULL) {
  708. X        nhost = r->name;
  709. X        ndir = r->dir;
  710. X    } else if (sscanf(host[0]=='#' ? host+1 : host, "%d", &x) != 1) {
  711. X        x = 0;
  712. X    }
  713. X
  714. X    if (--x >= 0) {
  715. X        if (x < nRecents) {
  716. X            nhost = recents[x].name;
  717. X            ndir = recents[x].dir;
  718. X        } else {
  719. X            x -= nRecents;
  720. X            if (x < nSites) {
  721. X                for (i = 0, s = firstsite; i < x; s2=s->next, s=s2)
  722. X                    ++i;                
  723. X                nhost = s->name;
  724. X            }
  725. X        }
  726. X    }
  727. X
  728. X    if (nhost != NULL) {
  729. X        (void) strcpy(host, nhost);
  730. X        if (lastdir != NULL) {
  731. X            *lastdir = 0;
  732. X            /* Don't cd if the dir is the root directory. */
  733. X            if (ndir != NULL && (strcmp("/", ndir) != 0))
  734. X                (void) strcpy(lastdir, ndir);
  735. X        }
  736. X    }
  737. X}    /* GetFullSiteName */
  738. X
  739. X
  740. X
  741. X
  742. Xint ruserpass2(char *host, char **username, char **pass, char **acct)
  743. X{
  744. X    FILE            *fp;
  745. X    char            *cp, *dp, *dst, *ep;
  746. X    str32            macname;
  747. X    char            *varname;
  748. X    int                site_found;
  749. X    string            str;
  750. X    static string    auser;
  751. X    static str32    apass, aacct;
  752. X
  753. X    site_found = 0;
  754. X
  755. X    if ((fp = fopen(rcname, "r")) != NULL) {
  756. X        parsing_rc = 1;
  757. X        while (FGets(str, fp)) {
  758. X            if (cp = strstr(str, "machine")) {
  759. X                /* Look for the machine token. */
  760. X                cp += 7;
  761. X                while (isspace(*cp))
  762. X                    cp++;
  763. X            } else
  764. X                continue;
  765. X            if (strncmp(cp, host, strlen(host)) == 0) {
  766. X                site_found = 1;
  767. X                while (!isspace(*cp))
  768. X                    ++cp;        /* skip the site name. */
  769. X                do {
  770. X                    /* Skip any comments ahead of time. */
  771. X                    for (dp=cp; *dp; dp++) {
  772. X                        if (*dp == '#') {
  773. X                            *dp = 0;
  774. X                            break;
  775. X                        }
  776. X                    }
  777. X
  778. X                    ep = cp;
  779. X                    while (1) {
  780. X                        varname = strtok(ep, RC_DELIM);
  781. X                        if (!varname) break;
  782. X                        dst = ep = NULL;
  783. X                        switch (*varname) {
  784. X                            case 'u':    /* user */
  785. X                                *username = dst = auser;
  786. X                                break;
  787. X                            case 'l':    /* login */
  788. X                                *username = dst = auser;
  789. X                                break;
  790. X                            case 'p':    /* password */
  791. X                                *pass = dst = apass;
  792. X                                break;
  793. X                            case 'a':    /* account */
  794. X                                *acct = dst = aacct;
  795. X                                break;
  796. X                        /*    case 'd':  /o default */
  797. X                        /* unused -- use 'set anon_password.' */
  798. X                            case 'm':    /* macdef or machine */
  799. X                                if (strcmp(varname, "macdef"))
  800. X                                    goto done;    /* new machine record... */
  801. X                                dst = macname;
  802. X                                break;
  803. X                            default:
  804. X                                (void) fprintf(stderr, "Unknown .netrc keyword \"%s\"\n",
  805. X                                    varname
  806. X                                );
  807. X                        }
  808. X                        if (dst) {
  809. X                            dp = strtok(ep, RC_DELIM);
  810. X                            if (dp)
  811. X                                (void) strcpy(dst, dp);
  812. X                            if (dst == macname) {
  813. X                                /*
  814. X                                 *    Read in the lines of the macro.
  815. X                                 *    The macro's end is denoted by
  816. X                                 *    a blank line.
  817. X                                 */
  818. X                                (void) make_macro(macname, fp);
  819. X                                goto nextline;
  820. X                            }
  821. X                        }
  822. X                    }
  823. Xnextline: ;
  824. X                } while (cp = FGets(str, fp));
  825. X                break;
  826. X            }        /* end if we found the machine record. */
  827. X        }
  828. Xdone:
  829. X        parsing_rc = 0;
  830. X        (void) fclose(fp);
  831. X    }
  832. X
  833. X    if (!site_found) {
  834. X        /* didn't find it in the rc. */
  835. X        return (0);
  836. X    }
  837. X
  838. X    return (1);    /* found */
  839. X}    /* ruserpass2 */
  840. X
  841. X/* eof ftprc.c */
  842. END_OF_FILE
  843.   if test 11194 -ne `wc -c <'ftprc.c'`; then
  844.     echo shar: \"'ftprc.c'\" unpacked with wrong size!
  845.   fi
  846.   # end of 'ftprc.c'
  847. fi
  848. if test -f 'getpass.h' -a "${1}" != "-c" ; then 
  849.   echo shar: Will not clobber existing file \"'getpass.h'\"
  850. else
  851.   echo shar: Extracting \"'getpass.h'\" \(278 characters\)
  852.   sed "s/^X//" >'getpass.h' <<'END_OF_FILE'
  853. X/* Getpass.h */
  854. X
  855. X#ifndef _getpass_h_
  856. X#define _getpass_h_
  857. X
  858. X/*  $RCSfile: getpass.h,v $
  859. X *  $Revision: 14020.11 $
  860. X *  $Date: 93/05/21 05:45:36 $
  861. X */
  862. X
  863. X#define kMaxPassLen 127
  864. X
  865. Xchar *Getpass(char *prompt);
  866. Xvoid echo(FILE *fp, int on);
  867. X
  868. X#endif    /* _getpass_h_ */
  869. X
  870. X/* eof Getpass.h */
  871. END_OF_FILE
  872.   if test 278 -ne `wc -c <'getpass.h'`; then
  873.     echo shar: \"'getpass.h'\" unpacked with wrong size!
  874.   fi
  875.   # end of 'getpass.h'
  876. fi
  877. if test -f 'glob.c' -a "${1}" != "-c" ; then 
  878.   echo shar: Will not clobber existing file \"'glob.c'\"
  879. else
  880.   echo shar: Extracting \"'glob.c'\" \(10232 characters\)
  881.   sed "s/^X//" >'glob.c' <<'END_OF_FILE'
  882. X/* glob.c */
  883. X
  884. X/*  $RCSfile: glob.c,v $
  885. X *  $Revision: 14020.11 $
  886. X *  $Date: 93/05/21 05:44:32 $
  887. X */
  888. X
  889. X#include "sys.h"
  890. X#include <sys/param.h>
  891. X#include <sys/stat.h>
  892. X
  893. X/* Dir.h.  Try <sys/dir.h> (add -DSYSDIRH) if <dirent.h> doesn't exist. */
  894. X
  895. X#ifndef SYSDIRH
  896. X#   include <dirent.h>
  897. X#else
  898. X#   include <sys/dir.h>
  899. X#endif
  900. X
  901. X#ifdef SCO324
  902. X#   define direct dirent
  903. X#endif
  904. X
  905. X#include <string.h>
  906. X#include <errno.h>
  907. X#include <pwd.h>
  908. X#include "util.h"
  909. X#include "glob.h"
  910. X#include "cmds.h"
  911. X#include "copyright.h"
  912. X
  913. X#ifndef NCARGS
  914. X#    define NCARGS  4096 /* # characters in exec arglist */
  915. X#endif
  916. X
  917. X#define    L_CURLY    '{'
  918. X#define    R_CURLY    '}'
  919. X
  920. X#define    QUOTE 0200
  921. X#define    TRIM 0177
  922. X#define    eq(a,b)        (strcmp(a, b)==0)
  923. X#define    GAVSIZ        (NCARGS/6)
  924. X#define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  925. X
  926. Xstatic void ginit(char **agargv);
  927. Xstatic void collect(char *as);
  928. Xstatic void acollect(char *as);
  929. Xstatic void sort(void);
  930. Xstatic void expand(char *as);
  931. Xstatic void matchdir(char *pattern);
  932. Xstatic int execbrc(char *p, char *s);
  933. Xstatic match(char *s, char *p);
  934. Xstatic amatch(char *s, char *p);
  935. X#if UNUSED
  936. Xstatic Gmatch(char *s, char *p);
  937. X#endif
  938. Xstatic void Gcat(char *s1, char *s2);
  939. Xstatic void addpath(char c);
  940. Xstatic void rscan(char **t, int (*f )(char));
  941. Xstatic tglob(char c);
  942. Xstatic char *strspl(char *cp, char *dp);
  943. Xstatic char *strend(char *cp);
  944. X
  945. Xstatic    char **gargv;    /* Pointer to the (stack) arglist */
  946. Xstatic    int gargc;        /* Number args in gargv */
  947. Xstatic    int gnleft;
  948. Xstatic    short gflag;
  949. Xchar    *globerr;
  950. Xchar    *home;            /* you must initialize this elsewhere! */
  951. Xextern    int errno;
  952. X
  953. Xstatic    int globcnt;
  954. X
  955. Xchar    *globchars = "`{[*?";
  956. X
  957. Xstatic    char *gpath, *gpathp, *lastgpathp;
  958. Xstatic    int globbed;
  959. Xstatic    char *entp;
  960. Xstatic    char **sortbas;
  961. X
  962. Xchar **
  963. Xglob(char *v)
  964. X{
  965. X    char agpath[BUFSIZ];
  966. X    char *agargv[GAVSIZ];
  967. X    char *vv[2];
  968. X    vv[0] = v;
  969. X    vv[1] = 0;
  970. X    gflag = (short) 0;
  971. X    rscan(vv, tglob);
  972. X    if (gflag == (short) 0)
  973. X        return (copyblk(vv));
  974. X
  975. X    globerr = 0;
  976. X    gpath = agpath; gpathp = gpath; *gpathp = 0;
  977. X    lastgpathp = &gpath[sizeof agpath - 2];
  978. X    ginit(agargv); globcnt = 0;
  979. X    collect(v);
  980. X    if (globcnt == 0 && (gflag & (short)1)) {
  981. X        blkfree(gargv), gargv = 0;
  982. X        return (0);
  983. X    } else
  984. X        return (gargv = copyblk(gargv));
  985. X}
  986. X
  987. Xstatic
  988. Xvoid ginit(char **agargv)
  989. X{
  990. X    agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  991. X    gnleft = NCARGS - 4;
  992. X}
  993. X
  994. Xstatic
  995. Xvoid collect(char *as)
  996. X{
  997. X    if (eq(as, "{") || eq(as, "{}")) {
  998. X        Gcat(as, "");
  999. X        sort();
  1000. X    } else
  1001. X        acollect(as);
  1002. X}
  1003. X
  1004. Xstatic
  1005. Xvoid acollect(char *as)
  1006. X{
  1007. X    register int ogargc = gargc;
  1008. X
  1009. X    gpathp = gpath; *gpathp = 0; globbed = 0;
  1010. X    expand(as);
  1011. X    if (gargc != ogargc)
  1012. X        sort();
  1013. X}
  1014. X
  1015. Xstatic
  1016. Xvoid sort(void)
  1017. X{
  1018. X    register char **p1, **p2, *c;
  1019. X    char **Gvp = &gargv[gargc];
  1020. X
  1021. X    p1 = sortbas;
  1022. X    while (p1 < Gvp-1) {
  1023. X        p2 = p1;
  1024. X        while (++p2 < Gvp)
  1025. X            if (strcmp(*p1, *p2) > 0)
  1026. X                c = *p1, *p1 = *p2, *p2 = c;
  1027. X        p1++;
  1028. X    }
  1029. X    sortbas = Gvp;
  1030. X}
  1031. X
  1032. Xstatic
  1033. Xvoid expand(char *as)
  1034. X{
  1035. X    register char *cs;
  1036. X    register char *sgpathp, *oldcs;
  1037. X    struct stat stb;
  1038. X
  1039. X    sgpathp = gpathp;
  1040. X    cs = as;
  1041. X    if (*cs == '~' && gpathp == gpath) {
  1042. X        addpath('~');
  1043. X        for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  1044. X            addpath(*cs++);
  1045. X        if (!*cs || *cs == '/') {
  1046. X            if (gpathp != gpath + 1) {
  1047. X                *gpathp = 0;
  1048. X                if (gethdir(gpath + 1))
  1049. X                    globerr = "Unknown user name after ~";
  1050. X                (void) strcpy(gpath, gpath + 1);
  1051. X            } else
  1052. X                (void) strcpy(gpath, home);
  1053. X            gpathp = strend(gpath);
  1054. X        }
  1055. X    }
  1056. X    while (!any(*cs, globchars)) {
  1057. X        if (*cs == 0) {
  1058. X            if (!globbed)
  1059. X                Gcat(gpath, "");
  1060. X            else if (stat(gpath, &stb) >= 0) {
  1061. X                Gcat(gpath, "");
  1062. X                globcnt++;
  1063. X            }
  1064. X            goto endit;
  1065. X        }
  1066. X        addpath(*cs++);
  1067. X    }
  1068. X    oldcs = cs;
  1069. X    while (cs > as && *cs != '/')
  1070. X        cs--, gpathp--;
  1071. X    if (*cs == '/')
  1072. X        cs++, gpathp++;
  1073. X    *gpathp = 0;
  1074. X    if (*oldcs == L_CURLY) {
  1075. X        (void) execbrc(cs, ((char *)0));
  1076. X        return;
  1077. X    }
  1078. X    matchdir(cs);
  1079. Xendit:
  1080. X    gpathp = sgpathp;
  1081. X    *gpathp = 0;
  1082. X}
  1083. X
  1084. Xstatic
  1085. Xvoid matchdir(char *pattern)
  1086. X{
  1087. X    struct stat stb;
  1088. X#ifdef SYSDIRH
  1089. X    register struct direct *dp;
  1090. X#else
  1091. X    register struct dirent *dp;
  1092. X#endif
  1093. X    DIR *dirp;
  1094. X
  1095. X    dirp = opendir((*gpath ? gpath : "."));
  1096. X    if (dirp == NULL) {
  1097. X        if (globbed)
  1098. X            return;
  1099. X        goto patherr2;
  1100. X    }
  1101. X    if (fstat(dirp->dd_fd, &stb) < 0)
  1102. X        goto patherr1;
  1103. X    if (!isdir(stb)) {
  1104. X        errno = ENOTDIR;
  1105. X        goto patherr1;
  1106. X    }
  1107. X    while ((dp = readdir(dirp)) != NULL) {
  1108. X        if (dp->d_ino == 0)
  1109. X            continue;
  1110. X        if (match(dp->d_name, pattern)) {
  1111. X            Gcat(gpath, dp->d_name);
  1112. X            globcnt++;
  1113. X        }
  1114. X    }
  1115. X    (void) closedir(dirp);
  1116. X    return;
  1117. X
  1118. Xpatherr1:
  1119. X    (void) closedir(dirp);
  1120. Xpatherr2:
  1121. X    globerr = "Bad directory components";
  1122. X}
  1123. X
  1124. Xstatic
  1125. Xint execbrc(char *p, char *s)
  1126. X{
  1127. X    char restbuf[BUFSIZ + 2];
  1128. X    register char *pe, *pm, *pl;
  1129. X    int brclev = 0;
  1130. X    char *lm, savec, *sgpathp;
  1131. X
  1132. X    for (lm = restbuf; *p != L_CURLY; *lm++ = *p++)
  1133. X        continue;
  1134. X    for (pe = ++p; *pe; pe++)
  1135. X    switch (*pe) {
  1136. X
  1137. X    case L_CURLY:
  1138. X        brclev++;
  1139. X        continue;
  1140. X
  1141. X    case R_CURLY:
  1142. X        if (brclev == 0)
  1143. X            goto pend;
  1144. X        brclev--;
  1145. X        continue;
  1146. X
  1147. X    case '[':
  1148. X        for (pe++; *pe && *pe != ']'; pe++)
  1149. X            continue;
  1150. X        continue;
  1151. X    }
  1152. Xpend:
  1153. X    brclev = 0;
  1154. X    for (pl = pm = p; pm <= pe; pm++)
  1155. X    switch (*pm & (QUOTE|TRIM)) {
  1156. X
  1157. X    case L_CURLY:
  1158. X        brclev++;
  1159. X        continue;
  1160. X
  1161. X    case R_CURLY:
  1162. X        if (brclev) {
  1163. X            brclev--;
  1164. X            continue;
  1165. X        }
  1166. X        goto doit;
  1167. X
  1168. X    case ','|QUOTE:
  1169. X    case ',':
  1170. X        if (brclev)
  1171. X            continue;
  1172. Xdoit:
  1173. X        savec = *pm;
  1174. X        *pm = 0;
  1175. X        (void) strcpy(lm, pl);
  1176. X        (void) strcat(restbuf, pe + 1);
  1177. X        *pm = savec;
  1178. X        if (s == 0) {
  1179. X            sgpathp = gpathp;
  1180. X            expand(restbuf);
  1181. X            gpathp = sgpathp;
  1182. X            *gpathp = 0;
  1183. X        } else if (amatch(s, restbuf))
  1184. X            return (1);
  1185. X        sort();
  1186. X        pl = pm + 1;
  1187. X        if (brclev)
  1188. X            return (0);
  1189. X        continue;
  1190. X
  1191. X    case '[':
  1192. X        for (pm++; *pm && *pm != ']'; pm++)
  1193. X            continue;
  1194. X        if (!*pm)
  1195. X            pm--;
  1196. X        continue;
  1197. X    }
  1198. X    if (brclev)
  1199. X        goto doit;
  1200. X    return (0);
  1201. X}
  1202. X
  1203. Xstatic
  1204. Xint match(char *s, char *p)
  1205. X{
  1206. X    register int c;
  1207. X    register char *sentp;
  1208. X    char sglobbed = globbed;
  1209. X
  1210. X    if (*s == '.' && *p != '.')
  1211. X        return (0);
  1212. X    sentp = entp;
  1213. X    entp = s;
  1214. X    c = amatch(s, p);
  1215. X    entp = sentp;
  1216. X    globbed = sglobbed;
  1217. X    return (c);
  1218. X}
  1219. X
  1220. Xstatic
  1221. Xint amatch(char *s, char *p)
  1222. X{
  1223. X    register int scc;
  1224. X    int ok, lc;
  1225. X    char *sgpathp;
  1226. X    struct stat stb;
  1227. X    int c, cc;
  1228. X
  1229. X    globbed = 1;
  1230. X    for (;;) {
  1231. X        scc = *s++ & TRIM;
  1232. X        switch (c = *p++) {
  1233. X
  1234. X        case L_CURLY:
  1235. X            return (execbrc(p - 1, s - 1));
  1236. X
  1237. X        case '[':
  1238. X            ok = 0;
  1239. X            lc = 077777;
  1240. X            while (cc = *p++) {
  1241. X                if (cc == ']') {
  1242. X                    if (ok)
  1243. X                        break;
  1244. X                    return (0);
  1245. X                }
  1246. X                if (cc == '-') {
  1247. X                    if (lc <= scc && scc <= *p++)
  1248. X                        ok++;
  1249. X                } else
  1250. X                    if (scc == (lc = cc))
  1251. X                        ok++;
  1252. X            }
  1253. X            if (cc == 0)
  1254. X                if (ok)
  1255. X                    p--;
  1256. X                else
  1257. X                    return 0;
  1258. X            continue;
  1259. X
  1260. X        case '*':
  1261. X            if (!*p)
  1262. X                return (1);
  1263. X            if (*p == '/') {
  1264. X                p++;
  1265. X                goto slash;
  1266. X            }
  1267. X            s--;
  1268. X            do {
  1269. X                if (amatch(s, p))
  1270. X                    return (1);
  1271. X            } while (*s++);
  1272. X            return (0);
  1273. X
  1274. X        case 0:
  1275. X            return (scc == 0);
  1276. X
  1277. X        default:
  1278. X            if (c != scc)
  1279. X                return (0);
  1280. X            continue;
  1281. X
  1282. X        case '?':
  1283. X            if (scc == 0)
  1284. X                return (0);
  1285. X            continue;
  1286. X
  1287. X        case '/':
  1288. X            if (scc)
  1289. X                return (0);
  1290. Xslash:
  1291. X            s = entp;
  1292. X            sgpathp = gpathp;
  1293. X            while (*s)
  1294. X                addpath(*s++);
  1295. X            addpath('/');
  1296. X            if (stat(gpath, &stb) == 0 && isdir(stb))
  1297. X                if (*p == 0) {
  1298. X                    Gcat(gpath, "");
  1299. X                    globcnt++;
  1300. X                } else
  1301. X                    expand(p);
  1302. X            gpathp = sgpathp;
  1303. X            *gpathp = 0;
  1304. X            return (0);
  1305. X        }
  1306. X    }
  1307. X}
  1308. X
  1309. X#if UNUSED
  1310. Xstatic
  1311. XGmatch(char *s, char *p)
  1312. X{
  1313. X    register int scc;
  1314. X    int ok, lc;
  1315. X    int c, cc;
  1316. X
  1317. X    for (;;) {
  1318. X        scc = *s++ & TRIM;
  1319. X        switch (c = *p++) {
  1320. X
  1321. X        case '[':
  1322. X            ok = 0;
  1323. X            lc = 077777;
  1324. X            while (cc = *p++) {
  1325. X                if (cc == ']') {
  1326. X                    if (ok)
  1327. X                        break;
  1328. X                    return (0);
  1329. X                }
  1330. X                if (cc == '-') {
  1331. X                    if (lc <= scc && scc <= *p++)
  1332. X                        ok++;
  1333. X                } else
  1334. X                    if (scc == (lc = cc))
  1335. X                        ok++;
  1336. X            }
  1337. X            if (cc == 0)
  1338. X                if (ok)
  1339. X                    p--;
  1340. X                else
  1341. X                    return 0;
  1342. X            continue;
  1343. X
  1344. X        case '*':
  1345. X            if (!*p)
  1346. X                return (1);
  1347. X            for (s--; *s; s++)
  1348. X                if (Gmatch(s, p))
  1349. X                    return (1);
  1350. X            return (0);
  1351. X
  1352. X        case 0:
  1353. X            return (scc == 0);
  1354. X
  1355. X        default:
  1356. X            if ((c & TRIM) != scc)
  1357. X                return (0);
  1358. X            continue;
  1359. X
  1360. X        case '?':
  1361. X            if (scc == 0)
  1362. X                return (0);
  1363. X            continue;
  1364. X
  1365. X        }
  1366. X    }
  1367. X}
  1368. X#endif
  1369. X
  1370. Xstatic
  1371. Xvoid Gcat(char *s1, char *s2)
  1372. X{
  1373. X    register int len = strlen(s1) + strlen(s2) + 1;
  1374. X
  1375. X    if (len >= gnleft || gargc >= GAVSIZ - 1)
  1376. X        globerr = "Arguments too long";
  1377. X    else {
  1378. X        gargc++;
  1379. X        gnleft -= len;
  1380. X        gargv[gargc] = 0;
  1381. X        gargv[gargc - 1] = strspl(s1, s2);
  1382. X    }
  1383. X}
  1384. X
  1385. Xstatic
  1386. Xvoid addpath(char c)
  1387. X{
  1388. X
  1389. X    if (gpathp >= lastgpathp)
  1390. X        globerr = "Pathname too long";
  1391. X    else {
  1392. X        *gpathp++ = c;
  1393. X        *gpathp = 0;
  1394. X    }
  1395. X}
  1396. X
  1397. Xstatic
  1398. Xvoid rscan(char **t, int (*f )(char))
  1399. X{
  1400. X    register char *p, c;
  1401. X
  1402. X    while (p = *t++) {
  1403. X        if (f == tglob)
  1404. X            if (*p == '~')
  1405. X                gflag |= (short) 2;
  1406. X            else if (eq(p, "{") || eq(p, "{}"))
  1407. X                continue;
  1408. X        while (c = *p++)
  1409. X            (*f)(c);
  1410. X    }
  1411. X}
  1412. X/*
  1413. Xstatic
  1414. Xscan(t, f)
  1415. X    register char **t;
  1416. X    int (*f)(char);
  1417. X{
  1418. X    register char *p, c;
  1419. X
  1420. X    while (p = *t++)
  1421. X        while (c = *p)
  1422. X            *p++ = (*f)(c);
  1423. X} */
  1424. X
  1425. Xstatic
  1426. Xint tglob(char c)
  1427. X{
  1428. X
  1429. X    if (any(c, globchars))
  1430. X        gflag |= (c == L_CURLY ? (short)2 : (short)1);
  1431. X    return (c);
  1432. X}
  1433. X/*
  1434. Xstatic
  1435. Xtrim(c)
  1436. X    char c;
  1437. X{
  1438. X
  1439. X    return (c & TRIM);
  1440. X} */
  1441. X
  1442. X
  1443. Xint letter(char c)
  1444. X{
  1445. X    return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
  1446. X}
  1447. X
  1448. Xint digit(char c)
  1449. X{
  1450. X    return (c >= '0' && c <= '9');
  1451. X}
  1452. X
  1453. Xint any(int c, char *s)
  1454. X{
  1455. X    while (*s)
  1456. X        if (*s++ == c)
  1457. X            return(1);
  1458. X    return(0);
  1459. X}
  1460. X
  1461. Xint blklen(char **av)
  1462. X{
  1463. X    register int i = 0;
  1464. X
  1465. X    while (*av++)
  1466. X        i++;
  1467. X    return (i);
  1468. X}
  1469. X
  1470. Xchar **
  1471. Xblkcpy(char **oav, char **bv)
  1472. X{
  1473. X    register char **av = oav;
  1474. X
  1475. X    while (*av++ = *bv++)
  1476. X        continue;
  1477. X    return (oav);
  1478. X}
  1479. X
  1480. Xvoid blkfree(char **av0)
  1481. X{
  1482. X    register char **av = av0;
  1483. X
  1484. X    while (*av)
  1485. X        free(*av++);
  1486. X}
  1487. X
  1488. Xstatic
  1489. Xchar *
  1490. Xstrspl(char *cp, char *dp)
  1491. X{
  1492. X    register char *ep = (char *) malloc((size_t)(strlen(cp) + strlen(dp) + 1L));
  1493. X
  1494. X    if (ep == (char *)0)
  1495. X        fatal("Out of memory");
  1496. X    (void) strcpy(ep, cp);
  1497. X    (void) strcat(ep, dp);
  1498. X    return (ep);
  1499. X}
  1500. X
  1501. Xchar **
  1502. Xcopyblk(char **v)
  1503. X{
  1504. X    register char **nv = (char **)malloc((size_t)((blklen(v) + 1) *
  1505. X                        sizeof(char **)));
  1506. X    if (nv == (char **)0)
  1507. X        fatal("Out of memory");
  1508. X
  1509. X    return (blkcpy(nv, v));
  1510. X}
  1511. X
  1512. Xstatic
  1513. Xchar *
  1514. Xstrend(char *cp)
  1515. X{
  1516. X    while (*cp)
  1517. X        cp++;
  1518. X    return (cp);
  1519. X}
  1520. X
  1521. X/*
  1522. X * Extract a home directory from the password file
  1523. X * The argument points to a buffer where the name of the
  1524. X * user whose home directory is sought is currently.
  1525. X * We write the home directory of the user back there.
  1526. X */
  1527. Xint gethdir(char *home_dir)
  1528. X{
  1529. X    register struct passwd *pp = getpwnam(home_dir);
  1530. X
  1531. X    if (pp == 0)
  1532. X        return (1);
  1533. X    (void) strcpy(home_dir, pp->pw_dir);
  1534. X    return (0);
  1535. X}    /* gethdir */
  1536. X
  1537. X/* eof glob.c */
  1538. END_OF_FILE
  1539.   if test 10232 -ne `wc -c <'glob.c'`; then
  1540.     echo shar: \"'glob.c'\" unpacked with wrong size!
  1541.   fi
  1542.   # end of 'glob.c'
  1543. fi
  1544. if test -f 'set.c' -a "${1}" != "-c" ; then 
  1545.   echo shar: Will not clobber existing file \"'set.c'\"
  1546. else
  1547.   echo shar: Extracting \"'set.c'\" \(7783 characters\)
  1548.   sed "s/^X//" >'set.c' <<'END_OF_FILE'
  1549. X/* Set.c */
  1550. X
  1551. X/*  $RCSfile: set.c,v $
  1552. X *  $Revision: 14020.12 $
  1553. X *  $Date: 93/07/09 11:45:48 $
  1554. X */
  1555. X
  1556. X#include "sys.h"
  1557. X
  1558. X#include <string.h>
  1559. X#include <ctype.h>
  1560. X
  1561. X#include "util.h"
  1562. X#include "cmds.h"
  1563. X#include "main.h"
  1564. X#include "set.h"
  1565. X#include "defaults.h"
  1566. X#include "copyright.h"
  1567. X
  1568. X/* Set.c globals: */
  1569. Xchar *verbose_msgs[4] = {
  1570. X    "Not printing anything.\n",
  1571. X    "Only printing necessary error messages.\n",
  1572. X    "Printing error messages and announcements from the remote host.\n",
  1573. X    "Printing all messages, errors, acknowledgments, and announcements.\n"
  1574. X};
  1575. X
  1576. Xchar *short_verbose_msgs[4] = {
  1577. X    "Quiet (-1)",
  1578. X    "Errors Only (0)",
  1579. X    "Terse (1)",
  1580. X    "Verbose (2)"
  1581. X};
  1582. X
  1583. Xstring                        vstr;
  1584. X
  1585. X/* Set.c externs: */
  1586. Xextern int                    progress_meter, connected;
  1587. Xextern int                    parsing_rc, keep_recent;
  1588. Xextern string                pager, anon_password, prompt;
  1589. Xextern str32                curtypename;
  1590. Xextern long                    logsize;
  1591. Xextern FILE                    *logf;
  1592. Xextern longstring            rcname, logfname, lcwd;
  1593. Xextern int                    auto_binary, ansi_escapes, debug;
  1594. Xextern int                    mprompt, remote_is_unix, verbose;
  1595. Xextern int                    startup_msg, anon_open;
  1596. X#ifndef NO_TIPS
  1597. Xextern int                    tips;
  1598. X#endif
  1599. X#ifdef GATEWAY
  1600. Xextern string                gateway, gate_login;
  1601. X#endif
  1602. X
  1603. X/* The variables must be sorted in alphabetical order, or else
  1604. X * match_var() will choke.
  1605. X */
  1606. Xstruct var vars[] = {
  1607. X    VARENTRY("anon-open",        BOOL, 0, &anon_open,    NULL),
  1608. X    VARENTRY("anon-password",    STR,  0, anon_password,    NULL),
  1609. X    VARENTRY("ansi-escapes",    BOOL, 0, &ansi_escapes,    NULL),
  1610. X    VARENTRY("auto-binary",        BOOL, 0, &auto_binary,    NULL),
  1611. X    VARENTRY("debug",            INT,  0, &debug,        NULL),
  1612. X#ifdef GATEWAY
  1613. X    VARENTRY("gateway-login",    STR,  0, gate_login,    set_gatelogin),
  1614. X    VARENTRY("gateway-host",    STR,  0, gateway,        NULL),
  1615. X#endif
  1616. X    VARENTRY("local-dir",        STR,  0, lcwd,            set_ldir),
  1617. X    VARENTRY("logfile",            STR,  0, logfname,        set_log),
  1618. X    VARENTRY("logsize",            LONG, 0, &logsize,        NULL),
  1619. X    VARENTRY("mprompt",            BOOL, 0, &mprompt,        NULL),
  1620. X    VARENTRY("netrc",            -STR, 0, rcname,        NULL),
  1621. X    VARENTRY("pager",            STR,  0, pager + 1,        set_pager),
  1622. X    VARENTRY("prompt",            STR,  0, prompt,        set_prompt),
  1623. X    VARENTRY("progress-reports",INT,  0, &progress_meter,NULL),
  1624. X    VARENTRY("recent-list",        BOOL, 0, &keep_recent,    NULL),
  1625. X    VARENTRY("remote-is-unix",    BOOL, 1, &remote_is_unix,NULL),
  1626. X    VARENTRY("startup-msg",        BOOL, 0, &startup_msg,    NULL),  /* TAR */
  1627. X#ifndef NO_TIPS
  1628. X    VARENTRY("tips",            BOOL, 0, &tips,            NULL),
  1629. X#endif
  1630. X    VARENTRY("type",            STR,  1, curtypename,    set_type),
  1631. X    VARENTRY("verbose",            STR,  0, vstr,            set_verbose),
  1632. X};
  1633. X
  1634. X
  1635. Xvoid set_verbose(char *new, int unset)
  1636. X{
  1637. X    int i, c;
  1638. X
  1639. X    if (unset == -1) verbose = !verbose;
  1640. X    else if (unset || !new) verbose = V_ERRS;
  1641. X    else {
  1642. X        if (isalpha(*new)) {
  1643. X            c = islower(*new) ? toupper(*new) : *new;    
  1644. X            for (i=0; i<(int)(sizeof(short_verbose_msgs)/sizeof(char *)); i++) {
  1645. X                if (short_verbose_msgs[i][0] == c)
  1646. X                    verbose = i - 1;
  1647. X            }
  1648. X        } else {
  1649. X            i = atoi(new);
  1650. X            if (i < V_QUIET) i = V_QUIET;
  1651. X            else if (i > V_VERBOSE) i = V_VERBOSE;
  1652. X            verbose = i;
  1653. X        }
  1654. X    }
  1655. X    (void) Strncpy(vstr, short_verbose_msgs[verbose+1]);
  1656. X    if (!parsing_rc && NOT_VQUIET) 
  1657. X        (void) fputs(verbose_msgs[verbose+1], stdout);
  1658. X}    /* set_verbose */
  1659. X
  1660. X
  1661. X
  1662. X
  1663. Xvoid set_prompt(char *new, int unset)
  1664. X{
  1665. X    (void) Strncpy(prompt, (unset || !new) ? dPROMPT : new);
  1666. X    init_prompt();
  1667. X}    /* set_prompt */
  1668. X
  1669. X
  1670. X
  1671. X
  1672. Xvoid set_log(char *fname, int unset)
  1673. X{
  1674. X    if (logf) {
  1675. X        (void) fclose(logf);
  1676. X        logf = NULL;
  1677. X    }
  1678. X    if (!unset && fname) {
  1679. X        (void) Strncpy(logfname, fname);
  1680. X        logf = fopen (LocalDotPath(logfname), "a");
  1681. X    }
  1682. X}    /* set_log */
  1683. X
  1684. X
  1685. X
  1686. X
  1687. Xvoid set_pager(char *new, int unset)
  1688. X{
  1689. X    if (unset)
  1690. X        (void) strcpy(pager, "-");
  1691. X    else {
  1692. X        if (!new)
  1693. X            new = dPAGER;
  1694. X        if (!new[0])
  1695. X            (void) Strncpy(pager, "-");
  1696. X        else {
  1697. X            (void) sprintf(pager, "|%s", (*new == '|' ? new + 1 : new));
  1698. X            (void) LocalPath(pager + 1);
  1699. X        }
  1700. X    }
  1701. X}    /* set_pager */
  1702. X
  1703. X
  1704. X
  1705. X
  1706. Xvoid set_type(char *newtype, int unset)
  1707. X{
  1708. X    int t = verbose;
  1709. X    verbose = V_QUIET;
  1710. X    if (!connected && t > V_QUIET)
  1711. X        (void) printf("Not connected.\n");
  1712. X    else if (newtype != NULL && !unset)
  1713. X        (void) _settype(newtype);
  1714. X    verbose = t;
  1715. X}    /* set_type */
  1716. X
  1717. X
  1718. X
  1719. X
  1720. Xvoid set_ldir(char *ldir, int unset)
  1721. X{
  1722. X    int t = verbose;
  1723. X    char *argv[2];
  1724. X
  1725. X    if (ldir && !unset) {
  1726. X        verbose = V_QUIET;
  1727. X        argv[1] = ldir;
  1728. X        (void) lcd(2, argv);
  1729. X        verbose = t;
  1730. X    }
  1731. X}    /* set_ldir */
  1732. X
  1733. X
  1734. X
  1735. X
  1736. X#ifdef GATEWAY
  1737. Xvoid set_gatelogin(char *glogin, int unset)
  1738. X{
  1739. X    if (unset || !glogin) {
  1740. X        gate_login[0] = gateway[0] = 0;
  1741. X    } else
  1742. X        (void) strcpy(gate_login, glogin);
  1743. X}    /* set_gatelogin */
  1744. X#endif
  1745. X
  1746. X
  1747. X
  1748. X
  1749. Xstruct var *match_var(char *varname)
  1750. X{
  1751. X    int i, c, ambig;
  1752. X    struct var *v;
  1753. X
  1754. X    c = strlen(varname);
  1755. X    for (i=0, v=vars; i<NVARS; i++, v++) {
  1756. X        if (strcmp(v->name, varname) == 0)
  1757. X            return v;    /* exact match. */
  1758. X        if (c < v->nmlen) {
  1759. X            if (strncmp(v->name, varname, c) == 0) {
  1760. X                /* Now make sure that it only matches one var name. */
  1761. X                if (c >= v[1].nmlen || (i == (NVARS - 1)))
  1762. X                    ambig = 0;
  1763. X                else
  1764. X                    ambig = !strncmp(v[1].name, varname, c);
  1765. X                if (!ambig)
  1766. X                    return v;
  1767. X                (void) fprintf(stderr, "%s: ambiguous variable name.\n", varname);
  1768. X                goto xx;
  1769. X            }
  1770. X        }
  1771. X    }
  1772. X    (void) fprintf(stderr, "%s: unknown variable.\n", varname);
  1773. Xxx:
  1774. X    return ((struct var *)0);
  1775. X}    /* match_var */
  1776. X
  1777. X
  1778. X
  1779. X
  1780. Xvoid show_var(struct var *v)
  1781. X{
  1782. X    int c;
  1783. X
  1784. X    if (v != (struct var *)0) {
  1785. X        (void) printf("%-20s= ", v->name);
  1786. X        c = v->type;
  1787. X        if (c < 0) c = -c;
  1788. X        if (v->conn_required && !connected)
  1789. X            (void) printf("(not connected)\n");
  1790. X        else switch (c) {
  1791. X            case INT:
  1792. X                (void) printf("%d\n", *(int *)v->var); break;
  1793. X            case LONG:
  1794. X                (void) printf("%ld\n", *(long *)v->var); break;
  1795. X            case STR:
  1796. X                (void) printf("\"%s\"\n", (char *)v->var); break;
  1797. X            case BOOL:
  1798. X                (void) printf("%s\n", *(int *)v->var == 0 ? "no" : "yes");
  1799. X        }
  1800. X    }
  1801. X}    /* show_var */
  1802. X
  1803. X
  1804. X
  1805. X
  1806. Xvoid show(char *varname)
  1807. X{
  1808. X    int i;
  1809. X    struct var *v;
  1810. X
  1811. X    if ((varname == NULL)    /* (Denotes show all vars) */
  1812. X        || (strcmp("all", varname) == 0))
  1813. X    {
  1814. X        for (i=0; i<NVARS; i++)
  1815. X            show_var(&vars[i]);
  1816. X    } else {
  1817. X        if ((v = match_var(varname)) != (struct var *)0)
  1818. X            show_var(v);
  1819. X    }
  1820. X}    /* show */
  1821. X
  1822. X
  1823. X
  1824. X
  1825. Xint do_show(int argc, char **argv)
  1826. X{
  1827. X    int i;
  1828. X
  1829. X    if (argc < 2)
  1830. X        show(NULL);
  1831. X    else
  1832. X        for (i=1; i<argc; i++)
  1833. X            show(argv[i]);
  1834. X    return NOERR;
  1835. X}    /* do_show */
  1836. X
  1837. X
  1838. X
  1839. X
  1840. Xint set(int argc, char **argv)
  1841. X{
  1842. X    int unset;
  1843. X    struct var *v;
  1844. X    char *var, *val = NULL;
  1845. X
  1846. X    if (argc < 2 || strncmp(argv[1], "all", (size_t)3) == 0) {
  1847. X        show(NULL);        /* show all variables. */
  1848. X    } else {
  1849. X        unset = argv[0][0] == 'u';
  1850. X        var = argv[1];
  1851. X        if (argc > 2) {
  1852. X            /* could be '= value' or just 'value.' */
  1853. X            if (*argv[2] == '=') {
  1854. X                if (argc > 3)
  1855. X                    val = argv[3];
  1856. X                else return USAGE;    /* can't do 'set var =' */
  1857. X            } else
  1858. X                val = argv[2];
  1859. X            if (val[0] == 0)
  1860. X                val = NULL;
  1861. X        }
  1862. X        v = match_var(var);
  1863. X        if (v != NULL) {
  1864. X            if (v->conn_required && !connected)
  1865. X                (void) fprintf(stderr, "%s: must be connected.\n", var);
  1866. X            else if (v->type < 0)    
  1867. X                (void) fprintf(stderr, "%s: read-only variable.\n", var);
  1868. X            else if (v->proc != (setvarproc) 0) {
  1869. X                (*v->proc)(val, unset);        /* a custom set proc. */
  1870. X            } else if (unset) switch(v->type) {
  1871. X                case BOOL:
  1872. X                case INT:
  1873. X                    *(int *) v->var = 0; break;
  1874. X                case LONG:
  1875. X                    *(long *) v->var = 0; break;
  1876. X                case STR:
  1877. X                    *(char *) v->var = 0; break;
  1878. X            } else {
  1879. X                if (val == NULL) switch(v->type) {
  1880. X                    /* User just said "set varname" */
  1881. X                    case BOOL:
  1882. X                    case INT:
  1883. X                        *(int *) v->var = 1; break;
  1884. X                    case LONG:
  1885. X                        *(long *) v->var = 1; break;
  1886. X                    case STR:
  1887. X                        *(char *) v->var = 0; break;
  1888. X                } else {
  1889. X                    /* User said "set varname = value" */
  1890. X                    switch (v->type) {
  1891. X                        case BOOL:
  1892. X                            *(int *)v->var = StrToBool(val); break;
  1893. X                        case INT:
  1894. X                            (void) sscanf(val, "%d", (int *) v->var); break;
  1895. X                        case LONG:
  1896. X                            (void) sscanf(val, "%ld", (long *) v->var); break;
  1897. X                        case STR:
  1898. X                            (void) strcpy(v->var, val); break;
  1899. X                    }
  1900. X                }
  1901. X            }
  1902. X        }
  1903. X    }
  1904. X    return NOERR;
  1905. X}    /* set */
  1906. X
  1907. X/* eof Set.c */
  1908. END_OF_FILE
  1909.   if test 7783 -ne `wc -c <'set.c'`; then
  1910.     echo shar: \"'set.c'\" unpacked with wrong size!
  1911.   fi
  1912.   # end of 'set.c'
  1913. fi
  1914. if test -f 'util.c' -a "${1}" != "-c" ; then 
  1915.   echo shar: Will not clobber existing file \"'util.c'\"
  1916. else
  1917.   echo shar: Extracting \"'util.c'\" \(15461 characters\)
  1918.   sed "s/^X//" >'util.c' <<'END_OF_FILE'
  1919. X/* Util.c */
  1920. X
  1921. X/*  $RCSfile: util.c,v $
  1922. X *  $Revision: 14020.13 $
  1923. X *  $Date: 93/05/23 09:38:13 $
  1924. X */
  1925. X
  1926. X#include "sys.h"
  1927. X
  1928. X#include <string.h>
  1929. X#include <errno.h>
  1930. X#include <ctype.h>
  1931. X#include <sys/time.h>
  1932. X#include <time.h>
  1933. X#include <pwd.h>
  1934. X
  1935. X#ifndef NO_VARARGS
  1936. X#    include <stdarg.h>
  1937. X#endif
  1938. X
  1939. X#ifndef NO_UNISTDH
  1940. X#    include <unistd.h>
  1941. X#endif
  1942. X
  1943. X#ifdef READLINE
  1944. X#    include <readline.h>
  1945. X#endif /* READLINE */
  1946. X
  1947. X#ifdef GETLINE
  1948. X#    include <getline.h>
  1949. X#endif
  1950. X
  1951. X#include "util.h"
  1952. X#include "cmds.h"
  1953. X#include "main.h"
  1954. X#include "ftp.h"
  1955. X#include "ftprc.h"
  1956. X#include "defaults.h"
  1957. X#include "copyright.h"
  1958. X
  1959. X/* Util.c globals */
  1960. Xint                    Opterr = 1;            /* if error message should be printed */
  1961. Xint                    Optind = 1;            /* index into parent argv vector */
  1962. Xint                    Optopt;                /* character checked for validity */
  1963. Xchar                *Optarg;            /* argument associated with option */
  1964. Xchar                *Optplace = EMSG;    /* saved position in an arg */
  1965. X
  1966. X/* Util.c externs */
  1967. Xextern int            toatty, fromatty;
  1968. Xextern int            verbose;
  1969. Xextern string        prompt2;
  1970. Xextern char            *line, *margv[];
  1971. Xextern int            margc;
  1972. Xextern int            debug, mprompt, activemcmd;
  1973. Xextern string        progname;
  1974. Xextern struct cmd    cmdtab[];
  1975. X
  1976. X#ifndef NO_VARARGS
  1977. Xvoid dbprintf(char *fmt, ...)
  1978. X{
  1979. X    va_list ap;
  1980. X
  1981. X    if (debug) {
  1982. X        (void) fprintf(DB_STREAM, "#DB# ");
  1983. X        va_start(ap, fmt);
  1984. X        (void) vfprintf(DB_STREAM, fmt, ap);
  1985. X        va_end(ap);
  1986. X        (void) fflush(DB_STREAM);
  1987. X    }
  1988. X}    /* dbprintf */
  1989. X#endif
  1990. X
  1991. X
  1992. X
  1993. X
  1994. X/*
  1995. X * Concatenate src on the end of dst.  The resulting string will have at most
  1996. X * n-1 characters, not counting the NUL terminator which is always appended
  1997. X * unlike strncat.  The other big difference is that strncpy uses n as the
  1998. X * max number of characters _appended_, while this routine uses n to limit
  1999. X * the overall length of dst.
  2000. X */
  2001. Xchar *_Strncat(char *dst, char *src, register size_t n)
  2002. X{
  2003. X    register size_t i;
  2004. X    register char *d, *s;
  2005. X
  2006. X    if (n != 0 && ((i = strlen(dst)) < (n - 1))) {
  2007. X        d = dst + i;
  2008. X        s = src;
  2009. X        /* If they specified a maximum of n characters, use n - 1 chars to
  2010. X         * hold the copy, and the last character in the array as a NUL.
  2011. X         * This is the difference between the regular strncpy routine.
  2012. X         * strncpy doesn't guarantee that your new string will have a
  2013. X         * NUL terminator, but this routine does.
  2014. X         */
  2015. X        for (++i; i<n; i++) {
  2016. X            if ((*d++ = *s++) == 0) {
  2017. X                /* Pad with zeros. */
  2018. X                for (; i<n; i++)
  2019. X                    *d++ = 0;
  2020. X                return dst;
  2021. X            }
  2022. X        }
  2023. X        /* If we get here, then we have a full string, with n - 1 characters,
  2024. X         * so now we NUL terminate it and go home.
  2025. X         */
  2026. X        *d = 0;
  2027. X    }
  2028. X    return (dst);
  2029. X}    /* _Strncat */
  2030. X
  2031. X
  2032. X/*
  2033. X * Copy src to dst, truncating or null-padding to always copy n-1 bytes.
  2034. X * Return dst.
  2035. X */
  2036. Xchar *_Strncpy(char *dst, char *src, register size_t n)
  2037. X{
  2038. X    register char *d;
  2039. X    register char *s;
  2040. X    register size_t i;
  2041. X
  2042. X    d = dst;
  2043. X    *d = 0;
  2044. X    if (n != 0) {
  2045. X        s = src;
  2046. X        /* If they specified a maximum of n characters, use n - 1 chars to
  2047. X         * hold the copy, and the last character in the array as a NUL.
  2048. X         * This is the difference between the regular strncpy routine.
  2049. X         * strncpy doesn't guarantee that your new string will have a
  2050. X         * NUL terminator, but this routine does.
  2051. X         */
  2052. X        for (i=1; i<n; i++) {
  2053. X            if ((*d++ = *s++) == 0) {
  2054. X                /* Pad with zeros. */
  2055. X                for (; i<n; i++)
  2056. X                    *d++ = 0;
  2057. X                return dst;
  2058. X            }
  2059. X        }
  2060. X        /* If we get here, then we have a full string, with n - 1 characters,
  2061. X         * so now we NUL terminate it and go home.
  2062. X         */
  2063. X        *d = 0;
  2064. X    }
  2065. X    return (dst);
  2066. X}    /* _Strncpy */
  2067. X
  2068. X
  2069. X
  2070. X
  2071. Xchar *Strpcpy(char *dst, char *src)
  2072. X{
  2073. X    while (*dst++ = *src++)
  2074. X        ;
  2075. X    return (--dst);    /* return current value of dst, NOT original value! */
  2076. X}    /* Strpcpy */
  2077. X
  2078. X
  2079. X
  2080. X/*
  2081. X * malloc's a copy of oldstr.
  2082. X */
  2083. Xchar *NewString(char *oldstr)
  2084. X{
  2085. X    size_t howLong;
  2086. X    char *newstr;
  2087. X
  2088. X    howLong = strlen(oldstr);
  2089. X    if ((newstr = malloc(howLong + 1)) != NULL)
  2090. X        (void) strcpy(newstr, oldstr);
  2091. X    return newstr;
  2092. X}    /* NewString */
  2093. X
  2094. X
  2095. X
  2096. X
  2097. X
  2098. Xvoid Getopt_Reset(void)
  2099. X{
  2100. X    Optind = 1;
  2101. X    Optplace = "";
  2102. X}    /* Getopt_Reset */
  2103. X
  2104. Xstatic char *NextOption(char *ostr)
  2105. X{
  2106. X    if ((Optopt = (int) *Optplace++) == (int) ':')
  2107. X        return 0;
  2108. X    return index(ostr, Optopt);
  2109. X}
  2110. X
  2111. Xint Getopt(int nargc, char **nargv, char *ostr)
  2112. X{
  2113. X    register char *oli;                   /* Option letter list index */
  2114. X
  2115. X    if (!*Optplace) {                       /* update scanning pointer */
  2116. X        if (Optind >= nargc || *(Optplace = nargv[Optind]) != '-')
  2117. X            return (EOF);
  2118. X        if (Optplace[1] && *++Optplace == '-') {    /* found "--" */
  2119. X            ++Optind;
  2120. X            return (EOF);
  2121. X        }
  2122. X    }                                   /* Option letter okay? */
  2123. X    oli = NextOption(ostr);
  2124. X    if (oli == NULL) {
  2125. X        if (!*Optplace)
  2126. X            ++Optind;
  2127. X        if (Opterr) {
  2128. X            (void) fprintf(stderr, "%s%s%c\n", *nargv, ": illegal option -- ", Optopt);
  2129. X            return(BADCH);
  2130. X        }
  2131. X    }
  2132. X    if (*++oli != ':') {               /* don't need argument */
  2133. X        Optarg = NULL;
  2134. X        if (!*Optplace)
  2135. X            ++Optind;
  2136. X    } else {                           /* need an argument */
  2137. X        if (*Optplace)                       /* no white space */
  2138. X            Optarg = Optplace;
  2139. X        else if (nargc <= ++Optind) {  /* no arg */
  2140. X            Optplace = EMSG;
  2141. X            if (Opterr) {
  2142. X                (void) fprintf(stderr, "%s%s%c\n", *nargv, ": option requires an argument -- ", Optopt);
  2143. X                return(BADCH);
  2144. X            }
  2145. X        } else                           /* white space */
  2146. X            Optarg = nargv[Optind];
  2147. X        Optplace = EMSG;
  2148. X        ++Optind;
  2149. X    }
  2150. X    return (Optopt);                   /* dump back Option letter */
  2151. X}                                       /* Getopt */
  2152. X
  2153. X
  2154. X
  2155. X
  2156. X/*
  2157. X * Converts an ls date, in either the "Feb  4  1992" or "Jan 16 13:42"
  2158. X * format to a time_t.
  2159. X */
  2160. Xunsigned long UnLSDate(char *dstr)
  2161. X{
  2162. X    char *cp = dstr;
  2163. X    int long mon, day, year, hr, min;
  2164. X    time_t now;
  2165. X    struct tm ut, *t;
  2166. X
  2167. X    switch (*cp++) {
  2168. X        case 'A':
  2169. X            mon = (*cp == 'u') ? 7 : 3;
  2170. X            break;
  2171. X        case 'D':
  2172. X            mon = 11;
  2173. X            break;
  2174. X        case 'F':
  2175. X            mon = 1;
  2176. X            break;
  2177. X        default:                       /* shut up un-init warning */
  2178. X        case 'J':
  2179. X            if (*cp++ == 'u')
  2180. X                mon = (*cp == 'l') ? 6 : 5;
  2181. X            else
  2182. X                mon = 0;
  2183. X            break;
  2184. X        case 'M':
  2185. X            mon = (*++cp == 'r') ? 2 : 4;
  2186. X            break;
  2187. X        case 'N':
  2188. X            mon = 10;
  2189. X            break;
  2190. X        case 'O':
  2191. X            mon = 9;
  2192. X            break;
  2193. X        case 'S':
  2194. X            mon = 8;
  2195. X    }
  2196. X    cp = dstr + 4;
  2197. X    day = 0;
  2198. X    if (*cp != ' ')
  2199. X        day = 10 * (*cp - '0');
  2200. X    cp++;
  2201. X    day += *cp++ - '0';
  2202. X    min = 0;
  2203. X    
  2204. X    (void) time(&now);
  2205. X    t = localtime(&now);
  2206. X
  2207. X    if (*++cp != ' ') {
  2208. X        /* It's a time, XX:YY, not a year. */
  2209. X        cp[2] = ' ';
  2210. X        (void) sscanf(cp, "%ld %ld", &hr, &min);
  2211. X        cp[2] = ':';
  2212. X        year = t->tm_year;
  2213. X        if (mon > t->tm_mon)
  2214. X            --year;
  2215. X    } else {
  2216. X        hr = min = 0;
  2217. X        (void) sscanf(cp, "%ld", &year);
  2218. X        year -= 1900;
  2219. X    }
  2220. X    ut.tm_sec = 0;
  2221. X    ut.tm_min = min;
  2222. X    ut.tm_hour = hr;
  2223. X    ut.tm_mday = day;
  2224. X    ut.tm_mon = mon;
  2225. X    ut.tm_year = year;
  2226. X    ut.tm_isdst = 0;
  2227. X    ut.tm_wday = ut.tm_yday = 0;
  2228. X    return ((unsigned long) mktime(&ut));
  2229. X}    /* UnLSDate */
  2230. X
  2231. X
  2232. X
  2233. X
  2234. Xvoid Perror(
  2235. X#ifdef DB_ERRS
  2236. X            char *fromProc
  2237. X            ,
  2238. X#ifdef __LINE__
  2239. X            int lineNum,
  2240. X#endif
  2241. X#endif
  2242. X            char *msg
  2243. X            )
  2244. X{
  2245. X    extern int errno;
  2246. X
  2247. X    if (NOT_VQUIET) {
  2248. X#ifdef sun
  2249. X    /*
  2250. X     * There is a problem in the SunOS headers when compiling with an ANSI
  2251. X     * compiler.  The problem is that there are macros in the form of
  2252. X     * #define MAC(x) 'x', and this will always be the character x instead
  2253. X     * of whatever parameter was passed to MAC.  If we get these errors, it
  2254. X     * usually means that you are trying to compile with gcc when you haven't
  2255. X     * run the 'fixincludes' script that fixes these macros.  We will ignore
  2256. X     * the error, but it means that the echo() function won't work correctly,
  2257. X     * and you will see your password echo.
  2258. X     */
  2259. X        if (errno == ENOTTY)
  2260. X            return;
  2261. X#endif
  2262. X        (void) fprintf(stderr, "NcFTP");
  2263. X#ifdef DB_ERRS
  2264. X        if (fromProc != NULL)
  2265. X            (void) fprintf(stderr, "/%s", fromProc);
  2266. X#ifdef __LINE__
  2267. X        (void) fprintf(stderr, "/%d", lineNum);
  2268. X#endif
  2269. X#endif
  2270. X        (void) fprintf(stderr, ": ");
  2271. X        if (msg != NULL)
  2272. X            (void) fprintf(stderr, "%s (%d): ", msg, errno);
  2273. X        perror(NULL);
  2274. X    }
  2275. X}    /* Perror */
  2276. X
  2277. X
  2278. X
  2279. X
  2280. Xsize_t RemoveTrailingNewline(char *cp, int *stripped)
  2281. X{
  2282. X    size_t len;
  2283. X    int nBytesStripped = 0;
  2284. X
  2285. X    if (cp != NULL) {
  2286. X        cp += (len = strlen(cp)) - 1;
  2287. X        if (*cp == '\n') {
  2288. X            *cp-- = 0;    /* get rid of the newline. */
  2289. X            nBytesStripped++;
  2290. X        }
  2291. X        if (*cp == '\r') { /* no returns either, please. */
  2292. X            *cp = 0;
  2293. X            nBytesStripped++;
  2294. X        }
  2295. X        if (stripped != NULL)
  2296. X            *stripped = nBytesStripped;
  2297. X        return len;
  2298. X    }
  2299. X    return (size_t)0;
  2300. X}    /* RemoveTrailingNewline */
  2301. X
  2302. X
  2303. X
  2304. X#ifdef GETLINE
  2305. Xextern size_t epromptlen;
  2306. X
  2307. X/*
  2308. X * The Getline library doesn't detect the ANSI escape sequences, so the
  2309. X * library would think that a string is longer than actually appears on
  2310. X * screen.  This function lets Getline work properly.  This function is
  2311. X * intended to fix that problem for the main command prompt only.  If any
  2312. X * other prompts want to use ANSI escapes, a (costly) function would have
  2313. X * to scan the prompt for all escape sequences.
  2314. X */
  2315. X/*ARGSUSED*/
  2316. Xstatic int MainPromptLen(char *pr)
  2317. X{
  2318. X    return (int)epromptlen;
  2319. X}
  2320. X#endif
  2321. X
  2322. Xchar *Gets(char *promptstr, char *sline, size_t size)
  2323. X{
  2324. X    char *cp, ch;
  2325. X    string plines;
  2326. X#ifdef GETLINE
  2327. X    int ismainprompt = (promptstr == prompt2);
  2328. X#endif
  2329. X
  2330. X    if (!fromatty || !toatty) {
  2331. X        /* Don't worry about a cmdline/history editor if you redirected a
  2332. X         * file at me.
  2333. X         */
  2334. X        if (!toatty && fromatty) {
  2335. X            /* It's okay to print a prompt if we are redirecting stdout,
  2336. X             * as long as stdin is still a tty.  Otherwise, don't print
  2337. X             * a prompt at all if stdin is redirected.
  2338. X             */
  2339. X#ifdef CURSES
  2340. X            tcap_put(promptstr);
  2341. X#else
  2342. X            (void) fputs(promptstr, stdout);
  2343. X#endif
  2344. X        }
  2345. X        cp = fgets(sline, (int)size, stdin);
  2346. X        (void) RemoveTrailingNewline(cp, NULL);
  2347. X        return cp;
  2348. X    }
  2349. X
  2350. X    /*
  2351. X     * The prompt string may actually be several lines if the user put a
  2352. X     * newline in it with the @N option.  In this case we only want to print
  2353. X     * the very last line, so the command-line editors won't screw up.  So
  2354. X     * now we print all the lines except the last line.
  2355. X     */
  2356. X    cp = rindex(promptstr, '\n');
  2357. X    if (cp != NULL) {
  2358. X        ch = *++cp;
  2359. X        *cp = 0;
  2360. X        (void) Strncpy(plines, promptstr);
  2361. X        *cp = ch;
  2362. X        promptstr = cp;
  2363. X#ifdef CURSES
  2364. X        tcap_put(plines);
  2365. X#else
  2366. X        (void) fputs(plines, stdout);
  2367. X#endif
  2368. X    }
  2369. X
  2370. X#ifdef READLINE
  2371. X    if ((cp = readline(promptstr)) != NULL) {
  2372. X        (void) _Strncpy(sline, cp, size);
  2373. X        free(cp);
  2374. X        (void) RemoveTrailingNewline(cp = sline, NULL);
  2375. X        add_history(cp);
  2376. X    }
  2377. X#else    /* READLINE */
  2378. X
  2379. X#ifdef GETLINE
  2380. X    if (toatty) {
  2381. X        if (ismainprompt)
  2382. X            gl_strwidth(MainPromptLen);
  2383. X        if ((cp = getline(promptstr)) != NULL) {
  2384. X            (void) _Strncpy(sline, cp, size);
  2385. X            if (!*cp) {
  2386. X                cp = NULL;
  2387. X            } else {
  2388. X                gl_histadd(cp);
  2389. X                cp = sline;
  2390. X            }
  2391. X        }
  2392. X        gl_strwidth((int (*)(char *)) strlen);
  2393. X    } else {
  2394. X#ifdef CURSES
  2395. X        tcap_put(promptstr);
  2396. X#else
  2397. X        (void) fputs(promptstr, stdout);
  2398. X#endif
  2399. X        cp = fgets(sline, (int) (size - 1), stdin);
  2400. X    }
  2401. X    (void) RemoveTrailingNewline(cp, NULL);
  2402. X#else /* !GETLINE */
  2403. X
  2404. X#ifdef CURSES
  2405. X    tcap_put(promptstr);
  2406. X#else
  2407. X    (void) fputs(promptstr, stdout);
  2408. X#endif
  2409. X
  2410. X    cp = fgets(sline, (int) (size - 1), stdin);
  2411. X    (void) RemoveTrailingNewline(cp, NULL);
  2412. X#endif /* !GETLINE */
  2413. X#endif /* !READLINE */
  2414. X    return cp;
  2415. X}    /* Gets */
  2416. X
  2417. X
  2418. X
  2419. X
  2420. Xchar **re_makeargv(char *promptstr, int *argc)
  2421. X{
  2422. X    size_t sz;
  2423. X
  2424. X    (void) strcat(line, " ");
  2425. X    sz = strlen(line);
  2426. X    (void) Gets(promptstr, &line[sz], (size_t) (CMDLINELEN - sz)) ;
  2427. X    (void) makeargv();
  2428. X    *argc = margc;
  2429. X    return (margv);
  2430. X}    /* re_makeargv */
  2431. X
  2432. X
  2433. X
  2434. X
  2435. Xchar *get_cwd(char *buf, int size)
  2436. X{
  2437. X#ifdef SYSV
  2438. X#    ifdef NO_UNISTDH
  2439. X#        ifdef GETCWDSIZET
  2440. X            extern char *getcwd(char *, size_t);
  2441. X#        else
  2442. X            extern char *getcwd(char *, int);
  2443. X#        endif
  2444. X#    endif
  2445. X    return (getcwd(buf, size - 1));
  2446. X#else
  2447. X    extern char *getwd(char *);
  2448. X    return (getwd(buf));
  2449. X#endif
  2450. X}   /* get_cwd */
  2451. X
  2452. X
  2453. X
  2454. Xint tmp_name(char *str)
  2455. X{
  2456. X    (void) strcpy(str, "/tmp/ncftpXXXXXX");
  2457. X    return (!mktemp(str));
  2458. X}    /* tmp_name */
  2459. X
  2460. X
  2461. X
  2462. X
  2463. Xchar *onoff(int boolf)
  2464. X{
  2465. X    return (boolf ? "on" : "off");
  2466. X}   /* onoff */
  2467. X
  2468. X
  2469. X
  2470. X
  2471. Xint StrToBool(char *s)
  2472. X{
  2473. X    int c;
  2474. X    int result;
  2475. X
  2476. X    c = tolower(*s);
  2477. X    result = 0;
  2478. X    switch (c) {
  2479. X        case 'f':           /* false */
  2480. X        case 'n':            /* no */
  2481. X            break;
  2482. X        case 'o':           /* test for "off" and "on" */
  2483. X            c = tolower(s[1]);
  2484. X            if (c == 'f')
  2485. X                break;
  2486. X            /* fall through */
  2487. X        case 't':           /* true */
  2488. X        case 'y':            /* yes */
  2489. X            result = 1;
  2490. X            break;
  2491. X        default:            /* 1, 0, -1, other number? */
  2492. X            if (atoi(s) != 0)
  2493. X                result = 1;
  2494. X    }
  2495. X    return result;
  2496. X}   /* StrToBool */
  2497. X
  2498. X
  2499. X
  2500. X
  2501. Xint confirm(char *cmd, char *file)
  2502. X{
  2503. X    str32 str, pr;
  2504. X
  2505. X    if (!fromatty || (activemcmd && !mprompt))
  2506. X        return 1;
  2507. X    (void) sprintf(pr, "%s %s? ", cmd, file);
  2508. X    (void) Gets(pr, str, sizeof(str));
  2509. X    return (*str != 'n' && *str != 'N');
  2510. X}    /* confirm */
  2511. X
  2512. X
  2513. X
  2514. Xvoid fatal(char *msg)
  2515. X{
  2516. X    (void) fprintf(stderr, "%s: %s\n", progname, msg);
  2517. X    close_up_shop();
  2518. X    exit(1);
  2519. X}    /* fatal */
  2520. X
  2521. X
  2522. X
  2523. X
  2524. Xint UserLoggedIn(void)
  2525. X{
  2526. X    static int inited = 0;
  2527. X    static int parent_pid, stderr_was_tty;
  2528. X
  2529. X    if (!inited) {
  2530. X        stderr_was_tty = isatty(2);
  2531. X        parent_pid = getppid();
  2532. X        inited++;
  2533. X    }
  2534. X    if ((stderr_was_tty && !isatty(2)) || (getppid() != parent_pid))
  2535. X        return 0;
  2536. X    return 1;
  2537. X}    /* UserLoggedIn */
  2538. X
  2539. X
  2540. X
  2541. X
  2542. Xstruct cmd *getcmd(char *name)
  2543. X{
  2544. X    struct cmd *c, *found;
  2545. X    int nmatches;
  2546. X    size_t len;
  2547. X    char *p;
  2548. X
  2549. X    found = (struct cmd *)0;
  2550. X    if (name != NULL) {
  2551. X        len = strlen(name);
  2552. X        nmatches = 0;
  2553. X        for (c = cmdtab; (p = c->c_name) != NULL; c++) {
  2554. X            if (strcmp(name, p) == 0) {
  2555. X                /* Exact match. */
  2556. X                found = c;
  2557. X                goto xx;
  2558. X            }
  2559. X            if (c->c_handler == unimpl)
  2560. X                continue;
  2561. X            if (strncmp(name, p, len) == 0) {
  2562. X                if (++nmatches > 1) {
  2563. X                    found = ((struct cmd *) -1);    
  2564. X                    goto xx;
  2565. X                }                
  2566. X                found = c;
  2567. X            } else if (found != NULL)
  2568. X                break;
  2569. X        }
  2570. X    }
  2571. Xxx:
  2572. X    return (found);
  2573. X}    /* getcmd */
  2574. X
  2575. X
  2576. X
  2577. X
  2578. Xvoid cmd_help(struct cmd *c)
  2579. X{
  2580. X    (void) printf("%s: %s.\n",
  2581. X        c->c_name,
  2582. X        c->c_help
  2583. X    );
  2584. X}    /* cmd_help */
  2585. X
  2586. X
  2587. X
  2588. X
  2589. Xvoid cmd_usage(struct cmd *c)
  2590. X{
  2591. X    if (c->c_usage != NULL)
  2592. X        (void) printf("Usage: %s%s\n",
  2593. X            c->c_name,
  2594. X            c->c_usage
  2595. X        );
  2596. X}    /* cmd_usage */
  2597. X
  2598. X
  2599. X
  2600. X
  2601. Xchar *GetHomeDir(char *home)
  2602. X{
  2603. X    struct passwd *pw;
  2604. X    pw = getpwuid(getuid());
  2605. X    return (strcpy(home, pw->pw_dir));
  2606. X}    /* GetHomeDir */
  2607. X
  2608. X
  2609. X
  2610. X
  2611. X/*
  2612. X * A simple function that translates most pathnames with ~, ~user, or
  2613. X * environment variables as the first item.  It won't do paths with env vars
  2614. X * or ~s in the middle of the path, but those are extremely rare.
  2615. X */
  2616. Xchar *LocalPath(char *path)
  2617. X{
  2618. X    longstring orig;
  2619. X    struct passwd *pw;
  2620. X    char *firstent = NULL;
  2621. X    char *cp, *dp, *rest;
  2622. X
  2623. X    (void) Strncpy(orig, path);
  2624. X    if (((cp = index(orig, '/')) != NULL) && (cp != orig)) {
  2625. X        *cp = 0;
  2626. X        rest = cp + 1;
  2627. X        if (orig[0] == '~') {
  2628. X            if (orig[1] == 0) {
  2629. X                pw = getpwuid(getuid());
  2630. X            } else {
  2631. X                pw = getpwnam(orig + 1);
  2632. X            }
  2633. X            if (pw != NULL)
  2634. X                firstent = pw->pw_dir;
  2635. X        } else if (orig[0] == '$') {
  2636. X            cp = orig + 1;
  2637. X            dp = orig + strlen(orig) - 1;
  2638. X            if ((*cp == '(' && *dp == ')') || (*cp == '{' && *dp == '}')) {
  2639. X                cp++;
  2640. X                *dp = 0;
  2641. X            }
  2642. X            firstent = getenv(cp);
  2643. X        }
  2644. X        if (firstent != NULL)
  2645. X            (void) sprintf(path, "%s/%s", firstent, rest);
  2646. X    }
  2647. X    return (path);
  2648. X}    /* LocalPath */
  2649. X
  2650. X
  2651. X
  2652. X/*
  2653. X * A special case, where invisible dot-files that would normally appear in
  2654. X * your home directory will appear instead as visible files in your $DOTDIR
  2655. X * directory if you have one.
  2656. X */
  2657. X
  2658. X#define LCMP(b) (strncmp(path, (b), (o = sizeof(b) - 1)) == 0)
  2659. X
  2660. Xchar *LocalDotPath(char *path)
  2661. X{
  2662. X    size_t o;
  2663. X    longstring s, s2, h;
  2664. X    char *cp = getenv("DOTDIR");
  2665. X
  2666. X    if (cp == NULL) {
  2667. X        goto aa;
  2668. X    } else {
  2669. X        if (*cp != '/' && *cp != '~') {
  2670. X            /* then maybe they mean relative to $HOME. */
  2671. X            (void) sprintf(s2, "%s/%s", GetHomeDir(h), cp);
  2672. X            cp = s2;
  2673. X        }
  2674. X        if (LCMP("~/.") ||
  2675. X            LCMP("$HOME/.") ||
  2676. X            LCMP("$home/.") ||
  2677. X            LCMP("$(HOME)/.") ||
  2678. X            LCMP("${HOME}/.")
  2679. X        ) {
  2680. X            (void) Strncpy(s, path);
  2681. X            (void) sprintf(path, "%s/%s", cp, s + o);
  2682. X            cp = path;
  2683. X        } else {
  2684. Xaa:            cp = LocalPath(path);
  2685. X        }
  2686. X    }
  2687. X    return cp;
  2688. X}    /* LocalDotPath */
  2689. X
  2690. X/* eof Util.c */
  2691. END_OF_FILE
  2692.   if test 15461 -ne `wc -c <'util.c'`; then
  2693.     echo shar: \"'util.c'\" unpacked with wrong size!
  2694.   fi
  2695.   # end of 'util.c'
  2696. fi
  2697. echo shar: End of archive 4 \(of 5\).
  2698. cp /dev/null ark4isdone
  2699. MISSING=""
  2700. for I in 1 2 3 4 5 ; do
  2701.     if test ! -f ark${I}isdone ; then
  2702.     MISSING="${MISSING} ${I}"
  2703.     fi
  2704. done
  2705. if test "${MISSING}" = "" ; then
  2706.     echo You have unpacked all 5 archives.
  2707.     rm -f ark[1-9]isdone
  2708. else
  2709.     echo You still must unpack the following archives:
  2710.     echo "        " ${MISSING}
  2711. fi
  2712. exit 0
  2713. exit 0 # Just in case...
  2714.