/***************************************************************************** POPular -- A POP3 server and proxy for large mail systems $Id: util.c,v 1.35 2001/04/30 15:14:14 sqrt Exp $ http://www.remote.org/jochen/mail/popular/ ****************************************************************************** Copyright (C) 1999-2001 Jochen Topf This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *****************************************************************************/ #if HAVE_CONFIG_H # include #endif #include "popular.h" #if 0 /***************************************************************************** lock_shmem() type is F_RDLCK or F_WRLCK Lock shared memory mapped file. This is currently not used! See documentation. *****************************************************************************/ int lock_shmem(int fd, int type) { struct flock fl; fl.l_type = type; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; while (fcntl(fd, F_SETLKW, &fl) == -1) { if (errno != EINTR) return -1; } return 0; } /***************************************************************************** unlock_shmem() Unlock shared memory mapped file. This is currently not used! See documentation. *****************************************************************************/ int unlock_shmem(int fd) { struct flock fl; fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; while (fcntl(fd, F_SETLKW, &fl) == -1) { if (errno != EINTR) return -1; } return 0; } #endif /***************************************************************************** get_int(string, min, max, overflow, error, empty) Get integer from . Returns if value is not between and , if there are additional chars in the and if the was NULL or the empty string. *****************************************************************************/ int get_int(const char *string, int min, int max, int overflow, int error, int empty) { char *tptr; long value; if ((!string) || (string[0] == '\0')) return empty; value = strtol(string, &tptr, 10); if (tptr[0] != '\0') return error; if ((value < min) || (value > max)) return overflow; return (int)value; } /***************************************************************************** timedesc2sec() *****************************************************************************/ int timedesc2sec(char *desc, int min, int max) { char *tptr=desc; long value; int sec=0; errno = 0; while (1) { if (*tptr == '-') return -1; value = strtol(tptr, &tptr, 10); if (errno && errno != EINVAL) return -1; switch (*tptr) { case 'd': sec += value*60*60*24; tptr++; break; case 'h': sec += value*60*60; tptr++; break; case 'm': sec += value*60; tptr++; break; case 's': sec += value; tptr++; break; case '\0': sec += value; if (sec < min || sec > max) return -1; return sec; default: return -1; } } return -1; } /***************************************************************************** sec2timedesc() *****************************************************************************/ char * sec2timedesc(int s) { static char buf[MAXBUF]; int d, h, m; int r=0; if (s < 0) return NULL; d = s / (60*60*24); s -= d*60*60*24; h = s / (60*60); s -= h*60*60; m = s / (60); s -= m*60; if (d) r += snprintf(buf+r, sizeof(buf), "%dd", d); if (h) r += snprintf(buf+r, sizeof(buf), "%dh", h); if (m) r += snprintf(buf+r, sizeof(buf), "%dm", m); if (s || r==0) snprintf(buf+r, sizeof(buf), "%ds", s); return buf; } /***************************************************************************** sec2prettytime() *****************************************************************************/ char * sec2prettytime(int s) { static char buf[MAXBUF]; int d, h, m; if (s < 0) return NULL; d = s / (60*60*24); s -= d*60*60*24; h = s / (60*60); s -= h*60*60; m = s / (60); s -= m*60; snprintf(buf, sizeof(buf), "%3d:%02d:%02d:%02d", d, h, m, s); return buf; } /***************************************************************************** get_port() *****************************************************************************/ int get_port(const char *s) { struct servent *se = getservbyname(s, "tcp"); if (se != NULL) return ntohs(se->s_port); return get_int(s, 1, 65535, -1, -1, -1); } /***************************************************************************** sep_args() *****************************************************************************/ int sep_args(char *string, char **argv, int maxlen) { typedef enum { sasWhitespace, sasArg, sasString } sep_args_state_t; sep_args_state_t state = sasWhitespace; char *p; int n=0; for (p=string; *p != '\0'; p++) { if (! isprint((int)*p)) return -1; /* parse error (! isprint) */ switch (state) { case sasWhitespace: if (isspace((int)*p)) { *p = '\0'; } else if (*p == '"') { *p = '\0'; if (n >= maxlen) return -2; /* too many arguments */ argv[n++] = p+1; state = sasString; } else { if (n >= maxlen) return -2; /* too many arguments */ argv[n++] = p; state = sasArg; } break; case sasArg: if (isspace((int)*p)) { *p = '\0'; state = sasWhitespace; } else if (*p == '"') { return -1; /* parse error (" in arg) */ } break; case sasString: if (*p == '"') { *p = '\0'; state = sasWhitespace; } break; default: return -3; /* should never be here */ } } if (state == sasString) return -1; /* parse error (unmatched ") */ return n; } /***************************************************************************** valid_id() *****************************************************************************/ int valid_id(const char *s) { const char *p; if (!s || *s == '\0') return 0; for (p=s; *p != '\0'; p++) { if (! (isalnum((int)*p) || *p == '.' || *p == '_' || *p == '-')) return 0; } return 1; } /***************************************************************************** print_ip(const struct sockaddr_in *sin, char *buf)) Puts the ASCII (dotted quad) representation of the IP address in into . must be preallocated with at least 16 bytes or NULL. If is NULL an internal static buffer is used. print_ip returns or a pointer to the static buffer. If the IP address ist INADDR_ANY the string "ANY" ist returned. *****************************************************************************/ char * print_ip(const struct sockaddr_in *sin, char *buf) { static char sbuf[16]; if (! buf) buf = sbuf; if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) { (void) strlcpy(buf, "ANY", sizeof(sbuf)); } else { (void) strlcpy(buf, inet_ntoa(sin->sin_addr), sizeof(sbuf)); } return buf; } /***************************************************************************** get_load() Returns current system load as long integer or -1 if the load couldn't be determined. This reads /proc/loadavg to find the load. *****************************************************************************/ long get_load() { #ifdef LOADAVG_FILE char buf[20]; int fd = open(LOADAVG_FILE, O_RDONLY); if (fd < 0) return -1; if (read(fd, buf, sizeof(buf)) <= 0) return -1; close(fd); buf[sizeof(buf)-1] = '\0'; /* this will automatically read everything in front of the first . and ignore the rest (the digits after the decimal dot and the other numbers in the file) */ return strtol(buf, (char **)NULL, 10); #else return -1; #endif } /***************************************************************************** touch() *****************************************************************************/ int touch(const char *dir, const char *file) { char buf[MAXBUF]; int fd; strlcpy(buf, dir, sizeof(buf)); strlcat(buf, "/", sizeof(buf)); strlcat(buf, file, sizeof(buf)); fd = open(buf, O_CREAT|O_WRONLY, 0644); if (fd < 0) return -1; close(fd); return 0; } /***************************************************************************** search_string() *****************************************************************************/ char * search_string(char *s, char *t, int len) { int i; int l = strlen(t); for (i=0; i <= len-l; i++) { if ((s[i] == t[0]) && (!strncmp(s+i+1, t+1, l-1))) return s+i; } return NULL; } /***************************************************************************** rel_select() reliable select *****************************************************************************/ int rel_select(fd_set *readset, int sec, int usec) { int r; struct timeval timeout; fd_set setcopy; do { timeout.tv_sec = sec; timeout.tv_usec = usec; memcpy(&setcopy, readset, sizeof(fd_set)); r = select(FD_SETSIZE, &setcopy, (fd_set *)0, (fd_set *) 0, &timeout); } while (r < 0 && errno==EINTR); memcpy(readset, &setcopy, sizeof(fd_set)); return r; } /***************************************************************************** rel_write() reliable write *****************************************************************************/ ssize_t rel_write(int fd, const char *buf, size_t count) { ssize_t len; int offset=0; while ((len = write(fd, buf+offset, count-offset))) { if ((len < 0) && (errno != EINTR)) return -1; if (len == count-offset) return count; if (len > 0) offset += len; } return 0; } /** THE END *****************************************************************/