|
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); |
| } |
} |