home *** CD-ROM | disk | FTP | other *** search
- /* Util.c */
-
- #include "Sys.h"
-
- #ifdef HAVE_GETCWD
- # ifndef HAVE_UNISTD_H
- extern char *getcwd();
- # endif
- #else
- # ifdef HAVE_GETWD
- # include <sys/param.h>
- # ifndef MAXPATHLEN
- # define MAXPATHLEN 1024
- # endif
- extern char *getwd(char *);
- # endif
- #endif
-
- #include <errno.h>
- #include <ctype.h>
-
- #ifdef HAVE_LIMITS_H
- # include <limits.h>
- #endif
-
- #include "Util.h"
- #include "Main.h"
- #include "Bookmark.h"
- #include "Curses.h"
-
- time_t gMailBoxTime; /* last modified time of mbox */
- int gWarnShellBug = 0;
- int gMarkTrailingSpace = 0;
-
- extern int gLoggedIn, gWinInit;
- extern string gOurDirectoryPath;
- extern longstring gRemoteCWD;
- extern string gActualHostName;
- extern long gEventNumber;
- extern string gHost;
- extern Bookmark gRmtInfo;
- extern UserInfo gUserInfo;
-
- /* Read a line, and axe the end-of-line. */
- char *FGets(char *str, size_t size, FILE *fp)
- {
- char *cp, *nlptr;
-
- cp = fgets(str, ((int) size) - 1, fp);
- if (cp != NULL) {
- nlptr = cp + strlen(cp) - 1;
- if (*nlptr == '\n')
- *nlptr = '\0';
- }
- return cp;
- } /* FGets */
-
-
-
-
- /* This should only be called if the program wouldn't function
- * usefully without the memory requested.
- */
- void OutOfMemory(void)
- {
- fprintf(stderr, "Out of memory!\n");
- Exit(kExitOutOfMemory);
- } /* OutOfMemory */
-
-
-
- /* A way to strcat to a dynamically allocated area of memory. */
- char *PtrCat(char *dst, char *src)
- {
- size_t len;
-
- len = strlen(dst) + strlen(src) + 1;
- if ((dst = Realloc(dst, len)) == NULL)
- return (NULL);
- strcat(dst, src);
- return (dst);
- } /* PtrCat */
-
-
-
- /* Extends an area of memory, then cats a '/' and a string afterward. */
- char *PtrCatSlash(char *dst, char *src)
- {
- size_t dlen;
- char *nu;
-
- while (*src == '/')
- ++src;
-
- dlen = strlen(dst);
- if (dst[dlen - 1] != '/') {
- dst = PtrCat(dst, "/");
- if (dst == NULL)
- nu = NULL;
- else
- nu = PtrCat(dst, src);
- } else {
- nu = PtrCat(dst, src);
- }
- return (nu);
- } /* PtrCatSlash */
-
-
-
- void *Realloc(void *ptr, size_t siz)
- {
- if (ptr == NULL)
- return (void *) malloc(siz);
- return ((void *) realloc(ptr, siz));
- } /* Realloc */
-
-
-
-
-
- void MakeStringPrintable(char *dst, unsigned char *src, size_t siz)
- {
- int c;
- size_t i;
- int endnl, numsp;
-
- i = 0;
- --siz; /* Leave room for nul. */
- while ((i < siz) && (*src != '\0')) {
- c = *src++;
- if (isprint(c) || (c == '\n') || (c == '\t')
- /* Needed to view chinese... */
- || (c & 0x80) || (c == 0x1b))
- {
- *dst++ = c;
- ++i;
- } else if (iscntrl(c) && (c != 0x7f)) {
- /* Need room for 2 characters, ^x. */
- if (i < siz - 1) {
- c = c + '@';
- *dst++ = '^';
- *dst++ = c;
- i += 2;
- }
- } else {
- /* Need room for 5 characters, \xxx.
- * The fifth character will be the \0 that is written by
- * sprintf, but we know we have room for that already since
- * we already accounted for that above.
- */
- if (i < siz - 3) {
- sprintf(dst, "\\%03o", c);
- i += 4;
- dst += 4;
- }
- }
- }
- *dst-- = '\0';
-
- /* See if this line ended with a \n. */
- endnl = 0;
- if (i > 0 && *dst == '\n') {
- endnl = 1;
- --i;
- --dst;
- }
-
- /* The user may want to be aware if there are trailing spaces
- * at the end of a line.
- */
- numsp = 0;
- while (i > 0) {
- c = *dst;
- if (c != ' ')
- break;
- numsp++;
- --i;
- --dst;
- }
-
- /* Mark trailing spaces as \x where x is a space. */
- ++dst;
-
- if (gMarkTrailingSpace) {
- while ((numsp > 0) && (i < siz)) {
- *dst++ = '\\';
- *dst++ = ' ';
- i += 2;
- --numsp;
- }
- }
-
- /* Tack the newline back onto the end of the string, if needed. */
- if (endnl)
- *dst++ = '\n';
-
- *dst = '\0';
- } /* MakeStringPrintable */
-
-
-
-
- /* This will abbreviate a string so that it fits into max characters.
- * It will use ellipses as appropriate. Make sure the string has
- * at least max + 1 characters allocated for it.
- */
- void AbbrevStr(char *dst, char *src, size_t max, int mode)
- {
- int len;
-
- len = (int) strlen(src);
- if (len > (int) max) {
- if (mode == 0) {
- /* ...Put ellipses at left */
- strcpy(dst, "...");
- Strncat(dst, src + len - (int) max + 3, max + 1);
- } else {
- /* Put ellipses at right... */
- Strncpy(dst, src, max + 1);
- strcpy(dst + max - 3, "...");
- }
- } else {
- Strncpy(dst, src, max + 1);
- }
- } /* AbbrevStr */
-
-
-
-
-
- /* Converts any uppercase characters in the string to lowercase.
- * Never would have guessed that, huh?
- */
- void StrLCase(char *dst)
- {
- register char *cp;
-
- for (cp=dst; *cp != '\0'; cp++)
- if (isupper((int) *cp))
- *cp = (char) tolower(*cp);
- } /* StrLCase */
-
-
-
-
- /* Use getcwd/getwd to get the full path of the current local
- * working directory.
- */
- char *GetCWD(char *buf, size_t size)
- {
- #ifdef HAVE_GETCWD
- static char *cwdBuf = NULL;
- static size_t cwdBufSize = 0;
-
- if (cwdBufSize == 0) {
- cwdBufSize = (size_t) 128;
- cwdBuf = (char *) malloc(cwdBufSize);
- }
-
- for (errno = 0; ; ) {
- if (cwdBuf == NULL) {
- Error(kDoPerror, "Not enough free memory to get the local working directory path.\n");
- (void) Strncpy(buf, ".", size);
- return NULL;
- }
-
- if (getcwd(cwdBuf, cwdBufSize) != NULL)
- break;
- if (errno != ERANGE) {
- Error(kDoPerror, "Can't get the local working directory path.\n");
- (void) Strncpy(buf, ".", size);
- return NULL;
- }
- cwdBufSize *= 2;
- cwdBuf = Realloc(cwdBuf, cwdBufSize);
- }
-
- return (Strncpy(buf, cwdBuf, size));
- #else
- #ifdef HAVE_GETWD
- static char *cwdBuf = NULL;
- char *dp;
-
- /* Due to the way getwd is usually implemented, it's
- * important to have a buffer large enough to hold the
- * whole thing. getwd usually starts at the end of the
- * buffer, and works backwards, returning you a pointer
- * to the beginning of it when it finishes.
- */
- if (size < MAXPATHLEN) {
- /* Buffer not big enough, so use a temporary one,
- * and then copy the first 'size' bytes of the
- * temporary buffer to your 'buf.'
- */
- if (cwdBuf == NULL) {
- cwdBuf = (char *) malloc((size_t) MAXPATHLEN);
- if (cwdBuf == NULL)
- OutOfMemory();
- }
- dp = cwdBuf;
- } else {
- /* Buffer is big enough already. */
- dp = buf;
- }
- *dp = '\0';
- if (getwd(dp) == NULL) {
- /* getwd() should write the reason why in the buffer then,
- * according to the man pages.
- */
- Error(kDontPerror, "Can't get the local working directory path. %s\n", dp);
- (void) Strncpy(buf, ".", size);
- return (NULL);
- }
- return (Strncpy(buf, dp, size));
-
- #else
- /* Not really a solution, but does anybody not have either of
- * getcwd or getwd?
- */
- Error(kDontPerror, "Can't get the cwd path; no getwd() or getcwd().\n");
- return (Strncpy(buf, ".", size));
- #endif
- #endif
- } /* GetCWD */
-
-
-
-
- char *Path(char *dst, size_t siz, char *parent, char *fname)
- {
- (void) Strncpy(dst, parent, siz);
- (void) Strncat(dst, "/", siz);
- return (Strncat(dst, fname, siz));
- } /* Path */
-
-
-
-
- char *OurDirectoryPath(char *dst, size_t siz, char *fname)
- {
- return (Path(dst, siz, gOurDirectoryPath, fname));
- } /* OurDirectoryPath */
-
-
-
-
- int MkDirs(char *path)
- {
- longstring mdCmd;
- int result;
-
- result = 0;
- if (access(path, F_OK) < 0) {
- STRNCPY(mdCmd, "mkdir -p "); /* -p is nice, but not mandatory. */
- STRNCAT(mdCmd, path);
- result = system(mdCmd);
- }
- return (result);
- } /* MkDirs */
-
-
-
-
- /* Closes the file supplied, if it isn't a std stream. */
- int CloseFile(FILE **f)
- {
- if (*f != NULL) {
- if ((*f != stdout) && (*f != stdin) && (*f != stderr)) {
- (void) fclose(*f);
- *f = NULL;
- return (1);
- }
- *f = NULL;
- }
- return (0);
- } /* CloseFile */
-
-
-
-
- /* Returns non-zero if we are the foreground process, or 0
- * if we are a background process at the time of the call.
- */
- int InForeGround(void)
- {
- #if defined(NO_FGTEST) || !defined(HAVE_TCGETPGRP)
- return (1);
- #else
- # ifndef GETPGRP_VOID
- # define GETMYPGRP (getpgrp(getpid()))
- # else
- # define GETMYPGRP (getpgrp())
- # endif
- int result, status;
- static int file = -2;
- static int mode = -2;
-
- result = 1;
- if (file == -2)
- file = open("/dev/tty", O_RDONLY);
-
- if (file >= 0) {
- status = tcgetpgrp(file);
- if (status >= 0) {
- result = (status == GETMYPGRP);
- if (mode != result) {
- if (mode == 0) {
- TraceMsg("In background.\n");
- } else
- TraceMsg("In foreground.\n");
- }
- mode = result;
- } else if (mode == -2) {
- TraceMsg("Foreground check failed.\n");
- mode = 0;
- }
- }
- return (result);
- #endif
- } /* InForeGround */
-
-
-
-
- /* Returns non-zero if it appears the user is still live at the
- * terminal.
- */
- 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 */
-
-
-
-
- int CheckNewMail(void)
- {
- struct stat stbuf;
-
- if (*gUserInfo.mail == '\0')
- return 0;
-
- if (stat(gUserInfo.mail, &stbuf) < 0) {
- /* Can't find mail_path so we'll never check it again */
- *gUserInfo.mail = '\0';
- return 0;
- }
-
- /*
- * Check if the size is non-zero and the access time is less than
- * the modify time -- this indicates unread mail.
- */
- if ((stbuf.st_size != 0) && (stbuf.st_atime <= stbuf.st_mtime)) {
- if (stbuf.st_mtime > gMailBoxTime) {
- (void) PrintF("You have new mail.\n");
- gMailBoxTime = stbuf.st_mtime;
- }
- return 1;
- }
-
- return 0;
- } /* CheckNewMail */
-
-
-
-
-
- size_t FlagStrCopy(char *dst, size_t siz, char *src)
- {
- time_t now;
- register char *p, *q;
- int flagType;
- int chType;
- int nextCh;
- int nPercents;
- int extraChar;
- size_t maxSize;
- size_t onScreenLen;
- size_t len;
- string tmpStr;
- char *copy;
-
- nPercents = 0;
- onScreenLen = 0;
- extraChar = 0;
- siz -= 2; /* Need room for nul, and extra char. */
- maxSize = siz;
-
- for (p = src, q = dst, *q = 0; *p != '\0'; p++) {
- chType = *p;
- switch (chType) {
- case '%':
- nPercents++;
- goto copyChar;
- case '@':
- flagType = *++p;
- nextCh = p[1];
- switch (flagType) {
- case '\0':
- goto done;
- break;
- case 'Z':
- /* Tell caller not to echo a final newline. */
- extraChar = '@';
- break;
- case 'M':
- if (CheckNewMail() > 0) {
- copy = "(Mail)";
- goto copyVisStr;
- }
- goto copyNothing;
-
- case 'n':
- if (gLoggedIn) {
- copy = gRmtInfo.bookmarkName;
- goto copyVisStr;
- }
- goto copyNothing;
-
- case 'N':
- copy = "\n";
- goto copyVisStr;
- break;
-
- /* Probably won't implement these. */
- case 'P': /* reset to no bold, no uline, no inverse, etc. */
- /* copy = "plain...";
- goto copyInvisStr; */
- break;
- case 'B': /* toggle boldface */
- break;
- case 'U': /* toggle underline */
- break;
- case 'R':
- case 'I': /* toggle inverse (reverse) video */
- break;
-
- case 'D': /* insert current directory */
- case 'J':
- if (gLoggedIn) {
- if ((flagType == 'J') && (gRmtInfo.isUnix)) {
- /* Not the whole path, just the dir name. */
- copy = strrchr(gRemoteCWD, '/');
- if (copy == NULL)
- copy = gRemoteCWD;
- else if ((copy != gRemoteCWD) && (copy[1]))
- ++copy;
- } else {
- copy = gRemoteCWD;
- }
- goto copyVisStr;
- }
- goto copyNothing;
-
- case 'H': /* insert name of connected host */
- if (gLoggedIn) {
- copy = gHost;
- goto copyVisStr;
- }
- goto copyNothing;
-
- case 'h': /* insert actual name of connected host */
- if (gLoggedIn) {
- copy = gActualHostName;
- goto copyVisStr;
- }
- goto copyNothing;
-
- case '!':
- case 'E': /* insert event number */
- (void) sprintf(tmpStr, "%ld", gEventNumber);
- copy = tmpStr;
- /*FALLTHROUGH*/
-
- copyVisStr:
- len = strlen(copy);
- if (siz > len) {
- q = strcpy(q, copy) + len;
- siz -= len;
- if (q[-1] == '\n') {
- onScreenLen = 0;
- } else
- onScreenLen += len;
- }
- break;
-
- copyNothing:
- if (isspace(nextCh) || (nextCh == ':'))
- ++p; /* Don't insert next character. */
- break;
-
- default:
- goto copyChar; /* just copy it; unknown switch */
- } /* end flagType */
- break;
-
- default:
- copyChar:
- if (siz > 0) {
- *q++ = *p;
- --siz;
- ++onScreenLen;
- }
- break;
- }
- }
-
- done:
- *q = '\0';
-
- #ifdef HAVE_STRFTIME
- if ((nPercents > 0) && ((copy = StrDup(dst)) != NULL)) {
- /* Only strftime if the user requested it (with a %something). */
- (void) time(&now);
- len = strlen(dst);
- onScreenLen += strftime(dst, maxSize, copy, localtime(&now));
- onScreenLen -= len;
- free(copy);
- }
- #endif
- if (extraChar != 0)
- dst[strlen(dst) + 1] = extraChar;
- return (onScreenLen);
- } /* FlagStrCopy */
-
-
-
-
- void OverflowAdd(long *dst, long plus)
- {
- #ifdef LONG_MAX
- long x;
-
- x = LONG_MAX - *dst;
- if (x < plus)
- *dst = LONG_MAX; /* Would overflow! */
- else
- *dst += plus;
- #else
- *dst += plus;
- #endif
- } /* OverflowAdd */
-
-
-
-
- FILE *POpen(char *cmd, char *mode, int saveScreen)
- {
- FILE *fp;
-
- #if 1
- if ((++gWarnShellBug <= 2) && (gWinInit == 1) && (*mode == 'w') && (CURSES_SHELL_BUG == 1)) {
- EPrintF("Sorry, that operation would crash the program with this OS.\n");
- errno = 0;
- return (NULL);
- }
- #else
- if (++gWarnShellBug == 1) {
- EPrintF("Warning: the screen may not update correctly on this OS.\n\n");
- sleep(2);
- }
- #endif
- if (saveScreen == 1)
- SaveScreen();
- fp = popen(cmd, mode);
- return fp;
- } /* POpen */
-
-
-
-
- #ifndef HAVE_MEMMOVE
- /* This code is derived from software contributed to Berkeley by
- * Chris Torek.
- */
-
- /*
- * sizeof(word) MUST BE A POWER OF TWO
- * SO THAT wmask BELOW IS ALL ONES
- */
- typedef int word; /* "word" used for optimal copy speed */
-
- #define wsize sizeof(word)
- #define wmask (wsize - 1)
-
- /*
- * Copy a block of memory, handling overlap.
- * This is the routine that actually implements
- * (the portable versions of) bcopy, memcpy, and memmove.
- */
- void *
- MemMove(void *dst0, void *src0, size_t length)
- {
- register char *dst = (char *) dst0;
- register const char *src = (char *) src0;
- register size_t t;
-
- if (length == 0 || dst == src) /* nothing to do */
- return dst;
-
- /*
- * Macros: loop-t-times; and loop-t-times, t>0
- */
- #define TLOOP(s) if (t) TLOOP1(s)
- #define TLOOP1(s) do { s; } while (--t)
-
- if ((unsigned long)dst < (unsigned long)src) {
- /*
- * Copy forward.
- */
- t = (int)src; /* only need low bits */
- if ((t | (int)dst) & wmask) {
- /*
- * Try to align operands. This cannot be done
- * unless the low bits match.
- */
- if ((t ^ (int)dst) & wmask || length < wsize)
- t = length;
- else
- t = wsize - (t & wmask);
- length -= t;
- TLOOP1(*dst++ = *src++);
- }
- /*
- * Copy whole words, then mop up any trailing bytes.
- */
- t = length / wsize;
- TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
- t = length & wmask;
- TLOOP(*dst++ = *src++);
- } else {
- /*
- * Copy backwards. Otherwise essentially the same.
- * Alignment works as before, except that it takes
- * (t&wmask) bytes to align, not wsize-(t&wmask).
- */
- src += length;
- dst += length;
- t = (int)src;
- if ((t | (int)dst) & wmask) {
- if ((t ^ (int)dst) & wmask || length <= wsize)
- t = length;
- else
- t &= wmask;
- length -= t;
- TLOOP1(*--dst = *--src);
- }
- t = length / wsize;
- TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
- t = length & wmask;
- TLOOP(*--dst = *--src);
- }
-
- return(dst0);
- } /* MemMove */
- #endif /* ! HAVE_MEMMOVE */
-
- /* eof */
-