Skip to content
Snippets Groups Projects
Commit dec3e894 authored by Lars Seipel's avatar Lars Seipel
Browse files

initial import

parents
No related branches found
No related tags found
No related merge requests found
Makefile 0 → 100644
TARGET=auto-wait-for-sssd
CC=cc
CFLAGS:=-Wall -O2 -g -Wno-parentheses $(shell pkg-config --cflags libbsd) $(CFLAGS)
LD=$(CC)
LDFLAGS=
LIBS=$(shell pkg-config --libs libbsd) -ldl
PREFIX=/usr/local
HFILES=\
arg.h \
log.h
OFILES=\
main.o \
time.o
all: $(TARGET)
.c.o:
$(CC) -c $(CFLAGS) $<
$(OFILES): $(HFILES) Makefile
$(TARGET): $(OFILES)
$(LD) -o $(TARGET) $(LDFLAGS) $(OFILES) $(LIBS)
install: $(TARGET)
install -m 755 $(TARGET) $(PREFIX)/bin
clean:
rm -f $(TARGET) $(OFILES)
asan:
@make "FLAGS=$(CFLAGS) -fsanitize=address" "LDFLAGS=$(LDFLAGS) -fsanitize=address"
lsan:
@make "FLAGS=$(CFLAGS) -fsanitize=leak" "LDFLAGS=$(LDFLAGS) -fsanitize=leak"
tsan:
@make "FLAGS=$(CFLAGS) -fsanitize=thread" "LDFLAGS=$(LDFLAGS) -fsanitize=thread"
usan:
@make "FLAGS=$(CFLAGS) -fsanitize=undefined" "LDFLAGS=$(LDFLAGS) -fsanitize=undefined"
.PHONY: all install clean asan tsan usan
arg.h 0 → 100644
/*
Derived from Inferno include/kern.h.
http://code.google.com/p/inferno-os/source/browse/include/kern.h
Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
Portions Copyright © 2009 The Go Authors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* command line */
extern char *argv0;
#define USED(x) ((void)(x))
#define ARGBEGIN for((argv0=(argv0?argv0:*argv)),argv++,argc--;\
argv[0] && argv[0][0]=='-' && argv[0][1];\
argc--, argv++) {\
char *_args, *_argt;\
char _argc;\
_args = &argv[0][1];\
if(_args[0]=='-' && _args[1]==0){\
argc--; argv++; break;\
}\
while((_argc = *_args++) != 0)\
switch(_argc)
#define ARGEND _argt=0;USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
#define ARGF() (_argt=_args, _args="",\
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
#define EARGF(x) (_argt=_args, _args="",\
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), fatalf("usage"), (char*)0)))
#define ARGC() _argc
log.h 0 → 100644
#ifndef AUTOWAITFOR_UTIL_H
#define AUTOWAITFOR_UTIL_H
#include <stdio.h>
#include <stdlib.h>
#define LOG_EMERG "<0>" /* system is unusable */
#define LOG_ALERT "<1>" /* action must be taken immediately */
#define LOG_CRIT "<2>" /* critical conditions */
#define LOG_ERR "<3>" /* error conditions */
#define LOG_WARNING "<4>" /* warning conditions */
#define LOG_NOTICE "<5>" /* normal but significant condition */
#define LOG_INFO "<6>" /* informational */
#define LOG_DEBUG "<7>" /* debug-level messages */
extern char *argv0;
#define outputf(level, fmt, args...) \
fprintf(stderr, level "%s " __FILE__ ":%d] " fmt "\n", argv0, \
__LINE__, ##args)
#define debugf(...) outputf(LOG_DEBUG, __VA_ARGS__)
#define infof(...) outputf(LOG_INFO, __VA_ARGS__)
#define warnf(...) outputf(LOG_WARNING, __VA_ARGS__)
#define errorf(...) outputf(LOG_ERR, __VA_ARGS__)
#define fatalf(...) \
do { \
outputf(LOG_EMERG, __VA_ARGS__); \
exit(1); \
} while (0)
#endif
main.c 0 → 100644
// Copyright © 2019 Lars Seipel <ls@slrz.net>
//
// Derived from autofs (modules/lookup_sss.c, v5.1.6)
//
// Copyright 2012 Ian Kent <raven@themaw.net>
// Copyright 2012 Red Hat, Inc.
//
// GNU General Public License v2.0+ (https://www.gnu.org/licenses/gpl-2.0.txt)
#include <bsd/stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include "arg.h"
#include "log.h"
#include "time.h"
#define SSS_SO_NAME "libsss_autofs"
#ifndef SSS_LIB_DIR
#define SSS_LIB_DIR "/usr/lib64/sssd/modules"
#endif
int _sss_setautomntent(const char *, void **);
int _sss_getautomntent_r(char **, char **, void *);
int _sss_getautomntbyname_r(char *, char **, void *);
int _sss_endautomntent(void **);
typedef int (*setautomntent_t)(const char *, void **);
typedef int (*getautomntent_t)(char **, char **, void *);
typedef int (*getautomntbyname_t)(char *, char **, void *);
typedef int (*endautomntent_t)(void **);
struct libsss_autofs {
void *dlhandle;
setautomntent_t setautomntent;
getautomntent_t getautomntent_r;
getautomntbyname_t getautomntbyname_r;
endautomntent_t endautomntent;
};
static int
libsss_autofs_open(struct libsss_autofs *ctxt)
{
char dlbuf[PATH_MAX];
char *estr;
void *dh;
size_t size;
size = snprintf(dlbuf, sizeof(dlbuf), "%s/%s.so", SSS_LIB_DIR,
SSS_SO_NAME);
if (size >= sizeof(dlbuf)) {
errorf("sss library path too long");
return 1;
}
dh = dlopen(dlbuf, RTLD_LAZY);
if (!dh)
return 1;
ctxt->dlhandle = dh;
ctxt->setautomntent = (setautomntent_t)dlsym(dh, "_sss_setautomntent");
if (!ctxt->setautomntent)
goto lib_names_fail;
ctxt->getautomntent_r =
(getautomntent_t)dlsym(dh, "_sss_getautomntent_r");
if (!ctxt->getautomntent_r)
goto lib_names_fail;
ctxt->getautomntbyname_r =
(getautomntbyname_t)dlsym(dh, "_sss_getautomntbyname_r");
if (!ctxt->getautomntbyname_r)
goto lib_names_fail;
ctxt->endautomntent = (endautomntent_t)dlsym(dh, "_sss_endautomntent");
if (!ctxt->setautomntent)
goto lib_names_fail;
return 0;
lib_names_fail:
if ((estr = dlerror()) == NULL)
errorf("failed to locate sss library entry points");
else
errorf("dlsym: %s", estr);
dlclose(dh);
return 1;
}
static int
libsss_autofs_close(struct libsss_autofs *ctxt)
{
int r;
if (r = dlclose(ctxt->dlhandle))
errorf("dlclose: %s", dlerror() ?: "<null>");
return r;
}
char *argv0;
static void
usage(int status)
{
fprintf(stderr,
"Usage: %s [options]\n"
" -h: show this help text\n"
" -v: be verbose\n",
argv0);
exit(status);
}
static const int64_t base_delay = 100 * Millisecond;
static const int64_t max_delay = 2 * Second;
int
main(int argc, char **argv)
{
const char *mapname = "auto.master";
int vflag = 0;
char fmtbuf[16];
ARGBEGIN
{
case 'h':
usage(0);
break;
case 'v':
vflag++;
break;
default:
usage(2);
}
ARGEND
if (*argv)
mapname = *argv;
struct libsss_autofs sss_autofs;
void *ctx = NULL;
int r = libsss_autofs_open(&sss_autofs);
if (r)
fatalf("libsss_autofs_open: %d", r);
int64_t delay = base_delay;
for (int i = 0; i < 1000; i++) {
r = sss_autofs.setautomntent(mapname, &ctx);
if (r == 0)
break;
ctx = NULL;
int64_t backoff_nsec = delay + arc4random_uniform(delay / 2);
struct timespec ts = totimespec(backoff_nsec);
warnf("setautomntent: %d (retry in %s)", r,
fmtduration(fmtbuf, sizeof fmtbuf, backoff_nsec));
nanosleep(&ts, NULL);
delay <<= 1;
if (delay > max_delay)
delay = max_delay;
}
if (!ctx)
goto Out;
char *key = NULL, *value = NULL;
while ((r = sss_autofs.getautomntent_r(&key, &value, ctx)) == 0) {
if (vflag)
printf("%s → %s\n", key ?: "<null>", value ?: "<null>");
free(key);
free(value);
key = value = NULL;
}
r = 0;
Out:
if (ctx)
sss_autofs.endautomntent(&ctx);
libsss_autofs_close(&sss_autofs);
return r;
}
time.c 0 → 100644
#include "time.h"
#include <assert.h>
typedef uint64_t usec_t;
static char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
char*
fmtduration(char *buf, size_t len, int64_t nsec)
{
return format_timespan(buf, len, nsec/1000LL, 1000ULL);
}
int64_t
timenow(clockid_t id)
{
struct timespec ts;
int r;
r = clock_gettime(id, &ts);
assert(r == 0);
return ts.tv_sec * Second + ts.tv_nsec;
}
struct timespec
totimespec(int64_t t)
{
struct timespec ts = {0};
ts.tv_sec = t / Second;
ts.tv_nsec = t % Second;
return ts;
}
struct timespec
timesub(struct timespec *t, struct timespec *u)
{
struct timespec r;
r.tv_sec = t->tv_sec - u->tv_sec;
r.tv_nsec = t->tv_nsec - u->tv_nsec;
if (r.tv_nsec < 0) {
r.tv_sec--;
r.tv_nsec += Second;
}
return r;
}
/***
The rest of the file was scrounged from systemd and the following
conditions apply:
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define USEC_FMT "%" PRIu64
#define USEC_INFINITY ((usec_t) -1)
#define MSEC_PER_SEC 1000ULL
#define USEC_PER_SEC ((usec_t) 1000000ULL)
#define USEC_PER_MSEC ((usec_t) 1000ULL)
#define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC))
#define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE))
#define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR))
#define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY))
#define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC))
#define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC))
static char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
static const struct {
const char *suffix;
usec_t usec;
} table[] = {
{ "y", USEC_PER_YEAR },
{ "month", USEC_PER_MONTH },
{ "w", USEC_PER_WEEK },
{ "d", USEC_PER_DAY },
{ "h", USEC_PER_HOUR },
{ "min", USEC_PER_MINUTE },
{ "s", USEC_PER_SEC },
{ "ms", USEC_PER_MSEC },
{ "us", 1 },
};
unsigned i;
char *p = buf;
bool something = false;
assert(buf);
assert(l > 0);
if (t == USEC_INFINITY) {
strncpy(p, "infinity", l-1);
p[l-1] = 0;
return p;
}
if (t <= 0) {
strncpy(p, "0", l-1);
p[l-1] = 0;
return p;
}
/* The result of this function can be parsed with parse_sec */
for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {
int k = 0;
size_t n;
bool done = false;
usec_t a, b;
if (t <= 0)
break;
if (t < accuracy && something)
break;
if (t < table[i].usec)
continue;
if (l <= 1)
break;
a = t / table[i].usec;
b = t % table[i].usec;
/* Let's see if we should shows this in dot notation */
if (t < USEC_PER_MINUTE && b > 0) {
usec_t cc;
int j;
j = 0;
for (cc = table[i].usec; cc > 1; cc /= 10)
j++;
for (cc = accuracy; cc > 1; cc /= 10) {
b /= 10;
j--;
}
if (j > 0) {
k = snprintf(p, l,
"%s"USEC_FMT".%0*llu%s",
p > buf ? " " : "",
a,
j,
(unsigned long long) b,
table[i].suffix);
t = 0;
done = true;
}
}
/* No? Then let's show it normally */
if (!done) {
k = snprintf(p, l,
"%s"USEC_FMT"%s",
p > buf ? " " : "",
a,
table[i].suffix);
t = b;
}
/* n = MIN((size_t) k, l); */
n = (size_t) k < l ? (size_t) k : l;
l -= n;
p += n;
something = true;
}
*p = 0;
return buf;
}
time.h 0 → 100644
#ifndef AUTOWAITFOR_TIME_H
#define AUTOWAITFOR_TIME_H
#include <stddef.h>
#include <stdint.h>
#include <time.h>
enum { Nanosecond = 1LL,
Microsecond = 1000LL * Nanosecond,
Millisecond = 1000LL * Microsecond,
Second = 1000LL * Millisecond,
Minute = 60LL * Second,
Hour = 60LL * Minute,
};
int64_t timenow(clockid_t);
struct timespec timesub(struct timespec *, struct timespec *);
struct timespec totimespec(int64_t t);
char *fmtduration(char *buf, size_t len, int64_t nsec);
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment