#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "iolib.h"
#include "freedt.h"
#include "config.h"
/* SuSv3 says this is in unistd.h, but glibc and others don't include it. */
extern char **environ;
void warn(const char *msg) {
format(fd_err, "@c: @c\n", progname, msg);
}
void warn2(const char *msg1, const char *msg2) {
format(fd_err, "@c: @c: @c\n", progname, msg1, msg2);
}
void die(const char *msg) {
warn(msg);
exit(111);
}
void die2(const char *msg1, const char *msg2) {
warn2(msg1, msg2);
exit(111);
}
static void show_version() {
format(fd_out, "@c from freedt version " VERSION "\n", progname);
}
void version() {
show_version();
exit(1);
}
void help() {
show_version();
format(fd_out, "\n@c"
"-V Show version information\n"
"-? Show usage information\n", proghelp);
exit(1);
}
void get_default_args(int argc, char **argv) {
while (1) {
int c = getopt(argc, argv, "+V?");
if (c == -1)
break;
switch (c) {
case 'V':
version();
default:
help();
}
}
}
void setuidgidroot() {
char *root, *uid, *gid;
root = getenv("ROOT");
if (root != NULL) {
if (chdir(root) < 0)
die2(root, "unable to chdir");
if (chroot(root) < 0)
die2(root, "unable to chroot");
}
gid = getenv("GID");
if (gid != NULL) {
gid_t g = atoi(gid);
if (setgid(g) < 0)
die("unable to setgid");
if (setgroups(1, &g) < 0)
die("unable to setgroups");
}
uid = getenv("UID");
if (uid != NULL) {
uid_t u = atoi(uid);
if (setuid(u) < 0)
die("unable to setuid");
}
}
static int environ_size() {
int num = 0;
char **p;
for (p = environ; *p != NULL; p++)
++num;
return num;
}
static int build_environ_copy() {
static int have_run = 0;
char **new_environ;
int num, i;
if (have_run)
return 0;
have_run = 1;
num = environ_size();
new_environ = malloc((num + 1) * sizeof *new_environ);
if (new_environ == NULL)
return -1;
for (i = 0; i < num; i++) {
new_environ[i] = strdup(environ[i]);
if (new_environ[i] == NULL) {
while (--i >= 0) {
free(new_environ[i]);
}
free(new_environ);
return -1;
}
}
new_environ[num] = NULL;
environ = new_environ;
return 0;
}
static char **find_environ(const char *name) {
char **p;
int l = strlen(name);
for (p = environ; *p != NULL; p++) {
if (strlen(*p) <= l)
continue;
if (strncmp(*p, name, l) == 0 && (*p)[l] == '=')
return p;
}
return NULL;
}
int fdt_setenv(const char *name, const char *value) {
char *s;
char **p;
if (build_environ_copy() < 0)
return -1;
s = malloc(strlen(name) + strlen(value) + 2);
if (s == NULL)
return -1;
strcpy(s, name);
strcat(s, "=");
strcat(s, value);
p = find_environ(name);
if (p == NULL) {
int num = environ_size();
char **new_environ;
new_environ = realloc(environ, (num + 2) * sizeof *environ);
if (new_environ == NULL) {
free(s);
return -1;
}
new_environ[num] = s;
new_environ[num + 1] = NULL;
environ = new_environ;
} else {
free(*p);
*p = s;
}
return 0;
}
int fdt_unsetenv(const char *name) {
char **p;
if (build_environ_copy() < 0)
return -1;
p = find_environ(name);
if (p == NULL)
return -1;
do {
*p = *(p + 1);
} while (*p++ != NULL);
return 0;
}
void change_fd_flags(int fd, int add, int remove) {
int flags = fcntl(fd, F_GETFL);
if (flags < 0)
die("unable to read FD flags");
flags |= add;
flags &= ~remove;
if (fcntl(fd, F_SETFL, flags) < 0)
die("unable to set FD flags");
}
void set_fd_cloexec(int fd) {
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
die("unable to set FD_CLOEXEC");
}
void reliable_sleep(int seconds) {
while (seconds > 0)
seconds = sleep(seconds);
}
int lock_fd(int fd, int block) {
struct flock lock;
int rc;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
do {
rc = fcntl(fd, block ? F_SETLKW : F_SETLK, &lock);
} while (rc < 0 && errno == EINTR);
return rc;
}
syntax highlighted by Code2HTML, v. 0.9.1