home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / ncftp / part04 < prev    next >
Encoding:
Text File  |  1993-11-02  |  59.8 KB  |  2,273 lines

  1. Newsgroups: comp.sources.misc
  2. From: mgleason@cse.unl.edu (Mike Gleason)
  3. Subject: v40i079:  ncftp - Alternative User Interface for FTP, v1.6, Part04/06
  4. Message-ID: <1993Nov2.232434.6463@sparky.sterling.com>
  5. X-Md4-Signature: d71867cd0b7b59f46522a93e5b22ae0e
  6. Keywords: ncftp
  7. Sender: kent@sparky.sterling.com (Kent Landfield)
  8. Organization: NCEMRSoft
  9. Date: Tue, 2 Nov 1993 23:24:34 GMT
  10. Approved: kent@sparky.sterling.com
  11.  
  12. Submitted-by: mgleason@cse.unl.edu (Mike Gleason)
  13. Posting-number: Volume 40, Issue 79
  14. Archive-name: ncftp/part04
  15. Environment: UNIX, ANSI-C, !SVR4
  16. Supersedes: ncftp: Volume 39, Issue 53-57
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then feed it
  20. # into a shell via "sh file" or similar.  To overwrite existing files,
  21. # type "sh file -c".
  22. # Contents:  ftprc.c main.c patchlevel.h set.c
  23. # Wrapped by kent@sparky on Mon Nov  1 16:19:17 1993
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 4 (of 6)."'
  27. if test -f 'ftprc.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'ftprc.c'\"
  29. else
  30.   echo shar: Extracting \"'ftprc.c'\" \(11813 characters\)
  31.   sed "s/^X//" >'ftprc.c' <<'END_OF_FILE'
  32. X/* ftprc.c */
  33. X
  34. X/*  $RCSfile: ftprc.c,v $
  35. X *  $Revision: 14020.11 $
  36. X *  $Date: 93/07/09 10:58:37 $
  37. X */
  38. X
  39. X#include "sys.h"
  40. X
  41. X#include <sys/stat.h>
  42. X
  43. X#include <ctype.h>
  44. X
  45. X#include "util.h"
  46. X#include "ftprc.h"
  47. X#include "main.h"
  48. X#include "cmds.h"
  49. X#include "set.h"
  50. X#include "defaults.h"
  51. X#include "copyright.h"
  52. X
  53. X/* ftprc.c global variables */
  54. Xsiteptr                    firstsite = NULL, lastsite = NULL;
  55. Xrecentsite                recents[dMAXRECENTS];
  56. Xint                        nRecents = 0;
  57. Xint                        nSites = 0;
  58. Xint                        keep_recent = dRECENT_ON;
  59. Xlongstring                rcname;
  60. Xlongstring                recent_file;
  61. Xint                        parsing_rc = 0;
  62. X
  63. Xextern char                *line, *margv[];
  64. Xextern int                margc, fromatty;
  65. Xextern string            anon_password;        /* most likely your email address */
  66. Xextern struct userinfo    uinfo;
  67. X
  68. Xint thrash_rc(void)
  69. X{
  70. X    struct stat            st;
  71. X    string                word, str;
  72. X    longstring            cwd;
  73. X    char                *cp, *dp, *rc;
  74. X    FILE                *fp;
  75. X    int                    i;
  76. X
  77. X    (void) get_cwd(cwd, sizeof(cwd));
  78. X    if (cwd[strlen(cwd) - 1] != '/')
  79. X        (void) Strncat(cwd, "/");
  80. X
  81. X    /* Because some versions of regular ftp complain about ncftp's
  82. X     * #set commands, FTPRC takes precedence over NETRC.
  83. X     */
  84. X    cp = getenv("DOTDIR");
  85. X    for (i=0; i<2; i++) {
  86. X        rc = (i == 0) ? FTPRC : NETRC;
  87. X
  88. X        (void) sprintf(rcname, "%s%s", cwd, rc);
  89. X        if (stat(rcname, &st) == 0)
  90. X            goto foundrc;
  91. X        
  92. X        (void) sprintf(rcname, "%s.%s", cwd, rc);
  93. X        if (stat(rcname, &st) == 0)
  94. X            goto foundrc;
  95. X
  96. X        if (cp != NULL) {
  97. X            (void) sprintf(rcname, "%s/.%s", cp, rc);
  98. X            if (stat(rcname, &st) == 0)
  99. X                goto foundrc;
  100. X        }
  101. X
  102. X        (void) sprintf(rcname, "%s/.%s", uinfo.homedir, rc);
  103. X        if (stat(rcname, &st) == 0)
  104. X            goto foundrc;
  105. X    }
  106. X
  107. X    return (0);    /* it's OK not to have an rc. */
  108. X    
  109. Xfoundrc:    
  110. X    if ((st.st_mode & 077) != 0)                /* rc must be unreadable by others. */
  111. X        (void) chmod(rcname, 0600);
  112. X
  113. X    if ((fp = fopen(rcname, "r")) == NULL) {
  114. X        PERROR("thrash_rc", rcname);
  115. X        return -1;
  116. X    }
  117. X    
  118. X    parsing_rc = 1;
  119. X    while ((cp = FGets(str, fp)) != 0) {
  120. X        while (isspace(*cp)) ++cp;        /* skip leading space. */
  121. X        if (*cp == '#') {
  122. X            if ((strncmp("set", ++cp, (size_t)3) == 0) || (strncmp("unset", cp, (size_t)5) == 0)) {
  123. X                (void) strcpy(line, cp);
  124. X                makeargv();
  125. X                (void) set(margc, margv);            
  126. X                /* setting or unsetting a variable. */
  127. X            } /* else a comment. */
  128. X        } else {
  129. X            if (strncmp(cp, "machine", (size_t) 7) == 0) {
  130. X                /* We have a new machine record. */
  131. X                cp += 7;
  132. X                while (isspace(*cp)) ++cp;    /* skip delimiting space. */
  133. X                dp = word;
  134. X                while (*cp && !isspace(*cp)) *dp++ = *cp++;    /* copy the name. */
  135. X                *dp = 0;
  136. X                AddNewSitePtr(word);
  137. X            }
  138. X        }
  139. X    }
  140. X    (void) fclose(fp);
  141. X    parsing_rc = 0;
  142. X    return 1;
  143. X}    /* thrash_rc */
  144. X
  145. X
  146. X
  147. X
  148. Xvoid AddNewSitePtr(char *word)
  149. X{
  150. X    siteptr            s;
  151. X
  152. X    if ((s = (siteptr) malloc(sizeof(site))) != 0) {
  153. X        s->next = NULL;
  154. X        if ((s->name = malloc(strlen(word) + 1)) != 0) {
  155. X            (void) strcpy(s->name, word);
  156. X            if (firstsite == NULL)
  157. X                firstsite = lastsite = s;
  158. X            else {
  159. X                lastsite->next = s;
  160. X                lastsite = s;
  161. X            }
  162. X            ++nSites;
  163. X        } else {
  164. X            Free(s);
  165. X        }
  166. X    }
  167. X}    /* AddNewSitePtr */
  168. X
  169. X
  170. X
  171. X
  172. Xstatic int RecentCmp(recentsite *a, recentsite *b)
  173. X{
  174. X    int i = 1;
  175. X    
  176. X    if (a->lastcall > b->lastcall)
  177. X        i = -1;
  178. X    else if (a->lastcall == b->lastcall)
  179. X        i = 0;
  180. X    return i;
  181. X}    /* RecentCmp */
  182. X
  183. X
  184. X
  185. X
  186. Xstatic siteptr FindNetrcSite(char *host)
  187. X{
  188. X    register siteptr s, s2;
  189. X
  190. X    /* see if 'host' is in our list of favorite sites (in NETRC). */
  191. X    for (s = firstsite; s != NULL; s2=s->next, s=s2) {
  192. X        if (strstr(s->name, host) != NULL) {
  193. X            return s;
  194. X        }
  195. X    }
  196. X    return NULL;
  197. X}    /* FindNetrcSite */
  198. X
  199. X
  200. X
  201. X
  202. Xstatic recentsite *FindRecentSite(char *host)
  203. X{
  204. X    register recentsite        *r;
  205. X    register int            i;
  206. X
  207. X    /* see if 'host' is in our list of favorite sites (in recent-log). */
  208. X    for (i=0; i<nRecents; i++) {
  209. X        r = &recents[i];
  210. X        if (strstr(r->name, host) != NULL) {
  211. X            return r;
  212. X        }
  213. X    }
  214. X    return NULL;
  215. X}    /* FindRecentSite */
  216. X
  217. X
  218. X
  219. X
  220. Xvoid ReadRecentSitesFile(void)
  221. X{
  222. X    FILE *rfp;
  223. X    recentsite *r;
  224. X    char name[64];
  225. X    int offset;
  226. X    longstring str;
  227. X
  228. X    nRecents = 0;
  229. X    if (recent_file[0] != 0 && keep_recent) {
  230. X        rfp = fopen(recent_file, "r");
  231. X        if (rfp != NULL) {
  232. X            for (; nRecents < dMAXRECENTS; ) {
  233. X                r = &recents[nRecents];
  234. X                if (FGets(str, rfp) == NULL)
  235. X                    break;
  236. X                (void) RemoveTrailingNewline(str, NULL);
  237. X                if (sscanf(str, "%s %lu %n",
  238. X                    name,
  239. X                    (unsigned long *) &r->lastcall,
  240. X                    &offset) >= 2)
  241. X                {
  242. X                    if ((r->name = NewString(name)) != NULL) {
  243. X                        r->dir = NewString(str + offset);
  244. X                        if (r->dir != NULL)
  245. X                            nRecents++;
  246. X                        else free(r->name);
  247. X                    }
  248. X                }
  249. X            }
  250. X            (void) fclose(rfp);
  251. X        }
  252. X    }
  253. X}    /* ReadRecentSitesFile */
  254. X
  255. X
  256. X
  257. Xstatic void SortRecentList(void)
  258. X{
  259. X    QSort(recents, nRecents, sizeof(recentsite), RecentCmp);
  260. X}    /* SortRecentList */
  261. X
  262. X
  263. X
  264. X
  265. Xvoid WriteRecentSitesFile(void)
  266. X{
  267. X    FILE            *rfp;
  268. X    recentsite        *r;
  269. X    int                i;
  270. X
  271. X    if ((recent_file[0] != 0) && (nRecents > 0) && (keep_recent)) {
  272. X        rfp = fopen(recent_file, "w");
  273. X        SortRecentList();
  274. X        if (rfp != NULL) {
  275. X            for (i=0; i<nRecents; i++) {
  276. X                r = &recents[i];
  277. X                (void) fprintf(rfp, "%-32s %11lu %s\n", r->name,
  278. X                    (unsigned long) r->lastcall, r->dir);
  279. X            }
  280. X            (void) fclose(rfp);
  281. X            (void) chmod(recent_file, 0600);
  282. X        }
  283. X    }
  284. X}    /* WriteRecentSitesFile */
  285. X
  286. X
  287. X
  288. X
  289. Xvoid AddRecentSite(char *host, char *lastdir)
  290. X{
  291. X    char            *nhost, *ndir;
  292. X    recentsite        *r;
  293. X    
  294. X    if (keep_recent) {
  295. X        nhost = NewString(host);
  296. X        /* Use '/' to denote that the current directory wasn't known,
  297. X         * because we won't try to cd to the root directory.
  298. X         */
  299. X        ndir = NewString(*lastdir ? lastdir : "/");
  300. X        
  301. X        /* Don't bother if we don't have the memory, or if it is already
  302. X         * in our NETRC.
  303. X         */
  304. X        if ((ndir != NULL) && (nhost != NULL) && (FindNetrcSite(host) == NULL)) {
  305. X            if (nRecents == dMAXRECENTS) {
  306. X                SortRecentList();
  307. X                r = &recents[dMAXRECENTS - 1];
  308. X                if (r->name != NULL)
  309. X                    free(r->name);
  310. X                if (r->dir != NULL)
  311. X                    free(r->dir);
  312. X            } else {
  313. X                r = &recents[nRecents];
  314. X                nRecents++;
  315. X            }
  316. X            r->name = nhost;            
  317. X            r->dir = ndir;
  318. X            (void) time(&r->lastcall);
  319. X            SortRecentList();
  320. X        }
  321. X    }
  322. X}    /* AddRecentSite */
  323. X
  324. X
  325. X
  326. X
  327. X/*
  328. X * After you are done with a site (by closing it or quitting), we
  329. X * need to update the list of recent sites called.
  330. X */
  331. Xvoid UpdateRecentSitesList(char *host, char *lastdir)
  332. X{
  333. X    recentsite *r;
  334. X    char *ndir;
  335. X
  336. X    if (keep_recent) {    
  337. X        r = FindRecentSite(host);
  338. X        if (r == NULL)
  339. X            AddRecentSite(host, lastdir);
  340. X        else {
  341. X            /* Update the last time connected, and the directory we left in. */
  342. X            if ((ndir = NewString(*lastdir ? lastdir : "/")) != NULL) {
  343. X                free(r->dir);
  344. X                r->dir = ndir;
  345. X            }
  346. X            (void) time(&r->lastcall);
  347. X        }
  348. X    }
  349. X}    /* UpdateRecentSitesList */
  350. X
  351. X
  352. X
  353. X/*
  354. X * Prints out the number of sites we know about, so the user can figure out
  355. X * an abbreviation or type it's number to open (setpeer).
  356. X */
  357. Xvoid PrintSiteList(void)
  358. X{
  359. X    int                        i, j;
  360. X    siteptr                    s, s2;
  361. X
  362. X    if (fromatty) {
  363. X        j = 0;
  364. X        i = 1;
  365. X        if (nRecents > 0) {
  366. X            j++;
  367. X            (void) printf("Recently called sites:\n");
  368. X            for (; i<=nRecents; i++) {
  369. X                (void) printf("%4d. %-32s", i, recents[i-1].name);
  370. X                i++;
  371. X                if (i <= nRecents) {
  372. X                    (void) printf("%5d. %-32s", i, recents[i-1].name);
  373. X                } else {
  374. X                    (void) printf("\n");
  375. X                    break;
  376. X                }
  377. X                (void) printf("\n");
  378. X            }
  379. X        }
  380. X        if (nSites > 0) {
  381. X            j++;
  382. X            (void) printf("Sites in your netrc (%s):\n", rcname);
  383. X            for (s = firstsite; s != NULL; s2=s->next, s=s2, ++i) {
  384. X                (void) printf("%4d. %-32s", i, s->name);
  385. X                s2=s->next;
  386. X                s=s2;
  387. X                i++;
  388. X                if (s != NULL) {
  389. X                    (void) printf("%5d. %-32s", i, s->name);
  390. X                } else {
  391. X                    (void) printf("\n");
  392. X                    break;
  393. X                }
  394. X                (void) printf("\n");
  395. X            }
  396. X        }
  397. X        if (j > 0) {
  398. X            (void) printf("\
  399. XNote that you can specify an abbreviation of any name, or #x, where x is the\n\
  400. Xnumber of the site you want to connect to.\n\n");
  401. X        }
  402. X    }
  403. X}    /* PrintRecentSiteList */
  404. X
  405. X
  406. X
  407. X
  408. X/*
  409. X * Given a sitename, check to see if the name was really an abbreviation
  410. X * of a site in the NETRC, or a site in our list of recently connected
  411. X * sites.  Also check if the name was in the format #x, where x which
  412. X * would mean to use recents[x].name as the site; if x was greater than
  413. X * the number of sites in the recent list, then index into the netrc
  414. X * site list.
  415. X */
  416. Xvoid GetFullSiteName(char *host, char *lastdir)
  417. X{
  418. X    register siteptr        s, s2;
  419. X    register recentsite        *r;
  420. X    char                    *ndir, *nhost, *cp;
  421. X    int                        x, i, isAllDigits;
  422. X
  423. X    ndir = nhost = NULL;
  424. X    x = 0;
  425. X
  426. X    /* Don't allow just numbers as abbreviations;  "open 2" could be
  427. X     * confused between site numbers in the open 'menu,' like
  428. X     * "2. unlinfo.unl.edu" and IP numbers "128.93.2.1" or even numbers
  429. X     * in the site name like "simtel20.army.mil."
  430. X     */
  431. X    
  432. X    for (isAllDigits = 1, cp = host; *cp != 0; cp++) {
  433. X        if (!isdigit(*cp)) {
  434. X            isAllDigits = 0;
  435. X            break;
  436. X        }
  437. X    }
  438. X
  439. X    if (!isAllDigits) {
  440. X        if (host[0] == '#')
  441. X            (void) sscanf(host + 1, "%d", &x);
  442. X        /* Try matching the abbreviation, since it isn't just a number. */
  443. X        /* see if 'host' is in our list of favorite sites (in NETRC). */
  444. X
  445. X        if (x == 0) {
  446. X            if ((s = FindNetrcSite(host)) != NULL) {
  447. X                nhost = s->name;
  448. X            } else if ((r = FindRecentSite(host)) != NULL) {
  449. X                nhost = r->name;
  450. X                ndir = r->dir;
  451. X            }
  452. X        }
  453. X    } else if (sscanf(host, "%d", &x) != 1) {
  454. X        x = 0;
  455. X    }
  456. X
  457. X    if (--x >= 0) {
  458. X        if (x < nRecents) {
  459. X            nhost = recents[x].name;
  460. X            ndir = recents[x].dir;
  461. X        } else {
  462. X            x -= nRecents;
  463. X            if (x < nSites) {
  464. X                for (i = 0, s = firstsite; i < x; s2=s->next, s=s2)
  465. X                    ++i;                
  466. X                nhost = s->name;
  467. X            }
  468. X        }
  469. X    }
  470. X
  471. X    if (nhost != NULL) {
  472. X        (void) strcpy(host, nhost);
  473. X        if (lastdir != NULL) {
  474. X            *lastdir = 0;
  475. X            /* Don't cd if the dir is the root directory. */
  476. X            if (ndir != NULL && (strcmp("/", ndir) != 0))
  477. X                (void) strcpy(lastdir, ndir);
  478. X        }
  479. X    }
  480. X}    /* GetFullSiteName */
  481. X
  482. X
  483. X
  484. X
  485. Xint ruserpass2(char *host, char **username, char **pass, char **acct)
  486. X{
  487. X    FILE            *fp;
  488. X    char            *cp, *dp, *dst, *ep;
  489. X    str32            macname;
  490. X    char            *varname;
  491. X    int                site_found;
  492. X    string            str;
  493. X    static string    auser;
  494. X    static str32    apass, aacct;
  495. X
  496. X    site_found = 0;
  497. X
  498. X    if ((fp = fopen(rcname, "r")) != NULL) {
  499. X        parsing_rc = 1;
  500. X        while (FGets(str, fp)) {
  501. X            if ((cp = strstr(str, "machine")) != 0) {
  502. X                /* Look for the machine token. */
  503. X                cp += 7;
  504. X                while (isspace(*cp))
  505. X                    cp++;
  506. X            } else
  507. X                continue;
  508. X            /* if (strstr(cp, host) != NULL) { */
  509. X            if (strncmp(host, cp, strlen(host)) == 0) {
  510. X                site_found = 1;
  511. X                while (!isspace(*cp))
  512. X                    ++cp;        /* skip the site name. */
  513. X                do {
  514. X                    /* Skip any comments ahead of time. */
  515. X                    for (dp=cp; *dp; dp++) {
  516. X                        if (*dp == '#') {
  517. X                            *dp = 0;
  518. X                            break;
  519. X                        }
  520. X                    }
  521. X
  522. X                    ep = cp;
  523. X                    while (1) {
  524. X                        varname = strtok(ep, RC_DELIM);
  525. X                        if (!varname) break;
  526. X                        dst = ep = NULL;
  527. X                        switch (*varname) {
  528. X                            case 'u':    /* user */
  529. X                                *username = dst = auser;
  530. X                                break;
  531. X                            case 'l':    /* login */
  532. X                                *username = dst = auser;
  533. X                                break;
  534. X                            case 'p':    /* password */
  535. X                                *pass = dst = apass;
  536. X                                break;
  537. X                            case 'a':    /* account */
  538. X                                *acct = dst = aacct;
  539. X                                break;
  540. X                        /*    case 'd':  /o default */
  541. X                        /* unused -- use 'set anon_password.' */
  542. X                            case 'm':    /* macdef or machine */
  543. X                                if (strcmp(varname, "macdef"))
  544. X                                    goto done;    /* new machine record... */
  545. X                                dst = macname;
  546. X                                break;
  547. X                            default:
  548. X                                (void) fprintf(stderr, "Unknown .netrc keyword \"%s\"\n",
  549. X                                    varname
  550. X                                );
  551. X                        }
  552. X                        if (dst) {
  553. X                            dp = strtok(ep, RC_DELIM);
  554. X                            if (dp)
  555. X                                (void) strcpy(dst, dp);
  556. X                            if (dst == macname) {
  557. X                                /*
  558. X                                 *    Read in the lines of the macro.
  559. X                                 *    The macro's end is denoted by
  560. X                                 *    a blank line.
  561. X                                 */
  562. X                                (void) make_macro(macname, fp);
  563. X                                goto nextline;
  564. X                            }
  565. X                        }
  566. X                    }
  567. Xnextline: ;
  568. X                } while ((cp = FGets(str, fp)) != 0);
  569. X                break;
  570. X            }        /* end if we found the machine record. */
  571. X        }
  572. Xdone:
  573. X        parsing_rc = 0;
  574. X        (void) fclose(fp);
  575. X    }
  576. X
  577. X    if (!site_found) {
  578. X        /* didn't find it in the rc. */
  579. X        return (0);
  580. X    }
  581. X
  582. X    return (1);    /* found */
  583. X}    /* ruserpass2 */
  584. X
  585. X/* eof ftprc.c */
  586. END_OF_FILE
  587.   if test 11813 -ne `wc -c <'ftprc.c'`; then
  588.     echo shar: \"'ftprc.c'\" unpacked with wrong size!
  589.   fi
  590.   # end of 'ftprc.c'
  591. fi
  592. if test -f 'main.c' -a "${1}" != "-c" ; then 
  593.   echo shar: Will not clobber existing file \"'main.c'\"
  594. else
  595.   echo shar: Extracting \"'main.c'\" \(24709 characters\)
  596.   sed "s/^X//" >'main.c' <<'END_OF_FILE'
  597. X/* main.c */
  598. X
  599. X/*  $RCSfile: main.c,v $
  600. X *  $Revision: 14020.15 $
  601. X *  $Date: 93/07/09 11:50:12 $
  602. X */
  603. X
  604. X#define _main_c_
  605. X
  606. X#define FTP_VERSION "1.6.0 (October 31, 1993)"
  607. X
  608. X/* #define BETA 1 */ /* If defined, it prints a little warning message. */
  609. X
  610. X#include "sys.h"
  611. X
  612. X#include <sys/stat.h>
  613. X#include <arpa/ftp.h>
  614. X#include <setjmp.h>
  615. X#include <signal.h>
  616. X#include <errno.h>
  617. X#include <ctype.h>
  618. X#include <netdb.h>
  619. X#include <pwd.h>
  620. X
  621. X#ifdef SYSLOG
  622. X#    include <syslog.h>
  623. X#endif
  624. X
  625. X#if defined(CURSES) && !defined(NO_CURSES_H)
  626. X#    undef HZ        /* Collides with HaZeltine ! */
  627. X#    include <curses.h>
  628. X#    ifdef TERMH
  629. X#        include <term.h>
  630. X#    endif
  631. X#endif    /* CURSES */
  632. X
  633. X#include "util.h"
  634. X#include "cmds.h"
  635. X#include "main.h"
  636. X#include "ftp.h"
  637. X#include "ftprc.h"
  638. X#include "open.h"
  639. X#include "set.h"
  640. X#include "defaults.h"
  641. X#include "copyright.h"
  642. X
  643. X/* main.c globals */
  644. Xint                    slrflag;
  645. Xint                    fromatty;            /* input is from a terminal */
  646. Xint                    toatty;                /* output is to a terminal */
  647. Xint                    doing_script;        /* is a file being <redirected to me? */
  648. Xchar                *altarg;            /* argv[1] with no shell-like preprocessing  */
  649. Xstruct servent        serv;                /* service spec for tcp/ftp */
  650. Xjmp_buf                toplevel;            /* non-local goto stuff for cmd scanner */
  651. Xchar                *line;                /* input line buffer */
  652. Xchar                *stringbase;        /* current scan point in line buffer */
  653. Xchar                *argbuf;            /* argument storage buffer */
  654. Xchar                *argbase;            /* current storage point in arg buffer */
  655. Xint                    margc;                /* count of arguments on input line */
  656. Xchar                *margv[20];            /* args parsed from input line */
  657. Xstruct userinfo        uinfo;                /* a copy of their pwent really */
  658. Xint                    ansi_escapes;        /* for fancy graphics */
  659. Xint                             startup_msg = 1;        /* TAR: display message on startup? */
  660. Xint                    ignore_rc;            /* are we supposed to ignore the netrc */
  661. Xstring                progname;            /* simple filename */
  662. Xstring                prompt, prompt2;    /* shell prompt string */
  663. Xstring                anon_password;        /* most likely your email address */
  664. Xstring                pager;                /* program to browse text files */
  665. Xstring                version = FTP_VERSION;
  666. Xlong                eventnumber;        /* number of commands we've done */
  667. XFILE                *logf = NULL;        /* log user activity */
  668. Xlongstring            logfname;            /* name of the logfile */
  669. Xlong                logsize = 4096L;    /* max log size. 0 == no limit */
  670. Xint                    percent_flags;        /* "%" in prompt string? */
  671. Xint                    at_flags;            /* "@" in prompt string? */
  672. Xstring                 mail_path;            /* your mailbox */
  673. Xtime_t                mbox_time;            /* last modified time of mbox */
  674. Xsize_t                epromptlen;            /* length of the last line of the
  675. X                                         * prompt as it will appear on screen,
  676. X                                         * (i.e. no invis escape codes).
  677. X                                         */
  678. X
  679. X#ifdef HPUX
  680. Xchar                *tcap_normal = "\033&d@";    /* Default ANSI escapes */
  681. Xchar                *tcap_boldface = "\033&dH";     /* Half Bright */
  682. Xchar                *tcap_underline = "\033&dD";
  683. Xchar                *tcap_reverse = "\033&dB";
  684. X
  685. X#else
  686. X
  687. Xchar                            *tcap_normal = "\033[0m";       /* Default ANSI escapes */
  688. Xchar                            *tcap_boldface = "\033[1m";
  689. Xchar                            *tcap_underline = "\033[4m";
  690. Xchar                            *tcap_reverse = "\033[7m";
  691. X
  692. X#endif
  693. X
  694. Xsize_t                tcl_normal = 4,        /* lengths of the above strings. */
  695. X                    tcl_bold = 4,
  696. X                    tcl_uline = 4,
  697. X                    tcl_rev = 4;
  698. X
  699. X#ifdef CURSES
  700. Xstatic char            tcbuf[2048];
  701. X#endif
  702. X
  703. X/* main.c externs */
  704. Xextern int            debug, verbose, mprompt;
  705. Xextern int            options, cpend, data, connected, logged_in;
  706. Xextern int            curtype, macnum, remote_is_unix;
  707. Xextern FILE            *cout;
  708. Xextern struct cmd    cmdtab[];
  709. Xextern str32        curtypename;
  710. Xextern char            *macbuf;
  711. Xextern char            *reply_string;
  712. Xextern char            *short_verbose_msgs[4];
  713. Xextern string        vstr;
  714. Xextern Hostname        hostname;
  715. Xextern longstring    cwd, lcwd, recent_file;
  716. Xextern int            Optind;
  717. Xextern char            *Optarg;
  718. X#ifdef GATEWAY
  719. Xextern string        gate_login;
  720. X#endif
  721. X
  722. Xvoid main(int argc, char **argv)
  723. X{
  724. X    register char        *cp;
  725. X    int                    top, opt, openopts = 0;
  726. X    string                tmp, oline;
  727. X    struct servent        *sptr;
  728. X
  729. X    if ((cp = rindex(argv[0], '/'))) cp++;
  730. X    else cp = argv[0];
  731. X    (void) Strncpy(progname, cp);
  732. X    
  733. X    sptr = getservbyname("ftp", "tcp");
  734. X    if (sptr == 0) fatal("ftp/tcp: unknown service");
  735. X    serv = *sptr;
  736. X
  737. X    if (init_arrays())            /* Reserve large blocks of memory now */
  738. X        fatal("could not reserve large amounts of memory.");
  739. X
  740. X#ifdef GZCAT
  741. X    if ((GZCAT == (char *)1) || (GZCAT == (char *)0)) {
  742. X        (void) fprintf(stderr,
  743. X"You compiled the program with -DGZCAT, but you must specify the path with it!\n\
  744. XRe-compile, this time with -DGZCAT=\\\"/path/to/gzcat\\\".\n");
  745. X        exit(1);
  746. X    }
  747. X#endif
  748. X#ifdef ZCAT
  749. X    if ((ZCAT == (char *)1) || (ZCAT == (char *)0)) {
  750. X        (void) fprintf(stderr,
  751. X"You compiled the program with -DZCAT, but you must specify the path with it!\n\
  752. XRe-compile, this time with -DZCAT=\\\"/path/to/zcat\\\".\n");
  753. X        exit(1);
  754. X    }
  755. X#endif
  756. X
  757. X    /*
  758. X     * Set up defaults for FTP.
  759. X     */
  760. X    mprompt = dMPROMPT;
  761. X    debug = dDEBUG;
  762. X    verbose = dVERBOSE;
  763. X    (void) Strncpy(vstr, short_verbose_msgs[verbose+1]);
  764. X
  765. X    (void) Strncpy(curtypename, dTYPESTR);
  766. X    curtype = dTYPE;
  767. X    (void) Strncpy(prompt, dPROMPT);
  768. X#ifdef GATEWAY
  769. X    (void) Strncpy(gate_login, dGATEWAY_LOGIN);
  770. X#endif
  771. X
  772. X#ifdef SOCKS
  773. X    SOCKSinit("ncftp");
  774. X#endif
  775. X    
  776. X    /*    Setup our pager variable, before we run through the rc,
  777. X        which may change it. */
  778. X    set_pager(getenv("PAGER"), 0);
  779. X#ifdef CURSES
  780. X    ansi_escapes = 1;
  781. X    termcap_init();
  782. X#else
  783. X    ansi_escapes = 0;
  784. X    if ((cp = getenv("TERM")) != NULL) {
  785. X        if ((*cp == 'v' && cp[1] == 't')        /* vt100, vt102, ... */
  786. X            || (strcmp(cp, "xterm") == 0))
  787. X            ansi_escapes = 1;
  788. X    }
  789. X#endif
  790. X    (void) getuserinfo();
  791. X
  792. X    /* Init the mailbox checking code. */
  793. X    (void) time(&mbox_time);
  794. X
  795. X    (void) Strncpy(anon_password, uinfo.username);
  796. X    if (getlocalhostname(uinfo.hostname, sizeof(uinfo.hostname)) == 0) {
  797. X        (void) Strncat(anon_password, "@");
  798. X        (void) Strncat(anon_password, uinfo.hostname);
  799. X    }
  800. X#if dLOGGING
  801. X    (void) Strncpy(logfname, dLOGNAME);
  802. X    (void) LocalDotPath(logfname);
  803. X#else
  804. X    *logfname = 0;
  805. X#endif
  806. X    (void) Strncpy(recent_file, dRECENTF);
  807. X    (void) LocalDotPath(recent_file);
  808. X
  809. X    (void) get_cwd(lcwd, (int) sizeof(lcwd));
  810. X
  811. X#ifdef SYSLOG
  812. X#    ifdef LOG_LOCAL3
  813. X    openlog ("NcFTP", LOG_PID, LOG_LOCAL3);
  814. X#    else
  815. X    openlog ("NcFTP", LOG_PID);
  816. X#    endif
  817. X#endif                /* SYSLOG */
  818. X
  819. X
  820. X    ignore_rc = 0;
  821. X    (void) strcpy(oline, "open ");
  822. X    while ((opt = Getopt(argc, argv, "D:V:INRHaicmup:rd:g:")) >= 0) {
  823. X        switch(opt) {
  824. X            case 'a':
  825. X            case 'c':
  826. X            case 'i':
  827. X            case 'm':
  828. X            case 'u':
  829. X            case 'r':
  830. X                (void) sprintf(tmp, "-%c ", opt);
  831. X                goto cattmp;
  832. X
  833. X            case 'p':
  834. X            case 'd':
  835. X            case 'g':
  836. X                (void) sprintf(tmp, "-%c %s ", opt, Optarg);
  837. X            cattmp:
  838. X                (void) strcat(oline, tmp);
  839. X                openopts++;
  840. X                break;
  841. X
  842. X            case 'D':
  843. X                debug = atoi(Optarg);
  844. X                break;
  845. X            
  846. X            case 'V':
  847. X                set_verbose(Optarg, 0);
  848. X                break;
  849. X
  850. X            case 'I':
  851. X                mprompt = !mprompt;
  852. X                break;
  853. X
  854. X            case 'N':
  855. X                ++ignore_rc;
  856. X                break;
  857. X
  858. X            case 'H':
  859. X                (void) show_version(0, NULL);
  860. X                exit (0);
  861. X
  862. X            default:
  863. X            usage:
  864. X                (void) fprintf(stderr, "Usage: %s [program options] [[open options] site.to.open[:path]]\n\
  865. XProgram Options:\n\
  866. X    -D x   : Set debugging level to x (a number).\n\
  867. X    -H     : Show version and compilation information.\n\
  868. X    -I     : Toggle interactive (mprompt) mode.\n\
  869. X    -N     : Toggle reading of the .netrc/.ncftprc.\n\
  870. X    -V x   : Set verbosity to level x (-1,0,1,2).\n\
  871. XOpen Options:\n\
  872. X    -a     : Open anonymously (this is the default).\n\
  873. X    -u     : Open, specify user/password.\n\
  874. X    -i     : Ignore machine entry in your .netrc.\n\
  875. X    -p N   : Use port #N for connection.\n\
  876. X    -r     : \"Redial\" until connected.\n\
  877. X    -d N   : Redial, pausing N seconds between tries.\n\
  878. X    -g N   : Redial, giving up after N tries.\n\
  879. X    :path  : ``Colon-mode:'' If \"path\" is a file, it opens site, retrieves\n\
  880. X             file \"path,\" then exits; if \"path\" is a remote directory,\n\
  881. X             it opens site then starts you in that directory..\n\
  882. X    -c     : If you're using colon-mode with a file path, this will cat the\n\
  883. X             file to stdout instead of storing on disk.\n\
  884. X    -m     : Just like -c, only it pipes the file to your $PAGER.\n\
  885. XExamples:\n\
  886. X    ncftp ftp.unl.edu:/pub/README (just fetches README then quits)\n\
  887. X    ncftp  (just enters ncftp command shell)\n\
  888. X    ncftp -V -u ftp.unl.edu\n\
  889. X    ncftp -c ftp.unl.edu:/pub/README (cats README to stdout then quits)\n\
  890. X    ncftp -D -r -d 120 -g 10 ftp.unl.edu\n", progname);
  891. X            exit(1);
  892. X        }
  893. X    }
  894. X
  895. X    cp = argv[Optind];  /* the site to open. */
  896. X    if (cp == NULL) {
  897. X        if (openopts)
  898. X            goto usage;
  899. X    } else
  900. X        (void) strcat(oline, cp);
  901. X
  902. X    if (ignore_rc <= 0)
  903. X        (void) thrash_rc();
  904. X    if (ignore_rc <= 1)
  905. X        ReadRecentSitesFile();
  906. X
  907. X    (void) fix_options();    /* adjust "options" according to "debug"  */
  908. X    
  909. X    fromatty = doing_script = isatty(0);
  910. X    toatty = isatty(1);
  911. X    (void) UserLoggedIn();    /* Init parent-death detection. */
  912. X    cpend = 0;  /* no pending replies */
  913. X    
  914. X    if (*logfname)
  915. X        logf = fopen (logfname, "a");
  916. X
  917. X
  918. X    /* The user specified a host, maybe in 'colon-mode', on the command
  919. X     * line.  Open it now...
  920. X     */
  921. X    if (argc > 1 && cp) {
  922. X        if (setjmp(toplevel))
  923. X            exit(0);
  924. X        (void) Signal(SIGINT, intr);
  925. X        (void) Signal(SIGPIPE, lostpeer);
  926. X        (void) strcpy(line, oline);
  927. X        makeargv();
  928. X        /* setpeer uses this to tell if it was called from the cmd-line. */
  929. X        eventnumber = 0L;
  930. X        (void) cmdOpen(margc, margv);
  931. X    }
  932. X    eventnumber = 1L;
  933. X
  934. X    (void) init_prompt();
  935. X
  936. X    if (startup_msg) {  /* TAR */
  937. X        if (ansi_escapes) {
  938. X#ifdef BETA
  939. X#    define BETA_MSG "\n\
  940. XFor testing purposes only.  Do not re-distribute or subject to novice users."
  941. X#else
  942. X#    define BETA_MSG ""
  943. X#endif
  944. X
  945. X#ifndef CURSES
  946. X        (void) printf("%sNcFTP %s by Mike Gleason, NCEMRSoft.%s%s%s%s\n", 
  947. X            tcap_boldface,
  948. X            FTP_VERSION,
  949. X            tcap_normal,
  950. X            tcap_reverse,
  951. X            BETA_MSG,
  952. X            tcap_normal
  953. X        );
  954. X#else
  955. X        char vis[256];
  956. X        (void) sprintf(vis, "%sNcFTP %s by Mike Gleason, NCEMRSoft.%s%s%s%s\n", 
  957. X            tcap_boldface,
  958. X            FTP_VERSION,
  959. X            tcap_normal,
  960. X            tcap_reverse,
  961. X            BETA_MSG,
  962. X            tcap_normal
  963. X        );
  964. X        tcap_put(vis);
  965. X#endif /* !CURSES */
  966. X        }
  967. X        else
  968. X        (void) printf("%s%s\n", FTP_VERSION, BETA_MSG);
  969. X    }  /* TAR */
  970. X    if (NOT_VQUIET)
  971. X        PrintTip();
  972. X    top = setjmp(toplevel) == 0;
  973. X    if (top) {
  974. X        (void) Signal(SIGINT, intr);
  975. X        (void) Signal(SIGPIPE, lostpeer);
  976. X    }
  977. X    for (;;) {
  978. X        (void) cmdscanner(top);
  979. X        top = 1;
  980. X    }
  981. X}    /* main */
  982. X
  983. X
  984. X
  985. X/*ARGSUSED*/
  986. Xvoid intr SIG_PARAMS
  987. X{
  988. X    dbprintf("intr()\n");
  989. X    (void) Signal(SIGINT, intr);
  990. X    (void) longjmp(toplevel, 1);
  991. X}    /* intr */
  992. X
  993. X
  994. X
  995. Xint getuserinfo(void)
  996. X{
  997. X    register char            *cp;
  998. X    struct passwd            *pw;
  999. X    string                    str;
  1000. X    extern char                *home;    /* for glob.c */
  1001. X    
  1002. X    home = uinfo.homedir;    /* for glob.c */
  1003. X    pw = getpwuid(uinfo.uid = getuid());
  1004. X    if (pw != NULL) {
  1005. X        (void) Strncpy(uinfo.username, pw->pw_name);
  1006. X        (void) Strncpy(uinfo.shell, pw->pw_shell);
  1007. X        (void) Strncpy(uinfo.homedir, pw->pw_dir);
  1008. X        cp = getenv("MAIL");
  1009. X        if (cp == NULL)
  1010. X            cp = getenv("mail");
  1011. X        if (cp == NULL)
  1012. X            (void) sprintf(str, "/usr/spool/mail/%s", uinfo.username);
  1013. X        else
  1014. X            (void) Strncpy(str, cp);
  1015. X        cp = str;
  1016. X
  1017. X        /*
  1018. X         * mbox variable may be like MAIL=(28 /usr/mail/me /usr/mail/you),
  1019. X         * so try to find the first mail path.
  1020. X         */
  1021. X        while ((*cp != '/') && (*cp != 0))
  1022. X            cp++;
  1023. X        (void) Strncpy(mail_path, cp);
  1024. X        if ((cp = index(mail_path, ' ')) != NULL)
  1025. X            *cp = '\0';
  1026. X        return (0);
  1027. X    } else {
  1028. X        PERROR("getuserinfo", "Could not get your passwd entry!");
  1029. X        (void) Strncpy(uinfo.shell, "/bin/sh");
  1030. X        (void) Strncpy(uinfo.homedir, ".");    /* current directory */
  1031. X        if ((cp = getenv("HOME")) != NULL)
  1032. X            (void) Strncpy(uinfo.homedir, cp);
  1033. X        mail_path[0] = 0;
  1034. X        return (-1);
  1035. X    }
  1036. X}    /* getuserinfo */
  1037. X
  1038. X
  1039. X
  1040. X
  1041. Xint init_arrays(void)
  1042. X{
  1043. X    if ((macbuf = (char *) malloc((size_t)(MACBUFLEN))) == NULL)
  1044. X        goto barf;
  1045. X    if ((line = (char *) malloc((size_t)(CMDLINELEN))) == NULL)
  1046. X        goto barf;
  1047. X    if ((argbuf = (char *) malloc((size_t)(CMDLINELEN))) == NULL)
  1048. X        goto barf;
  1049. X    if ((reply_string = (char *) malloc((size_t)(RECEIVEDLINELEN))) == NULL)
  1050. X        goto barf;
  1051. X    
  1052. X    *macbuf = '\0';
  1053. X    init_transfer_buffer();
  1054. X    return (0);
  1055. Xbarf:
  1056. X    return (-1);
  1057. X}    /* init_arrays */
  1058. X
  1059. X
  1060. X
  1061. X#ifndef BUFSIZ
  1062. X#define BUFSIZ 512
  1063. X#endif
  1064. X
  1065. Xvoid init_transfer_buffer(void)
  1066. X{
  1067. X    extern char *xferbuf;
  1068. X    extern size_t xferbufsize;
  1069. X    
  1070. X    /* Make sure we use a multiple of BUFSIZ for efficiency. */
  1071. X    xferbufsize = (MAX_XFER_BUFSIZE / BUFSIZ) * BUFSIZ;
  1072. X    while (1) {
  1073. X        xferbuf = (char *) malloc (xferbufsize);
  1074. X        if (xferbuf != NULL || xferbufsize < 1024)
  1075. X            break;
  1076. X        xferbufsize >>= 2;
  1077. X    }
  1078. X    
  1079. X    if (xferbuf != NULL) return;
  1080. X    fatal("out of memory for transfer buffer.");
  1081. X}    /* init_transfer_buffer */
  1082. X
  1083. X
  1084. X
  1085. X
  1086. Xvoid init_prompt(void)
  1087. X{
  1088. X    register char *cp;
  1089. X    
  1090. X    percent_flags = at_flags = 0;
  1091. X    for (cp = prompt; *cp; cp++) {
  1092. X        if (*cp == '%') percent_flags = 1;
  1093. X        else if (*cp == '@') at_flags = 1;
  1094. X    }
  1095. X}    /* init_prompt */
  1096. X
  1097. X
  1098. X
  1099. X/*ARGSUSED*/
  1100. Xvoid lostpeer SIG_PARAMS
  1101. X{
  1102. X    if (connected) {
  1103. X        close_streams(1);
  1104. X        if (data >= 0) {
  1105. X            (void) shutdown(data, 1+1);
  1106. X            (void) close(data);
  1107. X            data = -1;
  1108. X        }
  1109. X        connected = 0;
  1110. X    }
  1111. X    if (connected) {
  1112. X        close_streams(1);
  1113. X        connected = 0;
  1114. X    }
  1115. X    hostname[0] = cwd[0] = 0;
  1116. X    logged_in = macnum = 0;
  1117. X}    /* lostpeer */
  1118. X
  1119. X
  1120. X/*
  1121. X * Command parser.
  1122. X */
  1123. Xvoid cmdscanner(int top)
  1124. X{
  1125. X    register struct cmd *c;
  1126. X
  1127. X    if (!top)
  1128. X        (void) putchar('\n');
  1129. X    for (;;) {
  1130. X        if (!doing_script && !UserLoggedIn())
  1131. X            (void) quit(0, NULL);
  1132. X        if (Gets(strprompt(), line, (size_t)CMDLINELEN) == NULL) {
  1133. X            (void) quit(0, NULL);    /* control-d */
  1134. X        }
  1135. X        eventnumber++;
  1136. X        dbprintf("\"%s\"\n", line);
  1137. X        (void) makeargv();
  1138. X        if (margc == 0) {
  1139. X            continue;    /* blank line... */
  1140. X        }
  1141. X        c = getcmd(margv[0]);
  1142. X        if (c == (struct cmd *) -1) {
  1143. X            (void) printf("?Ambiguous command\n");
  1144. X            continue;
  1145. X        }
  1146. X        if (c == 0) {
  1147. X            if (!implicit_cd(margv[0]))
  1148. X                (void) printf("?Invalid command\n");
  1149. X            continue;
  1150. X        }
  1151. X        if (c->c_conn && !connected) {
  1152. X            (void) printf ("Not connected.\n");
  1153. X            continue;
  1154. X        }
  1155. X        if ((*c->c_handler)(margc, margv) == USAGE)
  1156. X            cmd_usage(c);
  1157. X        if (c->c_handler != help)
  1158. X            break;
  1159. X    }
  1160. X    (void) Signal(SIGINT, intr);
  1161. X    (void) Signal(SIGPIPE, lostpeer);
  1162. X}    /* cmdscanner */
  1163. X
  1164. X
  1165. X
  1166. X
  1167. Xchar *strprompt(void)
  1168. X{
  1169. X    time_t                    tyme;
  1170. X    char                    eventstr[8];
  1171. X    char                    *dname, *lastlinestart;
  1172. X    register char            *p, *q;
  1173. X    string                    str;
  1174. X    int                        flag;
  1175. X
  1176. X    if (at_flags == 0 && percent_flags == 0) {
  1177. X        epromptlen = strlen(prompt);
  1178. X        return (prompt);    /* But don't overwrite it! */
  1179. X    }
  1180. X    epromptlen = 0;
  1181. X    lastlinestart = prompt2;
  1182. X    if (at_flags) {
  1183. X        for (p = prompt, q = prompt2, *q = 0; (*p); p++) {
  1184. X            if (*p == '@') switch (flag = *++p) {
  1185. X                case '\0':
  1186. X                    --p;
  1187. X                    break;
  1188. X                case 'M':
  1189. X                    if (CheckNewMail() > 0)
  1190. X                        q = Strpcpy(q, "(Mail) ");
  1191. X                    break;
  1192. X                case 'N':
  1193. X                    q = Strpcpy(q, "\n");
  1194. X                    lastlinestart = q;
  1195. X                    epromptlen = 0;
  1196. X                    break;
  1197. X                case 'P':    /* reset to no bold, no uline, no inverse, etc. */
  1198. X                    if (ansi_escapes) {
  1199. X                        q = Strpcpy(q, tcap_normal);
  1200. X                        epromptlen += tcl_normal;
  1201. X                    }
  1202. X                    break;
  1203. X                case 'B':    /* toggle boldface */
  1204. X                    if (ansi_escapes) {
  1205. X                        q = Strpcpy(q, tcap_boldface);
  1206. X                        epromptlen += tcl_bold;
  1207. X                    }
  1208. X                    break;
  1209. X                case 'U':    /* toggle underline */
  1210. X                    if (ansi_escapes) {
  1211. X                        q = Strpcpy(q, tcap_underline);
  1212. X                        epromptlen += tcl_uline;
  1213. X                    }
  1214. X                    break;
  1215. X                case 'R':
  1216. X                case 'I':    /* toggle inverse (reverse) video */
  1217. X                    if (ansi_escapes) {
  1218. X                        q = Strpcpy(q, tcap_reverse);
  1219. X                        epromptlen += tcl_rev;
  1220. X                    }
  1221. X                    break;
  1222. X                case 'D':    /* insert current directory */
  1223. X                case 'J':
  1224. X                    if ((flag == 'J') && (remote_is_unix)) {
  1225. X                        /* Not the whole path, just the dir name. */
  1226. X                        dname = rindex(cwd, '/');
  1227. X                        if (dname == NULL)
  1228. X                            dname = cwd;
  1229. X                        else if ((dname != cwd) && (dname[1]))
  1230. X                            ++dname;
  1231. X                    } else
  1232. X                        dname = cwd;
  1233. X                    if (dname[0]) {
  1234. X                        q = Strpcpy(q, dname);
  1235. X                        q = Strpcpy(q, " ");
  1236. X                    }
  1237. X                    break;
  1238. X                case 'H':    /* insert name of connected host */
  1239. X                    if (logged_in) {
  1240. X                        (void) sprintf(str, "%s ", hostname);
  1241. X                        q = Strpcpy(q, str);
  1242. X                    }
  1243. X                    break;
  1244. X                case 'C':  /* Insert host:path (colon-mode format. */
  1245. X                    if (logged_in) {
  1246. X                        (void) sprintf(str, "%s:%s ", hostname, cwd);
  1247. X                        q = Strpcpy(q, str);
  1248. X                    } else
  1249. X                        q = Strpcpy(q, "(not connected)");
  1250. X                    break;
  1251. X                case 'c':
  1252. X                    if (logged_in) {
  1253. X                        (void) sprintf(str, "%s:%s\n", hostname, cwd);
  1254. X                        q = Strpcpy(q, str);
  1255. X                        lastlinestart = q;    /* there is a \n at the end. */
  1256. X                        epromptlen = 0;
  1257. X                    }
  1258. X                    break;
  1259. X                case '!':
  1260. X                case 'E':    /* insert event number */
  1261. X                    (void) sprintf(eventstr, "%ld", eventnumber);
  1262. X                    q = Strpcpy(q, eventstr);
  1263. X                    break;
  1264. X                default:
  1265. X                    *q++ = *p;    /* just copy it; unknown switch */
  1266. X            } else
  1267. X                *q++ = *p;
  1268. X        }
  1269. X        *q = '\0';
  1270. X    } else 
  1271. X        (void) strcpy(prompt2, prompt);
  1272. X    
  1273. X#ifndef NO_STRFTIME
  1274. X    if (percent_flags) {
  1275. X        /*    only strftime if the user requested it (with a %something),
  1276. X            otherwise don't waste time doing nothing. */
  1277. X        (void) time(&tyme);
  1278. X        (void) Strncpy(str, prompt2);
  1279. X        (void) strftime(prompt2, sizeof(str), str, localtime(&tyme));
  1280. X    }
  1281. X#endif
  1282. X    epromptlen = (size_t) ((long) strlen(lastlinestart) - (long) epromptlen);
  1283. X    return (prompt2);
  1284. X}    /* strprompt */
  1285. X
  1286. X
  1287. X/*
  1288. X * Slice a string up into argc/argv.
  1289. X */
  1290. X
  1291. Xvoid makeargv(void)
  1292. X{
  1293. X    char **argp;
  1294. X
  1295. X    margc = 0;
  1296. X    argp = margv;
  1297. X    stringbase = line;        /* scan from first of buffer */
  1298. X    argbase = argbuf;        /* store from first of buffer */
  1299. X    slrflag = 0;
  1300. X    while ((*argp++ = slurpstring()) != 0)
  1301. X        margc++;
  1302. X}    /* makeargv */
  1303. X
  1304. X
  1305. X
  1306. X
  1307. X/*
  1308. X * Parse string into argbuf;
  1309. X * implemented with FSM to
  1310. X * handle quoting and strings
  1311. X */
  1312. Xchar *slurpstring(void)
  1313. X{
  1314. X    int got_one = 0;
  1315. X    register char *sb = stringbase;
  1316. X    register char *ap = argbase;
  1317. X    char *tmp = argbase;        /* will return this if token found */
  1318. X
  1319. X    if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  1320. X        switch (slrflag) {    /* and $ as token for macro invoke */
  1321. X            case 0:
  1322. X                slrflag++;
  1323. X                stringbase++;
  1324. X                return ((*sb == '!') ? "!" : "$");
  1325. X                /* NOTREACHED */
  1326. X            case 1:
  1327. X                slrflag++;
  1328. X                altarg = stringbase;
  1329. X                break;
  1330. X            default:
  1331. X                break;
  1332. X        }
  1333. X    }
  1334. X
  1335. XS0:
  1336. X    switch (*sb) {
  1337. X
  1338. X    case '\0':
  1339. X        goto OUT;
  1340. X
  1341. X    case ' ':
  1342. X    case '\t':
  1343. X    case '\n':
  1344. X    case '=':
  1345. X        sb++; goto S0;
  1346. X
  1347. X    default:
  1348. X        switch (slrflag) {
  1349. X            case 0:
  1350. X                slrflag++;
  1351. X                break;
  1352. X            case 1:
  1353. X                slrflag++;
  1354. X                altarg = sb;
  1355. X                break;
  1356. X            default:
  1357. X                break;
  1358. X        }
  1359. X        goto S1;
  1360. X    }
  1361. X
  1362. XS1:
  1363. X    switch (*sb) {
  1364. X
  1365. X    case ' ':
  1366. X    case '\t':
  1367. X    case '\n':
  1368. X    case '=':
  1369. X    case '\0':
  1370. X        goto OUT;    /* end of token */
  1371. X
  1372. X    case '\\':
  1373. X        sb++; goto S2;    /* slurp next character */
  1374. X
  1375. X    case '"':
  1376. X        sb++; goto S3;    /* slurp quoted string */
  1377. X
  1378. X    default:
  1379. X        *ap++ = *sb++;    /* add character to token */
  1380. X        got_one = 1;
  1381. X        goto S1;
  1382. X    }
  1383. X
  1384. XS2:
  1385. X    switch (*sb) {
  1386. X
  1387. X    case '\0':
  1388. X        goto OUT;
  1389. X
  1390. X    default:
  1391. X        *ap++ = *sb++;
  1392. X        got_one = 1;
  1393. X        goto S1;
  1394. X    }
  1395. X
  1396. XS3:
  1397. X    switch (*sb) {
  1398. X
  1399. X    case '\0':
  1400. X        goto OUT;
  1401. X
  1402. X    case '"':
  1403. X        sb++; goto S1;
  1404. X
  1405. X    default:
  1406. X        *ap++ = *sb++;
  1407. X        got_one = 1;
  1408. X        goto S3;
  1409. X    }
  1410. X
  1411. XOUT:
  1412. X    if (got_one)
  1413. X        *ap++ = '\0';
  1414. X    argbase = ap;            /* update storage pointer */
  1415. X    stringbase = sb;        /* update scan pointer */
  1416. X    if (got_one) {
  1417. X        return(tmp);
  1418. X    }
  1419. X    switch (slrflag) {
  1420. X        case 0:
  1421. X            slrflag++;
  1422. X            break;
  1423. X        case 1:
  1424. X            slrflag++;
  1425. X            altarg = (char *) 0;
  1426. X            break;
  1427. X        default:
  1428. X            break;
  1429. X    }
  1430. X    return((char *)0);
  1431. X}    /* slurpstring */
  1432. X
  1433. X/*
  1434. X * Help command.
  1435. X * Call each command handler with argc == 0 and argv[0] == name.
  1436. X */
  1437. Xint
  1438. Xhelp(int argc, char **argv)
  1439. X{
  1440. X    register struct cmd        *c;
  1441. X    int                        showall = 0, helpall = 0;
  1442. X    char                    *arg;
  1443. X    int                        i, j, k;
  1444. X    int                     nRows, nCols;
  1445. X    int                     nCmds2Print;
  1446. X    int                     screenColumns;
  1447. X    int                     len, widestName;
  1448. X    char                     *cp, **cmdnames, spec[16];
  1449. X
  1450. X    if (argc == 2) {
  1451. X        showall = (strcmp(argv[1], "showall") == 0);
  1452. X        helpall = (strcmp(argv[1], "helpall") == 0);
  1453. X    }
  1454. X    if (argc == 1 || showall)  {
  1455. X        (void) printf("\
  1456. XCommands may be abbreviated.  'help showall' shows aliases, invisible and\n\
  1457. Xunsupported commands.  'help <command>' gives a brief description of <command>.\n\n");
  1458. X
  1459. X        for (c = cmdtab, nCmds2Print=0; c->c_name != NULL; c++) 
  1460. X            if (!c->c_hidden || showall)
  1461. X                nCmds2Print++;
  1462. X
  1463. X        if ((cmdnames = (char **) malloc(sizeof(char *) * nCmds2Print)) == NULL)
  1464. X            fatal("out of memory!");
  1465. X
  1466. X        for (c = cmdtab, i=0, widestName=0; c->c_name != NULL; c++) {
  1467. X            if (!c->c_hidden || showall) {
  1468. X                cmdnames[i++] = c->c_name;
  1469. X                len = (int) strlen(c->c_name);
  1470. X                if (len > widestName)
  1471. X                    widestName = len;
  1472. X            }
  1473. X        }
  1474. X
  1475. X        if ((cp = getenv("COLUMNS")) == NULL)
  1476. X            screenColumns = 80;
  1477. X        else
  1478. X            screenColumns = atoi(cp);
  1479. X
  1480. X        widestName += 2;    /* leave room for white-space in between cols. */
  1481. X        nCols = screenColumns / widestName;
  1482. X        /* if ((screenColumns % widestName) > 0) nCols++; */
  1483. X        nRows = nCmds2Print / nCols;
  1484. X        if ((nCmds2Print % nCols) > 0)
  1485. X            nRows++;
  1486. X
  1487. X        (void) sprintf(spec, "%%-%ds", widestName);
  1488. X        for (i=0; i<nRows; i++) {
  1489. X            for (j=0; j<nCols; j++) {
  1490. X                k = nRows*j + i;
  1491. X                if (k < nCmds2Print)
  1492. X                    (void) printf(spec, cmdnames[k]);
  1493. X            }
  1494. X            (void) printf("\n");
  1495. X        }
  1496. X        Free(cmdnames);
  1497. X    } else if (helpall) {
  1498. X        /* Really intended to debug the help strings. */
  1499. X        for (c = cmdtab; c->c_name != NULL; c++) {
  1500. X            cmd_help(c);
  1501. X            cmd_usage(c);
  1502. X        }
  1503. X    } else while (--argc > 0) {
  1504. X        arg = *++argv;
  1505. X        c = getcmd(arg);
  1506. X        if (c == (struct cmd *)-1)
  1507. X            (void) printf("?Ambiguous help command %s\n", arg);
  1508. X        else if (c == (struct cmd *)0)
  1509. X            (void) printf("?Invalid help command %s\n", arg);
  1510. X        else {
  1511. X            cmd_help(c);
  1512. X            cmd_usage(c);
  1513. X        }
  1514. X    }
  1515. X    return NOERR;
  1516. X}    /* help */
  1517. X
  1518. X
  1519. X/*
  1520. X * If the user wants to, s/he can specify the maximum size of the log
  1521. X * file, so it doesn't waste too much disk space.  If the log is too
  1522. X * fat, trim the older lines (at the top) until we're under the limit.
  1523. X */
  1524. Xvoid trim_log(void)
  1525. X{
  1526. X    FILE                *new, *old;
  1527. X    struct stat            st;
  1528. X    long                fat;
  1529. X    string                tmplogname, str;
  1530. X
  1531. X    if (logsize <= 0 || *logfname == 0 || stat(logfname, &st) ||
  1532. X        (old = fopen(logfname, "r")) == NULL)
  1533. X        return;    /* never trim, or no log */
  1534. X    fat = st.st_size - logsize;
  1535. X    if (fat <= 0L) return;    /* log too small yet */
  1536. X    while (fat > 0L) {
  1537. X        if (FGets(str, old) == NULL) return;
  1538. X        fat -= (long) strlen(str);
  1539. X    }
  1540. X    /* skip lines until a new site was opened */
  1541. X    while (1) {
  1542. X        if (FGets(str, old) == NULL) {
  1543. X            (void) fclose(old);
  1544. X            (void) unlink(logfname);
  1545. X            return;    /* nothing left, start anew */
  1546. X        }
  1547. X        if (*str != '\t') break;
  1548. X    }
  1549. X    
  1550. X    /* copy the remaining lines in "old" to "new" */
  1551. X    (void) Strncpy(tmplogname, logfname);
  1552. X    tmplogname[strlen(tmplogname) - 1] = 'T';
  1553. X    if ((new = fopen(tmplogname, "w")) == NULL) {
  1554. X        (void) PERROR("trim_log", tmplogname);
  1555. X        return;
  1556. X    }
  1557. X    (void) fputs(str, new);
  1558. X    while (FGets(str, old))
  1559. X        (void) fputs(str, new);
  1560. X    (void) fclose(old); (void) fclose(new);
  1561. X    if (unlink(logfname) < 0)
  1562. X        PERROR("trim_log", logfname);
  1563. X    if (rename(tmplogname, logfname) < 0)
  1564. X        PERROR("trim_log", tmplogname);
  1565. X}    /* trim_log */
  1566. X
  1567. X
  1568. X
  1569. X
  1570. Xint CheckNewMail(void)
  1571. X{
  1572. X    struct stat stbuf;
  1573. X
  1574. X    if (*mail_path == '\0') return 0;
  1575. X    if (stat(mail_path, &stbuf) < 0) {    /* cant find mail_path so we'll */
  1576. X        *mail_path = '\0';                /* never check it again */
  1577. X        return 0;
  1578. X    }
  1579. X
  1580. X    /*
  1581. X     * Check if the size is non-zero and the access time is less than
  1582. X     * the modify time -- this indicates unread mail.
  1583. X     */
  1584. X    if ((stbuf.st_size != 0) && (stbuf.st_atime <= stbuf.st_mtime)) {
  1585. X        if (stbuf.st_mtime > mbox_time) {
  1586. X            (void) printf("%s\n", NEWMAILMESSAGE);
  1587. X            mbox_time = stbuf.st_mtime;
  1588. X        }
  1589. X        return 1;
  1590. X    }
  1591. X
  1592. X    return 0;
  1593. X}    /* CheckNewMail */
  1594. X
  1595. X
  1596. X
  1597. X#ifdef CURSES
  1598. Xint termcap_get(char **dest, char *attr)
  1599. X{
  1600. X    static char area[1024];
  1601. X    static char *s = area;
  1602. X    char *buf, *cp;
  1603. X    int i, result = -1;
  1604. X    int len = 0;
  1605. X
  1606. X    *dest = NULL;
  1607. X    while (*attr != '\0') {
  1608. X        buf = tgetstr(attr, &s);
  1609. X        if (buf != NULL && buf[0] != '\0') {
  1610. X            for (i = 0; (buf[i] <= '9') && (buf[i] >= '0'); )
  1611. X                i++;
  1612. X            /* Get rid of the terminal delays, like "$<2>". */
  1613. X            if ((cp = strstr(&(buf[i]), "$<")) != NULL)
  1614. X                *cp = 0;
  1615. X            if (*dest == NULL)
  1616. X                *dest = (char *)malloc(strlen(&(buf[i])) + 1);
  1617. X            else
  1618. X                *dest = (char *)realloc(*dest, len + strlen(&(buf[i])) + 1);
  1619. X            if (*dest == NULL)
  1620. X                break;
  1621. X            (void) strcpy(*dest + len, &(buf[i]));
  1622. X            len += strlen (&(buf[i]));
  1623. X        }
  1624. X        attr += 2;
  1625. X    }
  1626. X    if (*dest == NULL)
  1627. X        *dest = "";
  1628. X    else
  1629. X        result = 0;
  1630. X    return (result);
  1631. X}    /* termcap_get */
  1632. X
  1633. X
  1634. X  
  1635. Xvoid termcap_init(void)
  1636. X{
  1637. X    char *term;
  1638. X
  1639. X    if ((term = getenv("TERM")) == NULL) {
  1640. X        term = "dumb";  /* TAR */
  1641. X        ansi_escapes = 0;
  1642. X    }
  1643. X    if (tgetent(tcbuf,term) != 1) {
  1644. X        (void) fprintf(stderr,"Can't get termcap entry for terminal [%s]\n", term);
  1645. X    } else {
  1646. X        (void) termcap_get(&tcap_normal, "meuese");
  1647. X        if (termcap_get(&tcap_boldface, "md") < 0) {
  1648. X            /* Dim-mode is better than nothing... */
  1649. X            (void) termcap_get(&tcap_normal, "mh");
  1650. X        }
  1651. X        (void) termcap_get(&tcap_underline, "us");
  1652. X        (void) termcap_get(&tcap_reverse, "so");
  1653. X        tcl_normal = strlen(tcap_normal);
  1654. X        tcl_bold = strlen(tcap_boldface);
  1655. X        tcl_uline = strlen(tcap_underline);
  1656. X        tcl_rev = strlen(tcap_reverse);
  1657. X    }
  1658. X
  1659. X}    /* termcap_init */
  1660. X
  1661. X
  1662. X
  1663. Xstatic int c_output(int c)
  1664. X{
  1665. X    return (putchar(c));
  1666. X}    /* c_output */
  1667. X
  1668. X
  1669. X
  1670. X
  1671. Xvoid tcap_put(char *cap)
  1672. X{
  1673. X    tputs(cap, 0, c_output);
  1674. X}    /* tcap_put */
  1675. X
  1676. X#endif /* CURSES */
  1677. X
  1678. X/* eof main.c */
  1679. X
  1680. END_OF_FILE
  1681.   if test 24709 -ne `wc -c <'main.c'`; then
  1682.     echo shar: \"'main.c'\" unpacked with wrong size!
  1683.   fi
  1684.   # end of 'main.c'
  1685. fi
  1686. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  1687.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  1688. else
  1689.   echo shar: Extracting \"'patchlevel.h'\" \(11724 characters\)
  1690.   sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  1691. X/* patchlevel.h */
  1692. X
  1693. X/*
  1694. X * v1.0.0 - December 6, 1992.
  1695. X *    Initial release.
  1696. X *
  1697. X * v1.0.1 - December 8, 1992.
  1698. X *  Added default value for NCARGS in glob.c for systems that don't define it.
  1699. X *  Fixed pdir bug which was caused by me mistakenly adding the page-a-
  1700. X *  compressed-file feature to ls instead of page.  Fixed bug in documentation,
  1701. X *  which had the same error!  Added spec for Ultrix in sys.h.  Fixed error
  1702. X *  in sys.h that recommended -Dconst instead of -Dconst="".  Added GETPASS
  1703. X *  compile flag to use getpass() instead of getpass2(), which make compiling
  1704. X *  easier if the compiler choked in cmds.c.  Added GETCWDSIZET for systems
  1705. X *  whose getcwd() takes a size_t instead of an int.
  1706. X *
  1707. X * v1.0.2 - Jan 17, 1993.
  1708. X *  Using the cpp symbol CONST instead of const to tell
  1709. X *  the compiler not to use the 'const' directive.  Checking for __sgi as
  1710. X *  well as sgi in sys.h.  Added #ifndef __GNUC__ block to make SunOS users
  1711. X *  use gcc.  You can avoid trying to include <unistd.h> by defining
  1712. X *  NO_UNISTDH.  Added DG/UX entry in sys.h.  Also added still another cpp
  1713. X *  symbol, BAD_INETADDR, which is used if inet_addr returns a structure
  1714. X *  instead of a u_long (this is only for DG/UX so far).  Changed long to
  1715. X *  int in wait().  Added default value for NCARGS in glob.c.  Added cpp
  1716. X *  symbol NO_STDLIBH for systems without <stdlib.h>.  Fixed 'quote.'
  1717. X *  Fixed 'size.'  Set all's string variable are printed in double quotes.
  1718. X *  Ansi-escapes is init'd to 1 if TERM==xterm.  Fixed 'type tenex.'  Set
  1719. X *  verbose makes sure verbose is within bounds and prints messages now.
  1720. X *  Better getpass2.  Tries .ncftprc before .netrc.  @N adds a \n to prompt.
  1721. X *  ls() is more flexible.  Macdef and $ print current macros if no arg
  1722. X *  is given.  getpass2 is now Getpass, and accompanying this are
  1723. X *  more cpp symbols SGTTYB and TERMIOS.  Better SCO support.  No longer using
  1724. X *  gets(), instead using own Gets() which is safer.  Better termcap support,
  1725. X *  or actually curses support, to get ansi-escape sequences.  Using -FC
  1726. X *  instead of -CF for ls flags, do avoid a rare conflict.  Progress meters
  1727. X *  work better.  Phil Dietz added a cool bar graph one, and I added another
  1728. X *  similar to the default percentage meter that shows the # KB transferred,
  1729. X *  which will work on systems not supporting SIZE.  Fixed floating point
  1730. X *  exception bug in put/mput.  Fixed implicit_cd to work with wuarchive-ish
  1731. X *  cd messages.  Added NeXT and DYNIX blocks in sys.h.  
  1732. X *  Fixed bug in _cd, that was trying to use wildcards when it
  1733. X *  shouldn't.  Fixed bug in macdef.  Fixed small bug in getreply.  Turned
  1734. X *  off echoing during the progress-meter.  Added syslogging capability.
  1735. X *
  1736. X * v1.5.0 - August 22, 1993
  1737. X *  Fixed error in CONST block in ftpdefs.h.  Fixed error in sys.h so that when
  1738. X *  you compile with -DGETPASS it uses getpass.  'ls' bug with wildcards
  1739. X *  fixed.  'ls' enhanced to take multiple remote paths.  Added new cpp symbol
  1740. X *  STRICT_PROTOS so I don't have to worry about the correct declarations of
  1741. X *  int returning functions.  Moved termcap_init() up.  Changed value of
  1742. X *  tcap_plain to "me" from "se."  Defining TERMIOS by default for SunOS.
  1743. X *  Edited perror to not print ioctl errors (for SunOS only).  Making sure
  1744. X *  we use ioctl only on tty files.  Using <arpa/ftp.h> for SCO to get
  1745. X *  MAXPATHLEN instead of <sys/arpa.h>.  386BSD and Pyramid OSx entries added
  1746. X *  to sys.h.  Fixed subtle error in FGets macro.  Using private _Strn
  1747. X *  string routines, with macros to them instead of the strn routines.
  1748. X *  Added support for GNU Readline (not included).  Added BROKEN_MEMCPY
  1749. X *  CPP symbol for other systems with same bug as that of SCO (see ftp.c).
  1750. X *  Changed mail detection code a bit, hopefully ending the false alarms
  1751. X *  that some systems were having.  New CPP symbol, dFTP_PORT, lets you define
  1752. X *  the default ftp port if your OS (i.e. ISC unix) is wrong.  Fixed bugs
  1753. X *  in 'rstatus' and 'syst;'  apparently no one noticed...  Phased out
  1754. X *  mls and mdir since ls does it all now.  Added dPROGRESS to defaults.h to
  1755. X *  set the default progress indicator.  Colon-mode wasn't quiet; fixed.
  1756. X *  Some new prompt @flags added.  @flags that may result in an empty string
  1757. X *  are set so that when they do print something, they tack on a trailing
  1758. X *  space.  May have fixed bug that caused 'page' to drop connection when
  1759. X *  you quit your pager.  NcFTP tries to prevent itself from becoming a
  1760. X *  mindless zombie process.  Fixed bug in 'rename.'  Added another progress
  1761. X *  indicator that doesn't use any backspaces.  Firewall support added by
  1762. X *  Dave Wolfe (dwolfe@pffft.sps.mot.com).  Saving the entire servent struct,
  1763. X *  not just a ptr to it.  Support the DOTDIR env variable.  Fetched files'
  1764. X *  modification times now set to that on the server.  Added RO-Var "netrc."
  1765. X *  Munged Makefile to support 'install' and 'uninstall,' and passing the
  1766. X *  installation parameters as a -D flag.  Awesome new recent site log!
  1767. X *  Can type 'open' by itself to print out the sites in our netrc/recent
  1768. X *  buffers.  Added show command.  Drastic changes in source code; cmds.c
  1769. X *  made smaller by spawning set.c and util.c; ftpdefs.h eliminated.  Improved
  1770. X *  on-line help.  Revamped the command table, by eliminating obselete fields
  1771. X *  and adding a usage field to print a cmd's usage message.  Removed all the
  1772. X *  useless settings of the 'code' variable.  Added tips.c.  Better support
  1773. X *  for ~s and environment vars in pathnames.  Ascii transfers can get whole
  1774. X *  lines at a time instead of just chars at a time, so ascii transfers may
  1775. X *  be a bit faster.  Old FTP commands are acknowledged at least.  Some
  1776. X *  additions for Apollo in sys.h.  Code in ftp.c cleaned up a bit, most
  1777. X *  notably the obnoxiously long recvrequest() function has been broken up
  1778. X *  into quite a few subroutines; it's still too long for my taste, though.
  1779. X *  Incorporated some stuff by Tom Dickey.  Enhanced Perror() function to
  1780. X *  print more stuff if DB_ERRS is defined.  Added 'ftpcat' mode.  You can
  1781. X *  now turnoff the startup msg.  GNU gzip support added.  Added dbprintf()
  1782. X *  function to print the debug messages.  Changed mind and decided to
  1783. X *  read the whole stream anyway on aborts for better stability;  you can
  1784. X *  still try the aborting the stream if you define TryAbort.  Added 'site'
  1785. X *  command.  Fixed bug where verbose was left set to V_QUIET when you used
  1786. X *  colon-mode.  Printing a warning when you try something like 'ls -t *.Z,'
  1787. X *  because wildcards don't work right with ls flags. Verbose and debug can
  1788. X *  be set directly from the cmd line (i.e. -D 3, not -DDD).  Verbosity can
  1789. X *  be set using their ascii names, in addition to it's number, like 'set
  1790. X *  verbose = quiet.'  Removed setpeer from cmds.c, and created new files,
  1791. X *  open.{c,h} dedicated to it; broke up setpeer into smaller sub-procs,
  1792. X *  and commented whole file (yay!).  Added a new user var, anon-open,
  1793. X *  for those folks who don't want anon logins as the default.
  1794. X *
  1795. X * v1.5.1 - August 29, 1993
  1796. X *  Bugs fixed in termcap code, mput, and pwd.  No longer adding blank
  1797. X *  lines to readline's history.  Netrc site abbreviations were matched
  1798. X *  by strncmp() when it should have been strstr().  Bug fixed in
  1799. X *  open's site "menu."  Revised tips a little to encourage .ncftprc instead
  1800. X *  of .netrc.  TRY_ABOR documented in the README.  Added stuff to the
  1801. X *  DYNIX entry.  Hacks added for SCO322.  Shortened bargraph prog meter
  1802. X *  by one char.  Better compat with getline.  Man page fixed by DWS again :)
  1803. X *
  1804. X * v1.5.2 - August 30, 1993.
  1805. X *  Back to using "me" instead of "se" to for termcap_normal.  Fixed Netrc
  1806. X *  site abbrev problem in a different way (by getting the fullsite name
  1807. X *  before calling ruserpass2).
  1808. X *
  1809. X * v1.5.3 - September 2, 1993.
  1810. X *  Changed 'sig_t' to 'Sig_t.'  Fixed another error in the termcap crap.
  1811. X *  Made having mktime() optional, at the expense of setting file dates
  1812. X *  to the same as the remote file.  Fixed an error during 'account'
  1813. X *  validation.  Added a warning about a bug I haven't fixed yet with
  1814. X *  non-UNIX systems hanging after listings.  Fixed bug where colon-mode
  1815. X *  sitenames weren't expanded.  Fixed a tip.  Using <readline/readline.h>
  1816. X *  and <getline/getline.h> instead of <readline.h> etc.  Fixed daylight
  1817. X *  savings time bug.  LocalPath checks $HOME now.
  1818. X *
  1819. X * v1.5.4 - September 14, 1993.
  1820. X *  Fixed bug where non-unix sites were hanging after listings.  Better
  1821. X *  SVR4 support.  Fixed bug during an ascii transfer with debug mode
  1822. X *  on.  Now checking the system type after a successful login, because
  1823. X *  some sites didn't allow commands to be executed until logged in; this
  1824. X *  prevents one (the only?) instance of the elusive short-file bug, because
  1825. X *  files were being fetched with ascii mode on.  Now checking for half-
  1826. X *  bright mode if boldface isn't available.  Numeric-only site abbreviations
  1827. X *  no longer accepted, so numbers will be treated only as indices from the
  1828. X *  open 'menu.'  You can include <term.h> for the 'tgetstr' prototype,
  1829. X *  if you define TERMH.  termcap_get() tweaked.  Fixed bug where macros
  1830. X *  from the previous site were still present when you opened a new site.
  1831. X *  Fixed bug where colon-mode paths were truncated.  Setting tenex mode
  1832. X *  automatically when you open a TOPS20 site.  Looking for <getline.h>
  1833. X *  instead of <getline/getline.h>; have to leave <readline/readline.h>,
  1834. X *  because that header also includes stuff like <readline/keymaps.h>.
  1835. X *  Catman support added to Makefile.  Fixed problem with terminfo, where
  1836. X *  $<2> etc., was not being removed from the terminal control strings.
  1837. X *
  1838. X * v1.5.5 - September 16, 1993.
  1839. X *  Fixed a bug where a key function wasn't returning it's results.
  1840. X *
  1841. X * v1.5.6 - September 20, 1993.
  1842. X *  Fixed bug in put, caused by "indent."  Checking for '.gz' extension
  1843. X *  for gzip in addition to '.z'.  A little better at preserving the
  1844. X *  transfer type.  Changed a syslog() call to use than 6 arguments,
  1845. X *  and reporting the full remote path to the system log now.  Have to
  1846. X *  explicitly define GZCAT in order to try paging gzip files now.
  1847. X *  Setting the current hostname correctly if using the gateway code.
  1848. X *  A lot of hacks added for SCO Xenix support: 1.  Can add -DNO_STRSTR
  1849. X *  to use own strstr();  2.  Can add -DNO_STRFTIME to make % flags in the
  1850. X *  prompt optional;  3. Can add -DNO_RENAME if you do not have rename(),
  1851. X *  or rename() doesn't work;  4. Added PTRTYPE if void ptrs are a problem.
  1852. X *
  1853. X * v1.6.0 - October 31, 1993.
  1854. X *  Added "term" support for Linux users.  Better SCO Xenix support.  Added
  1855. X *  -DLINGER, if you have a connection requiring it (so 'puts' to the remote
  1856. X *  system complete).  Added -DNET_ERRNO_H if you need to include
  1857. X *  <net/errno.h>.  Including more headers in sys.h.  Fixed another globulize
  1858. X *  bug.  Fixed a bug in confirm() where prompt was overwriting a str32.
  1859. X *  Added -DNO_CURSES_H if you do not want to try and include <curses.h>.
  1860. X *  Added -DHAS_GETCWD (usually automatic) and HAS_DOMAINNAME.  Logins as
  1861. X *  "ftp" act like "anonymous."  Fixed bug with "open #x".  Making sure you
  1862. X *  defined GZCAT as a string.  Turning off termcap attributes one by one,
  1863. X *  instead of using the turn-off-all-attributes.  A few fixes for the man
  1864. X *  page, including documentation of the progress-meter types.  AIX 2.x,
  1865. X *  AIX 3.x, ISC Unix, Dynix/PTX, and Besta support added to sys.h.  Safer
  1866. X *  use of getwd().  Colon-mode is quieter.  Getuserinfo function tweaked.
  1867. X *  Eliminated unnecessary GetHomeDir function in util.c.  Reworked Gets(),
  1868. X *  since it wasn't always stripping \n's.  Recent file can now read dir
  1869. X *  names with whitespace.  Opening msg uses a larger buffer, because of
  1870. X *  escape codes.  Philbar now prints K/sec stats.
  1871. X */
  1872. END_OF_FILE
  1873.   if test 11724 -ne `wc -c <'patchlevel.h'`; then
  1874.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  1875.   fi
  1876.   # end of 'patchlevel.h'
  1877. fi
  1878. if test -f 'set.c' -a "${1}" != "-c" ; then 
  1879.   echo shar: Will not clobber existing file \"'set.c'\"
  1880. else
  1881.   echo shar: Extracting \"'set.c'\" \(7930 characters\)
  1882.   sed "s/^X//" >'set.c' <<'END_OF_FILE'
  1883. X/* Set.c */
  1884. X
  1885. X/*  $RCSfile: set.c,v $
  1886. X *  $Revision: 14020.12 $
  1887. X *  $Date: 93/07/09 11:45:48 $
  1888. X */
  1889. X
  1890. X#include "sys.h"
  1891. X
  1892. X#include <ctype.h>
  1893. X
  1894. X#include "util.h"
  1895. X#include "cmds.h"
  1896. X#include "main.h"
  1897. X#include "set.h"
  1898. X#include "defaults.h"
  1899. X#include "copyright.h"
  1900. X
  1901. X#ifdef TERM_FTP
  1902. Xextern int compress_toggle;
  1903. X#endif
  1904. X
  1905. X/* Set.c globals: */
  1906. Xchar *verbose_msgs[4] = {
  1907. X    "Not printing anything.\n",
  1908. X    "Only printing necessary error messages.\n",
  1909. X    "Printing error messages and announcements from the remote host.\n",
  1910. X    "Printing all messages, errors, acknowledgments, and announcements.\n"
  1911. X};
  1912. X
  1913. Xchar *short_verbose_msgs[4] = {
  1914. X    "Quiet (-1)",
  1915. X    "Errors Only (0)",
  1916. X    "Terse (1)",
  1917. X    "Verbose (2)"
  1918. X};
  1919. X
  1920. Xstring                        vstr;
  1921. X
  1922. X/* Set.c externs: */
  1923. Xextern int                    progress_meter, connected;
  1924. Xextern int                    parsing_rc, keep_recent;
  1925. Xextern string                pager, anon_password, prompt;
  1926. Xextern str32                curtypename;
  1927. Xextern long                    logsize;
  1928. Xextern FILE                    *logf;
  1929. Xextern longstring            rcname, logfname, lcwd;
  1930. Xextern int                    auto_binary, ansi_escapes, debug;
  1931. Xextern int                    mprompt, remote_is_unix, verbose;
  1932. Xextern int                    startup_msg, anon_open;
  1933. X#ifndef NO_TIPS
  1934. Xextern int                    tips;
  1935. X#endif
  1936. X#ifdef GATEWAY
  1937. Xextern string                gateway, gate_login;
  1938. X#endif
  1939. X
  1940. X/* The variables must be sorted in alphabetical order, or else
  1941. X * match_var() will choke.
  1942. X */
  1943. Xstruct var vars[] = {
  1944. X    VARENTRY("anon-open",        BOOL, 0, &anon_open,    NULL),
  1945. X    VARENTRY("anon-password",    STR,  0, anon_password,    NULL),
  1946. X    VARENTRY("ansi-escapes",    BOOL, 0, &ansi_escapes,    NULL),
  1947. X    VARENTRY("auto-binary",        BOOL, 0, &auto_binary,    NULL),
  1948. X#ifdef TERM_FTP
  1949. X    VARENTRY("compress",        INT,  0,
  1950. X         &compress_toggle,NULL),
  1951. X#endif
  1952. X    VARENTRY("debug",            INT,  0, &debug,        NULL),
  1953. X#ifdef GATEWAY
  1954. X    VARENTRY("gateway-login",    STR,  0, gate_login,    set_gatelogin),
  1955. X    VARENTRY("gateway-host",    STR,  0, gateway,        NULL),
  1956. X#endif
  1957. X    VARENTRY("local-dir",        STR,  0, lcwd,            set_ldir),
  1958. X    VARENTRY("logfile",            STR,  0, logfname,        set_log),
  1959. X    VARENTRY("logsize",            LONG, 0, &logsize,        NULL),
  1960. X    VARENTRY("mprompt",            BOOL, 0, &mprompt,        NULL),
  1961. X    VARENTRY("netrc",            -STR, 0, rcname,        NULL),
  1962. X    VARENTRY("pager",            STR,  0, pager + 1,        set_pager),
  1963. X    VARENTRY("prompt",            STR,  0, prompt,        set_prompt),
  1964. X    VARENTRY("progress-reports",INT,  0, &progress_meter,NULL),
  1965. X    VARENTRY("recent-list",        BOOL, 0, &keep_recent,    NULL),
  1966. X    VARENTRY("remote-is-unix",    BOOL, 1, &remote_is_unix,NULL),
  1967. X    VARENTRY("startup-msg",        BOOL, 0, &startup_msg,    NULL),  /* TAR */
  1968. X#ifndef NO_TIPS
  1969. X    VARENTRY("tips",            BOOL, 0, &tips,            NULL),
  1970. X#endif
  1971. X    VARENTRY("type",            STR,  1, curtypename,    set_type),
  1972. X    VARENTRY("verbose",            STR,  0, vstr,            set_verbose),
  1973. X};
  1974. X
  1975. X
  1976. Xvoid set_verbose(char *new, int unset)
  1977. X{
  1978. X    int i, c;
  1979. X
  1980. X    if (unset == -1) verbose = !verbose;
  1981. X    else if (unset || !new) verbose = V_ERRS;
  1982. X    else {
  1983. X        if (isalpha(*new)) {
  1984. X            c = islower(*new) ? toupper(*new) : *new;    
  1985. X            for (i=0; i<(int)(sizeof(short_verbose_msgs)/sizeof(char *)); i++) {
  1986. X                if (short_verbose_msgs[i][0] == c)
  1987. X                    verbose = i - 1;
  1988. X            }
  1989. X        } else {
  1990. X            i = atoi(new);
  1991. X            if (i < V_QUIET) i = V_QUIET;
  1992. X            else if (i > V_VERBOSE) i = V_VERBOSE;
  1993. X            verbose = i;
  1994. X        }
  1995. X    }
  1996. X    (void) Strncpy(vstr, short_verbose_msgs[verbose+1]);
  1997. X    if (!parsing_rc && NOT_VQUIET) 
  1998. X        (void) fputs(verbose_msgs[verbose+1], stdout);
  1999. X}    /* set_verbose */
  2000. X
  2001. X
  2002. X
  2003. X
  2004. Xvoid set_prompt(char *new, int unset)
  2005. X{
  2006. X    (void) Strncpy(prompt, (unset || !new) ? dPROMPT : new);
  2007. X    init_prompt();
  2008. X}    /* set_prompt */
  2009. X
  2010. X
  2011. X
  2012. X
  2013. Xvoid set_log(char *fname, int unset)
  2014. X{
  2015. X    if (logf) {
  2016. X        (void) fclose(logf);
  2017. X        logf = NULL;
  2018. X    }
  2019. X    if (!unset && fname) {
  2020. X        (void) Strncpy(logfname, fname);
  2021. X        logf = fopen (LocalDotPath(logfname), "a");
  2022. X    }
  2023. X}    /* set_log */
  2024. X
  2025. X
  2026. X
  2027. X
  2028. Xvoid set_pager(char *new, int unset)
  2029. X{
  2030. X    if (unset)
  2031. X        (void) strcpy(pager, "-");
  2032. X    else {
  2033. X        if (!new)
  2034. X            new = dPAGER;
  2035. X        if (!new[0])
  2036. X            (void) Strncpy(pager, "-");
  2037. X        else {
  2038. X            (void) sprintf(pager, "|%s", (*new == '|' ? new + 1 : new));
  2039. X            (void) LocalPath(pager + 1);
  2040. X        }
  2041. X    }
  2042. X}    /* set_pager */
  2043. X
  2044. X
  2045. X
  2046. X
  2047. Xvoid set_type(char *newtype, int unset)
  2048. X{
  2049. X    int t = verbose;
  2050. X    verbose = V_QUIET;
  2051. X    if (!connected && t > V_QUIET)
  2052. X        (void) printf("Not connected.\n");
  2053. X    else if (newtype != NULL && !unset)
  2054. X        (void) _settype(newtype);
  2055. X    verbose = t;
  2056. X}    /* set_type */
  2057. X
  2058. X
  2059. X
  2060. X
  2061. Xvoid set_ldir(char *ldir, int unset)
  2062. X{
  2063. X    int t = verbose;
  2064. X    char *argv[2];
  2065. X
  2066. X    if (ldir && !unset) {
  2067. X        verbose = V_QUIET;
  2068. X        argv[1] = ldir;
  2069. X        (void) lcd(2, argv);
  2070. X        verbose = t;
  2071. X    }
  2072. X}    /* set_ldir */
  2073. X
  2074. X
  2075. X
  2076. X
  2077. X#ifdef GATEWAY
  2078. Xvoid set_gatelogin(char *glogin, int unset)
  2079. X{
  2080. X    if (unset || !glogin) {
  2081. X        gate_login[0] = gateway[0] = 0;
  2082. X    } else
  2083. X        (void) strcpy(gate_login, glogin);
  2084. X}    /* set_gatelogin */
  2085. X#endif
  2086. X
  2087. X
  2088. X
  2089. X
  2090. Xstruct var *match_var(char *varname)
  2091. X{
  2092. X    int i, ambig;
  2093. X    struct var *v;
  2094. X    short c;
  2095. X
  2096. X    c = (short) strlen(varname);
  2097. X    for (i=0, v=vars; i<NVARS; i++, v++) {
  2098. X        if (strcmp(v->name, varname) == 0)
  2099. X            return v;    /* exact match. */
  2100. X        if (c < v->nmlen) {
  2101. X            if (strncmp(v->name, varname, (size_t) c) == 0) {
  2102. X                /* Now make sure that it only matches one var name. */
  2103. X                if (c >= v[1].nmlen || (i == (NVARS - 1)))
  2104. X                    ambig = 0;
  2105. X                else
  2106. X                    ambig = !strncmp(v[1].name, varname, (size_t) c);
  2107. X                if (!ambig)
  2108. X                    return v;
  2109. X                (void) fprintf(stderr, "%s: ambiguous variable name.\n", varname);
  2110. X                goto xx;
  2111. X            }
  2112. X        }
  2113. X    }
  2114. X    (void) fprintf(stderr, "%s: unknown variable.\n", varname);
  2115. Xxx:
  2116. X    return ((struct var *)0);
  2117. X}    /* match_var */
  2118. X
  2119. X
  2120. X
  2121. X
  2122. Xvoid show_var(struct var *v)
  2123. X{
  2124. X    int c;
  2125. X
  2126. X    if (v != (struct var *)0) {
  2127. X        (void) printf("%-20s= ", v->name);
  2128. X        c = v->type;
  2129. X        if (c < 0) c = -c;
  2130. X        if (v->conn_required && !connected)
  2131. X            (void) printf("(not connected)\n");
  2132. X        else switch (c) {
  2133. X            case INT:
  2134. X                (void) printf("%d\n", *(int *)v->var); break;
  2135. X            case LONG:
  2136. X                (void) printf("%ld\n", *(long *)v->var); break;
  2137. X            case STR:
  2138. X                (void) printf("\"%s\"\n", (char *)v->var); break;
  2139. X            case BOOL:
  2140. X                (void) printf("%s\n", *(int *)v->var == 0 ? "no" : "yes");
  2141. X        }
  2142. X    }
  2143. X}    /* show_var */
  2144. X
  2145. X
  2146. X
  2147. X
  2148. Xvoid show(char *varname)
  2149. X{
  2150. X    int i;
  2151. X    struct var *v;
  2152. X
  2153. X    if ((varname == NULL)    /* (Denotes show all vars) */
  2154. X        || (strcmp("all", varname) == 0))
  2155. X    {
  2156. X        for (i=0; i<NVARS; i++)
  2157. X            show_var(&vars[i]);
  2158. X    } else {
  2159. X        if ((v = match_var(varname)) != (struct var *)0)
  2160. X            show_var(v);
  2161. X    }
  2162. X}    /* show */
  2163. X
  2164. X
  2165. X
  2166. X
  2167. Xint do_show(int argc, char **argv)
  2168. X{
  2169. X    int i;
  2170. X
  2171. X    if (argc < 2)
  2172. X        show(NULL);
  2173. X    else
  2174. X        for (i=1; i<argc; i++)
  2175. X            show(argv[i]);
  2176. X    return NOERR;
  2177. X}    /* do_show */
  2178. X
  2179. X
  2180. X
  2181. X
  2182. Xint set(int argc, char **argv)
  2183. X{
  2184. X    int unset;
  2185. X    struct var *v;
  2186. X    char *var, *val = NULL;
  2187. X
  2188. X    if (argc < 2 || strncmp(argv[1], "all", (size_t)3) == 0) {
  2189. X        show(NULL);        /* show all variables. */
  2190. X    } else {
  2191. X        unset = argv[0][0] == 'u';
  2192. X        var = argv[1];
  2193. X        if (argc > 2) {
  2194. X            /* could be '= value' or just 'value.' */
  2195. X            if (*argv[2] == '=') {
  2196. X                if (argc > 3)
  2197. X                    val = argv[3];
  2198. X                else return USAGE;    /* can't do 'set var =' */
  2199. X            } else
  2200. X                val = argv[2];
  2201. X            if (val[0] == 0)
  2202. X                val = NULL;
  2203. X        }
  2204. X        v = match_var(var);
  2205. X        if (v != NULL) {
  2206. X            if (v->conn_required && !connected)
  2207. X                (void) fprintf(stderr, "%s: must be connected.\n", var);
  2208. X            else if (v->type < 0)    
  2209. X                (void) fprintf(stderr, "%s: read-only variable.\n", var);
  2210. X            else if (v->proc != (setvarproc) 0) {
  2211. X                (*v->proc)(val, unset);        /* a custom set proc. */
  2212. X            } else if (unset) switch(v->type) {
  2213. X                case BOOL:
  2214. X                case INT:
  2215. X                    *(int *) v->var = 0; break;
  2216. X                case LONG:
  2217. X                    *(long *) v->var = 0; break;
  2218. X                case STR:
  2219. X                    *(char *) v->var = 0; break;
  2220. X            } else {
  2221. X                if (val == NULL) switch(v->type) {
  2222. X                    /* User just said "set varname" */
  2223. X                    case BOOL:
  2224. X                    case INT:
  2225. X                        *(int *) v->var = 1; break;
  2226. X                    case LONG:
  2227. X                        *(long *) v->var = 1; break;
  2228. X                    case STR:
  2229. X                        *(char *) v->var = 0; break;
  2230. X                } else {
  2231. X                    /* User said "set varname = value" */
  2232. X                    switch (v->type) {
  2233. X                        case BOOL:
  2234. X                            *(int *)v->var = StrToBool(val); break;
  2235. X                        case INT:
  2236. X                            (void) sscanf(val, "%d", (int *) v->var); break;
  2237. X                        case LONG:
  2238. X                            (void) sscanf(val, "%ld", (long *) v->var); break;
  2239. X                        case STR:
  2240. X                            (void) strcpy(v->var, val); break;
  2241. X                    }
  2242. X                }
  2243. X            }
  2244. X        }
  2245. X    }
  2246. X    return NOERR;
  2247. X}    /* set */
  2248. X
  2249. X/* eof Set.c */
  2250. END_OF_FILE
  2251.   if test 7930 -ne `wc -c <'set.c'`; then
  2252.     echo shar: \"'set.c'\" unpacked with wrong size!
  2253.   fi
  2254.   # end of 'set.c'
  2255. fi
  2256. echo shar: End of archive 4 \(of 6\).
  2257. cp /dev/null ark4isdone
  2258. MISSING=""
  2259. for I in 1 2 3 4 5 6 ; do
  2260.     if test ! -f ark${I}isdone ; then
  2261.     MISSING="${MISSING} ${I}"
  2262.     fi
  2263. done
  2264. if test "${MISSING}" = "" ; then
  2265.     echo You have unpacked all 6 archives.
  2266.     rm -f ark[1-9]isdone
  2267. else
  2268.     echo You still must unpack the following archives:
  2269.     echo "        " ${MISSING}
  2270. fi
  2271. exit 0
  2272. exit 0 # Just in case...
  2273.