misc.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva/*
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * Copyright (c) 2000 Markus Friedl. All rights reserved.
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva *
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * Redistribution and use in source and binary forms, with or without
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * modification, are permitted provided that the following conditions
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * are met:
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * 1. Redistributions of source code must retain the above copyright
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * notice, this list of conditions and the following disclaimer.
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * 2. Redistributions in binary form must reproduce the above copyright
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * notice, this list of conditions and the following disclaimer in the
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * documentation and/or other materials provided with the distribution.
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva *
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30ad4487f491cce61c10639362ccf67a3e4bf0a0Joe Bandenburg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40bb86b15037ea7692f11b39c298658a068d948asean oneill */
40bb86b15037ea7692f11b39c298658a068d948asean oneill/*
40bb86b15037ea7692f11b39c298658a068d948asean oneill * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
40bb86b15037ea7692f11b39c298658a068d948asean oneill * Use is subject to license terms.
40bb86b15037ea7692f11b39c298658a068d948asean oneill */
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill#include "includes.h"
40bb86b15037ea7692f11b39c298658a068d948asean oneillRCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $");
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill#pragma ident "%Z%%M% %I% %E% SMI"
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill#include "misc.h"
40bb86b15037ea7692f11b39c298658a068d948asean oneill#include "log.h"
40bb86b15037ea7692f11b39c298658a068d948asean oneill#include "xmalloc.h"
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill/* remove newline at end of string */
40bb86b15037ea7692f11b39c298658a068d948asean oneillchar *
40bb86b15037ea7692f11b39c298658a068d948asean oneillchop(char *s)
40bb86b15037ea7692f11b39c298658a068d948asean oneill{
40bb86b15037ea7692f11b39c298658a068d948asean oneill char *t = s;
40bb86b15037ea7692f11b39c298658a068d948asean oneill while (*t) {
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (*t == '\n' || *t == '\r') {
40bb86b15037ea7692f11b39c298658a068d948asean oneill *t = '\0';
40bb86b15037ea7692f11b39c298658a068d948asean oneill return s;
40bb86b15037ea7692f11b39c298658a068d948asean oneill }
40bb86b15037ea7692f11b39c298658a068d948asean oneill t++;
40bb86b15037ea7692f11b39c298658a068d948asean oneill }
40bb86b15037ea7692f11b39c298658a068d948asean oneill return s;
40bb86b15037ea7692f11b39c298658a068d948asean oneill
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva}
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill/* set/unset filedescriptor to non-blocking */
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueevavoid
40bb86b15037ea7692f11b39c298658a068d948asean oneillset_nonblock(int fd)
40bb86b15037ea7692f11b39c298658a068d948asean oneill{
40bb86b15037ea7692f11b39c298658a068d948asean oneill int val;
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva
40bb86b15037ea7692f11b39c298658a068d948asean oneill val = fcntl(fd, F_GETFL, 0);
01c4b582dfa5e7a7c33a5f1c6c7c1d3ed5f56544sean oneill if (val < 0) {
40bb86b15037ea7692f11b39c298658a068d948asean oneill error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
40bb86b15037ea7692f11b39c298658a068d948asean oneill return;
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva }
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (val & O_NONBLOCK) {
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva debug2("fd %d is O_NONBLOCK", fd);
40bb86b15037ea7692f11b39c298658a068d948asean oneill return;
40bb86b15037ea7692f11b39c298658a068d948asean oneill }
40bb86b15037ea7692f11b39c298658a068d948asean oneill debug("fd %d setting O_NONBLOCK", fd);
40bb86b15037ea7692f11b39c298658a068d948asean oneill val |= O_NONBLOCK;
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (fcntl(fd, F_SETFL, val) == -1)
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
40bb86b15037ea7692f11b39c298658a068d948asean oneill fd, strerror(errno));
40bb86b15037ea7692f11b39c298658a068d948asean oneill}
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneillvoid
40bb86b15037ea7692f11b39c298658a068d948asean oneillunset_nonblock(int fd)
40bb86b15037ea7692f11b39c298658a068d948asean oneill{
40bb86b15037ea7692f11b39c298658a068d948asean oneill int val;
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill val = fcntl(fd, F_GETFL, 0);
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (val < 0) {
40bb86b15037ea7692f11b39c298658a068d948asean oneill error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
40bb86b15037ea7692f11b39c298658a068d948asean oneill return;
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva }
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva if (!(val & O_NONBLOCK)) {
40bb86b15037ea7692f11b39c298658a068d948asean oneill debug2("fd %d is not O_NONBLOCK", fd);
40bb86b15037ea7692f11b39c298658a068d948asean oneill return;
40bb86b15037ea7692f11b39c298658a068d948asean oneill }
567df49a25d2745e1fc9fcfd39506078b62698d4Eugenia Sergueeva debug("fd %d clearing O_NONBLOCK", fd);
40bb86b15037ea7692f11b39c298658a068d948asean oneill val &= ~O_NONBLOCK;
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (fcntl(fd, F_SETFL, val) == -1)
40bb86b15037ea7692f11b39c298658a068d948asean oneill debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
40bb86b15037ea7692f11b39c298658a068d948asean oneill fd, strerror(errno));
99973e2356cf31656e2d239d89559ca67e62e82dEugenia Sergueeva}
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill/* disable nagle on socket */
40bb86b15037ea7692f11b39c298658a068d948asean oneillvoid
40bb86b15037ea7692f11b39c298658a068d948asean oneillset_nodelay(int fd)
40bb86b15037ea7692f11b39c298658a068d948asean oneill{
40bb86b15037ea7692f11b39c298658a068d948asean oneill int opt;
40bb86b15037ea7692f11b39c298658a068d948asean oneill socklen_t optlen;
99973e2356cf31656e2d239d89559ca67e62e82dEugenia Sergueeva
40bb86b15037ea7692f11b39c298658a068d948asean oneill optlen = sizeof opt;
99973e2356cf31656e2d239d89559ca67e62e82dEugenia Sergueeva if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
40bb86b15037ea7692f11b39c298658a068d948asean oneill error("getsockopt TCP_NODELAY: %.100s", strerror(errno));
40bb86b15037ea7692f11b39c298658a068d948asean oneill return;
40bb86b15037ea7692f11b39c298658a068d948asean oneill }
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (opt == 1) {
40bb86b15037ea7692f11b39c298658a068d948asean oneill debug2("fd %d is TCP_NODELAY", fd);
40bb86b15037ea7692f11b39c298658a068d948asean oneill return;
40bb86b15037ea7692f11b39c298658a068d948asean oneill }
40bb86b15037ea7692f11b39c298658a068d948asean oneill opt = 1;
40bb86b15037ea7692f11b39c298658a068d948asean oneill debug("fd %d setting TCP_NODELAY", fd);
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
40bb86b15037ea7692f11b39c298658a068d948asean oneill error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
40bb86b15037ea7692f11b39c298658a068d948asean oneill}
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill/* Characters considered whitespace in strsep calls. */
40bb86b15037ea7692f11b39c298658a068d948asean oneill#define WHITESPACE " \t\r\n"
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill/* return next token in configuration line */
40bb86b15037ea7692f11b39c298658a068d948asean oneillchar *
40bb86b15037ea7692f11b39c298658a068d948asean oneillstrdelim(char **s)
40bb86b15037ea7692f11b39c298658a068d948asean oneill{
40bb86b15037ea7692f11b39c298658a068d948asean oneill char *old;
40bb86b15037ea7692f11b39c298658a068d948asean oneill int wspace = 0;
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (*s == NULL)
40bb86b15037ea7692f11b39c298658a068d948asean oneill return NULL;
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill old = *s;
4323bc0a739f6c3b7d9b72b0a9ba23925dc43efasean oneill
4323bc0a739f6c3b7d9b72b0a9ba23925dc43efasean oneill *s = strpbrk(*s, WHITESPACE "=");
4323bc0a739f6c3b7d9b72b0a9ba23925dc43efasean oneill if (*s == NULL)
4323bc0a739f6c3b7d9b72b0a9ba23925dc43efasean oneill return (old);
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill /* Allow only one '=' to be skipped */
40bb86b15037ea7692f11b39c298658a068d948asean oneill if (*s[0] == '=')
01c4b582dfa5e7a7c33a5f1c6c7c1d3ed5f56544sean oneill wspace = 1;
40bb86b15037ea7692f11b39c298658a068d948asean oneill *s[0] = '\0';
40bb86b15037ea7692f11b39c298658a068d948asean oneill
40bb86b15037ea7692f11b39c298658a068d948asean oneill *s += strspn(*s + 1, WHITESPACE) + 1;
if (*s[0] == '=' && !wspace)
*s += strspn(*s + 1, WHITESPACE) + 1;
return (old);
}
struct passwd *
pwcopy(struct passwd *pw)
{
struct passwd *copy = xmalloc(sizeof(*copy));
memset(copy, 0, sizeof(*copy));
copy->pw_name = xstrdup(pw->pw_name);
copy->pw_passwd = xstrdup(pw->pw_passwd);
copy->pw_gecos = xstrdup(pw->pw_gecos);
copy->pw_uid = pw->pw_uid;
copy->pw_gid = pw->pw_gid;
#ifdef HAVE_PW_EXPIRE_IN_PASSWD
copy->pw_expire = pw->pw_expire;
#endif
#ifdef HAVE_PW_CHANGE_IN_PASSWD
copy->pw_change = pw->pw_change;
#endif
#ifdef HAVE_PW_CLASS_IN_PASSWD
copy->pw_class = xstrdup(pw->pw_class);
#endif
copy->pw_dir = xstrdup(pw->pw_dir);
copy->pw_shell = xstrdup(pw->pw_shell);
return copy;
}
void
pwfree(struct passwd **pw)
{
struct passwd *p;
if (pw == NULL || *pw == NULL)
return;
p = *pw;
*pw = NULL;
xfree(p->pw_name);
xfree(p->pw_passwd);
xfree(p->pw_gecos);
#ifdef HAVE_PW_CLASS_IN_PASSWD
xfree(p->pw_class);
#endif
xfree(p->pw_dir);
xfree(p->pw_shell);
xfree(p);
}
/*
* Convert ASCII string to TCP/IP port number.
* Port must be >0 and <=65535.
* Return 0 if invalid.
*/
int
a2port(const char *s)
{
long port;
char *endp;
errno = 0;
port = strtol(s, &endp, 0);
if (s == endp || *endp != '\0' ||
(errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
port <= 0 || port > 65535)
return 0;
return port;
}
#define SECONDS 1
#define MINUTES (SECONDS * 60)
#define HOURS (MINUTES * 60)
#define DAYS (HOURS * 24)
#define WEEKS (DAYS * 7)
/*
* Convert a time string into seconds; format is
* a sequence of:
* time[qualifier]
*
* Valid time qualifiers are:
* <none> seconds
* s|S seconds
* m|M minutes
* h|H hours
* d|D days
* w|W weeks
*
* Examples:
* 90m 90 minutes
* 1h30m 90 minutes
* 2d 2 days
* 1w 1 week
*
* Return -1 if time string is invalid.
*/
long
convtime(const char *s)
{
long total, secs;
const char *p;
char *endp;
errno = 0;
total = 0;
p = s;
if (p == NULL || *p == '\0')
return -1;
while (*p) {
secs = strtol(p, &endp, 10);
if (p == endp ||
(errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
secs < 0)
return -1;
switch (*endp++) {
case '\0':
endp--;
break;
case 's':
case 'S':
break;
case 'm':
case 'M':
secs *= MINUTES;
break;
case 'h':
case 'H':
secs *= HOURS;
break;
case 'd':
case 'D':
secs *= DAYS;
break;
case 'w':
case 'W':
secs *= WEEKS;
break;
default:
return -1;
}
total += secs;
if (total < 0)
return -1;
p = endp;
}
return total;
}
char *
cleanhostname(char *host)
{
if (*host == '[' && host[strlen(host) - 1] == ']') {
host[strlen(host) - 1] = '\0';
return (host + 1);
} else
return host;
}
char *
colon(char *cp)
{
int flag = 0;
if (*cp == ':') /* Leading colon is part of file name. */
return (0);
if (*cp == '[')
flag = 1;
for (; *cp; ++cp) {
if (*cp == '@' && *(cp+1) == '[')
flag = 1;
if (*cp == ']' && *(cp+1) == ':' && flag)
return (cp+1);
if (*cp == ':' && !flag)
return (cp);
if (*cp == '/')
return (0);
}
return (0);
}
/* function to assist building execv() arguments */
/* PRINTFLIKE2 */
void
addargs(arglist *args, char *fmt, ...)
{
va_list ap;
char buf[1024];
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
if (args->list == NULL) {
args->nalloc = 32;
args->num = 0;
} else if (args->num+2 >= args->nalloc)
args->nalloc *= 2;
args->list = xrealloc(args->list, args->nalloc * sizeof(char *));
args->list[args->num++] = xstrdup(buf);
args->list[args->num] = NULL;
}
mysig_t
mysignal(int sig, mysig_t act)
{
#ifdef HAVE_SIGACTION
struct sigaction sa, osa;
if (sigaction(sig, NULL, &osa) == -1)
return (mysig_t) -1;
if (osa.sa_handler != act) {
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
#if defined(SA_INTERRUPT)
if (sig == SIGALRM)
sa.sa_flags |= SA_INTERRUPT;
#endif
sa.sa_handler = act;
if (sigaction(sig, &sa, NULL) == -1)
return (mysig_t) -1;
}
return (osa.sa_handler);
#else
return (signal(sig, act));
#endif
}