home *** CD-ROM | disk | FTP | other *** search
- /* Util.c */
-
- /* $RCSfile: util.c,v $
- * $Revision: 14020.13 $
- * $Date: 93/05/23 09:38:13 $
- */
-
- #include "sys.h"
-
- #include <string.h>
- #include <errno.h>
- #include <ctype.h>
- #include <sys/time.h>
- #include <time.h>
- #include <pwd.h>
-
- #ifndef NO_VARARGS
- # include <stdarg.h>
- #endif
-
- #ifndef NO_UNISTDH
- # include <unistd.h>
- #endif
-
- #ifdef READLINE
- # include <readline.h>
- #endif /* READLINE */
-
- #ifdef GETLINE
- # include <getline.h>
- #endif
-
- #include "util.h"
- #include "cmds.h"
- #include "main.h"
- #include "ftp.h"
- #include "ftprc.h"
- #include "defaults.h"
- #include "copyright.h"
-
- /* Util.c globals */
- int Opterr = 1; /* if error message should be printed */
- int Optind = 1; /* index into parent argv vector */
- int Optopt; /* character checked for validity */
- char *Optarg; /* argument associated with option */
- char *Optplace = EMSG; /* saved position in an arg */
-
- /* Util.c externs */
- extern int toatty, fromatty;
- extern int verbose;
- extern string prompt2;
- extern char *line, *margv[];
- extern int margc;
- extern int debug, mprompt, activemcmd;
- extern string progname;
- extern struct cmd cmdtab[];
-
- #ifndef NO_VARARGS
- void dbprintf(char *fmt, ...)
- {
- va_list ap;
-
- if (debug) {
- (void) fprintf(DB_STREAM, "#DB# ");
- va_start(ap, fmt);
- (void) vfprintf(DB_STREAM, fmt, ap);
- va_end(ap);
- (void) fflush(DB_STREAM);
- }
- } /* dbprintf */
- #endif
-
-
-
-
- /*
- * Concatenate src on the end of dst. The resulting string will have at most
- * n-1 characters, not counting the NUL terminator which is always appended
- * unlike strncat. The other big difference is that strncpy uses n as the
- * max number of characters _appended_, while this routine uses n to limit
- * the overall length of dst.
- */
- char *_Strncat(char *dst, char *src, register size_t n)
- {
- register size_t i;
- register char *d, *s;
-
- if (n != 0 && ((i = strlen(dst)) < (n - 1))) {
- d = dst + i;
- s = src;
- /* If they specified a maximum of n characters, use n - 1 chars to
- * hold the copy, and the last character in the array as a NUL.
- * This is the difference between the regular strncpy routine.
- * strncpy doesn't guarantee that your new string will have a
- * NUL terminator, but this routine does.
- */
- for (++i; i<n; i++) {
- if ((*d++ = *s++) == 0) {
- /* Pad with zeros. */
- for (; i<n; i++)
- *d++ = 0;
- return dst;
- }
- }
- /* If we get here, then we have a full string, with n - 1 characters,
- * so now we NUL terminate it and go home.
- */
- *d = 0;
- }
- return (dst);
- } /* _Strncat */
-
-
- /*
- * Copy src to dst, truncating or null-padding to always copy n-1 bytes.
- * Return dst.
- */
- char *_Strncpy(char *dst, char *src, register size_t n)
- {
- register char *d;
- register char *s;
- register size_t i;
-
- d = dst;
- *d = 0;
- if (n != 0) {
- s = src;
- /* If they specified a maximum of n characters, use n - 1 chars to
- * hold the copy, and the last character in the array as a NUL.
- * This is the difference between the regular strncpy routine.
- * strncpy doesn't guarantee that your new string will have a
- * NUL terminator, but this routine does.
- */
- for (i=1; i<n; i++) {
- if ((*d++ = *s++) == 0) {
- /* Pad with zeros. */
- for (; i<n; i++)
- *d++ = 0;
- return dst;
- }
- }
- /* If we get here, then we have a full string, with n - 1 characters,
- * so now we NUL terminate it and go home.
- */
- *d = 0;
- }
- return (dst);
- } /* _Strncpy */
-
-
-
-
- char *Strpcpy(char *dst, char *src)
- {
- while (*dst++ = *src++)
- ;
- return (--dst); /* return current value of dst, NOT original value! */
- } /* Strpcpy */
-
-
-
- /*
- * malloc's a copy of oldstr.
- */
- char *NewString(char *oldstr)
- {
- size_t howLong;
- char *newstr;
-
- howLong = strlen(oldstr);
- if ((newstr = malloc(howLong + 1)) != NULL)
- (void) strcpy(newstr, oldstr);
- return newstr;
- } /* NewString */
-
-
-
-
-
- void Getopt_Reset(void)
- {
- Optind = 1;
- Optplace = "";
- } /* Getopt_Reset */
-
- static char *NextOption(char *ostr)
- {
- if ((Optopt = (int) *Optplace++) == (int) ':')
- return 0;
- return index(ostr, Optopt);
- }
-
- int Getopt(int nargc, char **nargv, char *ostr)
- {
- register char *oli; /* Option letter list index */
-
- if (!*Optplace) { /* update scanning pointer */
- if (Optind >= nargc || *(Optplace = nargv[Optind]) != '-')
- return (EOF);
- if (Optplace[1] && *++Optplace == '-') { /* found "--" */
- ++Optind;
- return (EOF);
- }
- } /* Option letter okay? */
- oli = NextOption(ostr);
- if (oli == NULL) {
- if (!*Optplace)
- ++Optind;
- if (Opterr) {
- (void) fprintf(stderr, "%s%s%c\n", *nargv, ": illegal option -- ", Optopt);
- return(BADCH);
- }
- }
- if (*++oli != ':') { /* don't need argument */
- Optarg = NULL;
- if (!*Optplace)
- ++Optind;
- } else { /* need an argument */
- if (*Optplace) /* no white space */
- Optarg = Optplace;
- else if (nargc <= ++Optind) { /* no arg */
- Optplace = EMSG;
- if (Opterr) {
- (void) fprintf(stderr, "%s%s%c\n", *nargv, ": option requires an argument -- ", Optopt);
- return(BADCH);
- }
- } else /* white space */
- Optarg = nargv[Optind];
- Optplace = EMSG;
- ++Optind;
- }
- return (Optopt); /* dump back Option letter */
- } /* Getopt */
-
-
-
-
- /*
- * Converts an ls date, in either the "Feb 4 1992" or "Jan 16 13:42"
- * format to a time_t.
- */
- unsigned long UnLSDate(char *dstr)
- {
- char *cp = dstr;
- int long mon, day, year, hr, min;
- time_t now;
- struct tm ut, *t;
-
- switch (*cp++) {
- case 'A':
- mon = (*cp == 'u') ? 7 : 3;
- break;
- case 'D':
- mon = 11;
- break;
- case 'F':
- mon = 1;
- break;
- default: /* shut up un-init warning */
- case 'J':
- if (*cp++ == 'u')
- mon = (*cp == 'l') ? 6 : 5;
- else
- mon = 0;
- break;
- case 'M':
- mon = (*++cp == 'r') ? 2 : 4;
- break;
- case 'N':
- mon = 10;
- break;
- case 'O':
- mon = 9;
- break;
- case 'S':
- mon = 8;
- }
- cp = dstr + 4;
- day = 0;
- if (*cp != ' ')
- day = 10 * (*cp - '0');
- cp++;
- day += *cp++ - '0';
- min = 0;
-
- (void) time(&now);
- t = localtime(&now);
-
- if (*++cp != ' ') {
- /* It's a time, XX:YY, not a year. */
- cp[2] = ' ';
- (void) sscanf(cp, "%ld %ld", &hr, &min);
- cp[2] = ':';
- year = t->tm_year;
- if (mon > t->tm_mon)
- --year;
- } else {
- hr = min = 0;
- (void) sscanf(cp, "%ld", &year);
- year -= 1900;
- }
- ut.tm_sec = 0;
- ut.tm_min = min;
- ut.tm_hour = hr;
- ut.tm_mday = day;
- ut.tm_mon = mon;
- ut.tm_year = year;
- ut.tm_isdst = 0;
- ut.tm_wday = ut.tm_yday = 0;
- return ((unsigned long) mktime(&ut));
- } /* UnLSDate */
-
-
-
-
- void Perror(
- #ifdef DB_ERRS
- char *fromProc
- ,
- #ifdef __LINE__
- int lineNum,
- #endif
- #endif
- char *msg
- )
- {
- extern int errno;
-
- if (NOT_VQUIET) {
- #ifdef sun
- /*
- * There is a problem in the SunOS headers when compiling with an ANSI
- * compiler. The problem is that there are macros in the form of
- * #define MAC(x) 'x', and this will always be the character x instead
- * of whatever parameter was passed to MAC. If we get these errors, it
- * usually means that you are trying to compile with gcc when you haven't
- * run the 'fixincludes' script that fixes these macros. We will ignore
- * the error, but it means that the echo() function won't work correctly,
- * and you will see your password echo.
- */
- if (errno == ENOTTY)
- return;
- #endif
- (void) fprintf(stderr, "NcFTP");
- #ifdef DB_ERRS
- if (fromProc != NULL)
- (void) fprintf(stderr, "/%s", fromProc);
- #ifdef __LINE__
- (void) fprintf(stderr, "/%d", lineNum);
- #endif
- #endif
- (void) fprintf(stderr, ": ");
- if (msg != NULL)
- (void) fprintf(stderr, "%s (%d): ", msg, errno);
- perror(NULL);
- }
- } /* Perror */
-
-
-
-
- size_t RemoveTrailingNewline(char *cp, int *stripped)
- {
- size_t len;
- int nBytesStripped = 0;
-
- if (cp != NULL) {
- cp += (len = strlen(cp)) - 1;
- if (*cp == '\n') {
- *cp-- = 0; /* get rid of the newline. */
- nBytesStripped++;
- }
- if (*cp == '\r') { /* no returns either, please. */
- *cp = 0;
- nBytesStripped++;
- }
- if (stripped != NULL)
- *stripped = nBytesStripped;
- return len;
- }
- return (size_t)0;
- } /* RemoveTrailingNewline */
-
-
-
- #ifdef GETLINE
- extern size_t epromptlen;
-
- /*
- * The Getline library doesn't detect the ANSI escape sequences, so the
- * library would think that a string is longer than actually appears on
- * screen. This function lets Getline work properly. This function is
- * intended to fix that problem for the main command prompt only. If any
- * other prompts want to use ANSI escapes, a (costly) function would have
- * to scan the prompt for all escape sequences.
- */
- /*ARGSUSED*/
- static int MainPromptLen(char *pr)
- {
- return (int)epromptlen;
- }
- #endif
-
- char *Gets(char *promptstr, char *sline, size_t size)
- {
- char *cp, ch;
- string plines;
- #ifdef GETLINE
- int ismainprompt = (promptstr == prompt2);
- #endif
-
- if (!fromatty || !toatty) {
- /* Don't worry about a cmdline/history editor if you redirected a
- * file at me.
- */
- if (!toatty && fromatty) {
- /* It's okay to print a prompt if we are redirecting stdout,
- * as long as stdin is still a tty. Otherwise, don't print
- * a prompt at all if stdin is redirected.
- */
- #ifdef CURSES
- tcap_put(promptstr);
- #else
- (void) fputs(promptstr, stdout);
- #endif
- }
- cp = fgets(sline, (int)size, stdin);
- (void) RemoveTrailingNewline(cp, NULL);
- return cp;
- }
-
- /*
- * The prompt string may actually be several lines if the user put a
- * newline in it with the @N option. In this case we only want to print
- * the very last line, so the command-line editors won't screw up. So
- * now we print all the lines except the last line.
- */
- cp = rindex(promptstr, '\n');
- if (cp != NULL) {
- ch = *++cp;
- *cp = 0;
- (void) Strncpy(plines, promptstr);
- *cp = ch;
- promptstr = cp;
- #ifdef CURSES
- tcap_put(plines);
- #else
- (void) fputs(plines, stdout);
- #endif
- }
-
- #ifdef READLINE
- if ((cp = readline(promptstr)) != NULL) {
- (void) _Strncpy(sline, cp, size);
- free(cp);
- (void) RemoveTrailingNewline(cp = sline, NULL);
- add_history(cp);
- }
- #else /* READLINE */
-
- #ifdef GETLINE
- if (toatty) {
- if (ismainprompt)
- gl_strwidth(MainPromptLen);
- if ((cp = getline(promptstr)) != NULL) {
- (void) _Strncpy(sline, cp, size);
- if (!*cp) {
- cp = NULL;
- } else {
- gl_histadd(cp);
- cp = sline;
- }
- }
- gl_strwidth((int (*)(char *)) strlen);
- } else {
- #ifdef CURSES
- tcap_put(promptstr);
- #else
- (void) fputs(promptstr, stdout);
- #endif
- cp = fgets(sline, (int) (size - 1), stdin);
- }
- (void) RemoveTrailingNewline(cp, NULL);
- #else /* !GETLINE */
-
- #ifdef CURSES
- tcap_put(promptstr);
- #else
- (void) fputs(promptstr, stdout);
- #endif
-
- cp = fgets(sline, (int) (size - 1), stdin);
- (void) RemoveTrailingNewline(cp, NULL);
- #endif /* !GETLINE */
- #endif /* !READLINE */
- return cp;
- } /* Gets */
-
-
-
-
- char **re_makeargv(char *promptstr, int *argc)
- {
- size_t sz;
-
- (void) strcat(line, " ");
- sz = strlen(line);
- (void) Gets(promptstr, &line[sz], (size_t) (CMDLINELEN - sz)) ;
- (void) makeargv();
- *argc = margc;
- return (margv);
- } /* re_makeargv */
-
-
-
-
- char *get_cwd(char *buf, int size)
- {
- #ifdef SYSV
- # ifdef NO_UNISTDH
- # ifdef GETCWDSIZET
- extern char *getcwd(char *, size_t);
- # else
- extern char *getcwd(char *, int);
- # endif
- # endif
- return (getcwd(buf, size - 1));
- #else
- extern char *getwd(char *);
- return (getwd(buf));
- #endif
- } /* get_cwd */
-
-
-
- int tmp_name(char *str)
- {
- (void) strcpy(str, "/tmp/ncftpXXXXXX");
- return (!mktemp(str));
- } /* tmp_name */
-
-
-
-
- char *onoff(int boolf)
- {
- return (boolf ? "on" : "off");
- } /* onoff */
-
-
-
-
- int StrToBool(char *s)
- {
- int c;
- int result;
-
- c = tolower(*s);
- result = 0;
- switch (c) {
- case 'f': /* false */
- case 'n': /* no */
- break;
- case 'o': /* test for "off" and "on" */
- c = tolower(s[1]);
- if (c == 'f')
- break;
- /* fall through */
- case 't': /* true */
- case 'y': /* yes */
- result = 1;
- break;
- default: /* 1, 0, -1, other number? */
- if (atoi(s) != 0)
- result = 1;
- }
- return result;
- } /* StrToBool */
-
-
-
-
- int confirm(char *cmd, char *file)
- {
- str32 str, pr;
-
- if (!fromatty || (activemcmd && !mprompt))
- return 1;
- (void) sprintf(pr, "%s %s? ", cmd, file);
- (void) Gets(pr, str, sizeof(str));
- return (*str != 'n' && *str != 'N');
- } /* confirm */
-
-
-
- void fatal(char *msg)
- {
- (void) fprintf(stderr, "%s: %s\n", progname, msg);
- close_up_shop();
- exit(1);
- } /* fatal */
-
-
-
-
- int UserLoggedIn(void)
- {
- static int inited = 0;
- static int parent_pid, stderr_was_tty;
-
- if (!inited) {
- stderr_was_tty = isatty(2);
- parent_pid = getppid();
- inited++;
- }
- if ((stderr_was_tty && !isatty(2)) || (getppid() != parent_pid))
- return 0;
- return 1;
- } /* UserLoggedIn */
-
-
-
-
- struct cmd *getcmd(char *name)
- {
- struct cmd *c, *found;
- int nmatches;
- size_t len;
- char *p;
-
- found = (struct cmd *)0;
- if (name != NULL) {
- len = strlen(name);
- nmatches = 0;
- for (c = cmdtab; (p = c->c_name) != NULL; c++) {
- if (strcmp(name, p) == 0) {
- /* Exact match. */
- found = c;
- goto xx;
- }
- if (c->c_handler == unimpl)
- continue;
- if (strncmp(name, p, len) == 0) {
- if (++nmatches > 1) {
- found = ((struct cmd *) -1);
- goto xx;
- }
- found = c;
- } else if (found != NULL)
- break;
- }
- }
- xx:
- return (found);
- } /* getcmd */
-
-
-
-
- void cmd_help(struct cmd *c)
- {
- (void) printf("%s: %s.\n",
- c->c_name,
- c->c_help
- );
- } /* cmd_help */
-
-
-
-
- void cmd_usage(struct cmd *c)
- {
- if (c->c_usage != NULL)
- (void) printf("Usage: %s%s\n",
- c->c_name,
- c->c_usage
- );
- } /* cmd_usage */
-
-
-
-
- char *GetHomeDir(char *home)
- {
- struct passwd *pw;
- pw = getpwuid(getuid());
- return (strcpy(home, pw->pw_dir));
- } /* GetHomeDir */
-
-
-
-
- /*
- * A simple function that translates most pathnames with ~, ~user, or
- * environment variables as the first item. It won't do paths with env vars
- * or ~s in the middle of the path, but those are extremely rare.
- */
- char *LocalPath(char *path)
- {
- longstring orig;
- struct passwd *pw;
- char *firstent = NULL;
- char *cp, *dp, *rest;
-
- (void) Strncpy(orig, path);
- if (((cp = index(orig, '/')) != NULL) && (cp != orig)) {
- *cp = 0;
- rest = cp + 1;
- if (orig[0] == '~') {
- if (orig[1] == 0) {
- pw = getpwuid(getuid());
- } else {
- pw = getpwnam(orig + 1);
- }
- if (pw != NULL)
- firstent = pw->pw_dir;
- } else if (orig[0] == '$') {
- cp = orig + 1;
- dp = orig + strlen(orig) - 1;
- if ((*cp == '(' && *dp == ')') || (*cp == '{' && *dp == '}')) {
- cp++;
- *dp = 0;
- }
- firstent = getenv(cp);
- }
- if (firstent != NULL)
- (void) sprintf(path, "%s/%s", firstent, rest);
- }
- return (path);
- } /* LocalPath */
-
-
-
- /*
- * A special case, where invisible dot-files that would normally appear in
- * your home directory will appear instead as visible files in your $DOTDIR
- * directory if you have one.
- */
-
- #define LCMP(b) (strncmp(path, (b), (o = sizeof(b) - 1)) == 0)
-
- char *LocalDotPath(char *path)
- {
- size_t o;
- longstring s, s2, h;
- char *cp = getenv("DOTDIR");
-
- if (cp == NULL) {
- goto aa;
- } else {
- if (*cp != '/' && *cp != '~') {
- /* then maybe they mean relative to $HOME. */
- (void) sprintf(s2, "%s/%s", GetHomeDir(h), cp);
- cp = s2;
- }
- if (LCMP("~/.") ||
- LCMP("$HOME/.") ||
- LCMP("$home/.") ||
- LCMP("$(HOME)/.") ||
- LCMP("${HOME}/.")
- ) {
- (void) Strncpy(s, path);
- (void) sprintf(path, "%s/%s", cp, s + o);
- cp = path;
- } else {
- aa: cp = LocalPath(path);
- }
- }
- return cp;
- } /* LocalDotPath */
-
- /* eof Util.c */
-