]> andersk Git - openssh.git/blobdiff - misc.c
- (tim) [configure.ac] Some platforms need sys/types.h for arpa/nameser.h.
[openssh.git] / misc.c
diff --git a/misc.c b/misc.c
index ac616de0234e1ff2afd6177108088ee3061c0281..4bc07a42a88c0ad4be4bd18693934a27ab6f271d 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: misc.c,v 1.22 2003/09/18 08:49:45 markus Exp $");
+RCSID("$OpenBSD: misc.c,v 1.30 2005/04/09 04:32:54 djm Exp $");
 
 #include "misc.h"
 #include "log.h"
@@ -46,7 +46,7 @@ chop(char *s)
 }
 
 /* set/unset filedescriptor to non-blocking */
-void
+int
 set_nonblock(int fd)
 {
        int val;
@@ -54,20 +54,23 @@ set_nonblock(int fd)
        val = fcntl(fd, F_GETFL, 0);
        if (val < 0) {
                error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
-               return;
+               return (-1);
        }
        if (val & O_NONBLOCK) {
-               debug2("fd %d is O_NONBLOCK", fd);
-               return;
+               debug3("fd %d is O_NONBLOCK", fd);
+               return (0);
        }
        debug2("fd %d setting O_NONBLOCK", fd);
        val |= O_NONBLOCK;
-       if (fcntl(fd, F_SETFL, val) == -1)
-               debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
-                   fd, strerror(errno));
+       if (fcntl(fd, F_SETFL, val) == -1) {
+               debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
+                   strerror(errno));
+               return (-1);
+       }
+       return (0);
 }
 
-void
+int
 unset_nonblock(int fd)
 {
        int val;
@@ -75,17 +78,20 @@ unset_nonblock(int fd)
        val = fcntl(fd, F_GETFL, 0);
        if (val < 0) {
                error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
-               return;
+               return (-1);
        }
        if (!(val & O_NONBLOCK)) {
-               debug2("fd %d is not O_NONBLOCK", fd);
-               return;
+               debug3("fd %d is not O_NONBLOCK", fd);
+               return (0);
        }
        debug("fd %d clearing O_NONBLOCK", fd);
        val &= ~O_NONBLOCK;
-       if (fcntl(fd, F_SETFL, val) == -1)
-               debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s",
+       if (fcntl(fd, F_SETFL, val) == -1) {
+               debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
                    fd, strerror(errno));
+               return (-1);
+       }
+       return (0);
 }
 
 /* disable nagle on socket */
@@ -97,7 +103,7 @@ set_nodelay(int fd)
 
        optlen = sizeof opt;
        if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
-               error("getsockopt TCP_NODELAY: %.100s", strerror(errno));
+               debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
                return;
        }
        if (opt == 1) {
@@ -269,6 +275,48 @@ convtime(const char *s)
        return total;
 }
 
+/*
+ * Search for next delimiter between hostnames/addresses and ports.
+ * Argument may be modified (for termination).
+ * Returns *cp if parsing succeeds.
+ * *cp is set to the start of the next delimiter, if one was found.
+ * If this is the last field, *cp is set to NULL.
+ */
+char *
+hpdelim(char **cp)
+{
+       char *s, *old;
+
+       if (cp == NULL || *cp == NULL)
+               return NULL;
+
+       old = s = *cp;
+       if (*s == '[') {
+               if ((s = strchr(s, ']')) == NULL)
+                       return NULL;
+               else
+                       s++;
+       } else if ((s = strpbrk(s, ":/")) == NULL)
+               s = *cp + strlen(*cp); /* skip to end (see first case below) */
+
+       switch (*s) {
+       case '\0':
+               *cp = NULL;     /* no more fields*/
+               break;
+
+       case ':':
+       case '/':
+               *s = '\0';      /* terminate */
+               *cp = s + 1;
+               break;
+
+       default:
+               return NULL;
+       }
+
+       return old;
+}
+
 char *
 cleanhostname(char *host)
 {
@@ -308,7 +356,7 @@ addargs(arglist *args, char *fmt, ...)
 {
        va_list ap;
        char buf[1024];
-       int nalloc;
+       u_int nalloc;
 
        va_start(ap, fmt);
        vsnprintf(buf, sizeof(buf), fmt, ap);
@@ -326,3 +374,71 @@ addargs(arglist *args, char *fmt, ...)
        args->list[args->num++] = xstrdup(buf);
        args->list[args->num] = NULL;
 }
+
+/*
+ * Expands tildes in the file name.  Returns data allocated by xmalloc.
+ * Warning: this calls getpw*.
+ */
+char *
+tilde_expand_filename(const char *filename, uid_t uid)
+{
+       const char *path;
+       char user[128], ret[MAXPATHLEN];
+       struct passwd *pw;
+       int len;
+
+       if (*filename != '~')
+               return (xstrdup(filename));
+       filename++;
+
+       path = strchr(filename, '/');
+       if (path != NULL && path > filename) {          /* ~user/path */
+               if (path - filename > sizeof(user) - 1)
+                       fatal("tilde_expand_filename: ~username too long");
+               memcpy(user, filename, path - filename);
+               user[path - filename] = '\0';
+               if ((pw = getpwnam(user)) == NULL)
+                       fatal("tilde_expand_filename: No such user %s", user);
+       } else if ((pw = getpwuid(uid)) == NULL)        /* ~/path */
+               fatal("tilde_expand_filename: No such uid %d", uid);
+
+       if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
+               fatal("tilde_expand_filename: Path too long");
+
+       /* Make sure directory has a trailing '/' */
+       len = strlen(pw->pw_dir);
+       if ((len == 0 || pw->pw_dir[len - 1] != '/') &&
+           strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
+               fatal("tilde_expand_filename: Path too long");
+
+       /* Skip leading '/' from specified path */
+       if (path != NULL)
+               filename = path + 1;
+       if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
+               fatal("tilde_expand_filename: Path too long");
+
+       return (xstrdup(ret));
+}
+
+/*
+ * Read an entire line from a public key file into a static buffer, discarding
+ * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
+ */
+int
+read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
+   u_long *lineno)
+{
+       while (fgets(buf, bufsz, f) != NULL) {
+               (*lineno)++;
+               if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
+                       return 0;
+               } else {
+                       debug("%s: %s line %lu exceeds size limit", __func__,
+                           filename, *lineno);
+                       /* discard remainder of line */
+                       while (fgetc(f) != '\n' && !feof(f))
+                               ;       /* nothing */
+               }
+       }
+       return -1;
+}
This page took 0.095497 seconds and 4 git commands to generate.