161 lines
4.0 KiB
C
161 lines
4.0 KiB
C
|
/* Copyright (C) 2011 Red Hat, Inc.
|
||
|
|
||
|
Written by Jindrich Novy <jnovy@redhat.com>.
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License as
|
||
|
published by the Free Software Foundation; either version 2 of the
|
||
|
License, or (at your option) any later version.
|
||
|
|
||
|
This program 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
|
||
|
General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public
|
||
|
License along with this program; see the file COPYING. If not,
|
||
|
write to the Free Software Foundation, Inc.,
|
||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||
|
|
||
|
#define _GNU_SOURCE
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <unistd.h>
|
||
|
#include <getopt.h>
|
||
|
#include <string.h>
|
||
|
#include <dirent.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <fcntl.h>
|
||
|
|
||
|
static void check_asprintf( char **strp, const char *fmt, ... ) {
|
||
|
va_list args;
|
||
|
|
||
|
va_start(args, fmt);
|
||
|
|
||
|
if (vasprintf(strp, fmt, args) == -1 || !*strp) {
|
||
|
fprintf(stderr, "Allocation failed.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
va_end(args);
|
||
|
}
|
||
|
|
||
|
static void write_script( int tfd, char *s ) {
|
||
|
if (write(tfd, s, strlen(s)) == -1) {
|
||
|
fprintf(stderr, "Error writing to temporary file\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv) {
|
||
|
struct stat st;
|
||
|
char *path, *enablepath;
|
||
|
char tmp[] = "/var/tmp/sclXXXXXX";
|
||
|
char *cmd = NULL, *bash_cmd, *echo, *enabled;
|
||
|
int i, tfd, ffd, stdin_read = 0;
|
||
|
|
||
|
if (!strcmp(argv[argc-1], "-")) { /* reading command from stdin */
|
||
|
size_t r = 0;
|
||
|
cmd = malloc(BUFSIZ);
|
||
|
|
||
|
if (!cmd) {
|
||
|
fprintf(stderr, "Can't allocate memory.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
for (;(r += fread(cmd+r, 1, BUFSIZ, stdin));) {
|
||
|
if (feof(stdin)) break;
|
||
|
cmd = realloc(cmd, r);
|
||
|
if (!cmd) {
|
||
|
fprintf(stderr, "Can't reallocate memory.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
}
|
||
|
if (!r) {
|
||
|
fprintf(stderr, "Error reading command from stdin.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
stdin_read = 1;
|
||
|
}
|
||
|
|
||
|
if (!stdin_read) {
|
||
|
if (argc < 4) {
|
||
|
fprintf(stderr, "Usage: %s <action> [<collection1>, <collection2> ...] <command>\n"
|
||
|
"If <command> is '-' then the command will be read from standard input.\n", argv[0]);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
cmd = argv[argc-1];
|
||
|
}
|
||
|
|
||
|
tfd = mkstemp(tmp);
|
||
|
|
||
|
check_asprintf(&enabled, "scl_enabled %s\n[ $? == 0 ] && exit 1\n"
|
||
|
"eval \"SCLS=( ${x_scls[*]} )\"\n"
|
||
|
"SCLS+=(%s)\n"
|
||
|
"export X_SCLS=$(printf '%%q ' \"${SCLS[@]}\")\n", argv[2], argv[2]);
|
||
|
write_script(tfd, enabled);
|
||
|
free(enabled);
|
||
|
|
||
|
for (i=2; i<argc-1; i++) {
|
||
|
FILE *f;
|
||
|
size_t r;
|
||
|
char scl_dir[BUFSIZ];
|
||
|
|
||
|
check_asprintf(&path, "/etc/scl/prefixes/%s", argv[i]);
|
||
|
if (!(f=fopen(path,"r"))) {
|
||
|
fprintf(stderr, "Unable to open %s!\n", path);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
r = fread(scl_dir, 1, BUFSIZ, f);
|
||
|
if (!r) {
|
||
|
fprintf(stderr, "Unable to read or file empty %s!\n", path);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
scl_dir[r-1] = '\0';
|
||
|
strncat(scl_dir, "/", BUFSIZ-1);
|
||
|
strncat(scl_dir, argv[i], BUFSIZ-1);
|
||
|
strncat(scl_dir, "/", BUFSIZ-1);
|
||
|
fclose(f);
|
||
|
free(path);
|
||
|
|
||
|
check_asprintf(&path, "%s", scl_dir);
|
||
|
if (lstat(path, &st)) {
|
||
|
fprintf(stderr, "%s doesn't exist\n", path);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
if (!S_ISDIR(st.st_mode)) {
|
||
|
fprintf(stderr, "%s is not a directory\n", path);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
check_asprintf(&enablepath, "%s/%s", path, argv[1]);
|
||
|
check_asprintf(&echo, ". %s\n", enablepath);
|
||
|
|
||
|
ffd = open(enablepath, O_RDONLY);
|
||
|
|
||
|
if (ffd != -1) {
|
||
|
write_script(tfd, echo);
|
||
|
} else {
|
||
|
fprintf(stderr, "WARNING: %s scriptlet does not exist!\n", enablepath);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
close(ffd);
|
||
|
free(echo);
|
||
|
free(enablepath);
|
||
|
free(path);
|
||
|
}
|
||
|
|
||
|
write_script(tfd, cmd);
|
||
|
write_script(tfd, "\n");
|
||
|
close(tfd);
|
||
|
|
||
|
check_asprintf(&bash_cmd, "/bin/bash %s", tmp);
|
||
|
i = system(bash_cmd);
|
||
|
free(bash_cmd);
|
||
|
|
||
|
return WEXITSTATUS(i);
|
||
|
}
|