| 
version 1.1.1.1, 2012/02/21 16:23:02
 | 
version 1.1.1.4, 2014/06/15 16:12:54
 | 
| 
 Line 1
 | 
 Line 1
 | 
 |  /* | 
  /* | 
|  * Copyright (c) 1999-2005, 2007, 2009-2011 |  * Copyright (c) 1999-2005, 2007, 2009-2013 | 
 |   *      Todd C. Miller <Todd.Miller@courtesan.com> | 
   *      Todd C. Miller <Todd.Miller@courtesan.com> | 
 |   * | 
   * | 
 |   * Permission to use, copy, modify, and distribute this software for any | 
   * Permission to use, copy, modify, and distribute this software for any | 
| 
 Line 22
 | 
 Line 22
 | 
 |  #include <config.h> | 
  #include <config.h> | 
 |   | 
   | 
 |  #include <sys/types.h> | 
  #include <sys/types.h> | 
 |  #include <sys/param.h> | 
   | 
 |  #include <sys/time.h> | 
  #include <sys/time.h> | 
 |  #ifdef HAVE_FLOCK | 
  #ifdef HAVE_FLOCK | 
 |  # include <sys/file.h> | 
  # include <sys/file.h> | 
 |  #endif /* HAVE_FLOCK */ | 
  #endif /* HAVE_FLOCK */ | 
| #include <stdio.h> | #ifdef STDC_HEADERS | 
|   | # include <stdlib.h> | 
|   | # include <stddef.h> | 
|   | #else | 
|   | # ifdef HAVE_STDLIB_H | 
|   | #  include <stdlib.h> | 
|   | # endif | 
|   | #endif /* STDC_HEADERS */ | 
 |  #ifdef HAVE_STRING_H | 
  #ifdef HAVE_STRING_H | 
 |   | 
  # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) | 
 |   | 
  #  include <memory.h> | 
 |   | 
  # endif | 
 |  # include <string.h> | 
  # include <string.h> | 
 |  #endif /* HAVE_STRING_H */ | 
  #endif /* HAVE_STRING_H */ | 
 |  #ifdef HAVE_STRINGS_H | 
  #ifdef HAVE_STRINGS_H | 
 |  # include <strings.h> | 
  # include <strings.h> | 
| #endif /* HAVE_STRINGS_H */ | #endif /* HAVE_STRING_H */ | 
|   | #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) | 
|   | # include <malloc.h> | 
|   | #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ | 
 |  #include <ctype.h> | 
  #include <ctype.h> | 
 |  #include <limits.h> | 
   | 
 |  #ifdef HAVE_UNISTD_H | 
  #ifdef HAVE_UNISTD_H | 
 |  # include <unistd.h> | 
  # include <unistd.h> | 
 |  #endif /* HAVE_UNISTD_H */ | 
  #endif /* HAVE_UNISTD_H */ | 
 |  #include <fcntl.h> | 
  #include <fcntl.h> | 
| #if TIME_WITH_SYS_TIME | #ifdef HAVE_STDBOOL_H | 
|   | # include <stdbool.h> | 
|   | #else | 
|   | # include "compat/stdbool.h" | 
|   | #endif | 
|   | #ifdef TIME_WITH_SYS_TIME | 
 |  # include <time.h> | 
  # include <time.h> | 
 |  #endif | 
  #endif | 
| #ifndef HAVE_TIMESPEC | #ifndef HAVE_STRUCT_TIMESPEC | 
 |  # include "compat/timespec.h" | 
  # include "compat/timespec.h" | 
 |  #endif | 
  #endif | 
 |   | 
   | 
 |  #include "missing.h" | 
  #include "missing.h" | 
 |  #include "fileops.h" | 
  #include "fileops.h" | 
 |   | 
  #include "sudo_debug.h" | 
 |   | 
   | 
 |  #ifndef LINE_MAX | 
   | 
 |  # define LINE_MAX 2048 | 
   | 
 |  #endif | 
   | 
 |   | 
   | 
 |  /* | 
  /* | 
 |   * Update the access and modify times on an fd or file. | 
   * Update the access and modify times on an fd or file. | 
 |   */ | 
   */ | 
| 
 Line 61  int
 | 
 Line 74  int
 | 
 |  touch(int fd, char *path, struct timeval *tvp) | 
  touch(int fd, char *path, struct timeval *tvp) | 
 |  { | 
  { | 
 |      struct timeval times[2]; | 
      struct timeval times[2]; | 
 |   | 
      int rval = -1; | 
 |   | 
      debug_decl(touch, SUDO_DEBUG_UTIL) | 
 |   | 
   | 
 |      if (tvp != NULL) { | 
      if (tvp != NULL) { | 
 |          times[0].tv_sec = times[1].tv_sec = tvp->tv_sec; | 
          times[0].tv_sec = times[1].tv_sec = tvp->tv_sec; | 
| 
 Line 69  touch(int fd, char *path, struct timeval *tvp)
 | 
 Line 84  touch(int fd, char *path, struct timeval *tvp)
 | 
 |   | 
   | 
 |  #if defined(HAVE_FUTIME) || defined(HAVE_FUTIMES) | 
  #if defined(HAVE_FUTIME) || defined(HAVE_FUTIMES) | 
 |      if (fd != -1) | 
      if (fd != -1) | 
|         return futimes(fd, tvp ? times : NULL); |         rval = futimes(fd, tvp ? times : NULL); | 
 |      else | 
      else | 
 |  #endif | 
  #endif | 
 |      if (path != NULL) | 
      if (path != NULL) | 
|         return utimes(path, tvp ? times : NULL); |         rval = utimes(path, tvp ? times : NULL); | 
|     else |     debug_return_int(rval); | 
|         return -1; |   | 
 |  } | 
  } | 
 |   | 
   | 
 |  /* | 
  /* | 
 |   * Lock/unlock a file. | 
   * Lock/unlock a file. | 
 |   */ | 
   */ | 
 |  #ifdef HAVE_LOCKF | 
  #ifdef HAVE_LOCKF | 
| int | bool | 
 |  lock_file(int fd, int lockit) | 
  lock_file(int fd, int lockit) | 
 |  { | 
  { | 
 |      int op = 0; | 
      int op = 0; | 
 |   | 
      debug_decl(lock_file, SUDO_DEBUG_UTIL) | 
 |   | 
   | 
 |      switch (lockit) { | 
      switch (lockit) { | 
 |          case SUDO_LOCK: | 
          case SUDO_LOCK: | 
| 
 Line 98  lock_file(int fd, int lockit)
 | 
 Line 113  lock_file(int fd, int lockit)
 | 
 |              op = F_ULOCK; | 
              op = F_ULOCK; | 
 |              break; | 
              break; | 
 |      } | 
      } | 
|     return lockf(fd, op, 0) == 0; |     debug_return_bool(lockf(fd, op, 0) == 0); | 
 |  } | 
  } | 
| #elif HAVE_FLOCK | #elif defined(HAVE_FLOCK) | 
| int | bool | 
 |  lock_file(int fd, int lockit) | 
  lock_file(int fd, int lockit) | 
 |  { | 
  { | 
 |      int op = 0; | 
      int op = 0; | 
 |   | 
      debug_decl(lock_file, SUDO_DEBUG_UTIL) | 
 |   | 
   | 
 |      switch (lockit) { | 
      switch (lockit) { | 
 |          case SUDO_LOCK: | 
          case SUDO_LOCK: | 
| 
 Line 117  lock_file(int fd, int lockit)
 | 
 Line 133  lock_file(int fd, int lockit)
 | 
 |              op = LOCK_UN; | 
              op = LOCK_UN; | 
 |              break; | 
              break; | 
 |      } | 
      } | 
|     return flock(fd, op) == 0; |     debug_return_bool(flock(fd, op) == 0); | 
 |  } | 
  } | 
 |  #else | 
  #else | 
| int | bool | 
 |  lock_file(int fd, int lockit) | 
  lock_file(int fd, int lockit) | 
 |  { | 
  { | 
 |  #ifdef F_SETLK | 
  #ifdef F_SETLK | 
 |      int func; | 
      int func; | 
 |      struct flock lock; | 
      struct flock lock; | 
 |   | 
      debug_decl(lock_file, SUDO_DEBUG_UTIL) | 
 |   | 
   | 
 |      lock.l_start = 0; | 
      lock.l_start = 0; | 
 |      lock.l_len = 0; | 
      lock.l_len = 0; | 
| 
 Line 134  lock_file(int fd, int lockit)
 | 
 Line 151  lock_file(int fd, int lockit)
 | 
 |      lock.l_whence = SEEK_SET; | 
      lock.l_whence = SEEK_SET; | 
 |      func = (lockit == SUDO_LOCK) ? F_SETLKW : F_SETLK; | 
      func = (lockit == SUDO_LOCK) ? F_SETLKW : F_SETLK; | 
 |   | 
   | 
|     return fcntl(fd, func, &lock) == 0; |     debug_return_bool(fcntl(fd, func, &lock) == 0); | 
 |  #else | 
  #else | 
|     return TRUE; |     return true; | 
 |  #endif | 
  #endif | 
 |  } | 
  } | 
 |  #endif | 
  #endif | 
 |   | 
   | 
 |  /* | 
  /* | 
|  * Read a line of input, remove comments and strip off leading |  * Read a line of input, honoring line continuation chars. | 
|  * and trailing spaces.  Returns static storage that is reused. |  * Remove comments and strips off leading and trailing spaces. | 
|   |  * Returns the line length and updates the buf and bufsize pointers. | 
|   |  * XXX - just use a struct w/ state, including getline buffer? | 
|   |  *       could also make comment char and line continuation configurable | 
 |   */ | 
   */ | 
| char * | ssize_t | 
| sudo_parseln(FILE *fp) | sudo_parseln(char **bufp, size_t *bufsizep, unsigned int *lineno, FILE *fp) | 
 |  { | 
  { | 
|     size_t len; |     size_t linesize = 0, total = 0; | 
|     char *cp = NULL; |     ssize_t len; | 
|     static char buf[LINE_MAX]; |     char *cp, *line = NULL; | 
|   |     bool continued; | 
|   |     debug_decl(sudo_parseln, SUDO_DEBUG_UTIL) | 
 |   | 
   | 
|     if (fgets(buf, sizeof(buf), fp) != NULL) { |     do { | 
|         /* Remove comments */ |         continued = false; | 
|         if ((cp = strchr(buf, '#')) != NULL) |         len = getline(&line, &linesize, fp); | 
|   |         if (len == -1) | 
|   |             break; | 
|   |         if (lineno != NULL) | 
|   |             (*lineno)++; | 
|   |  | 
|   |         /* Remove trailing newline(s) if present. */ | 
|   |         while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) | 
|   |             line[--len] = '\0'; | 
|   |  | 
|   |         /* Remove comments or check for line continuation (but not both) */ | 
|   |         if ((cp = strchr(line, '#')) != NULL) { | 
 |              *cp = '\0'; | 
              *cp = '\0'; | 
 |   | 
              len = (size_t)(cp - line); | 
 |   | 
          } else if (len > 0 && line[len - 1] == '\\' && (len == 1 || line[len - 2] != '\\')) { | 
 |   | 
              line[--len] = '\0'; | 
 |   | 
              continued = true; | 
 |   | 
          } | 
 |   | 
   | 
|         /* Trim leading and trailing whitespace/newline */ |         /* Trim leading and trailing whitespace */ | 
|         len = strlen(buf); |         if (!continued) { | 
|         while (len > 0 && isspace((unsigned char)buf[len - 1])) |             while (len > 0 && isblank((unsigned char)line[len - 1])) | 
|             buf[--len] = '\0'; |                 line[--len] = '\0'; | 
|         for (cp = buf; isblank((unsigned char)*cp); cp++) |         } | 
|             continue; |         for (cp = line; isblank((unsigned char)*cp); cp++) | 
|     } |             len--; | 
|     return cp; |  | 
|   |         if (*bufp == NULL || total + len >= *bufsizep) { | 
|   |             void *tmp; | 
|   |             size_t size = total + len + 1; | 
|   |  | 
|   |             if (size < 64) { | 
|   |                 size = 64; | 
|   |             } else if (size <= 0x80000000) { | 
|   |                 /* Round up to next highest power of two. */ | 
|   |                 size--; | 
|   |                 size |= size >> 1; | 
|   |                 size |= size >> 2; | 
|   |                 size |= size >> 4; | 
|   |                 size |= size >> 8; | 
|   |                 size |= size >> 16; | 
|   |                 size++; | 
|   |             } | 
|   |             if ((tmp = realloc(*bufp, size)) == NULL) | 
|   |                 break; | 
|   |             *bufp = tmp; | 
|   |             *bufsizep = size; | 
|   |         } | 
|   |         memcpy(*bufp + total, cp, len + 1); | 
|   |         total += len; | 
|   |     } while (continued); | 
|   |     free(line); | 
|   |     if (len == -1 && total == 0) | 
|   |         debug_return_size_t((size_t)-1); | 
|   |     debug_return_size_t(total); | 
 |  } | 
  } |