home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume40 / ncftp / part02 / util.c < prev   
Encoding:
C/C++ Source or Header  |  1993-11-02  |  16.3 KB  |  819 lines

  1. /* Util.c */
  2.  
  3. /*  $RCSfile: util.c,v $
  4.  *  $Revision: 14020.13 $
  5.  *  $Date: 93/05/23 09:38:13 $
  6.  */
  7.  
  8. #include "sys.h"
  9.  
  10. #include <errno.h>
  11. #include <ctype.h>
  12. #include <pwd.h>
  13.  
  14. #ifndef NO_VARARGS
  15. #    include <stdarg.h>
  16. #endif
  17.  
  18. #ifdef READLINE
  19. #    include <readline/readline.h>
  20. #endif /* READLINE */
  21.  
  22. #ifdef GETLINE
  23. #    include <getline.h>
  24. #endif
  25.  
  26. #include "util.h"
  27. #include "cmds.h"
  28. #include "main.h"
  29. #include "ftp.h"
  30. #include "ftprc.h"
  31. #include "defaults.h"
  32. #include "copyright.h"
  33.  
  34. /* Util.c globals */
  35. int                    Opterr = 1;            /* if error message should be printed */
  36. int                    Optind = 1;            /* index into parent argv vector */
  37. int                    Optopt;                /* character checked for validity */
  38. char                *Optarg;            /* argument associated with option */
  39. char                *Optplace = EMSG;    /* saved position in an arg */
  40.  
  41. /* Util.c externs */
  42. extern int            toatty, fromatty;
  43. extern int            verbose;
  44. extern string        prompt2;
  45. extern char            *line, *margv[];
  46. extern int            margc;
  47. extern int            debug, mprompt, activemcmd;
  48. extern string        progname;
  49. extern struct cmd    cmdtab[];
  50. extern struct userinfo uinfo;
  51.  
  52. #ifndef NO_VARARGS
  53. void dbprintf(char *fmt, ...)
  54. {
  55.     va_list ap;
  56.  
  57.     if (debug) {
  58.         (void) fprintf(DB_STREAM, "#DB# ");
  59.         va_start(ap, fmt);
  60.         (void) vfprintf(DB_STREAM, fmt, ap);
  61.         va_end(ap);
  62.         (void) fflush(DB_STREAM);
  63.     }
  64. }    /* dbprintf */
  65. #endif
  66.  
  67.  
  68.  
  69.  
  70. /*
  71.  * Concatenate src on the end of dst.  The resulting string will have at most
  72.  * n-1 characters, not counting the NUL terminator which is always appended
  73.  * unlike strncat.  The other big difference is that strncpy uses n as the
  74.  * max number of characters _appended_, while this routine uses n to limit
  75.  * the overall length of dst.
  76.  */
  77. char *_Strncat(char *dst, char *src, register size_t n)
  78. {
  79.     register size_t i;
  80.     register char *d, *s;
  81.  
  82.     if (n != 0 && ((i = strlen(dst)) < (n - 1))) {
  83.         d = dst + i;
  84.         s = src;
  85.         /* If they specified a maximum of n characters, use n - 1 chars to
  86.          * hold the copy, and the last character in the array as a NUL.
  87.          * This is the difference between the regular strncpy routine.
  88.          * strncpy doesn't guarantee that your new string will have a
  89.          * NUL terminator, but this routine does.
  90.          */
  91.         for (++i; i<n; i++) {
  92.             if ((*d++ = *s++) == 0) {
  93.                 /* Pad with zeros. */
  94.                 for (; i<n; i++)
  95.                     *d++ = 0;
  96.                 return dst;
  97.             }
  98.         }
  99.         /* If we get here, then we have a full string, with n - 1 characters,
  100.          * so now we NUL terminate it and go home.
  101.          */
  102.         *d = 0;
  103.     }
  104.     return (dst);
  105. }    /* _Strncat */
  106.  
  107.  
  108. /*
  109.  * Copy src to dst, truncating or null-padding to always copy n-1 bytes.
  110.  * Return dst.
  111.  */
  112. char *_Strncpy(char *dst, char *src, register size_t n)
  113. {
  114.     register char *d;
  115.     register char *s;
  116.     register size_t i;
  117.  
  118.     d = dst;
  119.     *d = 0;
  120.     if (n != 0) {
  121.         s = src;
  122.         /* If they specified a maximum of n characters, use n - 1 chars to
  123.          * hold the copy, and the last character in the array as a NUL.
  124.          * This is the difference between the regular strncpy routine.
  125.          * strncpy doesn't guarantee that your new string will have a
  126.          * NUL terminator, but this routine does.
  127.          */
  128.         for (i=1; i<n; i++) {
  129.             if ((*d++ = *s++) == 0) {
  130.                 /* Pad with zeros. */
  131.                 for (; i<n; i++)
  132.                     *d++ = 0;
  133.                 return dst;
  134.             }
  135.         }
  136.         /* If we get here, then we have a full string, with n - 1 characters,
  137.          * so now we NUL terminate it and go home.
  138.          */
  139.         *d = 0;
  140.     }
  141.     return (dst);
  142. }    /* _Strncpy */
  143.  
  144.  
  145.  
  146.  
  147. char *Strpcpy(char *dst, char *src)
  148. {
  149.     while ((*dst++ = *src++) != '\0')
  150.         ;
  151.     return (--dst);    /* return current value of dst, NOT original value! */
  152. }    /* Strpcpy */
  153.  
  154.  
  155.  
  156. /*
  157.  * malloc's a copy of oldstr.
  158.  */
  159. char *NewString(char *oldstr)
  160. {
  161.     size_t howLong;
  162.     char *newstr;
  163.  
  164.     howLong = strlen(oldstr);
  165.     if ((newstr = malloc(howLong + 1)) != NULL)
  166.         (void) strcpy(newstr, oldstr);
  167.     return newstr;
  168. }    /* NewString */
  169.  
  170.  
  171.  
  172.  
  173.  
  174. void Getopt_Reset(void)
  175. {
  176.     Optind = 1;
  177.     Optplace = "";
  178. }    /* Getopt_Reset */
  179.  
  180. static char *NextOption(char *ostr)
  181. {
  182.     if ((Optopt = (int) *Optplace++) == (int) ':')
  183.         return 0;
  184.     return index(ostr, Optopt);
  185. }
  186.  
  187. int Getopt(int nargc, char **nargv, char *ostr)
  188. {
  189.     register char *oli;                   /* Option letter list index */
  190.  
  191.     if (!*Optplace) {                       /* update scanning pointer */
  192.         if (Optind >= nargc || *(Optplace = nargv[Optind]) != '-')
  193.             return (EOF);
  194.         if (Optplace[1] && *++Optplace == '-') {    /* found "--" */
  195.             ++Optind;
  196.             return (EOF);
  197.         }
  198.     }                                   /* Option letter okay? */
  199.     oli = NextOption(ostr);
  200.     if (oli == NULL) {
  201.         if (!*Optplace)
  202.             ++Optind;
  203.         if (Opterr) {
  204.             (void) fprintf(stderr, "%s%s%c\n", *nargv, ": illegal option -- ", Optopt);
  205.             return(BADCH);
  206.         }
  207.     }
  208.     if (*++oli != ':') {               /* don't need argument */
  209.         Optarg = NULL;
  210.         if (!*Optplace)
  211.             ++Optind;
  212.     } else {                           /* need an argument */
  213.         if (*Optplace)                       /* no white space */
  214.             Optarg = Optplace;
  215.         else if (nargc <= ++Optind) {  /* no arg */
  216.             Optplace = EMSG;
  217.             if (Opterr) {
  218.                 (void) fprintf(stderr, "%s%s%c\n", *nargv, ": option requires an argument -- ", Optopt);
  219.                 return(BADCH);
  220.             }
  221.         } else                           /* white space */
  222.             Optarg = nargv[Optind];
  223.         Optplace = EMSG;
  224.         ++Optind;
  225.     }
  226.     return (Optopt);                   /* dump back Option letter */
  227. }                                       /* Getopt */
  228.  
  229.  
  230.  
  231.  
  232. /*
  233.  * Converts an ls date, in either the "Feb  4  1992" or "Jan 16 13:42"
  234.  * format to a time_t.
  235.  */
  236. unsigned long UnLSDate(char *dstr)
  237. {
  238. #ifdef NO_MKTIME
  239.     return (0);
  240. #else
  241.     char *cp = dstr;
  242.     int long mon, day, year, hr, min;
  243.     time_t now;
  244.     struct tm ut, *t;
  245.  
  246.     switch (*cp++) {
  247.         case 'A':
  248.             mon = (*cp == 'u') ? 7 : 3;
  249.             break;
  250.         case 'D':
  251.             mon = 11;
  252.             break;
  253.         case 'F':
  254.             mon = 1;
  255.             break;
  256.         default:                       /* shut up un-init warning */
  257.         case 'J':
  258.             if (*cp++ == 'u')
  259.                 mon = (*cp == 'l') ? 6 : 5;
  260.             else
  261.                 mon = 0;
  262.             break;
  263.         case 'M':
  264.             mon = (*++cp == 'r') ? 2 : 4;
  265.             break;
  266.         case 'N':
  267.             mon = 10;
  268.             break;
  269.         case 'O':
  270.             mon = 9;
  271.             break;
  272.         case 'S':
  273.             mon = 8;
  274.     }
  275.     cp = dstr + 4;
  276.     day = 0;
  277.     if (*cp != ' ')
  278.         day = 10 * (*cp - '0');
  279.     cp++;
  280.     day += *cp++ - '0';
  281.     min = 0;
  282.     
  283.     (void) time(&now);
  284.     t = localtime(&now);
  285.  
  286.     if (*++cp != ' ') {
  287.         /* It's a time, XX:YY, not a year. */
  288.         cp[2] = ' ';
  289.         (void) sscanf(cp, "%ld %ld", &hr, &min);
  290.         cp[2] = ':';
  291.         year = t->tm_year;
  292.         if (mon > t->tm_mon)
  293.             --year;
  294.     } else {
  295.         hr = min = 0;
  296.         (void) sscanf(cp, "%ld", &year);
  297.         year -= 1900;
  298.     }
  299.     ut.tm_sec = 1;
  300.     ut.tm_min = min;
  301.     ut.tm_hour = hr;
  302.     ut.tm_mday = day;
  303.     ut.tm_mon = mon;
  304.     ut.tm_year = year;
  305.     ut.tm_isdst = t->tm_isdst;
  306.     ut.tm_wday = ut.tm_yday = 0;
  307.     return ((unsigned long) mktime(&ut));
  308. #endif    /* NO_MKTIME */
  309. }    /* UnLSDate */
  310.  
  311.  
  312.  
  313.  
  314. void Perror(
  315. #ifdef DB_ERRS
  316.             char *fromProc
  317.             ,
  318. #ifdef __LINE__
  319.             int lineNum,
  320. #endif
  321. #endif
  322.             char *msg
  323.             )
  324. {
  325.     extern int errno;
  326.  
  327.     if (NOT_VQUIET) {
  328. #ifdef sun
  329.     /*
  330.      * There is a problem in the SunOS headers when compiling with an ANSI
  331.      * compiler.  The problem is that there are macros in the form of
  332.      * #define MAC(x) 'x', and this will always be the character x instead
  333.      * of whatever parameter was passed to MAC.  If we get these errors, it
  334.      * usually means that you are trying to compile with gcc when you haven't
  335.      * run the 'fixincludes' script that fixes these macros.  We will ignore
  336.      * the error, but it means that the echo() function won't work correctly,
  337.      * and you will see your password echo.
  338.      */
  339.         if (errno == ENOTTY)
  340.             return;
  341. #endif
  342.         (void) fprintf(stderr, "NcFTP");
  343. #ifdef DB_ERRS
  344.         if (fromProc != NULL)
  345.             (void) fprintf(stderr, "/%s", fromProc);
  346. #ifdef __LINE__
  347.         (void) fprintf(stderr, "/%d", lineNum);
  348. #endif
  349. #endif
  350.         (void) fprintf(stderr, ": ");
  351.         if (msg != NULL)
  352.             (void) fprintf(stderr, "%s (%d): ", msg, errno);
  353.         perror(NULL);
  354.     }
  355. }    /* Perror */
  356.  
  357.  
  358.  
  359.  
  360. size_t RemoveTrailingNewline(char *cp, int *stripped)
  361. {
  362.     size_t len;
  363.     int nBytesStripped = 0;
  364.  
  365.     if (cp != NULL) {
  366.         cp += (len = strlen(cp)) - 1;
  367.         if (*cp == '\n') {
  368.             *cp-- = 0;    /* get rid of the newline. */
  369.             nBytesStripped++;
  370.         }
  371.         if (*cp == '\r') { /* no returns either, please. */
  372.             *cp = 0;
  373.             nBytesStripped++;
  374.         }
  375.         if (stripped != NULL)
  376.             *stripped = nBytesStripped;
  377.         return len;
  378.     }
  379.     return (size_t)0;
  380. }    /* RemoveTrailingNewline */
  381.  
  382.  
  383.  
  384. #ifdef GETLINE
  385. extern size_t epromptlen;
  386.  
  387. /*
  388.  * The Getline library doesn't detect the ANSI escape sequences, so the
  389.  * library would think that a string is longer than actually appears on
  390.  * screen.  This function lets Getline work properly.  This function is
  391.  * intended to fix that problem for the main command prompt only.  If any
  392.  * other prompts want to use ANSI escapes, a (costly) function would have
  393.  * to scan the prompt for all escape sequences.
  394.  */
  395. /*ARGSUSED*/
  396. static size_t MainPromptLen(char *pr)
  397. {
  398.     return (int)epromptlen;
  399. }
  400. #endif
  401.  
  402. static char *StdioGets(char *promptstr, char *sline, size_t size)
  403. {
  404.     char *cp;
  405.  
  406.     if (fromatty) {
  407.         /* It's okay to print a prompt if we are redirecting stdout,
  408.          * as long as stdin is still a tty.  Otherwise, don't print
  409.          * a prompt at all if stdin is redirected.
  410.          */
  411. #ifdef CURSES
  412.         tcap_put(promptstr);
  413. #else
  414.         (void) fputs(promptstr, stdout);
  415. #endif
  416.     }
  417.     sline[0] = 0;
  418.     cp = fgets(sline, (int)(size - 2), stdin);
  419.     (void) RemoveTrailingNewline(sline, NULL);
  420.     return cp;
  421. }    /* StdioGets */
  422.  
  423.  
  424. /* Given a prompt string, a destination string, and it's size, return feedback
  425.  * from the user in the destination string, with any trailing newlines
  426.  * stripped.  Returns NULL if EOF encountered.
  427.  */
  428. char *Gets(char *promptstr, char *sline, size_t size)
  429. {
  430.     char *cp, ch;
  431.     string plines;
  432. #ifdef GETLINE
  433.     int ismainprompt = (promptstr == prompt2);
  434. #endif
  435.  
  436.     if (!fromatty || !toatty) {
  437.         /* Don't worry about a cmdline/history editor if you redirected a
  438.          * file at me.
  439.          */
  440.         return (StdioGets(promptstr, sline, size));
  441.     }
  442.  
  443.     sline[0] = 0;    /* Clear it, in case of an error later. */
  444.  
  445.     /*
  446.      * The prompt string may actually be several lines if the user put a
  447.      * newline in it with the @N option.  In this case we only want to print
  448.      * the very last line, so the command-line editors won't screw up.  So
  449.      * now we print all the lines except the last line.
  450.      */
  451.     cp = rindex(promptstr, '\n');
  452.     if (cp != NULL) {
  453.         ch = *++cp;
  454.         *cp = 0;
  455.         (void) Strncpy(plines, promptstr);
  456.         *cp = ch;
  457.         promptstr = cp;
  458. #ifdef CURSES
  459.         tcap_put(plines);
  460. #else
  461.         (void) fputs(plines, stdout);
  462. #endif
  463.     }
  464.  
  465. #ifdef READLINE
  466.     if ((cp = readline(promptstr)) != NULL) {
  467.         (void) _Strncpy(sline, cp, size);
  468.         free(cp);
  469.         (void) RemoveTrailingNewline(cp = sline, NULL);
  470.         if (*cp != 0)    /* Don't add blank lines to history buffer. */
  471.             add_history(cp);
  472.     }
  473. #else    /* READLINE */
  474.  
  475. #ifdef GETLINE
  476.     if (toatty) {
  477.         if (ismainprompt)
  478.             gl_strwidth(MainPromptLen);
  479.         if ((cp = getline(promptstr)) != NULL) {
  480.             if (*cp == '\0')    /* You hit ^D. */
  481.                 return NULL;
  482.             cp = _Strncpy(sline, cp, size);
  483.             (void) RemoveTrailingNewline(cp, NULL);
  484.             if (*cp != '\0') {    /* Don't add blank lines to history buffer. */
  485.                 gl_histadd(cp);
  486.             }
  487.         }
  488.         /* Hope your strlen is declared as returning a size_t. */
  489.         gl_strwidth(strlen);
  490.     } else {
  491.         cp = StdioGets(promptstr, sline, size);
  492.     }
  493. #else /* !GETLINE */
  494.     cp = StdioGets(promptstr, sline, size);
  495. #endif /* !GETLINE */
  496. #endif /* !READLINE */
  497.     return cp;
  498. }    /* Gets */
  499.  
  500.  
  501.  
  502.  
  503. char **re_makeargv(char *promptstr, int *argc)
  504. {
  505.     size_t sz;
  506.  
  507.     (void) strcat(line, " ");
  508.     sz = strlen(line);
  509.     (void) Gets(promptstr, &line[sz], (size_t) (CMDLINELEN - sz)) ;
  510.     (void) makeargv();
  511.     *argc = margc;
  512.     return (margv);
  513. }    /* re_makeargv */
  514.  
  515.  
  516.  
  517. #ifndef HAS_GETCWD
  518. extern char *getwd(char *);
  519. #endif
  520.  
  521. char *get_cwd(char *buf, int size)
  522. {
  523. #ifdef HAS_GETCWD
  524. #    ifdef NO_UNISTDH
  525. #        ifdef GETCWDSIZET
  526.             extern char *getcwd(char *, size_t);
  527. #        else
  528.             extern char *getcwd(char *, int);
  529. #        endif
  530. #    endif
  531.     return (getcwd(buf, size - 1));
  532. #else
  533. #ifndef MAXPATHLEN
  534. #    define MAXPATHLEN (1024)
  535. #endif
  536.     static char *cwdbuf = NULL;
  537.  
  538.     if (cwdbuf == NULL) {
  539.         cwdbuf = (char *)malloc((size_t) MAXPATHLEN);
  540.         if (cwdbuf == NULL)
  541.             fatal("out of memory for getwd buffer.");
  542.     }
  543.     return (_Strncpy(buf, getwd(cwdbuf), (size_t)size));
  544. #endif
  545. }   /* get_cwd */
  546.  
  547.  
  548.  
  549. int tmp_name(char *str)
  550. {
  551.     (void) strcpy(str, "/tmp/ncftpXXXXXX");
  552.     return (!mktemp(str));
  553. }    /* tmp_name */
  554.  
  555.  
  556.  
  557.  
  558. char *onoff(int boolf)
  559. {
  560.     return (boolf ? "on" : "off");
  561. }   /* onoff */
  562.  
  563.  
  564.  
  565.  
  566. int StrToBool(char *s)
  567. {
  568.     int c;
  569.     int result;
  570.  
  571.     c = tolower(*s);
  572.     result = 0;
  573.     switch (c) {
  574.         case 'f':           /* false */
  575.         case 'n':            /* no */
  576.             break;
  577.         case 'o':           /* test for "off" and "on" */
  578.             c = tolower(s[1]);
  579.             if (c == 'f')
  580.                 break;
  581.             /* fall through */
  582.         case 't':           /* true */
  583.         case 'y':            /* yes */
  584.             result = 1;
  585.             break;
  586.         default:            /* 1, 0, -1, other number? */
  587.             if (atoi(s) != 0)
  588.                 result = 1;
  589.     }
  590.     return result;
  591. }   /* StrToBool */
  592.  
  593.  
  594.  
  595.  
  596. int confirm(char *cmd, char *file)
  597. {
  598.     string str, pr;
  599.  
  600.     if (!fromatty || (activemcmd && !mprompt))
  601.         return 1;
  602.     (void) sprintf(pr, "%s %s? ", cmd, file);
  603.     (void) Gets(pr, str, sizeof(str));
  604.     return (*str != 'n' && *str != 'N');
  605. }    /* confirm */
  606.  
  607.  
  608.  
  609. void fatal(char *msg)
  610. {
  611.     (void) fprintf(stderr, "%s: %s\n", progname, msg);
  612.     close_up_shop();
  613.     exit(1);
  614. }    /* fatal */
  615.  
  616.  
  617.  
  618.  
  619. int UserLoggedIn(void)
  620. {
  621.     static int inited = 0;
  622.     static int parent_pid, stderr_was_tty;
  623.  
  624.     if (!inited) {
  625.         stderr_was_tty = isatty(2);
  626.         parent_pid = getppid();
  627.         inited++;
  628.     }
  629.     if ((stderr_was_tty && !isatty(2)) || (getppid() != parent_pid))
  630.         return 0;
  631.     return 1;
  632. }    /* UserLoggedIn */
  633.  
  634.  
  635.  
  636.  
  637. struct cmd *getcmd(char *name)
  638. {
  639.     struct cmd *c, *found;
  640.     int nmatches;
  641.     size_t len;
  642.     char *p;
  643.  
  644.     found = (struct cmd *)0;
  645.     if (name != NULL) {
  646.         len = strlen(name);
  647.         nmatches = 0;
  648.         for (c = cmdtab; (p = c->c_name) != NULL; c++) {
  649.             if (strcmp(name, p) == 0) {
  650.                 /* Exact match. */
  651.                 found = c;
  652.                 goto xx;
  653.             }
  654.             if (c->c_handler == unimpl)
  655.                 continue;
  656.             if (strncmp(name, p, len) == 0) {
  657.                 if (++nmatches > 1) {
  658.                     found = ((struct cmd *) -1);    
  659.                     goto xx;
  660.                 }                
  661.                 found = c;
  662.             } else if (found != NULL)
  663.                 break;
  664.         }
  665.     }
  666. xx:
  667.     return (found);
  668. }    /* getcmd */
  669.  
  670.  
  671.  
  672.  
  673. void cmd_help(struct cmd *c)
  674. {
  675.     (void) printf("%s: %s.\n",
  676.         c->c_name,
  677.         c->c_help
  678.     );
  679. }    /* cmd_help */
  680.  
  681.  
  682.  
  683.  
  684. void cmd_usage(struct cmd *c)
  685. {
  686.     if (c->c_usage != NULL)
  687.         (void) printf("Usage: %s%s\n",
  688.             c->c_name,
  689.             c->c_usage
  690.         );
  691. }    /* cmd_usage */
  692.  
  693.  
  694.  
  695.  
  696. /*
  697.  * A simple function that translates most pathnames with ~, ~user, or
  698.  * environment variables as the first item.  It won't do paths with env vars
  699.  * or ~s in the middle of the path, but those are extremely rare.
  700.  */
  701. char *LocalPath(char *path)
  702. {
  703.     longstring orig;
  704.     struct passwd *pw;
  705.     char *firstent = NULL;
  706.     char *cp, *dp, *rest;
  707.  
  708.     (void) Strncpy(orig, path);
  709.     if (((cp = index(orig, '/')) != NULL) && (cp != orig)) {
  710.         *cp = 0;
  711.         rest = cp + 1;
  712.         if (orig[0] == '~') {
  713.             if (orig[1] == 0) {
  714.                 firstent = uinfo.homedir;
  715.             } else {
  716.                 pw = getpwnam(orig + 1);
  717.                 if (pw != NULL)
  718.                     firstent = pw->pw_dir;
  719.             }
  720.         } else if (orig[0] == '$') {
  721.             cp = orig + 1;
  722.             dp = orig + strlen(orig) - 1;
  723.             if ((*cp == '(' && *dp == ')') || (*cp == '{' && *dp == '}')) {
  724.                 cp++;
  725.                 *dp = 0;
  726.             }
  727.             firstent = getenv(cp);
  728.         }
  729.         if (firstent != NULL)
  730.             (void) sprintf(path, "%s/%s", firstent, rest);
  731.     }
  732.     return (path);
  733. }    /* LocalPath */
  734.  
  735.  
  736.  
  737. /*
  738.  * A special case, where invisible dot-files that would normally appear in
  739.  * your home directory will appear instead as visible files in your $DOTDIR
  740.  * directory if you have one.
  741.  */
  742.  
  743. #define LCMP(b) (strncmp(path, (b), (o = sizeof(b) - 1)) == 0)
  744.  
  745. char *LocalDotPath(char *path)
  746. {
  747.     size_t o;
  748.     longstring s, s2;
  749.     char *cp = getenv("DOTDIR");
  750.  
  751.     if (cp == NULL) {
  752.         goto aa;
  753.     } else {
  754.         if (*cp != '/' && *cp != '~') {
  755.             /* then maybe they mean relative to $HOME. */
  756.             (void) sprintf(s2, "%s/%s", uinfo.homedir, cp);
  757.             cp = s2;
  758.         }
  759.         if (LCMP("~/.") ||
  760.             LCMP("$HOME/.") ||
  761.             LCMP("$home/.") ||
  762.             LCMP("$(HOME)/.") ||
  763.             LCMP("${HOME}/.")
  764.         ) {
  765.             (void) Strncpy(s, path);
  766.             (void) sprintf(path, "%s/%s", cp, s + o);
  767.             cp = path;
  768.         } else {
  769. aa:            cp = LocalPath(path);
  770.         }
  771.     }
  772.     return cp;
  773. }    /* LocalDotPath */
  774.  
  775. #ifdef NO_STRSTR
  776.  
  777. /*
  778.  *  The Elm Mail System  -  $Revision: 5.1 $   $State: Exp $
  779.  *
  780.  *            Copyright (c) 1988-1992 USENET Community Trust
  781.  *            Copyright (c) 1986,1987 Dave Taylor
  782.  */
  783.  
  784. char *strstr(s1, s2)
  785. char *s1, *s2;
  786. {
  787.     int len;
  788.     char *ptr;
  789.     char *tmpptr;
  790.  
  791.     ptr = NULL;
  792.     len = strlen(s2);
  793.  
  794.     if ( len <= strlen(s1)) {
  795.         tmpptr = s1;
  796.         while ((ptr = index(tmpptr, (int)*s2)) != NULL) {
  797.             if (strncmp(ptr, s2, len) == 0) {
  798.                 break;
  799.             }
  800.             tmpptr = ptr+1;
  801.         }
  802.     }
  803.     return (ptr);
  804. }
  805.  
  806. #endif
  807.  
  808.  
  809. #ifdef NO_RENAME
  810. int rename(oldname, newname)
  811. const char *oldname, *newname;
  812. {
  813.     return (link(oldname, newname) == 0 ? unlink(oldname) : -1);
  814. }
  815. #endif /*NO_RENAME*/
  816.  
  817.  
  818. /* eof Util.c */
  819.