📄 util.c
字号:
(void) putc('.', TrafficLogFile); } fputs(l, mci->mci_out); (void) putc('!', mci->mci_out); fputs(mci->mci_mailer->m_eol, mci->mci_out); (void) putc(' ', mci->mci_out); if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%s!\n%05d >>> ", l, getpid()); *q = svchar; l = q; slop = 1; } /* output last part */ if (l[0] == '.' && slop == 0 && bitnset(M_XDOT, mci->mci_mailer->m_flags)) { (void) putc('.', mci->mci_out); if (TrafficLogFile != NULL) (void) putc('.', TrafficLogFile); } if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%.*s\n", p - l, l); for ( ; l < p; ++l) (void) putc(*l, mci->mci_out); fputs(mci->mci_mailer->m_eol, mci->mci_out); if (*l == '\n') ++l; } while (l[0] != '\0');}/*** XUNLINK -- unlink a file, doing logging as appropriate.**** Parameters:** f -- name of file to unlink.**** Returns:** none.**** Side Effects:** f is unlinked.*/xunlink(f) char *f;{ register int i;# ifdef LOG if (LogLevel > 98) syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f);# endif /* LOG */ i = unlink(f);# ifdef LOG if (i < 0 && LogLevel > 97) syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);# endif /* LOG */}/*** XFCLOSE -- close a file, doing logging as appropriate.**** Parameters:** fp -- file pointer for the file to close** a, b -- miscellaneous crud to print for debugging**** Returns:** none.**** Side Effects:** fp is closed.*/xfclose(fp, a, b) FILE *fp; char *a, *b;{ if (tTd(53, 99)) printf("xfclose(%x) %s %s\n", fp, a, b);#ifdef XDEBUG if (fileno(fp) == 1) syserr("xfclose(%s %s): fd = 1", a, b);#endif if (fclose(fp) < 0 && tTd(53, 99)) printf("xfclose FAILURE: %s\n", errstring(errno));}/*** SFGETS -- "safe" fgets -- times out and ignores random interrupts.**** Parameters:** buf -- place to put the input line.** siz -- size of buf.** fp -- file to read from.** timeout -- the timeout before error occurs.** during -- what we are trying to read (for error messages).**** Returns:** NULL on error (including timeout). This will also leave** buf containing a null string.** buf otherwise.**** Side Effects:** none.*/static jmp_buf CtxReadTimeout;static int readtimeout();static EVENT *GlobalTimeout = NULL;static bool EnableTimeout = FALSE;static int ReadProgress;char *sfgets(buf, siz, fp, timeout, during) char *buf; int siz; FILE *fp; time_t timeout; char *during;{ register EVENT *ev = NULL; register char *p; if (fp == NULL) { buf[0] = '\0'; return NULL; } /* set the timeout */ if (timeout != 0) { if (setjmp(CtxReadTimeout) != 0) {# ifdef LOG syslog(LOG_NOTICE, "timeout waiting for input from %s during %s\n", CurHostName? CurHostName: "local", during);# endif errno = 0; usrerr("451 timeout waiting for input during %s", during); buf[0] = '\0';#ifdef XDEBUG checkfd012(during);#endif return (NULL); } if (GlobalTimeout == NULL) ev = setevent(timeout, readtimeout, 0); else EnableTimeout = TRUE; } /* try to read */ p = NULL; while (!feof(fp) && !ferror(fp)) { errno = 0; p = fgets(buf, siz, fp); if (p != NULL || errno != EINTR) break; clearerr(fp); } /* clear the event if it has not sprung */ if (GlobalTimeout == NULL) clrevent(ev); else EnableTimeout = FALSE; /* clean up the books and exit */ LineNumber++; if (p == NULL) { buf[0] = '\0'; if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%05d <<< [EOF]\n", getpid()); return (NULL); } if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%05d <<< %s", getpid(), buf); if (SevenBit) for (p = buf; *p != '\0'; p++) *p &= ~0200; return (buf);}voidsfgetset(timeout) time_t timeout;{ /* cancel pending timer */ if (GlobalTimeout != NULL) { clrevent(GlobalTimeout); GlobalTimeout = NULL; } /* schedule fresh one if so requested */ if (timeout != 0) { ReadProgress = LineNumber; GlobalTimeout = setevent(timeout, readtimeout, timeout); }}staticreadtimeout(timeout) time_t timeout;{ /* terminate if ordinary timeout */ if (GlobalTimeout == NULL) longjmp(CtxReadTimeout, 1); /* terminate if no progress was made -- reset state */ if (EnableTimeout && (LineNumber <= ReadProgress)) { EnableTimeout = FALSE; GlobalTimeout = NULL; longjmp(CtxReadTimeout, 2); } /* schedule a new timeout */ GlobalTimeout = NULL; sfgetset(timeout);}/*** FGETFOLDED -- like fgets, but know about folded lines.**** Parameters:** buf -- place to put result.** n -- bytes available.** f -- file to read from.**** Returns:** input line(s) on success, NULL on error or EOF.** This will normally be buf -- unless the line is too** long, when it will be xalloc()ed.**** Side Effects:** buf gets lines from f, with continuation lines (lines** with leading white space) appended. CRLF's are mapped** into single newlines. Any trailing NL is stripped.*/char *fgetfolded(buf, n, f) char *buf; register int n; FILE *f;{ register char *p = buf; char *bp = buf; register int i; n--; while ((i = getc(f)) != EOF) { if (i == '\r') { i = getc(f); if (i != '\n') { if (i != EOF) (void) ungetc(i, f); i = '\r'; } } if (--n <= 0) { /* allocate new space */ char *nbp; int nn; nn = (p - bp); if (nn < MEMCHUNKSIZE) nn *= 2; else nn += MEMCHUNKSIZE; nbp = xalloc(nn); bcopy(bp, nbp, p - bp); p = &nbp[p - bp]; if (bp != buf) free(bp); bp = nbp; n = nn - (p - bp); } *p++ = i; if (i == '\n') { LineNumber++; i = getc(f); if (i != EOF) (void) ungetc(i, f); if (i != ' ' && i != '\t') break; } } if (p == bp) return (NULL); *--p = '\0'; return (bp);}/*** CURTIME -- return current time.**** Parameters:** none.**** Returns:** the current time.**** Side Effects:** none.*/time_tcurtime(){ auto time_t t; (void) time(&t); return (t);}/*** ATOBOOL -- convert a string representation to boolean.**** Defaults to "TRUE"**** Parameters:** s -- string to convert. Takes "tTyY" as true,** others as false.**** Returns:** A boolean representation of the string.**** Side Effects:** none.*/boolatobool(s) register char *s;{ if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) return (TRUE); return (FALSE);}/*** ATOOCT -- convert a string representation to octal.**** Parameters:** s -- string to convert.**** Returns:** An integer representing the string interpreted as an** octal number.**** Side Effects:** none.*/atooct(s) register char *s;{ register int i = 0; while (*s >= '0' && *s <= '7') i = (i << 3) | (*s++ - '0'); return (i);}/*** WAITFOR -- wait for a particular process id.**** Parameters:** pid -- process id to wait for.**** Returns:** status of pid.** -1 if pid never shows up.**** Side Effects:** none.*/intwaitfor(pid) int pid;{#ifdef WAITUNION union wait st;#else auto int st;#endif int i; do { errno = 0; i = wait(&st); } while ((i >= 0 || errno == EINTR) && i != pid); if (i < 0) return -1;#ifdef WAITUNION return st.w_status;#else return st;#endif}/*** BITINTERSECT -- tell if two bitmaps intersect**** Parameters:** a, b -- the bitmaps in question**** Returns:** TRUE if they have a non-null intersection** FALSE otherwise**** Side Effects:** none.*/boolbitintersect(a, b) BITMAP a; BITMAP b;{ int i; for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) if ((a[i] & b[i]) != 0) return (TRUE); return (FALSE);}/*** BITZEROP -- tell if a bitmap is all zero**** Parameters:** map -- the bit map to check**** Returns:** TRUE if map is all zero.** FALSE if there are any bits set in map.**** Side Effects:** none.*/boolbitzerop(map) BITMAP map;{ int i; for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) if (map[i] != 0) return (FALSE); return (TRUE);}/*** STRCONTAINEDIN -- tell if one string is contained in another**** Parameters:** a -- possible substring.** b -- possible superstring.**** Returns:** TRUE if a is contained in b.** FALSE otherwise.*/boolstrcontainedin(a, b) register char *a; register char *b;{ int la; int lb; int c; la = strlen(a); lb = strlen(b); c = *a; if (isascii(c) && isupper(c)) c = tolower(c); for (; lb-- >= la; b++) { if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c) continue; if (strncasecmp(a, b, la) == 0) return TRUE; } return FALSE;}/*** CHECKFD012 -- check low numbered file descriptors**** File descriptors 0, 1, and 2 should be open at all times.** This routine verifies that, and fixes it if not true.**** Parameters:** where -- a tag printed if the assertion failed**** Returns:** none*/checkfd012(where) char *where;{#ifdef XDEBUG register int i; struct stat stbuf; for (i = 0; i < 3; i++) { if (fstat(i, &stbuf) < 0 && errno != EOPNOTSUPP) { /* oops.... */ int fd; syserr("%s: fd %d not open", where, i); fd = open("/dev/null", i == 0 ? O_RDONLY : O_WRONLY, 0666); if (fd != i) { (void) dup2(fd, i); (void) close(fd); } } }#endif /* XDEBUG */}/*** PRINTOPENFDS -- print the open file descriptors (for debugging)**** Parameters:** logit -- if set, send output to syslog; otherwise** print for debugging.**** Returns:** none.*/#include <netdb.h>#include <arpa/inet.h>printopenfds(logit) bool logit;{ register int fd; extern int DtableSize; for (fd = 0; fd < DtableSize; fd++) dumpfd(fd, FALSE, logit);}/*** DUMPFD -- dump a file descriptor**** Parameters:** fd -- the file descriptor to dump.** printclosed -- if set, print a notification even if** it is closed; otherwise print nothing.** logit -- if set, send output to syslog instead of stdout.*/dumpfd(fd, printclosed, logit) int fd; bool printclosed; bool logit;{ register struct hostent *hp; register char *p; char *fmtstr; struct sockaddr_in sin; auto int slen; struct stat st; char buf[200]; p = buf; sprintf(p, "%3d: ", fd); p += strlen(p); if (fstat(fd, &st) < 0) { if (printclosed || errno != EBADF) { sprintf(p, "CANNOT STAT (%s)", errstring(errno)); goto printit; } return; } slen = fcntl(fd, F_GETFL, NULL); if (slen != -1) { sprintf(p, "fl=0x%x, ", slen); p += strlen(p); } sprintf(p, "mode=%o: ", st.st_mode); p += strlen(p); switch (st.st_mode & S_IFMT) {#ifdef S_IFSOCK case S_IFSOCK: sprintf(p, "SOCK "); p += strlen(p); slen = sizeof sin; if (getsockname(fd, (struct sockaddr *) &sin, &slen) < 0) sprintf(p, "(badsock)"); else { hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET); sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr) : hp->h_name, ntohs(sin.sin_port)); } p += strlen(p); sprintf(p, "->"); p += strlen(p); slen = sizeof sin; if (getpeername(fd, (struct sockaddr *) &sin, &slen) < 0) sprintf(p, "(badsock)"); else { hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET); sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr) : hp->h_name, ntohs(sin.sin_port)); } break;#endif case S_IFCHR: sprintf(p, "CHR: "); p += strlen(p); goto defprint; case S_IFBLK: sprintf(p, "BLK: "); p += strlen(p); goto defprint;#if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) case S_IFIFO: sprintf(p, "FIFO: "); p += strlen(p); goto defprint;#endif#ifdef S_IFDIR case S_IFDIR: sprintf(p, "DIR: "); p += strlen(p); goto defprint;#endif#ifdef S_IFLNK case S_IFLNK: sprintf(p, "LNK: "); p += strlen(p); goto defprint;#endif default:defprint: if (sizeof st.st_size > sizeof (long)) fmtstr = "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%qd"; else fmtstr = "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%ld"; sprintf(p, fmtstr, major(st.st_dev), minor(st.st_dev), st.st_ino, st.st_nlink, st.st_uid, st.st_gid, st.st_size); break; }printit:#ifdef LOG if (logit) syslog(LOG_DEBUG, "%s", buf); else#endif printf("%s\n", buf);}/*** SHORTENSTRING -- return short version of a string**** If the string is already short, just return it. If it is too** long, return the head and tail of the string.**** Parameters:** s -- the string to shorten.** m -- the max length of the string.**** Returns:** Either s or a short version of s.*/#ifndef MAXSHORTSTR# define MAXSHORTSTR 203#endifchar *shortenstring(s, m) register char *s; int m;{ int l; static char buf[MAXSHORTSTR + 1]; l = strlen(s); if (l < m) return s; if (m > MAXSHORTSTR) m = MAXSHORTSTR; else if (m < 10) { if (m < 5) { strncpy(buf, s, m); buf[m] = '\0'; return buf; } strncpy(buf, s, m - 3); strcpy(buf + m - 3, "..."); return buf; } m = (m - 3) / 2; strncpy(buf, s, m); strcpy(buf + m, "..."); strcpy(buf + m + 3, s + l - m); return buf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -