/*****************************************************************************
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 <jochen@remote.org>
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 <config.h>
#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 <string>. Returns <overflow> if value is not between <min>
and <max>, <error> if there are additional chars in the <string> and <empty>
if the <string> 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 <sin>
into <buf>. <buf> must be preallocated with at least 16 bytes or NULL. If
<buf> is NULL an internal static buffer is used.
print_ip returns <buf> 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 *****************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1