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