Compare commits
7 Commits
4e0ed30861
...
4ac7072f2a
Author | SHA1 | Date |
---|---|---|
Jonas 'Sortie' Termansen | 4ac7072f2a | |
Jonas 'Sortie' Termansen | c57ff050e9 | |
Jonas 'Sortie' Termansen | da86ca1873 | |
Jonas 'Sortie' Termansen | e9877d8080 | |
Jonas 'Sortie' Termansen | 03ee6d4d89 | |
Jonas 'Sortie' Termansen | 98c92bcdcc | |
Jonas 'Sortie' Termansen | 47e1cc439a |
2
Makefile
2
Makefile
|
@ -447,7 +447,9 @@ $(LIVE_INITRD): sysroot
|
||||||
mkdir -p $(LIVE_INITRD).d/etc/init
|
mkdir -p $(LIVE_INITRD).d/etc/init
|
||||||
echo require single-user exit-code > $(LIVE_INITRD).d/etc/init/default
|
echo require single-user exit-code > $(LIVE_INITRD).d/etc/init/default
|
||||||
echo "root::0:0:root:/root:sh" > $(LIVE_INITRD).d/etc/passwd
|
echo "root::0:0:root:/root:sh" > $(LIVE_INITRD).d/etc/passwd
|
||||||
|
echo "include /etc/default/passwd.d/*" >> $(LIVE_INITRD).d/etc/passwd
|
||||||
echo "root::0:root" > $(LIVE_INITRD).d/etc/group
|
echo "root::0:root" > $(LIVE_INITRD).d/etc/group
|
||||||
|
echo "include /etc/default/group.d/*" >> $(LIVE_INITRD).d/etc/group
|
||||||
mkdir -p $(LIVE_INITRD).d/home
|
mkdir -p $(LIVE_INITRD).d/home
|
||||||
mkdir -p $(LIVE_INITRD).d/root -m 700
|
mkdir -p $(LIVE_INITRD).d/root -m 700
|
||||||
cp -RT "$(SYSROOT)/etc/skel" $(LIVE_INITRD).d/root
|
cp -RT "$(SYSROOT)/etc/skel" $(LIVE_INITRD).d/root
|
||||||
|
|
|
@ -367,6 +367,8 @@ fstab/scanfsent.o \
|
||||||
fstab/setfsent.o \
|
fstab/setfsent.o \
|
||||||
getopt/getopt_long.o \
|
getopt/getopt_long.o \
|
||||||
getopt/getopt.o \
|
getopt/getopt.o \
|
||||||
|
glob/glob.o \
|
||||||
|
glob/globfree.o \
|
||||||
grp/endgrent.o \
|
grp/endgrent.o \
|
||||||
grp/fgetgrent.o \
|
grp/fgetgrent.o \
|
||||||
grp/fgetgrent_r.o \
|
grp/fgetgrent_r.o \
|
||||||
|
@ -476,7 +478,9 @@ pwd/getpwnam.o \
|
||||||
pwd/getpwnam_r.o \
|
pwd/getpwnam_r.o \
|
||||||
pwd/getpwuid.o \
|
pwd/getpwuid.o \
|
||||||
pwd/getpwuid_r.o \
|
pwd/getpwuid_r.o \
|
||||||
|
pwd/__openent.o \
|
||||||
pwd/openpw.o \
|
pwd/openpw.o \
|
||||||
|
pwd/scanpwent.o \
|
||||||
pwd/setpwent.o \
|
pwd/setpwent.o \
|
||||||
sched/sched_yield.o \
|
sched/sched_yield.o \
|
||||||
pty/openpty.o \
|
pty/openpty.o \
|
||||||
|
|
|
@ -0,0 +1,474 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* glob/glob.c
|
||||||
|
* Search for paths matching a pattern.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <glob.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int strcoll_indirect(const void* a_ptr, const void* b_ptr)
|
||||||
|
{
|
||||||
|
const char* a = *(const char* const*) a_ptr;
|
||||||
|
const char* b = *(const char* const*) b_ptr;
|
||||||
|
return strcoll(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct segment
|
||||||
|
{
|
||||||
|
char* prefix;
|
||||||
|
size_t prefix_length;
|
||||||
|
DIR* dir;
|
||||||
|
bool trivial;
|
||||||
|
bool leading_period;
|
||||||
|
bool match_directory;
|
||||||
|
bool done;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
size_t start;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
regex_t regex;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int glob(const char* restrict pattern,
|
||||||
|
int flags,
|
||||||
|
int (*errfunc)(const char*, int),
|
||||||
|
glob_t* restrict gl)
|
||||||
|
{
|
||||||
|
if ( !(flags & GLOB_DOOFFS) )
|
||||||
|
gl->gl_offs = 0;
|
||||||
|
if ( !(flags & GLOB_APPEND) )
|
||||||
|
{
|
||||||
|
gl->gl_pathv = NULL;
|
||||||
|
gl->gl_pathc = 0;
|
||||||
|
}
|
||||||
|
if ( gl->gl_offs == SIZE_MAX )
|
||||||
|
return GLOB_NOSPACE;
|
||||||
|
size_t initial_pathc = gl->gl_pathc;
|
||||||
|
// Reserve room for at least one string and the trailing null to prevent
|
||||||
|
// the possibly of late errors in the GLOB_NOCHECK case.
|
||||||
|
size_t pathl;
|
||||||
|
if ( __builtin_add_overflow(gl->gl_offs, gl->gl_pathc, &pathl) ||
|
||||||
|
__builtin_add_overflow(pathl, 2, &pathl) )
|
||||||
|
return GLOB_NOSPACE;
|
||||||
|
char** new_pathv = reallocarray(gl->gl_pathv, pathl, sizeof(char*));
|
||||||
|
if ( !new_pathv )
|
||||||
|
return GLOB_NOSPACE;
|
||||||
|
gl->gl_pathv = new_pathv;
|
||||||
|
size_t paths_length = gl->gl_pathc + 1;
|
||||||
|
// Parse the pattern into segments where trivial segments are fixed path
|
||||||
|
// components that can be directly opened and non-trivial segments require
|
||||||
|
// searching a directory for entries that match the pattern.
|
||||||
|
struct segment* segments = NULL;
|
||||||
|
size_t segments_count = 0;
|
||||||
|
size_t segments_length = 0;
|
||||||
|
int result = 0;
|
||||||
|
for ( size_t offset = 0; pattern[offset] && !result; )
|
||||||
|
{
|
||||||
|
// Combine multiple trivial path components into a trivial segment, but
|
||||||
|
// each non-trivial path component must be its own segment.
|
||||||
|
size_t segment_length = 0;
|
||||||
|
bool is_trivial = true;
|
||||||
|
for ( size_t i = 0; pattern[offset + i]; i++ )
|
||||||
|
{
|
||||||
|
if ( pattern[offset + i] == '*' ||
|
||||||
|
pattern[offset + i] == '?' ||
|
||||||
|
pattern[offset + i] == '[' )
|
||||||
|
{
|
||||||
|
if ( segment_length )
|
||||||
|
break;
|
||||||
|
is_trivial = false;
|
||||||
|
}
|
||||||
|
if ( pattern[offset + i] == '/' || !pattern[offset + i + 1] )
|
||||||
|
{
|
||||||
|
segment_length = i + 1;
|
||||||
|
if ( !is_trivial )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Grow the list of segments as needed.
|
||||||
|
if ( segments_count == segments_length )
|
||||||
|
{
|
||||||
|
size_t old_length = segments_length ? segments_length : 1;
|
||||||
|
struct segment* new_segments =
|
||||||
|
reallocarray(segments, old_length, 2 * sizeof(struct segment));
|
||||||
|
if ( !new_segments )
|
||||||
|
{
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
segments = new_segments;
|
||||||
|
segments_length = 2 * old_length;
|
||||||
|
}
|
||||||
|
struct segment* segment = &segments[segments_count++];
|
||||||
|
segment->match_directory = pattern[offset + segment_length - 1] == '/';
|
||||||
|
// Trivial segments just contain the pattern indices to directly open.
|
||||||
|
if ( (segment->trivial = is_trivial) )
|
||||||
|
{
|
||||||
|
segment->start = offset;
|
||||||
|
segment->length = segment_length;
|
||||||
|
}
|
||||||
|
// Non-trivial segments are translated to a regular expression that is
|
||||||
|
// compiled right now so it can be efficiently reused during the search.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Match a leading period only if the pattern explicitly starts with
|
||||||
|
// a period. POSIX requires that leading periods aren't matched by
|
||||||
|
// the * and ? and [ operators, but also are not matched by negated
|
||||||
|
// patterns like [^a]. It's unspecified whether [.] would match a
|
||||||
|
// leading period. Although regular expressions can express such
|
||||||
|
// patterns, it's difficult to translate, and it's much easier to
|
||||||
|
// just special case the leading period like this.
|
||||||
|
segment->leading_period = pattern[offset] == '.';
|
||||||
|
char* re = NULL;
|
||||||
|
size_t re_size;
|
||||||
|
FILE* fp = open_memstream(&re, &re_size);
|
||||||
|
bool escaped = false;
|
||||||
|
fputc('^', fp);
|
||||||
|
// Translate the pattern to an extended regular expression.
|
||||||
|
for ( size_t i = 0; fp && i < segment_length; i++ )
|
||||||
|
{
|
||||||
|
unsigned char c = pattern[offset + i];
|
||||||
|
if ( !escaped && c == '*' )
|
||||||
|
fputs(".*", fp);
|
||||||
|
else if ( !escaped && c == '?' )
|
||||||
|
fputs(".", fp);
|
||||||
|
else if ( !escaped && c == '[' )
|
||||||
|
{
|
||||||
|
// The whole character range is passed directly to regcomp
|
||||||
|
// so the correct end just has to be found, taking the edge
|
||||||
|
// cases into account. POSIX requires using ! instead of ^
|
||||||
|
// for character range negations. As an extension, ^ is
|
||||||
|
// also just passed directly to regcomp and works.
|
||||||
|
const char* expr = pattern + offset + i;
|
||||||
|
size_t max = segment_length - i;
|
||||||
|
size_t len = 1;
|
||||||
|
if ( len < max && (expr[len] == '!' || expr[len] == '^') )
|
||||||
|
len++;
|
||||||
|
if ( len < max && expr[len] == ']' )
|
||||||
|
len++;
|
||||||
|
while ( len < max && expr[len] != ']' )
|
||||||
|
{
|
||||||
|
if ( 2 <= max - len && expr[len] == '[' &&
|
||||||
|
(expr[len + 1] == '.' || expr[len + 1] == '=' ||
|
||||||
|
expr[len + 1] == ':' ) )
|
||||||
|
{
|
||||||
|
char t = expr[len + 1];
|
||||||
|
len += 2;
|
||||||
|
while ( 2 <= max - len &&
|
||||||
|
!(expr[len] == t && expr[len + 1] == ']') )
|
||||||
|
len++;
|
||||||
|
len += max - len < 2 ? max - len : 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
if ( len < max && expr[len] == ']' )
|
||||||
|
{
|
||||||
|
for ( size_t n = 0; n <= len; n++ )
|
||||||
|
{
|
||||||
|
if ( n == 1 && expr[n] == '!' )
|
||||||
|
fputc('^', fp);
|
||||||
|
else
|
||||||
|
fputc((unsigned char) expr[n], fp);
|
||||||
|
}
|
||||||
|
i += len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fputs("\\[", fp);
|
||||||
|
}
|
||||||
|
else if ( !escaped && c == '\\' && !(flags & GLOB_NOESCAPE) )
|
||||||
|
escaped = true;
|
||||||
|
else if ( c != '/' )
|
||||||
|
{
|
||||||
|
if ( c == '\\' || c == '(' || c == ')' || c == '{' ||
|
||||||
|
c == '}' || c == '.' || c == '*' || c == '[' ||
|
||||||
|
c == ']' || c == '^' || c == '$' || c == '+' ||
|
||||||
|
c == '?' || c == '|' )
|
||||||
|
fputc('\\', fp);
|
||||||
|
fputc(c, fp);
|
||||||
|
escaped = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputc('$', fp);
|
||||||
|
if ( !fp || ferror(fp) || fflush(fp) == EOF )
|
||||||
|
{
|
||||||
|
if ( fp )
|
||||||
|
fclose(fp);
|
||||||
|
free(re);
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
segments_count--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
// Compile and reuse the regular expression for this segment.
|
||||||
|
int ret = regcomp(&segment->regex, re, REG_EXTENDED);
|
||||||
|
free(re);
|
||||||
|
if ( ret )
|
||||||
|
{
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
segments_count--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += segment_length;
|
||||||
|
}
|
||||||
|
// Start the search with the first segment.
|
||||||
|
if ( !result && segments_count )
|
||||||
|
{
|
||||||
|
segments[0].prefix = NULL;
|
||||||
|
segments[0].prefix_length = 0;
|
||||||
|
segments[0].dir = NULL;
|
||||||
|
segments[0].done = false;
|
||||||
|
// If the first segment is non-trivial then the current working
|
||||||
|
// directory needs to be opened and searched.
|
||||||
|
if ( !segments[0].trivial && !(segments[0].dir = opendir(".")) )
|
||||||
|
{
|
||||||
|
if ( errno == ENOMEM )
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
else if ( (errfunc && errfunc(".", errno)) || (flags & GLOB_ERR) )
|
||||||
|
result = GLOB_ABORTED;
|
||||||
|
else
|
||||||
|
segments[0].done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Search the filesystem depth first for paths matching the pattern. The
|
||||||
|
// segments array is used for the hierarchical state to avoid recursion.
|
||||||
|
// Each active segment has a directory currently being searched and yields
|
||||||
|
// paths to be explored by the subsequent segment. The last segment adds
|
||||||
|
// paths to the output array if they match the pattern. The search is
|
||||||
|
// complete when the outermost segment is done or has failed.
|
||||||
|
size_t current_segment = 0;
|
||||||
|
while ( segments_count &&
|
||||||
|
(current_segment || !(segments[0].done || result) ))
|
||||||
|
{
|
||||||
|
struct segment* segment = &segments[current_segment];
|
||||||
|
// Pop to the the parent segment if the directory has been searched or
|
||||||
|
// if an error has happened and the search is aborting.
|
||||||
|
if ( segment->done || result )
|
||||||
|
{
|
||||||
|
free(segment->prefix);
|
||||||
|
segment->prefix = NULL;
|
||||||
|
if ( segment->dir )
|
||||||
|
closedir(segment->dir);
|
||||||
|
current_segment--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char* name;
|
||||||
|
size_t name_length;
|
||||||
|
unsigned char type = DT_UNKNOWN;
|
||||||
|
// A trivial segment yields only the singular path it can match.
|
||||||
|
if ( segment->trivial )
|
||||||
|
{
|
||||||
|
name = strndup(pattern + segment->start, segment->length);
|
||||||
|
name_length = segment->length;
|
||||||
|
segment->done = true;
|
||||||
|
}
|
||||||
|
// Search the directory for entries matching the pattern.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
struct dirent* entry = readdir(segment->dir);
|
||||||
|
if ( !entry )
|
||||||
|
{
|
||||||
|
const char* path = segment->prefix ? segment->prefix : ".";
|
||||||
|
if ( errno == ENOMEM )
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
else if ( (errfunc && errfunc(path, errno)) ||
|
||||||
|
(flags & GLOB_ERR) )
|
||||||
|
result = GLOB_ABORTED;
|
||||||
|
segment->done = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Skip known non-directories when a directory needs to be found.
|
||||||
|
if ( (current_segment + 1 < segments_count ||
|
||||||
|
segment->match_directory) &&
|
||||||
|
entry->d_type != DT_UNKNOWN &&
|
||||||
|
entry->d_type != DT_DIR &&
|
||||||
|
entry->d_type != DT_LNK )
|
||||||
|
continue;
|
||||||
|
if ( !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") )
|
||||||
|
continue;
|
||||||
|
if ( entry->d_name[0] == '.' && !segment->leading_period )
|
||||||
|
continue;
|
||||||
|
if ( regexec(&segment->regex, entry->d_name, 0, NULL, 0) )
|
||||||
|
continue;
|
||||||
|
name = strdup(entry->d_name);
|
||||||
|
name_length = strlen(entry->d_name);
|
||||||
|
type = entry->d_type;
|
||||||
|
}
|
||||||
|
if ( !name )
|
||||||
|
{
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Append the segment's prefix with the name but keep an extra byte for
|
||||||
|
// a possible trailing slash and of course the terminating nul byte.
|
||||||
|
size_t size = 0;
|
||||||
|
if ( __builtin_add_overflow(segment->prefix_length, name_length,
|
||||||
|
&size) ||
|
||||||
|
__builtin_add_overflow(size, 1 + 1, &size) )
|
||||||
|
{
|
||||||
|
free(name);
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char* path = malloc(size);
|
||||||
|
if ( !path )
|
||||||
|
{
|
||||||
|
free(name);
|
||||||
|
free(path);
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( segment->prefix_length )
|
||||||
|
memcpy(path, segment->prefix, segment->prefix_length);
|
||||||
|
memcpy(path + segment->prefix_length, name, name_length);
|
||||||
|
path[segment->prefix_length + name_length] = '\0';
|
||||||
|
int fd = segment->dir ? dirfd(segment->dir) : AT_FDCWD;
|
||||||
|
// If this is not the last segment, push to the next segment to search
|
||||||
|
// the directory just found.
|
||||||
|
if ( current_segment + 1 < segments_count )
|
||||||
|
{
|
||||||
|
struct segment* next_segment = &segments[current_segment + 1];
|
||||||
|
int mode = next_segment->trivial ? O_SEARCH : O_RDONLY;
|
||||||
|
int subdirfd = openat(fd, name, mode | O_DIRECTORY | O_CLOEXEC);
|
||||||
|
free(name);
|
||||||
|
next_segment->dir = subdirfd < 0 ? NULL : fdopendir(subdirfd);
|
||||||
|
if ( !next_segment->dir )
|
||||||
|
{
|
||||||
|
if ( 0 <= subdirfd )
|
||||||
|
close(subdirfd);
|
||||||
|
if ( errno != ENOENT && errno != ENOTDIR &&
|
||||||
|
((errfunc && errfunc(path, errno)) || (flags & GLOB_ERR)) )
|
||||||
|
result = GLOB_ABORTED;
|
||||||
|
free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
next_segment->prefix = path;
|
||||||
|
next_segment->prefix_length = size - 2;
|
||||||
|
// Add a trailing slash to the searched directory entries.
|
||||||
|
if ( !segment->trivial )
|
||||||
|
{
|
||||||
|
next_segment->prefix[next_segment->prefix_length++] = '/';
|
||||||
|
next_segment->prefix[next_segment->prefix_length] = '\0';
|
||||||
|
}
|
||||||
|
next_segment->done = false;
|
||||||
|
current_segment++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// The last segment just needs to output paths if they exist.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool want_slash = (flags & GLOB_MARK) || segment->match_directory;
|
||||||
|
bool exists = true, is_dir = false;
|
||||||
|
// The path is known to already exist for non-trivial segments since
|
||||||
|
// it was returned by readdir, but we may need to check if the path
|
||||||
|
// is a directory if readdir didn't tell us already.
|
||||||
|
if ( !segment->trivial &&
|
||||||
|
(!want_slash || (type != DT_UNKNOWN && type != DT_LNK)) )
|
||||||
|
is_dir = type == DT_DIR;
|
||||||
|
// Just check if the path exists if we don't add slashes to dirs.
|
||||||
|
else if ( !want_slash )
|
||||||
|
exists = !faccessat(fd, name, F_OK, AT_SYMLINK_NOFOLLOW);
|
||||||
|
// Otherwise use the slower stat operation to obtain the inode type.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
exists = !fstatat(fd, name, &st, AT_SYMLINK_NOFOLLOW);
|
||||||
|
if ( want_slash && S_ISLNK(st.st_mode) )
|
||||||
|
fstatat(fd, name, &st, 0);
|
||||||
|
is_dir = S_ISDIR(st.st_mode);
|
||||||
|
}
|
||||||
|
free(name);
|
||||||
|
if ( segment->match_directory && !is_dir )
|
||||||
|
{
|
||||||
|
free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( want_slash && path[size - 3] != '/' )
|
||||||
|
path[size - 2] = '/', path[size - 1] = '\0';
|
||||||
|
if ( !exists )
|
||||||
|
{
|
||||||
|
if ( errno != ENOENT &&
|
||||||
|
((errfunc && errfunc(path, errno)) || (flags & GLOB_ERR)) )
|
||||||
|
result = GLOB_ABORTED;
|
||||||
|
free(path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Grow the output array as needed.
|
||||||
|
if ( gl->gl_pathc == paths_length )
|
||||||
|
{
|
||||||
|
size_t old_pathc = gl->gl_pathc ? gl->gl_pathc : 1;
|
||||||
|
if ( __builtin_mul_overflow(2, old_pathc, &pathl) ||
|
||||||
|
__builtin_add_overflow(gl->gl_offs, pathl, &pathl) ||
|
||||||
|
__builtin_add_overflow(1, pathl, &pathl) ||
|
||||||
|
!(new_pathv = reallocarray(gl->gl_pathv, pathl,
|
||||||
|
sizeof(char*))) )
|
||||||
|
{
|
||||||
|
free(path);
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gl->gl_pathv = new_pathv;
|
||||||
|
paths_length = old_pathc * 2;
|
||||||
|
}
|
||||||
|
gl->gl_pathv[gl->gl_offs + gl->gl_pathc++] = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Clean up the segments and free the compiled regular expressions.
|
||||||
|
if ( segments_count && segments[0].dir )
|
||||||
|
closedir(segments[0].dir);
|
||||||
|
for ( size_t i = 0; i < segments_count; i++ )
|
||||||
|
if ( !segments[i].trivial )
|
||||||
|
regfree(&segments[i].regex);
|
||||||
|
free(segments);
|
||||||
|
// Output the input pattern if nothing matched when GLOB_NOCHECK.
|
||||||
|
if ( !result && gl->gl_pathc == initial_pathc )
|
||||||
|
{
|
||||||
|
if ( (flags & GLOB_NOCHECK) )
|
||||||
|
{
|
||||||
|
if ( (gl->gl_pathv[gl->gl_offs] = strdup(pattern)) )
|
||||||
|
gl->gl_pathc = 1;
|
||||||
|
else
|
||||||
|
result = GLOB_NOSPACE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = GLOB_NOMATCH;
|
||||||
|
}
|
||||||
|
// Sort the new entries per LC_COLLATE per POSIX.
|
||||||
|
if ( !(flags & GLOB_NOSORT) )
|
||||||
|
qsort(gl->gl_pathv + gl->gl_offs + initial_pathc,
|
||||||
|
gl->gl_pathc - initial_pathc, sizeof(char*),
|
||||||
|
strcoll_indirect);
|
||||||
|
gl->gl_pathv[gl->gl_offs + gl->gl_pathc] = NULL;
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* glob/globfree.c
|
||||||
|
* Free allocate glob storage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glob.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void globfree(glob_t* gl)
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; i < gl->gl_pathc; i++ )
|
||||||
|
free(gl->gl_pathv[gl->gl_offs + i]);
|
||||||
|
free(gl->gl_pathv);
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -18,9 +18,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
FILE* opengr(void)
|
FILE* opengr(void)
|
||||||
{
|
{
|
||||||
return fopen("/etc/group", "r");
|
return __openent("/etc/group");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,8 +24,9 @@ FILE* __grp_file = NULL;
|
||||||
|
|
||||||
void setgrent(void)
|
void setgrent(void)
|
||||||
{
|
{
|
||||||
if ( __grp_file )
|
FILE* new_file = opengr();
|
||||||
|
if ( !new_file && __grp_file )
|
||||||
rewind(__grp_file);
|
rewind(__grp_file);
|
||||||
else
|
else
|
||||||
__grp_file = opengr();
|
__grp_file = new_file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* glob.h
|
||||||
|
* Search for paths matching a pattern.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_GLOB_H
|
||||||
|
#define _INCLUDE_GLOB_H
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#ifndef __size_t_defined
|
||||||
|
#define __size_t_defined
|
||||||
|
#define __need_size_t
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t gl_pathc;
|
||||||
|
char** gl_pathv;
|
||||||
|
size_t gl_offs;
|
||||||
|
} glob_t;
|
||||||
|
|
||||||
|
#define GLOB_APPEND (1 << 0)
|
||||||
|
#define GLOB_DOOFFS (1 << 1)
|
||||||
|
#define GLOB_ERR (1 << 2)
|
||||||
|
#define GLOB_MARK (1 << 3)
|
||||||
|
#define GLOB_NOCHECK (1 << 4)
|
||||||
|
#define GLOB_NOESCAPE (1 << 5)
|
||||||
|
#define GLOB_NOSORT (1 << 6)
|
||||||
|
|
||||||
|
#define GLOB_ABORTED 1
|
||||||
|
#define GLOB_NOMATCH 2
|
||||||
|
#define GLOB_NOSPACE 3
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int glob(const char* __restrict, int, int (*)(const char *, int),
|
||||||
|
glob_t* __restrict);
|
||||||
|
void globfree(glob_t*);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -62,6 +62,8 @@ struct passwd
|
||||||
|
|
||||||
#if defined(__is_sortix_libc)
|
#if defined(__is_sortix_libc)
|
||||||
extern FILE* __pwd_file;
|
extern FILE* __pwd_file;
|
||||||
|
|
||||||
|
FILE* __openent(const char*);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int bcrypt_newhash(const char*, int, char*, size_t);
|
int bcrypt_newhash(const char*, int, char*, size_t);
|
||||||
|
@ -79,6 +81,7 @@ int getpwnam_r(const char* __restrict, struct passwd* __restrict,
|
||||||
struct passwd* getpwuid(uid_t);
|
struct passwd* getpwuid(uid_t);
|
||||||
int getpwuid_r(uid_t, struct passwd* __restrict, char* __restrict, size_t,
|
int getpwuid_r(uid_t, struct passwd* __restrict, char* __restrict, size_t,
|
||||||
struct passwd** __restrict);
|
struct passwd** __restrict);
|
||||||
|
int scanpwent(char* __restrict, struct passwd* __restrict);
|
||||||
FILE* openpw(void);
|
FILE* openpw(void);
|
||||||
void setpwent(void);
|
void setpwent(void);
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,9 @@ int getaddrinfo(const char* restrict node,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement missing flags.
|
// TODO: Implement missing flags.
|
||||||
int supported = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_CANONNAME;
|
// TODO: Revisit AI_ADDRCONFIG when IPv6 is implemented.
|
||||||
|
int supported = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV |
|
||||||
|
AI_CANONNAME | AI_ADDRCONFIG;
|
||||||
if ( flags & ~supported )
|
if ( flags & ~supported )
|
||||||
return EAI_BADFLAGS;
|
return EAI_BADFLAGS;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pwd/__openent.c
|
||||||
|
* Preprocesses include statements in an entry database.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <glob.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
bool __openent_append(FILE* out, const char* path)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen(path, "r");
|
||||||
|
if ( !fp )
|
||||||
|
return false;
|
||||||
|
char* line = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
ssize_t amount;
|
||||||
|
bool success = true;
|
||||||
|
while ( success && 0 < (amount = getline(&line, &size, fp)) )
|
||||||
|
{
|
||||||
|
size_t length = amount;
|
||||||
|
size_t offset = 0;
|
||||||
|
while ( offset < length && isspace((unsigned char) line[offset]) )
|
||||||
|
offset++;
|
||||||
|
if ( !line[offset] || line[offset] == '#' )
|
||||||
|
continue;
|
||||||
|
size_t include_length = strlen("include");
|
||||||
|
if ( !strncmp(line + offset, "include", include_length) &&
|
||||||
|
isspace((unsigned char) line[offset + include_length]) )
|
||||||
|
{
|
||||||
|
while ( length && isspace((unsigned char) line[length - 1]) )
|
||||||
|
line[--length] = '\0';
|
||||||
|
offset = offset + include_length;
|
||||||
|
while ( offset < length && isspace((unsigned char) line[offset]) )
|
||||||
|
offset++;
|
||||||
|
const char* pattern = line + offset;
|
||||||
|
glob_t gl;
|
||||||
|
if ( !glob(pattern, GLOB_NOCHECK, NULL, &gl) )
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; success && i < gl.gl_pathc; i++ )
|
||||||
|
if ( !__openent_append(out, gl.gl_pathv[i]) &&
|
||||||
|
errno != ENOENT )
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
success = false;
|
||||||
|
globfree(&gl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( fwrite(line, 1, length, out) != length )
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
if ( ferror(fp) )
|
||||||
|
success = false;
|
||||||
|
fclose(fp);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* __openent(const char* path)
|
||||||
|
{
|
||||||
|
char* data;
|
||||||
|
size_t size;
|
||||||
|
FILE* memstream = open_memstream(&data, &size);
|
||||||
|
if ( !memstream )
|
||||||
|
return NULL;
|
||||||
|
if ( !__openent_append(memstream, path) ||
|
||||||
|
ferror(memstream) || fflush(memstream) == EOF )
|
||||||
|
{
|
||||||
|
fclose(memstream);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fclose(memstream);
|
||||||
|
size = strlen(data);
|
||||||
|
FILE* result = fmemopen(NULL, size, "r+");
|
||||||
|
if ( !result )
|
||||||
|
return free(data), NULL;
|
||||||
|
size_t amount = fwrite(data, 1, size, result);
|
||||||
|
free(data);
|
||||||
|
if ( amount != size || fflush(result) == EOF )
|
||||||
|
return fclose(result), NULL;
|
||||||
|
rewind(result);
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -17,70 +17,9 @@
|
||||||
* Reads a passwd entry from a FILE.
|
* Reads a passwd entry from a FILE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static char* next_field(char** current)
|
|
||||||
{
|
|
||||||
char* result = *current;
|
|
||||||
if ( result )
|
|
||||||
{
|
|
||||||
char* next = result;
|
|
||||||
while ( *next && *next != ':' )
|
|
||||||
next++;
|
|
||||||
if ( !*next )
|
|
||||||
next = NULL;
|
|
||||||
else
|
|
||||||
*next++ = '\0';
|
|
||||||
*current = next;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool next_field_uintmax(char** current, uintmax_t* result)
|
|
||||||
{
|
|
||||||
char* id_str = next_field(current);
|
|
||||||
if ( !id_str )
|
|
||||||
return false;
|
|
||||||
char* id_endptr;
|
|
||||||
uintmax_t id_umax = strtoumax(id_str, &id_endptr, 10);
|
|
||||||
if ( *id_endptr )
|
|
||||||
return false;
|
|
||||||
*result = id_umax;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool next_field_gid(char** current, gid_t* result)
|
|
||||||
{
|
|
||||||
uintmax_t id_umax;
|
|
||||||
if ( !next_field_uintmax(current, &id_umax) )
|
|
||||||
return false;
|
|
||||||
gid_t gid = (gid_t) id_umax;
|
|
||||||
if ( (uintmax_t) gid != (uintmax_t) id_umax )
|
|
||||||
return false;
|
|
||||||
*result = gid;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool next_field_uid(char** current, uid_t* result)
|
|
||||||
{
|
|
||||||
uintmax_t id_umax;
|
|
||||||
if ( !next_field_uintmax(current, &id_umax) )
|
|
||||||
return false;
|
|
||||||
uid_t uid = (uid_t) id_umax;
|
|
||||||
if ( (uintmax_t) uid != (uintmax_t) id_umax )
|
|
||||||
return false;
|
|
||||||
*result = uid;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fgetpwent_r(FILE* restrict fp,
|
int fgetpwent_r(FILE* restrict fp,
|
||||||
struct passwd* restrict result,
|
struct passwd* restrict result,
|
||||||
|
@ -144,22 +83,7 @@ int fgetpwent_r(FILE* restrict fp,
|
||||||
}
|
}
|
||||||
buf[buf_used] = '\0';
|
buf[buf_used] = '\0';
|
||||||
|
|
||||||
char* parse_str = buf;
|
if ( !scanpwent(buf, result) )
|
||||||
if ( !(result->pw_name = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_passwd = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !next_field_uid(&parse_str, &result->pw_uid) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !next_field_gid(&parse_str, &result->pw_gid) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_gecos = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_dir = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_shell = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( parse_str )
|
|
||||||
goto parse_failure;
|
goto parse_failure;
|
||||||
|
|
||||||
funlockfile(fp);
|
funlockfile(fp);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -22,5 +22,5 @@
|
||||||
|
|
||||||
FILE* openpw(void)
|
FILE* openpw(void)
|
||||||
{
|
{
|
||||||
return fopen("/etc/passwd", "r");
|
return __openent("/etc/passwd");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pwd/scanfpwent.c
|
||||||
|
* Parse passwd entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
static char* next_field(char** current)
|
||||||
|
{
|
||||||
|
char* result = *current;
|
||||||
|
if ( result )
|
||||||
|
{
|
||||||
|
char* next = result;
|
||||||
|
while ( *next && *next != ':' )
|
||||||
|
next++;
|
||||||
|
if ( !*next )
|
||||||
|
next = NULL;
|
||||||
|
else
|
||||||
|
*next++ = '\0';
|
||||||
|
*current = next;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next_field_uintmax(char** current, uintmax_t* result)
|
||||||
|
{
|
||||||
|
char* id_str = next_field(current);
|
||||||
|
if ( !id_str )
|
||||||
|
return false;
|
||||||
|
char* id_endptr;
|
||||||
|
uintmax_t id_umax = strtoumax(id_str, &id_endptr, 10);
|
||||||
|
if ( *id_endptr )
|
||||||
|
return false;
|
||||||
|
*result = id_umax;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next_field_gid(char** current, gid_t* result)
|
||||||
|
{
|
||||||
|
uintmax_t id_umax;
|
||||||
|
if ( !next_field_uintmax(current, &id_umax) )
|
||||||
|
return false;
|
||||||
|
gid_t gid = (gid_t) id_umax;
|
||||||
|
if ( (uintmax_t) gid != (uintmax_t) id_umax )
|
||||||
|
return false;
|
||||||
|
*result = gid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next_field_uid(char** current, uid_t* result)
|
||||||
|
{
|
||||||
|
uintmax_t id_umax;
|
||||||
|
if ( !next_field_uintmax(current, &id_umax) )
|
||||||
|
return false;
|
||||||
|
uid_t uid = (uid_t) id_umax;
|
||||||
|
if ( (uintmax_t) uid != (uintmax_t) id_umax )
|
||||||
|
return false;
|
||||||
|
*result = uid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scanpwent(char* str, struct passwd* passwd)
|
||||||
|
{
|
||||||
|
while ( *str && isspace((unsigned char) *str) )
|
||||||
|
str++;
|
||||||
|
if ( !*str || *str == '#' ||
|
||||||
|
!(passwd->pw_name = next_field(&str)) ||
|
||||||
|
!(passwd->pw_passwd = next_field(&str)) ||
|
||||||
|
!next_field_uid(&str, &passwd->pw_uid) ||
|
||||||
|
!next_field_gid(&str, &passwd->pw_gid) ||
|
||||||
|
!(passwd->pw_gecos = next_field(&str)) ||
|
||||||
|
!(passwd->pw_dir = next_field(&str)) ||
|
||||||
|
!(passwd->pw_shell = next_field(&str)) )
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,8 +24,9 @@ FILE* __pwd_file = NULL;
|
||||||
|
|
||||||
void setpwent(void)
|
void setpwent(void)
|
||||||
{
|
{
|
||||||
if ( __pwd_file )
|
FILE* new_file = openpw();
|
||||||
|
if ( !new_file && __pwd_file )
|
||||||
rewind(__pwd_file);
|
rewind(__pwd_file);
|
||||||
else
|
else
|
||||||
__pwd_file = openpw();
|
__pwd_file = new_file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -114,7 +114,7 @@ static off_t fmemopen_seek(void* state_ptr, off_t offset, int whence)
|
||||||
case SEEK_END: base = (off_t) state->buffer_used; break;
|
case SEEK_END: base = (off_t) state->buffer_used; break;
|
||||||
default: return errno = EINVAL, -1;
|
default: return errno = EINVAL, -1;
|
||||||
}
|
}
|
||||||
if ( offset < -base || base - (off_t) state->buffer_size < offset )
|
if ( offset < -base || (off_t) state->buffer_size - base < offset )
|
||||||
return errno = EOVERFLOW, -1;
|
return errno = EOVERFLOW, -1;
|
||||||
return (off_t) (state->buffer_offset = (size_t) (base + offset));
|
return (off_t) (state->buffer_offset = (size_t) (base + offset));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
@@ -468,8 +471,12 @@
|
@@ -467,8 +470,12 @@
|
||||||
} else {
|
} else {
|
||||||
strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
|
strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
|
||||||
UNIX_DG_TMP_SOCKET_SIZE);
|
UNIX_DG_TMP_SOCKET_SIZE);
|
||||||
|
@ -26,7 +26,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
|
unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1403,7 +1410,8 @@
|
@@ -1385,7 +1392,8 @@
|
||||||
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
|
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
|
||||||
memset(&iov, 0, sizeof(iov));
|
memset(&iov, 0, sizeof(iov));
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
mh.msg_controllen = sizeof(cmsgbuf.buf);
|
mh.msg_controllen = sizeof(cmsgbuf.buf);
|
||||||
cmsg = CMSG_FIRSTHDR(&mh);
|
cmsg = CMSG_FIRSTHDR(&mh);
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
@@ -1440,6 +1448,7 @@
|
@@ -1422,6 +1430,7 @@
|
||||||
void
|
void
|
||||||
atelnet(int nfd, unsigned char *buf, unsigned int size)
|
atelnet(int nfd, unsigned char *buf, unsigned int size)
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
unsigned char *p, *end;
|
unsigned char *p, *end;
|
||||||
unsigned char obuf[4];
|
unsigned char obuf[4];
|
||||||
|
|
||||||
@@ -1465,6 +1474,9 @@
|
@@ -1447,6 +1456,9 @@
|
||||||
if (atomicio(vwrite, nfd, obuf, 3) != 3)
|
if (atomicio(vwrite, nfd, obuf, 3) != 3)
|
||||||
warn("Write Error!");
|
warn("Write Error!");
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -1578,16 +1590,20 @@
|
@@ -1590,16 +1602,20 @@
|
||||||
err(1, NULL);
|
err(1, NULL);
|
||||||
}
|
}
|
||||||
if (Tflag != -1) {
|
if (Tflag != -1) {
|
||||||
|
@ -77,7 +77,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
errno = ENOPROTOOPT;
|
errno = ENOPROTOOPT;
|
||||||
err(1, "set IPv6 traffic class not supported");
|
err(1, "set IPv6 traffic class not supported");
|
||||||
}
|
}
|
||||||
@@ -1605,13 +1621,16 @@
|
@@ -1617,13 +1633,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ttl != -1) {
|
if (ttl != -1) {
|
||||||
|
@ -96,7 +96,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minttl != -1) {
|
if (minttl != -1) {
|
||||||
@@ -1649,7 +1668,9 @@
|
@@ -1661,7 +1680,9 @@
|
||||||
{ "af41", IPTOS_DSCP_AF41 },
|
{ "af41", IPTOS_DSCP_AF41 },
|
||||||
{ "af42", IPTOS_DSCP_AF42 },
|
{ "af42", IPTOS_DSCP_AF42 },
|
||||||
{ "af43", IPTOS_DSCP_AF43 },
|
{ "af43", IPTOS_DSCP_AF43 },
|
||||||
|
@ -106,7 +106,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/nc/netcat.c libssl/apps/nc/n
|
||||||
{ "cs0", IPTOS_DSCP_CS0 },
|
{ "cs0", IPTOS_DSCP_CS0 },
|
||||||
{ "cs1", IPTOS_DSCP_CS1 },
|
{ "cs1", IPTOS_DSCP_CS1 },
|
||||||
{ "cs2", IPTOS_DSCP_CS2 },
|
{ "cs2", IPTOS_DSCP_CS2 },
|
||||||
@@ -1659,11 +1680,21 @@
|
@@ -1671,11 +1692,21 @@
|
||||||
{ "cs6", IPTOS_DSCP_CS6 },
|
{ "cs6", IPTOS_DSCP_CS6 },
|
||||||
{ "cs7", IPTOS_DSCP_CS7 },
|
{ "cs7", IPTOS_DSCP_CS7 },
|
||||||
{ "ef", IPTOS_DSCP_EF },
|
{ "ef", IPTOS_DSCP_EF },
|
||||||
|
@ -214,6 +214,20 @@ diff -Paur --no-dereference -- libssl.upstream/apps/openssl/s_socket.c libssl/ap
|
||||||
static int init_server(int *sock, int port, int type);
|
static int init_server(int *sock, int port, int type);
|
||||||
static int init_server_long(int *sock, int port, char *ip, int type);
|
static int init_server_long(int *sock, int port, char *ip, int type);
|
||||||
static int do_accept(int acc_sock, int *sock);
|
static int do_accept(int acc_sock, int *sock);
|
||||||
|
diff -Paur --no-dereference -- libssl.upstream/configure libssl/configure
|
||||||
|
--- libssl.upstream/configure
|
||||||
|
+++ libssl/configure
|
||||||
|
@@ -11775,6 +11775,10 @@
|
||||||
|
HOST_OS=midipix
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_SOURCE -D_GNU_SOURCE"
|
||||||
|
;;
|
||||||
|
+ *sortix*)
|
||||||
|
+ HOST_OS=sortix
|
||||||
|
+ HOST_ABI=elf
|
||||||
|
+ ;;
|
||||||
|
*netbsd*)
|
||||||
|
HOST_OS=netbsd
|
||||||
|
HOST_ABI=elf
|
||||||
diff -Paur --no-dereference -- libssl.upstream/crypto/bio/b_sock.c libssl/crypto/bio/b_sock.c
|
diff -Paur --no-dereference -- libssl.upstream/crypto/bio/b_sock.c libssl/crypto/bio/b_sock.c
|
||||||
--- libssl.upstream/crypto/bio/b_sock.c
|
--- libssl.upstream/crypto/bio/b_sock.c
|
||||||
+++ libssl/crypto/bio/b_sock.c
|
+++ libssl/crypto/bio/b_sock.c
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
NAME=libssl
|
NAME=libssl
|
||||||
BUILD_LIBRARIES=
|
BUILD_LIBRARIES=
|
||||||
VERSION=3.7.0
|
VERSION=3.7.1
|
||||||
DISTNAME=libressl-$VERSION
|
DISTNAME=libressl-$VERSION
|
||||||
COMPRESSION=tar.gz
|
COMPRESSION=tar.gz
|
||||||
ARCHIVE=$DISTNAME.$COMPRESSION
|
ARCHIVE=$DISTNAME.$COMPRESSION
|
||||||
SHA256SUM=3fc1290f4007ec75f6e9acecbb25512630d1b9ab8c53ba79844e395868c3e006
|
SHA256SUM=98086961a2b8b657ed0fea3056fb2db14294b6bfa193c15a5236a0a35c843ded
|
||||||
UPSTREAM_SITE=https://ftp.openbsd.org/pub/OpenBSD/LibreSSL
|
UPSTREAM_SITE=https://ftp.openbsd.org/pub/OpenBSD/LibreSSL
|
||||||
UPSTREAM_ARCHIVE=$ARCHIVE
|
UPSTREAM_ARCHIVE=$ARCHIVE
|
||||||
LICENSE=OpenSSL
|
LICENSE=OpenSSL
|
||||||
|
|
|
@ -157,77 +157,3 @@ diff -Paur --no-dereference -- libxml2.upstream/nanohttp.c libxml2/nanohttp.c
|
||||||
{
|
{
|
||||||
struct hostent *h;
|
struct hostent *h;
|
||||||
struct in_addr ia;
|
struct in_addr ia;
|
||||||
diff -Paur --no-dereference -- libxml2.upstream/runtest.c libxml2/runtest.c
|
|
||||||
--- libxml2.upstream/runtest.c
|
|
||||||
+++ libxml2/runtest.c
|
|
||||||
@@ -198,6 +198,33 @@
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#elif defined(__sortix__)
|
|
||||||
+
|
|
||||||
+typedef struct
|
|
||||||
+{
|
|
||||||
+ size_t gl_pathc; /* Count of paths matched so far */
|
|
||||||
+ char **gl_pathv; /* List of matched pathnames. */
|
|
||||||
+ size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
|
|
||||||
+} glob_t;
|
|
||||||
+
|
|
||||||
+#define GLOB_DOOFFS 0
|
|
||||||
+static int glob(const char *pattern, int flags,
|
|
||||||
+ int errfunc(const char *epath, int eerrno),
|
|
||||||
+ glob_t *pglob) {
|
|
||||||
+ (void) pattern;
|
|
||||||
+ (void) flags;
|
|
||||||
+ (void) errfunc;
|
|
||||||
+ (void) pglob;
|
|
||||||
+ pglob->gl_pathc = 0;
|
|
||||||
+ pglob->gl_pathv = NULL;
|
|
||||||
+ pglob->gl_offs = 0;
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void globfree(glob_t *pglob) {
|
|
||||||
+ (void) pglob;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
#else
|
|
||||||
#include <glob.h>
|
|
||||||
#endif
|
|
||||||
diff -Paur --no-dereference -- libxml2.upstream/testrecurse.c libxml2/testrecurse.c
|
|
||||||
--- libxml2.upstream/testrecurse.c
|
|
||||||
+++ libxml2/testrecurse.c
|
|
||||||
@@ -146,6 +146,33 @@
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#elif defined(__sortix__)
|
|
||||||
+
|
|
||||||
+typedef struct
|
|
||||||
+{
|
|
||||||
+ size_t gl_pathc; /* Count of paths matched so far */
|
|
||||||
+ char **gl_pathv; /* List of matched pathnames. */
|
|
||||||
+ size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
|
|
||||||
+} glob_t;
|
|
||||||
+
|
|
||||||
+#define GLOB_DOOFFS 0
|
|
||||||
+static int glob(const char *pattern, int flags,
|
|
||||||
+ int errfunc(const char *epath, int eerrno),
|
|
||||||
+ glob_t *pglob) {
|
|
||||||
+ (void) pattern;
|
|
||||||
+ (void) flags;
|
|
||||||
+ (void) errfunc;
|
|
||||||
+ (void) pglob;
|
|
||||||
+ pglob->gl_pathc = 0;
|
|
||||||
+ pglob->gl_pathv = NULL;
|
|
||||||
+ pglob->gl_offs = 0;
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void globfree(glob_t *pglob) {
|
|
||||||
+ (void) pglob;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
#else
|
|
||||||
#include <glob.h>
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -313,7 +313,7 @@ diff -Paur --no-dereference -- mdocml.upstream/eqn.c mdocml/eqn.c
|
||||||
diff -Paur --no-dereference -- mdocml.upstream/main.c mdocml/main.c
|
diff -Paur --no-dereference -- mdocml.upstream/main.c mdocml/main.c
|
||||||
--- mdocml.upstream/main.c
|
--- mdocml.upstream/main.c
|
||||||
+++ mdocml/main.c
|
+++ mdocml/main.c
|
||||||
@@ -19,14 +19,16 @@
|
@@ -19,7 +19,6 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -321,50 +321,7 @@ diff -Paur --no-dereference -- mdocml.upstream/main.c mdocml/main.c
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
@@ -606,7 +605,38 @@
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
+/* PATCH: Sortix doesn't have glob.h at this time. */
|
|
||||||
+#if defined(__has_include) && __has_include(<glob.h>)
|
|
||||||
#include <glob.h>
|
|
||||||
+#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
@@ -531,10 +533,16 @@
|
|
||||||
const char *sec, const char *arch, const char *name,
|
|
||||||
struct manpage **res, size_t *ressz)
|
|
||||||
{
|
|
||||||
+#if defined(__has_include) && __has_include(<glob.h>)
|
|
||||||
glob_t globinfo;
|
|
||||||
+#endif
|
|
||||||
struct manpage *page;
|
|
||||||
char *file;
|
|
||||||
+#if defined(__has_include) && __has_include(<glob.h>)
|
|
||||||
int form, globres;
|
|
||||||
+#else
|
|
||||||
+ int form;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
form = FORM_SRC;
|
|
||||||
mandoc_asprintf(&file, "%s/man%s/%s.%s",
|
|
||||||
@@ -559,6 +567,7 @@
|
|
||||||
free(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if defined(__has_include) && __has_include(<glob.h>)
|
|
||||||
mandoc_asprintf(&file, "%s/man%s/%s.*",
|
|
||||||
paths->paths[ipath], sec, name);
|
|
||||||
globres = glob(file, 0, NULL, &globinfo);
|
|
||||||
@@ -570,6 +579,7 @@
|
|
||||||
file = mandoc_strdup(*globinfo.gl_pathv);
|
|
||||||
globfree(&globinfo);
|
|
||||||
if (globres != 0)
|
|
||||||
+#endif
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
found:
|
|
||||||
@@ -606,7 +616,38 @@
|
|
||||||
*res = NULL;
|
*res = NULL;
|
||||||
*ressz = lastsz = 0;
|
*ressz = lastsz = 0;
|
||||||
while (argc) {
|
while (argc) {
|
||||||
|
@ -404,7 +361,7 @@ diff -Paur --no-dereference -- mdocml.upstream/main.c mdocml/main.c
|
||||||
if (cfg->sec != NULL) {
|
if (cfg->sec != NULL) {
|
||||||
if (fs_lookup(paths, ipath, cfg->sec,
|
if (fs_lookup(paths, ipath, cfg->sec,
|
||||||
cfg->arch, *argv, res, ressz) &&
|
cfg->arch, *argv, res, ressz) &&
|
||||||
@@ -989,7 +1030,7 @@
|
@@ -989,7 +1019,7 @@
|
||||||
if (pager == NULL || *pager == '\0')
|
if (pager == NULL || *pager == '\0')
|
||||||
pager = getenv("PAGER");
|
pager = getenv("PAGER");
|
||||||
if (pager == NULL || *pager == '\0')
|
if (pager == NULL || *pager == '\0')
|
||||||
|
@ -413,7 +370,7 @@ diff -Paur --no-dereference -- mdocml.upstream/main.c mdocml/main.c
|
||||||
cp = mandoc_strdup(pager);
|
cp = mandoc_strdup(pager);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1014,7 +1055,7 @@
|
@@ -1014,7 +1044,7 @@
|
||||||
/* Hand over to the pager. */
|
/* Hand over to the pager. */
|
||||||
|
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
|
|
|
@ -48,17 +48,7 @@ diff -Paur --no-dereference -- nano.upstream/src/nano.c nano/src/nano.c
|
||||||
diff -Paur --no-dereference -- nano.upstream/src/rcfile.c nano/src/rcfile.c
|
diff -Paur --no-dereference -- nano.upstream/src/rcfile.c nano/src/rcfile.c
|
||||||
--- nano.upstream/src/rcfile.c
|
--- nano.upstream/src/rcfile.c
|
||||||
+++ nano/src/rcfile.c
|
+++ nano/src/rcfile.c
|
||||||
@@ -27,7 +27,9 @@
|
@@ -577,6 +577,11 @@
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
+#if __has_include(<glob.h>)
|
|
||||||
#include <glob.h>
|
|
||||||
+#endif
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
@@ -577,6 +579,11 @@
|
|
||||||
* null-terminate it, and return a pointer to the succeeding text. */
|
* null-terminate it, and return a pointer to the succeeding text. */
|
||||||
char *parse_next_regex(char *ptr)
|
char *parse_next_regex(char *ptr)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +60,7 @@ diff -Paur --no-dereference -- nano.upstream/src/rcfile.c nano/src/rcfile.c
|
||||||
char *starting_point = ptr;
|
char *starting_point = ptr;
|
||||||
|
|
||||||
if (*(ptr - 1) != '"') {
|
if (*(ptr - 1) != '"') {
|
||||||
@@ -584,11 +591,28 @@
|
@@ -584,11 +589,28 @@
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +93,7 @@ diff -Paur --no-dereference -- nano.upstream/src/rcfile.c nano/src/rcfile.c
|
||||||
|
|
||||||
if (*ptr == '\0') {
|
if (*ptr == '\0') {
|
||||||
jot_error(N_("Regex strings must begin and end with a \" character"));
|
jot_error(N_("Regex strings must begin and end with a \" character"));
|
||||||
@@ -601,7 +625,8 @@
|
@@ -601,7 +623,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Null-terminate the regex and skip until the next non-blank. */
|
/* Null-terminate the regex and skip until the next non-blank. */
|
||||||
|
@ -113,32 +103,3 @@ diff -Paur --no-dereference -- nano.upstream/src/rcfile.c nano/src/rcfile.c
|
||||||
|
|
||||||
while (isblank((unsigned char)*ptr))
|
while (isblank((unsigned char)*ptr))
|
||||||
ptr++;
|
ptr++;
|
||||||
@@ -966,8 +991,10 @@
|
|
||||||
void parse_includes(char *ptr)
|
|
||||||
{
|
|
||||||
char *pattern, *expanded;
|
|
||||||
+#if __has_include(<glob.h>)
|
|
||||||
glob_t files;
|
|
||||||
int result;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
check_for_nonempty_syntax();
|
|
||||||
|
|
||||||
@@ -978,6 +1005,7 @@
|
|
||||||
|
|
||||||
/* Expand a tilde first, then try to match the globbing pattern. */
|
|
||||||
expanded = real_dir_from_tilde(pattern);
|
|
||||||
+#if __has_include(<glob.h>)
|
|
||||||
result = glob(expanded, GLOB_ERR, NULL, &files);
|
|
||||||
|
|
||||||
/* If there are matches, process each of them. Otherwise, only
|
|
||||||
@@ -989,6 +1017,9 @@
|
|
||||||
jot_error(N_("Error expanding %s: %s"), pattern, strerror(errno));
|
|
||||||
|
|
||||||
globfree(&files);
|
|
||||||
+#else
|
|
||||||
+ parse_one_include(expanded);
|
|
||||||
+#endif
|
|
||||||
free(expanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
diff -Paur --no-dereference -- ssh.upstream/auth.c ssh/auth.c
|
diff -Paur --no-dereference -- ssh.upstream/auth.c ssh/auth.c
|
||||||
--- ssh.upstream/auth.c
|
--- ssh.upstream/auth.c
|
||||||
+++ ssh/auth.c
|
+++ ssh/auth.c
|
||||||
@@ -100,7 +100,9 @@
|
@@ -99,7 +99,9 @@
|
||||||
int
|
int
|
||||||
allowed_user(struct ssh *ssh, struct passwd * pw)
|
allowed_user(struct ssh *ssh, struct passwd * pw)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ diff -Paur --no-dereference -- ssh.upstream/auth.c ssh/auth.c
|
||||||
const char *hostname = NULL, *ipaddr = NULL;
|
const char *hostname = NULL, *ipaddr = NULL;
|
||||||
u_int i;
|
u_int i;
|
||||||
int r;
|
int r;
|
||||||
@@ -121,6 +123,8 @@
|
@@ -120,6 +122,8 @@
|
||||||
*/
|
*/
|
||||||
if (options.chroot_directory == NULL ||
|
if (options.chroot_directory == NULL ||
|
||||||
strcasecmp(options.chroot_directory, "none") == 0) {
|
strcasecmp(options.chroot_directory, "none") == 0) {
|
||||||
|
@ -20,7 +20,7 @@ diff -Paur --no-dereference -- ssh.upstream/auth.c ssh/auth.c
|
||||||
char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
|
char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
|
||||||
_PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
|
_PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
|
||||||
|
|
||||||
@@ -138,6 +142,7 @@
|
@@ -137,6 +141,7 @@
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
free(shell);
|
free(shell);
|
||||||
|
@ -83,7 +83,7 @@ diff -Paur --no-dereference -- ssh.upstream/channels.c ssh/channels.c
|
||||||
c->path = xstrdup(host);
|
c->path = xstrdup(host);
|
||||||
} else { /* SOCKS4A: two strings */
|
} else { /* SOCKS4A: two strings */
|
||||||
have = sshbuf_len(input);
|
have = sshbuf_len(input);
|
||||||
@@ -2450,8 +2451,8 @@
|
@@ -2458,8 +2459,8 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((euid != 0) && (getuid() != euid)) {
|
if ((euid != 0) && (getuid() != euid)) {
|
||||||
|
@ -482,7 +482,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
-rmdir $(DESTDIR)$(sysconfdir)
|
-rmdir $(DESTDIR)$(sysconfdir)
|
||||||
-rmdir $(DESTDIR)$(bindir)
|
-rmdir $(DESTDIR)$(bindir)
|
||||||
-rmdir $(DESTDIR)$(sbindir)
|
-rmdir $(DESTDIR)$(sbindir)
|
||||||
@@ -553,7 +544,7 @@
|
@@ -557,7 +548,7 @@
|
||||||
|
|
||||||
regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \
|
regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -491,7 +491,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -567,7 +558,7 @@
|
@@ -571,7 +562,7 @@
|
||||||
|
|
||||||
regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
|
regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -500,7 +500,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -578,7 +569,7 @@
|
@@ -582,7 +573,7 @@
|
||||||
|
|
||||||
regress/unittests/sshsig/test_sshsig$(EXEEXT): ${UNITTESTS_TEST_SSHSIG_OBJS} \
|
regress/unittests/sshsig/test_sshsig$(EXEEXT): ${UNITTESTS_TEST_SSHSIG_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -509,7 +509,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -587,7 +578,7 @@
|
@@ -591,7 +582,7 @@
|
||||||
|
|
||||||
regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \
|
regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -518,7 +518,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -599,7 +590,7 @@
|
@@ -603,7 +594,7 @@
|
||||||
regress/unittests/authopt/test_authopt$(EXEEXT): \
|
regress/unittests/authopt/test_authopt$(EXEEXT): \
|
||||||
${UNITTESTS_TEST_AUTHOPT_OBJS} \
|
${UNITTESTS_TEST_AUTHOPT_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -527,7 +527,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -609,7 +600,7 @@
|
@@ -613,7 +604,7 @@
|
||||||
regress/unittests/conversion/test_conversion$(EXEEXT): \
|
regress/unittests/conversion/test_conversion$(EXEEXT): \
|
||||||
${UNITTESTS_TEST_CONVERSION_OBJS} \
|
${UNITTESTS_TEST_CONVERSION_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -536,7 +536,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -621,7 +612,7 @@
|
@@ -625,7 +616,7 @@
|
||||||
|
|
||||||
regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \
|
regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -545,7 +545,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -633,7 +624,7 @@
|
@@ -637,7 +628,7 @@
|
||||||
regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \
|
regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \
|
||||||
${UNITTESTS_TEST_HOSTKEYS_OBJS} \
|
${UNITTESTS_TEST_HOSTKEYS_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -554,7 +554,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -643,7 +634,7 @@
|
@@ -647,7 +638,7 @@
|
||||||
regress/unittests/match/test_match$(EXEEXT): \
|
regress/unittests/match/test_match$(EXEEXT): \
|
||||||
${UNITTESTS_TEST_MATCH_OBJS} \
|
${UNITTESTS_TEST_MATCH_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -563,7 +563,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -660,7 +651,7 @@
|
@@ -664,7 +655,7 @@
|
||||||
regress/unittests/misc/test_misc$(EXEEXT): \
|
regress/unittests/misc/test_misc$(EXEEXT): \
|
||||||
${UNITTESTS_TEST_MISC_OBJS} \
|
${UNITTESTS_TEST_MISC_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -572,7 +572,7 @@ diff -Paur --no-dereference -- ssh.upstream/Makefile.in ssh/Makefile.in
|
||||||
regress/unittests/test_helper/libtest_helper.a \
|
regress/unittests/test_helper/libtest_helper.a \
|
||||||
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS)
|
||||||
|
|
||||||
@@ -670,7 +661,7 @@
|
@@ -674,7 +665,7 @@
|
||||||
regress/unittests/utf8/test_utf8$(EXEEXT): \
|
regress/unittests/utf8/test_utf8$(EXEEXT): \
|
||||||
${UNITTESTS_TEST_UTF8_OBJS} \
|
${UNITTESTS_TEST_UTF8_OBJS} \
|
||||||
regress/unittests/test_helper/libtest_helper.a libssh.a
|
regress/unittests/test_helper/libtest_helper.a libssh.a
|
||||||
|
@ -618,7 +618,7 @@ diff -Paur --no-dereference -- ssh.upstream/misc.c ssh/misc.c
|
||||||
/* remove newline at end of string */
|
/* remove newline at end of string */
|
||||||
char *
|
char *
|
||||||
chop(char *s)
|
chop(char *s)
|
||||||
@@ -2745,17 +2772,17 @@
|
@@ -2742,17 +2769,17 @@
|
||||||
|
|
||||||
if (geteuid() == 0 &&
|
if (geteuid() == 0 &&
|
||||||
initgroups(pw->pw_name, pw->pw_gid) == -1) {
|
initgroups(pw->pw_name, pw->pw_gid) == -1) {
|
||||||
|
@ -669,7 +669,7 @@ diff -Paur --no-dereference -- ssh.upstream/monitor_fdpass.c ssh/monitor_fdpass.
|
||||||
diff -Paur --no-dereference -- ssh.upstream/mux.c ssh/mux.c
|
diff -Paur --no-dereference -- ssh.upstream/mux.c ssh/mux.c
|
||||||
--- ssh.upstream/mux.c
|
--- ssh.upstream/mux.c
|
||||||
+++ ssh/mux.c
|
+++ ssh/mux.c
|
||||||
@@ -497,7 +497,7 @@
|
@@ -495,7 +495,7 @@
|
||||||
/* prepare reply */
|
/* prepare reply */
|
||||||
if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 ||
|
if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 ||
|
||||||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
|
(r = sshbuf_put_u32(reply, rid)) != 0 ||
|
||||||
|
@ -829,7 +829,7 @@ diff -Paur --no-dereference -- ssh.upstream/openbsd-compat/getrrsetbyname.c ssh/
|
||||||
#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO
|
#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO
|
||||||
extern int h_errno;
|
extern int h_errno;
|
||||||
#endif
|
#endif
|
||||||
@@ -612,4 +634,6 @@
|
@@ -643,4 +665,6 @@
|
||||||
return (n);
|
return (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,7 +922,7 @@ diff -Paur --no-dereference -- ssh.upstream/pathnames.h ssh/pathnames.h
|
||||||
diff -Paur --no-dereference -- ssh.upstream/progressmeter.c ssh/progressmeter.c
|
diff -Paur --no-dereference -- ssh.upstream/progressmeter.c ssh/progressmeter.c
|
||||||
--- ssh.upstream/progressmeter.c
|
--- ssh.upstream/progressmeter.c
|
||||||
+++ ssh/progressmeter.c
|
+++ ssh/progressmeter.c
|
||||||
@@ -81,7 +81,8 @@
|
@@ -80,7 +80,8 @@
|
||||||
static int
|
static int
|
||||||
can_output(void)
|
can_output(void)
|
||||||
{
|
{
|
||||||
|
@ -931,11 +931,11 @@ diff -Paur --no-dereference -- ssh.upstream/progressmeter.c ssh/progressmeter.c
|
||||||
+ return (getpgid(0) == tcgetpgrp(STDOUT_FILENO));
|
+ return (getpgid(0) == tcgetpgrp(STDOUT_FILENO));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* size needed to format integer type v, using (nbits(v) * log2(10) / 10) */
|
||||||
diff -Paur --no-dereference -- ssh.upstream/readconf.c ssh/readconf.c
|
diff -Paur --no-dereference -- ssh.upstream/readconf.c ssh/readconf.c
|
||||||
--- ssh.upstream/readconf.c
|
--- ssh.upstream/readconf.c
|
||||||
+++ ssh/readconf.c
|
+++ ssh/readconf.c
|
||||||
@@ -510,6 +510,10 @@
|
@@ -509,6 +509,10 @@
|
||||||
int
|
int
|
||||||
default_ssh_port(void)
|
default_ssh_port(void)
|
||||||
{
|
{
|
||||||
|
@ -946,7 +946,7 @@ diff -Paur --no-dereference -- ssh.upstream/readconf.c ssh/readconf.c
|
||||||
static int port;
|
static int port;
|
||||||
struct servent *sp;
|
struct servent *sp;
|
||||||
|
|
||||||
@@ -518,6 +522,7 @@
|
@@ -517,6 +521,7 @@
|
||||||
port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
|
port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
|
||||||
}
|
}
|
||||||
return port;
|
return port;
|
||||||
|
@ -974,7 +974,7 @@ diff -Paur --no-dereference -- ssh.upstream/regress/netcat.c ssh/regress/netcat.
|
||||||
diff -Paur --no-dereference -- ssh.upstream/scp.c ssh/scp.c
|
diff -Paur --no-dereference -- ssh.upstream/scp.c ssh/scp.c
|
||||||
--- ssh.upstream/scp.c
|
--- ssh.upstream/scp.c
|
||||||
+++ ssh/scp.c
|
+++ ssh/scp.c
|
||||||
@@ -645,7 +645,7 @@
|
@@ -647,7 +647,7 @@
|
||||||
mode = MODE_SCP;
|
mode = MODE_SCP;
|
||||||
|
|
||||||
if ((pwd = getpwuid(userid = getuid())) == NULL)
|
if ((pwd = getpwuid(userid = getuid())) == NULL)
|
||||||
|
@ -983,7 +983,7 @@ diff -Paur --no-dereference -- ssh.upstream/scp.c ssh/scp.c
|
||||||
|
|
||||||
if (!isatty(STDOUT_FILENO))
|
if (!isatty(STDOUT_FILENO))
|
||||||
showprogress = 0;
|
showprogress = 0;
|
||||||
@@ -1007,7 +1007,7 @@
|
@@ -1009,7 +1009,7 @@
|
||||||
|
|
||||||
static struct sftp_conn *
|
static struct sftp_conn *
|
||||||
do_sftp_connect(char *host, char *user, int port, char *sftp_direct,
|
do_sftp_connect(char *host, char *user, int port, char *sftp_direct,
|
||||||
|
@ -995,7 +995,7 @@ diff -Paur --no-dereference -- ssh.upstream/scp.c ssh/scp.c
|
||||||
diff -Paur --no-dereference -- ssh.upstream/servconf.c ssh/servconf.c
|
diff -Paur --no-dereference -- ssh.upstream/servconf.c ssh/servconf.c
|
||||||
--- ssh.upstream/servconf.c
|
--- ssh.upstream/servconf.c
|
||||||
+++ ssh/servconf.c
|
+++ ssh/servconf.c
|
||||||
@@ -309,7 +309,10 @@
|
@@ -308,7 +308,10 @@
|
||||||
if (options->pid_file == NULL)
|
if (options->pid_file == NULL)
|
||||||
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
|
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
|
||||||
if (options->moduli_file == NULL)
|
if (options->moduli_file == NULL)
|
||||||
|
@ -1007,7 +1007,7 @@ diff -Paur --no-dereference -- ssh.upstream/servconf.c ssh/servconf.c
|
||||||
if (options->login_grace_time == -1)
|
if (options->login_grace_time == -1)
|
||||||
options->login_grace_time = 120;
|
options->login_grace_time = 120;
|
||||||
if (options->permit_root_login == PERMIT_NOT_SET)
|
if (options->permit_root_login == PERMIT_NOT_SET)
|
||||||
@@ -454,7 +457,12 @@
|
@@ -453,7 +456,12 @@
|
||||||
|
|
||||||
/* Turn privilege separation and sandboxing on by default */
|
/* Turn privilege separation and sandboxing on by default */
|
||||||
if (use_privsep == -1)
|
if (use_privsep == -1)
|
||||||
|
@ -1023,7 +1023,7 @@ diff -Paur --no-dereference -- ssh.upstream/servconf.c ssh/servconf.c
|
||||||
diff -Paur --no-dereference -- ssh.upstream/session.c ssh/session.c
|
diff -Paur --no-dereference -- ssh.upstream/session.c ssh/session.c
|
||||||
--- ssh.upstream/session.c
|
--- ssh.upstream/session.c
|
||||||
+++ ssh/session.c
|
+++ ssh/session.c
|
||||||
@@ -104,6 +104,15 @@
|
@@ -103,6 +103,15 @@
|
||||||
#include <selinux/selinux.h>
|
#include <selinux/selinux.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1039,7 +1039,7 @@ diff -Paur --no-dereference -- ssh.upstream/session.c ssh/session.c
|
||||||
#define IS_INTERNAL_SFTP(c) \
|
#define IS_INTERNAL_SFTP(c) \
|
||||||
(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
|
(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
|
||||||
(c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
|
(c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
|
||||||
@@ -1052,9 +1061,11 @@
|
@@ -1051,9 +1060,11 @@
|
||||||
#endif /* HAVE_LOGIN_CAP */
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
|
|
||||||
if (!options.use_pam) {
|
if (!options.use_pam) {
|
||||||
|
@ -1157,7 +1157,7 @@ diff -Paur --no-dereference -- ssh.upstream/sftp-server-main.c ssh/sftp-server-m
|
||||||
diff -Paur --no-dereference -- ssh.upstream/ssh-add.c ssh/ssh-add.c
|
diff -Paur --no-dereference -- ssh.upstream/ssh-add.c ssh/ssh-add.c
|
||||||
--- ssh.upstream/ssh-add.c
|
--- ssh.upstream/ssh-add.c
|
||||||
+++ ssh/ssh-add.c
|
+++ ssh/ssh-add.c
|
||||||
@@ -979,8 +979,8 @@
|
@@ -982,8 +982,8 @@
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if ((pw = getpwuid(getuid())) == NULL) {
|
if ((pw = getpwuid(getuid())) == NULL) {
|
||||||
|
@ -1171,7 +1171,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-add.c ssh/ssh-add.c
|
||||||
diff -Paur --no-dereference -- ssh.upstream/ssh-agent.c ssh/ssh-agent.c
|
diff -Paur --no-dereference -- ssh.upstream/ssh-agent.c ssh/ssh-agent.c
|
||||||
--- ssh.upstream/ssh-agent.c
|
--- ssh.upstream/ssh-agent.c
|
||||||
+++ ssh/ssh-agent.c
|
+++ ssh/ssh-agent.c
|
||||||
@@ -1749,8 +1749,8 @@
|
@@ -1748,8 +1748,8 @@
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((euid != 0) && (getuid() != euid)) {
|
if ((euid != 0) && (getuid() != euid)) {
|
||||||
|
@ -1218,7 +1218,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh.c ssh/ssh.c
|
||||||
diff -Paur --no-dereference -- ssh.upstream/sshconnect.c ssh/sshconnect.c
|
diff -Paur --no-dereference -- ssh.upstream/sshconnect.c ssh/sshconnect.c
|
||||||
--- ssh.upstream/sshconnect.c
|
--- ssh.upstream/sshconnect.c
|
||||||
+++ ssh/sshconnect.c
|
+++ ssh/sshconnect.c
|
||||||
@@ -164,7 +164,8 @@
|
@@ -163,7 +163,8 @@
|
||||||
* Execute the proxy command.
|
* Execute the proxy command.
|
||||||
* Note that we gave up any extra privileges above.
|
* Note that we gave up any extra privileges above.
|
||||||
*/
|
*/
|
||||||
|
@ -1228,7 +1228,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshconnect.c ssh/sshconnect.c
|
||||||
perror(argv[0]);
|
perror(argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -248,7 +249,7 @@
|
@@ -247,7 +248,7 @@
|
||||||
* extra privileges above.
|
* extra privileges above.
|
||||||
*/
|
*/
|
||||||
ssh_signal(SIGPIPE, SIG_DFL);
|
ssh_signal(SIGPIPE, SIG_DFL);
|
||||||
|
@ -1237,7 +1237,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshconnect.c ssh/sshconnect.c
|
||||||
perror(argv[0]);
|
perror(argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -306,7 +307,9 @@
|
@@ -305,7 +306,9 @@
|
||||||
for (allow_local = 0; allow_local < 2; allow_local++) {
|
for (allow_local = 0; allow_local < 2; allow_local++) {
|
||||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||||
if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
|
if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
|
||||||
|
@ -1247,7 +1247,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshconnect.c ssh/sshconnect.c
|
||||||
ifa->ifa_addr->sa_family != af ||
|
ifa->ifa_addr->sa_family != af ||
|
||||||
strcmp(ifa->ifa_name, options.bind_interface) != 0)
|
strcmp(ifa->ifa_name, options.bind_interface) != 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -1671,7 +1674,7 @@
|
@@ -1670,7 +1673,7 @@
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
ssh_signal(SIGPIPE, SIG_DFL);
|
ssh_signal(SIGPIPE, SIG_DFL);
|
||||||
debug3("Executing %s -c \"%s\"", shell, args);
|
debug3("Executing %s -c \"%s\"", shell, args);
|
||||||
|
@ -1279,7 +1279,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.8 ssh/sshd.8
|
||||||
.Pp
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
@@ -994,14 +994,6 @@
|
@@ -1008,14 +1008,6 @@
|
||||||
during privilege separation in the pre-authentication phase.
|
during privilege separation in the pre-authentication phase.
|
||||||
The directory should not contain any files and must be owned by root
|
The directory should not contain any files and must be owned by root
|
||||||
and not group or world-writable.
|
and not group or world-writable.
|
||||||
|
@ -1297,7 +1297,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.8 ssh/sshd.8
|
||||||
diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
--- ssh.upstream/sshd.c
|
--- ssh.upstream/sshd.c
|
||||||
+++ ssh/sshd.c
|
+++ ssh/sshd.c
|
||||||
@@ -129,6 +129,15 @@
|
@@ -128,6 +128,15 @@
|
||||||
#include "srclimit.h"
|
#include "srclimit.h"
|
||||||
#include "dh.h"
|
#include "dh.h"
|
||||||
|
|
||||||
|
@ -1313,7 +1313,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
/* Re-exec fds */
|
/* Re-exec fds */
|
||||||
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
|
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
|
||||||
#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
|
#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
|
||||||
@@ -234,7 +243,11 @@
|
@@ -233,7 +242,11 @@
|
||||||
static int startup_pipe = -1; /* in child */
|
static int startup_pipe = -1; /* in child */
|
||||||
|
|
||||||
/* variables used for privilege separation */
|
/* variables used for privilege separation */
|
||||||
|
@ -1325,7 +1325,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
struct monitor *pmonitor = NULL;
|
struct monitor *pmonitor = NULL;
|
||||||
int privsep_is_preauth = 1;
|
int privsep_is_preauth = 1;
|
||||||
static int privsep_chroot = 1;
|
static int privsep_chroot = 1;
|
||||||
@@ -460,8 +473,8 @@
|
@@ -455,8 +468,8 @@
|
||||||
fatal("chdir(\"/\"): %s", strerror(errno));
|
fatal("chdir(\"/\"): %s", strerror(errno));
|
||||||
|
|
||||||
/* Drop our privileges */
|
/* Drop our privileges */
|
||||||
|
@ -1336,7 +1336,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
gidset[0] = privsep_pw->pw_gid;
|
gidset[0] = privsep_pw->pw_gid;
|
||||||
if (setgroups(1, gidset) == -1)
|
if (setgroups(1, gidset) == -1)
|
||||||
fatal("setgroups: %.100s", strerror(errno));
|
fatal("setgroups: %.100s", strerror(errno));
|
||||||
@@ -1579,6 +1592,10 @@
|
@@ -1589,6 +1602,10 @@
|
||||||
/* Initialize configuration options to their default values. */
|
/* Initialize configuration options to their default values. */
|
||||||
initialize_server_options(&options);
|
initialize_server_options(&options);
|
||||||
|
|
||||||
|
@ -1346,10 +1346,10 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
+
|
+
|
||||||
/* Parse command-line arguments. */
|
/* Parse command-line arguments. */
|
||||||
while ((opt = getopt(ac, av,
|
while ((opt = getopt(ac, av,
|
||||||
"C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrtV")) != -1) {
|
"C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) {
|
||||||
@@ -1695,10 +1712,32 @@
|
@@ -1708,10 +1725,32 @@
|
||||||
rexec_flag = 0;
|
rexec_flag = 0;
|
||||||
if (!test_flag && rexec_flag && !path_absolute(av[0]))
|
if (!test_flag && !do_dump_cfg && rexec_flag && !path_absolute(av[0]))
|
||||||
fatal("sshd re-exec requires execution with an absolute path");
|
fatal("sshd re-exec requires execution with an absolute path");
|
||||||
- if (rexeced_flag)
|
- if (rexeced_flag)
|
||||||
- closefrom(REEXEC_MIN_FREE_FD);
|
- closefrom(REEXEC_MIN_FREE_FD);
|
||||||
|
@ -1384,7 +1384,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
|
|
||||||
seed_rng();
|
seed_rng();
|
||||||
|
|
||||||
@@ -2074,7 +2113,8 @@
|
@@ -2081,7 +2120,8 @@
|
||||||
* Write out the pid file after the sigterm handler
|
* Write out the pid file after the sigterm handler
|
||||||
* is setup and the listen sockets are bound
|
* is setup and the listen sockets are bound
|
||||||
*/
|
*/
|
||||||
|
@ -1394,7 +1394,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
FILE *f = fopen(options.pid_file, "w");
|
FILE *f = fopen(options.pid_file, "w");
|
||||||
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
@@ -2086,6 +2126,15 @@
|
@@ -2093,6 +2133,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1410,7 +1410,7 @@ diff -Paur --no-dereference -- ssh.upstream/sshd.c ssh/sshd.c
|
||||||
/* Accept a connection and return in a forked child */
|
/* Accept a connection and return in a forked child */
|
||||||
server_accept_loop(&sock_in, &sock_out,
|
server_accept_loop(&sock_in, &sock_out,
|
||||||
&newsock, config_s);
|
&newsock, config_s);
|
||||||
@@ -2445,10 +2494,10 @@
|
@@ -2447,10 +2496,10 @@
|
||||||
do_cleanup(the_active_state, the_authctxt);
|
do_cleanup(the_active_state, the_authctxt);
|
||||||
if (use_privsep && privsep_is_preauth &&
|
if (use_privsep && privsep_is_preauth &&
|
||||||
pmonitor != NULL && pmonitor->m_pid > 1) {
|
pmonitor != NULL && pmonitor->m_pid > 1) {
|
||||||
|
@ -1473,7 +1473,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.1 ssh/ssh-keygen.1
|
||||||
diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.c ssh/ssh-keygen.c
|
diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.c ssh/ssh-keygen.c
|
||||||
--- ssh.upstream/ssh-keygen.c
|
--- ssh.upstream/ssh-keygen.c
|
||||||
+++ ssh/ssh-keygen.c
|
+++ ssh/ssh-keygen.c
|
||||||
@@ -829,7 +829,7 @@
|
@@ -831,7 +831,7 @@
|
||||||
}
|
}
|
||||||
sshkey_free(prv);
|
sshkey_free(prv);
|
||||||
free(comment);
|
free(comment);
|
||||||
|
@ -1482,7 +1482,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.c ssh/ssh-keygen.c
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -987,7 +987,7 @@
|
@@ -989,7 +989,7 @@
|
||||||
free(line);
|
free(line);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
fingerprint_private(path);
|
fingerprint_private(path);
|
||||||
|
@ -1491,7 +1491,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.c ssh/ssh-keygen.c
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1035,7 +1035,7 @@
|
@@ -1037,7 +1037,7 @@
|
||||||
|
|
||||||
if (invalid)
|
if (invalid)
|
||||||
fatal("%s is not a public key file.", path);
|
fatal("%s is not a public key file.", path);
|
||||||
|
@ -1500,7 +1500,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.c ssh/ssh-keygen.c
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1075,14 +1075,32 @@
|
@@ -1077,14 +1077,32 @@
|
||||||
|
|
||||||
/* Check whether private key exists and is not zero-length */
|
/* Check whether private key exists and is not zero-length */
|
||||||
if (stat(prv_file, &st) == 0) {
|
if (stat(prv_file, &st) == 0) {
|
||||||
|
@ -1534,7 +1534,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.c ssh/ssh-keygen.c
|
||||||
/*
|
/*
|
||||||
* Private key doesn't exist or is invalid; proceed with
|
* Private key doesn't exist or is invalid; proceed with
|
||||||
* key generation.
|
* key generation.
|
||||||
@@ -3347,7 +3365,7 @@
|
@@ -3363,7 +3381,7 @@
|
||||||
/* we need this for the home * directory. */
|
/* we need this for the home * directory. */
|
||||||
pw = getpwuid(getuid());
|
pw = getpwuid(getuid());
|
||||||
if (!pw)
|
if (!pw)
|
||||||
|
@ -1543,7 +1543,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-keygen.c ssh/ssh-keygen.c
|
||||||
pw = pwcopy(pw);
|
pw = pwcopy(pw);
|
||||||
if (gethostname(hostname, sizeof(hostname)) == -1)
|
if (gethostname(hostname, sizeof(hostname)) == -1)
|
||||||
fatal("gethostname: %s", strerror(errno));
|
fatal("gethostname: %s", strerror(errno));
|
||||||
@@ -3703,8 +3721,10 @@
|
@@ -3719,8 +3737,10 @@
|
||||||
}
|
}
|
||||||
return do_download_sk(sk_provider, sk_device);
|
return do_download_sk(sk_provider, sk_device);
|
||||||
}
|
}
|
||||||
|
@ -1570,7 +1570,7 @@ diff -Paur --no-dereference -- ssh.upstream/ssh-keyscan.c ssh/ssh-keyscan.c
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "sshbuf.h"
|
#include "sshbuf.h"
|
||||||
@@ -54,6 +59,14 @@
|
@@ -55,6 +60,14 @@
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "addr.h"
|
#include "addr.h"
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
NAME=ssh
|
NAME=ssh
|
||||||
BUILD_LIBRARIES='libz libssl'
|
BUILD_LIBRARIES='libz libssl'
|
||||||
VERSION=9.2p1
|
VERSION=9.3p1
|
||||||
DISTNAME=openssh-$VERSION
|
DISTNAME=openssh-$VERSION
|
||||||
COMPRESSION=tar.gz
|
COMPRESSION=tar.gz
|
||||||
ARCHIVE=$DISTNAME.$COMPRESSION
|
ARCHIVE=$DISTNAME.$COMPRESSION
|
||||||
SHA256SUM=3f66dbf1655fb45f50e1c56da62ab01218c228807b21338d634ebcdf9d71cf46
|
SHA256SUM=e9baba7701a76a51f3d85a62c383a3c9dcd97fa900b859bc7db114c1868af8a8
|
||||||
UPSTREAM_SITE=https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable
|
UPSTREAM_SITE=https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable
|
||||||
UPSTREAM_ARCHIVE=$ARCHIVE
|
UPSTREAM_ARCHIVE=$ARCHIVE
|
||||||
LICENSE='SSH-OpenSSH AND BSD-2-Clause AND BSD-3-Clause AND ISC AND MIT'
|
LICENSE='SSH-OpenSSH AND BSD-2-Clause AND BSD-3-Clause AND ISC AND MIT'
|
||||||
|
|
284
sh/sh.c
284
sh/sh.c
|
@ -27,6 +27,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <glob.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <ioleast.h>
|
#include <ioleast.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
@ -106,21 +107,6 @@ void update_env(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matches_simple_pattern(const char* string, const char* pattern)
|
|
||||||
{
|
|
||||||
size_t wildcard_index = strcspn(pattern, "*");
|
|
||||||
if ( !pattern[wildcard_index] )
|
|
||||||
return strcmp(string, pattern) == 0;
|
|
||||||
if ( pattern[0] == '*' && string[0] == '.' )
|
|
||||||
return false;
|
|
||||||
size_t string_length = strlen(string);
|
|
||||||
size_t pattern_length = strlen(pattern);
|
|
||||||
size_t pattern_last = pattern_length - (wildcard_index + 1);
|
|
||||||
return strncmp(string, pattern, wildcard_index) == 0 &&
|
|
||||||
strcmp(string + string_length - pattern_last,
|
|
||||||
pattern + wildcard_index + 1) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void array_shrink_free(void*** array_ptr,
|
void array_shrink_free(void*** array_ptr,
|
||||||
size_t* used_ptr,
|
size_t* used_ptr,
|
||||||
size_t* length_ptr,
|
size_t* length_ptr,
|
||||||
|
@ -347,13 +333,6 @@ bool token_expand_variables_split(void*** out,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int strcoll_indirect(const void* a_ptr, const void* b_ptr)
|
|
||||||
{
|
|
||||||
const char* a = *(const char* const*) a_ptr;
|
|
||||||
const char* b = *(const char* const*) b_ptr;
|
|
||||||
return strcoll(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool token_expand_wildcards(void*** out,
|
bool token_expand_wildcards(void*** out,
|
||||||
size_t* out_used,
|
size_t* out_used,
|
||||||
size_t* out_length,
|
size_t* out_length,
|
||||||
|
@ -361,217 +340,112 @@ bool token_expand_wildcards(void*** out,
|
||||||
{
|
{
|
||||||
size_t old_used = *out_used;
|
size_t old_used = *out_used;
|
||||||
|
|
||||||
size_t index = 0;
|
|
||||||
size_t num_escaped_wildcards = 0; // We don't properly support them yet.
|
|
||||||
|
|
||||||
struct stringbuf buf;
|
struct stringbuf buf;
|
||||||
stringbuf_begin(&buf);
|
stringbuf_begin(&buf);
|
||||||
|
|
||||||
|
// First check if the token contains any wildcards at all.
|
||||||
bool escape = false;
|
bool escape = false;
|
||||||
bool single_quote = false;
|
bool single_quote = false;
|
||||||
bool double_quote = false;
|
bool double_quote = false;
|
||||||
for ( ; token[index]; index++ )
|
bool any_wildcards = false;
|
||||||
|
for ( size_t i = 0; token[i]; i++ )
|
||||||
{
|
{
|
||||||
if ( !escape && !single_quote && token[index] == '\\' )
|
char c = token[i];
|
||||||
{
|
if ( !escape && !single_quote && c == '\\' )
|
||||||
escape = true;
|
escape = true;
|
||||||
}
|
else if ( !escape && !double_quote && c == '\'' )
|
||||||
else if ( !escape && !double_quote && token[index] == '\'' )
|
|
||||||
{
|
|
||||||
single_quote = !single_quote;
|
single_quote = !single_quote;
|
||||||
}
|
else if ( !escape && !single_quote && c == '"' )
|
||||||
else if ( !escape && !single_quote && token[index] == '"' )
|
|
||||||
{
|
|
||||||
double_quote = !double_quote;
|
double_quote = !double_quote;
|
||||||
}
|
|
||||||
else if ( !(escape || single_quote || double_quote) &&
|
else if ( !(escape || single_quote || double_quote) &&
|
||||||
token[index] == '*' )
|
(c == '?' || c == '*' || c == '[') )
|
||||||
{
|
{
|
||||||
break;
|
any_wildcards = true;
|
||||||
|
stringbuf_append_c(&buf, c);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( escape && double_quote &&
|
if ( escape && double_quote &&
|
||||||
token[index] != '$' && token[index] != '`' &&
|
c != '$' && c != '`' && c != '"' && c != '\\' )
|
||||||
token[index] != '"' && token[index] != '\\' )
|
|
||||||
stringbuf_append_c(&buf, '\\');
|
stringbuf_append_c(&buf, '\\');
|
||||||
if ( token[index] == '*' )
|
else if ( (escape || single_quote || double_quote) &&
|
||||||
num_escaped_wildcards++;
|
(c == '?' || c == '*' || c == '[') )
|
||||||
stringbuf_append_c(&buf, token[index]);
|
stringbuf_append_c(&buf, '\\');
|
||||||
|
stringbuf_append_c(&buf, c);
|
||||||
escape = false;
|
escape = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( token[index] != '*' || num_escaped_wildcards )
|
char* pattern = stringbuf_finish(&buf);
|
||||||
|
if ( !pattern )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the token didn't contain any wildcards, just return it.
|
||||||
|
if ( !any_wildcards )
|
||||||
{
|
{
|
||||||
char* value;
|
free(pattern);
|
||||||
free(stringbuf_finish(&buf));
|
|
||||||
just_return_input:
|
just_return_input:
|
||||||
value = strdup(token);
|
pattern = strdup(token);
|
||||||
if ( !value )
|
if ( !pattern )
|
||||||
return false;
|
return false;
|
||||||
if ( !array_add(out, out_used, out_length, value) )
|
if ( !array_add(out, out_used, out_length, pattern) )
|
||||||
return free(value), false;
|
return free(pattern), false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* before = stringbuf_finish(&buf);
|
// Search the filesystem for paths matching the pattern.
|
||||||
if ( !before )
|
glob_t gl;
|
||||||
return false;
|
int globerr = glob(pattern, 0, NULL, &gl);
|
||||||
stringbuf_begin(&buf);
|
|
||||||
|
|
||||||
index++;
|
|
||||||
|
|
||||||
for ( ; token[index]; index++ )
|
|
||||||
{
|
|
||||||
if ( !escape && !single_quote && token[index] == '\\' )
|
|
||||||
{
|
|
||||||
escape = true;
|
|
||||||
}
|
|
||||||
else if ( !escape && !double_quote && token[index] == '\'' )
|
|
||||||
{
|
|
||||||
single_quote = !single_quote;
|
|
||||||
}
|
|
||||||
else if ( !escape && !single_quote && token[index] == '"' )
|
|
||||||
{
|
|
||||||
double_quote = !double_quote;
|
|
||||||
}
|
|
||||||
else if ( !(escape || single_quote || double_quote) &&
|
|
||||||
token[index] == '*' )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( escape && double_quote &&
|
|
||||||
token[index] != '$' && token[index] != '`' &&
|
|
||||||
token[index] != '"' && token[index] != '\\' )
|
|
||||||
stringbuf_append_c(&buf, '\\');
|
|
||||||
if ( token[index] == '*' )
|
|
||||||
num_escaped_wildcards++;
|
|
||||||
stringbuf_append_c(&buf, token[index]);
|
|
||||||
escape = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( token[index] == '*' )
|
|
||||||
{
|
|
||||||
// TODO: We don't support double use of wildcards yet.
|
|
||||||
free(stringbuf_finish(&buf));
|
|
||||||
free(before);
|
|
||||||
goto just_return_input;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* after = stringbuf_finish(&buf);
|
|
||||||
if ( !after )
|
|
||||||
return free(before), false;
|
|
||||||
|
|
||||||
char* pattern;
|
|
||||||
if ( asprintf(&pattern, "%s*%s", before, after) < 0 )
|
|
||||||
return free(after), free(before), false;
|
|
||||||
free(after);
|
|
||||||
free(before);
|
|
||||||
|
|
||||||
size_t wildcard_pos = strcspn(pattern, "*");
|
|
||||||
bool found_slash = false;
|
|
||||||
size_t last_slash = 0;
|
|
||||||
for ( size_t n = 0; n < wildcard_pos; n++ )
|
|
||||||
if ( pattern[n] == '/' )
|
|
||||||
last_slash = n, found_slash = true;
|
|
||||||
size_t match_from = found_slash ? last_slash + 1 : 0;
|
|
||||||
|
|
||||||
size_t pattern_prefix = 0;
|
|
||||||
DIR* dir = NULL;
|
|
||||||
if ( !found_slash )
|
|
||||||
{
|
|
||||||
if ( !(dir = opendir(".")) )
|
|
||||||
{
|
|
||||||
free(pattern);
|
|
||||||
goto just_return_input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char* dirpath = strdup(pattern);
|
|
||||||
if ( !dirpath )
|
|
||||||
{
|
|
||||||
free(pattern);
|
|
||||||
goto just_return_input;
|
|
||||||
}
|
|
||||||
dirpath[last_slash] = '\0';
|
|
||||||
pattern_prefix = last_slash + 1;
|
|
||||||
dir = opendir(dirpath);
|
|
||||||
free(dirpath);
|
|
||||||
if ( !dir )
|
|
||||||
{
|
|
||||||
free(pattern);
|
|
||||||
goto just_return_input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size_t num_inserted = 0;
|
|
||||||
struct dirent* entry;
|
|
||||||
while ( (entry = readdir(dir)) )
|
|
||||||
{
|
|
||||||
if ( !matches_simple_pattern(entry->d_name, pattern + match_from) )
|
|
||||||
continue;
|
|
||||||
stringbuf_begin(&buf);
|
|
||||||
for ( size_t i = 0; i < pattern_prefix; i++ )
|
|
||||||
{
|
|
||||||
if ( pattern[i] == '\n' )
|
|
||||||
{
|
|
||||||
stringbuf_append_c(&buf, '\'');
|
|
||||||
stringbuf_append_c(&buf, '\n');
|
|
||||||
stringbuf_append_c(&buf, '\'');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( might_need_shell_quote(pattern[i]) )
|
|
||||||
stringbuf_append_c(&buf, '\\');
|
|
||||||
stringbuf_append_c(&buf, pattern[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( size_t i = 0; entry->d_name[i]; i++ )
|
|
||||||
{
|
|
||||||
if ( entry->d_name[i] == '\n' )
|
|
||||||
{
|
|
||||||
stringbuf_append_c(&buf, '\'');
|
|
||||||
stringbuf_append_c(&buf, '\n');
|
|
||||||
stringbuf_append_c(&buf, '\'');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( might_need_shell_quote(entry->d_name[i]) )
|
|
||||||
stringbuf_append_c(&buf, '\\');
|
|
||||||
stringbuf_append_c(&buf, entry->d_name[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char* name = stringbuf_finish(&buf);
|
|
||||||
if ( !name )
|
|
||||||
{
|
|
||||||
free(pattern);
|
|
||||||
closedir(dir);
|
|
||||||
array_shrink_free(out, out_used, out_length, old_used);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !array_add(out, out_used, out_length, name) )
|
|
||||||
{
|
|
||||||
free(name);
|
|
||||||
free(pattern);
|
|
||||||
closedir(dir);
|
|
||||||
array_shrink_free(out, out_used, out_length, old_used);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
num_inserted++;
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
free(pattern);
|
free(pattern);
|
||||||
if ( num_inserted == 0 )
|
if ( globerr )
|
||||||
goto just_return_input;
|
{
|
||||||
char** out_tokens;
|
globfree(&gl);
|
||||||
memcpy(&out_tokens, out, sizeof(out_tokens));
|
// GLOB_NOCHECK is not used since we don't want the escaped pattern back
|
||||||
char** sort_from = out_tokens + old_used;
|
// since it would contain e.g. \* which is difficult to discern from a
|
||||||
size_t sort_count = *out_used - old_used;
|
// real file actually called \* and the original token is escaped in the
|
||||||
qsort(sort_from, sort_count, sizeof(char*), strcoll_indirect);
|
// correct fashion.
|
||||||
|
if ( globerr == GLOB_NOMATCH )
|
||||||
|
goto just_return_input;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape the paths as tokens.
|
||||||
|
for ( size_t n = 0; n < gl.gl_pathc; n++ )
|
||||||
|
{
|
||||||
|
const char* path = gl.gl_pathv[n];
|
||||||
|
stringbuf_begin(&buf);
|
||||||
|
for ( size_t i = 0; path[i]; i++ )
|
||||||
|
{
|
||||||
|
if ( path[i] == '\n' )
|
||||||
|
{
|
||||||
|
stringbuf_append_c(&buf, '\'');
|
||||||
|
stringbuf_append_c(&buf, '\n');
|
||||||
|
stringbuf_append_c(&buf, '\'');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( might_need_shell_quote(path[i]) )
|
||||||
|
stringbuf_append_c(&buf, '\\');
|
||||||
|
stringbuf_append_c(&buf, path[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char* new_token = stringbuf_finish(&buf);
|
||||||
|
if ( !new_token )
|
||||||
|
{
|
||||||
|
globfree(&gl);
|
||||||
|
array_shrink_free(out, out_used, out_length, old_used);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !array_add(out, out_used, out_length, new_token) )
|
||||||
|
{
|
||||||
|
free(new_token);
|
||||||
|
globfree(&gl);
|
||||||
|
array_shrink_free(out, out_used, out_length, old_used);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
globfree(&gl);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,24 @@ releasing Sortix x.y, foo." to allow the maintainer to easily
|
||||||
.Xr grep 1
|
.Xr grep 1
|
||||||
for it after a release.
|
for it after a release.
|
||||||
.Sh CHANGES
|
.Sh CHANGES
|
||||||
|
.Ss Add include and comment support to passwd(5) and group(5)
|
||||||
|
The
|
||||||
|
.Xr passwd 5
|
||||||
|
and
|
||||||
|
.Xr group 5
|
||||||
|
files have gained support for include statements via libc support.
|
||||||
|
Installations must now include
|
||||||
|
.Pa /etc/default/passwd.d/*
|
||||||
|
and
|
||||||
|
.Pa /etc/default/group.d/*
|
||||||
|
respectively in order to have system users and groups.
|
||||||
|
.Pp
|
||||||
|
An upgrade hook will add the inclusions to
|
||||||
|
.Pa /etc/passwd
|
||||||
|
and
|
||||||
|
.Pa /etc/group .
|
||||||
|
Applications accessing passwd and group databases must be recompiled with the
|
||||||
|
latest libc.
|
||||||
.Ss Add memory statistics to struct psctl_stat
|
.Ss Add memory statistics to struct psctl_stat
|
||||||
The
|
The
|
||||||
.Xr psctl 2
|
.Xr psctl 2
|
||||||
|
|
|
@ -80,7 +80,7 @@ per the instructions in
|
||||||
.Xr release-iso-modification 7 .
|
.Xr release-iso-modification 7 .
|
||||||
.Pp
|
.Pp
|
||||||
If you want to ssh into your installation, it's recommended to amend the
|
If you want to ssh into your installation, it's recommended to amend the
|
||||||
installation .iso with your public key, pregenerated the server keys and obtain
|
installation .iso with your public key, pregenerate the server keys and obtain
|
||||||
fingerprints, and seed randomness using this procedure.
|
fingerprints, and seed randomness using this procedure.
|
||||||
.Pp
|
.Pp
|
||||||
The release modification procedure lets you customize aspects such as the
|
The release modification procedure lets you customize aspects such as the
|
||||||
|
|
|
@ -55,6 +55,8 @@ install: all
|
||||||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-tix-manifest-mode
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-tix-manifest-mode
|
||||||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-leaked-files
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-leaked-files
|
||||||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-init
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-init
|
||||||
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-passwd
|
||||||
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-group
|
||||||
|
|
||||||
sysinstall: $(SYSINSTALL_OBJS)
|
sysinstall: $(SYSINSTALL_OBJS)
|
||||||
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount
|
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount
|
||||||
|
|
|
@ -296,6 +296,64 @@ void upgrade_prepare(const struct release* old_release,
|
||||||
free(init_target_path);
|
free(init_target_path);
|
||||||
free(init_default_path);
|
free(init_default_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: After releasing Sortix 1.1, remove this compatibility.
|
||||||
|
if ( hook_needs_to_be_run(source_prefix, target_prefix,
|
||||||
|
"sortix-1.1-passwd") )
|
||||||
|
{
|
||||||
|
char* passwd_path = join_paths(target_prefix, "/etc/passwd");
|
||||||
|
if ( !passwd_path )
|
||||||
|
{
|
||||||
|
warn("malloc");
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
FILE* fp = fopen(passwd_path, "a");
|
||||||
|
if ( fp )
|
||||||
|
{
|
||||||
|
printf(" - Including /etc/default/passwd.d/* in /etc/passwd...\n");
|
||||||
|
if ( fprintf(fp, "include /etc/default/passwd.d/*\n") < 0 ||
|
||||||
|
fclose(fp) == EOF )
|
||||||
|
{
|
||||||
|
warn("%s", passwd_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( errno != ENOENT )
|
||||||
|
{
|
||||||
|
warn("%s", passwd_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
free(passwd_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: After releasing Sortix 1.1, remove this compatibility.
|
||||||
|
if ( hook_needs_to_be_run(source_prefix, target_prefix,
|
||||||
|
"sortix-1.1-group") )
|
||||||
|
{
|
||||||
|
char* group_path = join_paths(target_prefix, "/etc/group");
|
||||||
|
if ( !group_path )
|
||||||
|
{
|
||||||
|
warn("malloc");
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
FILE* fp = fopen(group_path, "a");
|
||||||
|
if ( fp )
|
||||||
|
{
|
||||||
|
printf(" - Including /etc/default/group.d/* in /etc/group...\n");
|
||||||
|
if ( fprintf(fp, "include /etc/default/group.d/*\n") < 0 ||
|
||||||
|
fclose(fp) == EOF )
|
||||||
|
{
|
||||||
|
warn("%s", group_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( errno != ENOENT )
|
||||||
|
{
|
||||||
|
warn("%s", group_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
free(group_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void upgrade_finalize(const struct release* old_release,
|
void upgrade_finalize(const struct release* old_release,
|
||||||
|
|
|
@ -220,16 +220,23 @@ static bool passwd_check(const char* passwd_path,
|
||||||
warn("%s", passwd_path);
|
warn("%s", passwd_path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct passwd* pwd;
|
char* line = NULL;
|
||||||
while ( (errno = 0, pwd = fgetpwent(passwd)) )
|
size_t size = 0;
|
||||||
|
ssize_t length;
|
||||||
|
while ( 0 < (length = getline(&line, &size, passwd) ) )
|
||||||
{
|
{
|
||||||
if ( check(pwd, check_ctx) )
|
if ( line[size - 1] == '\n' )
|
||||||
|
line[--size] = '\0';
|
||||||
|
struct passwd pwd;
|
||||||
|
if ( scanpwent(line, &pwd) && check(&pwd, check_ctx) )
|
||||||
{
|
{
|
||||||
|
free(line);
|
||||||
fclose(passwd);
|
fclose(passwd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( errno != 0 )
|
free(line);
|
||||||
|
if ( ferror(passwd) )
|
||||||
warn("%s", passwd_path);
|
warn("%s", passwd_path);
|
||||||
fclose(passwd);
|
fclose(passwd);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1025,10 +1032,13 @@ int main(void)
|
||||||
}
|
}
|
||||||
explicit_bzero(first, sizeof(first));
|
explicit_bzero(first, sizeof(first));
|
||||||
if ( !install_configurationf("etc/passwd", "a",
|
if ( !install_configurationf("etc/passwd", "a",
|
||||||
"root:%s:0:0:root:/root:sh\n", hash) )
|
"root:%s:0:0:root:/root:sh\n"
|
||||||
|
"include /etc/default/passwd.d/*\n", hash) )
|
||||||
continue;
|
continue;
|
||||||
textf("User '%s' added to /etc/passwd\n", "root");
|
textf("User '%s' added to /etc/passwd\n", "root");
|
||||||
if ( !install_configurationf("etc/group", "a", "root::0:root\n") )
|
if ( !install_configurationf("etc/group", "a",
|
||||||
|
"root::0:root\n"
|
||||||
|
"include /etc/default/group.d/*\n") )
|
||||||
continue;
|
continue;
|
||||||
install_skel("/root", 0, 0);
|
install_skel("/root", 0, 0);
|
||||||
textf("Group '%s' added to /etc/group.\n", "root");
|
textf("Group '%s' added to /etc/group.\n", "root");
|
||||||
|
@ -1230,7 +1240,7 @@ int main(void)
|
||||||
"connections as well.\n\n");
|
"connections as well.\n\n");
|
||||||
bool might_want_sshd =
|
bool might_want_sshd =
|
||||||
any_ssh_keys ||
|
any_ssh_keys ||
|
||||||
any_sshd_keys ||
|
any_sshd_keys ||
|
||||||
!access_or_die("/etc/sshd_config", F_OK);
|
!access_or_die("/etc/sshd_config", F_OK);
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -155,24 +156,50 @@ int main(int argc, char* argv[])
|
||||||
if ( crypt_newhash(first, cipher, newhash, sizeof(newhash)) < 0 )
|
if ( crypt_newhash(first, cipher, newhash, sizeof(newhash)) < 0 )
|
||||||
err(1, "crypt_newhash");
|
err(1, "crypt_newhash");
|
||||||
explicit_bzero(first, sizeof(first));
|
explicit_bzero(first, sizeof(first));
|
||||||
|
|
||||||
// TODO: This is subject to races and is obviously an insecure design.
|
// TODO: This is subject to races and is obviously an insecure design.
|
||||||
// The backend and coordination of the passwd database should be moved
|
// The backend and coordination of the passwd database should be moved
|
||||||
// to its own daemon.
|
// to its own daemon.
|
||||||
|
FILE* in = fopen("/etc/passwd", "r");
|
||||||
|
if ( !in )
|
||||||
|
err(1, "/etc/passwd");
|
||||||
int fd = open("/etc/passwd.new", O_WRONLY | O_CREAT | O_EXCL, 0644);
|
int fd = open("/etc/passwd.new", O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||||
if ( fd < 0 )
|
if ( fd < 0 )
|
||||||
err(1, "/etc/passwd.new");
|
err(1, "/etc/passwd.new");
|
||||||
fchown(fd, 0, 0); // HACK.
|
fchown(fd, 0, 0); // HACK.
|
||||||
FILE* fp = fdopen(fd, "w");
|
FILE* fp = fdopen(fd, "w");
|
||||||
if ( !fp )
|
if ( !fp )
|
||||||
err(1, "fdopen");
|
|
||||||
setpwent();
|
|
||||||
while ( (errno = 0, pwd = getpwent()) )
|
|
||||||
{
|
{
|
||||||
|
unlink("/etc/passwd.new");
|
||||||
|
err(1, "fdopen");
|
||||||
|
}
|
||||||
|
char* line = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
ssize_t length;
|
||||||
|
bool found = false;
|
||||||
|
while ( 0 < (length = getline(&line, &size, in)) )
|
||||||
|
{
|
||||||
|
char* copy = strdup(line);
|
||||||
|
if ( !copy )
|
||||||
|
{
|
||||||
|
unlink("/etc/passwd.new");
|
||||||
|
err(1, "malloc");
|
||||||
|
}
|
||||||
|
if ( copy[length - 1] == '\n' )
|
||||||
|
copy[--length] = '\0';
|
||||||
|
struct passwd passwd;
|
||||||
|
if ( !scanpwent(copy, (pwd = &passwd)) )
|
||||||
|
{
|
||||||
|
fputs(line, fp);
|
||||||
|
free(copy);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
fputs(pwd->pw_name, fp);
|
fputs(pwd->pw_name, fp);
|
||||||
fputc(':', fp);
|
fputc(':', fp);
|
||||||
if ( !strcmp(pwd->pw_name, username) )
|
if ( !strcmp(pwd->pw_name, username) )
|
||||||
|
{
|
||||||
fputs(newhash, fp);
|
fputs(newhash, fp);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fputs(pwd->pw_passwd, fp);
|
fputs(pwd->pw_passwd, fp);
|
||||||
fputc(':', fp);
|
fputc(':', fp);
|
||||||
|
@ -191,17 +218,25 @@ int main(int argc, char* argv[])
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
err(1, "/etc/passwd.new");
|
err(1, "/etc/passwd.new");
|
||||||
}
|
}
|
||||||
|
free(copy);
|
||||||
}
|
}
|
||||||
if ( errno != 0 )
|
free(line);
|
||||||
|
if ( ferror(in) )
|
||||||
{
|
{
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
err(1, "getpwent");
|
err(1, "/etc/passwd");
|
||||||
}
|
}
|
||||||
if ( fclose(fp) == EOF )
|
fclose(in);
|
||||||
|
if ( ferror(fp) || fclose(fp) == EOF )
|
||||||
{
|
{
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
err(1, "/etc/passwd.new");
|
err(1, "/etc/passwd.new");
|
||||||
}
|
}
|
||||||
|
if ( !found )
|
||||||
|
{
|
||||||
|
unlink("/etc/passwd.new");
|
||||||
|
errx(1, "user %s is not directly in /etc/passwd", username);
|
||||||
|
}
|
||||||
if ( rename("/etc/passwd.new", "/etc/passwd") < 0 )
|
if ( rename("/etc/passwd.new", "/etc/passwd") < 0 )
|
||||||
{
|
{
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
|
|
Loading…
Reference in New Issue