#include "utility.h"
#include <sys/resource.h>
CFStringRef createCFString(char * string)
{
return CFStringCreateWithCString(kCFAllocatorDefault, string,
kCFStringEncodingUTF8);
}
Boolean check_file(const char * filename)
{
Boolean result = true; struct stat stat_buf;
if (stat(filename, &stat_buf) != 0) {
perror(filename);
result = false;
goto finish;
}
if ( !(stat_buf.st_mode & S_IFREG) ) {
qerror("%s is not a regular file\n", filename);
result = false;
goto finish;
}
if (access(filename, R_OK) != 0) {
qerror("%s is not readable\n", filename);
result = false;
goto finish;
}
finish:
return result;
}
Boolean check_dir(const char * dirname, int writeable, int print_err)
{
int result = true; struct stat stat_buf;
if (stat(dirname, &stat_buf) != 0) {
if (print_err) {
perror(dirname);
}
result = false;
goto finish;
}
if ( !(stat_buf.st_mode & S_IFDIR) ) {
if (print_err) {
qerror("%s is not a directory\n", dirname);
}
result = false;
goto finish;
}
if (writeable) {
if (access(dirname, W_OK) != 0) {
if (print_err) {
qerror("%s is not writeable\n", dirname);
}
result = false;
goto finish;
}
}
finish:
return result;
}
void qerror(const char * format, ...)
{
va_list ap;
if (g_verbose_level <= kKXKextManagerLogLevelSilent) return;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fflush(stderr);
return;
}
void verbose_log(const char * format, ...)
{
va_list ap;
if (g_verbose_level < kKXKextManagerLogLevelDefault) return;
fprintf(stdout, "%s: ", progname);
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
fprintf(stdout, "\n");
fflush(stdout);
return;
}
void error_log(const char * format, ...)
{
va_list ap;
if (g_verbose_level <= kKXKextManagerLogLevelSilent) return;
fprintf(stderr, "%s: ", progname);
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
fprintf(stderr, "\n");
fflush(stderr);
return;
}
int user_approve(int default_answer, const char * format, ...)
{
int result = 1;
va_list ap;
char fake_buffer[2];
int output_length;
char * output_string;
char * prompt_string = NULL;
int c, x;
va_start(ap, format);
output_length = vsnprintf(fake_buffer, 1, format, ap);
va_end(ap);
output_string = (char *)malloc(output_length + 1);
if (!output_string) {
qerror("memory allocation failure\n");
result = -1;
goto finish;
}
va_start(ap, format);
vsprintf(output_string, format, ap);
va_end(ap);
prompt_string = default_answer ? " [Y/n]" : " [y/N]";
while ( 1 ) {
fprintf(stdout, "%s%s%s", output_string, prompt_string, "? ");
fflush(stdout);
c = fgetc(stdin);
if (c == EOF) {
result = -1;
goto finish;
}
if ( c != '\n' ) {
do {
x = fgetc(stdin);
} while (x != '\n' && x != EOF);
if (x == EOF) {
result = -1;
goto finish;
}
}
if (c == '\n') {
result = default_answer ? 1 : 0;
goto finish;
} else if (tolower(c) == 'y') {
result = 1;
goto finish;
} else if (tolower(c) == 'n') {
result = 0;
goto finish;
}
}
finish:
if (output_string) free(output_string);
return result;
}
const char * user_input(const char * format, ...)
{
char * result = NULL; va_list ap;
char fake_buffer[2];
int output_length;
char * output_string = NULL;
unsigned index;
size_t size = 80; int c;
result = (char *)malloc(size);
if (!result) {
goto finish;
}
index = 0;
va_start(ap, format);
output_length = vsnprintf(fake_buffer, 1, format, ap);
va_end(ap);
output_string = (char *)malloc(output_length + 1);
if (!output_string) {
qerror("memory allocation failure\n");
result = NULL;
goto finish;
}
va_start(ap, format);
vsprintf(output_string, format, ap);
va_end(ap);
fprintf(stdout, "%s ", output_string);
fflush(stdout);
c = fgetc(stdin);
while (c != '\n' && c != EOF) {
if (index >= (size - 1)) {
qerror("input line too long\n");
if (result) free(result);
result = NULL;
goto finish;
}
result[index++] = (char)c;
c = fgetc(stdin);
}
result[index] = '\0';
if (c == EOF) {
if (result) free(result);
result = NULL;
goto finish;
}
finish:
if (output_string) free(output_string);
return result;
}
int addKextsToManager(
KXKextManagerRef aManager,
CFArrayRef kextNames,
CFMutableArrayRef kextNamesToUse,
Boolean do_tests)
{
int result = 1; KXKextManagerError kxresult = kKXKextManagerErrorNone;
CFIndex i, count;
KXKextRef theKext = NULL; CFURLRef kextURL = NULL;
count = CFArrayGetCount(kextNames);
for (i = 0; i < count; i++) {
char name_buffer[MAXPATHLEN];
CFStringRef kextName = (CFStringRef)CFArrayGetValueAtIndex(
kextNames, i);
if (kextURL) {
CFRelease(kextURL);
kextURL = NULL;
}
kextURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
kextName, kCFURLPOSIXPathStyle, true);
if (!kextURL) {
qerror("memory allocation failure\n");
result = -1;
goto finish;
}
if (!CFStringGetCString(kextName,
name_buffer, sizeof(name_buffer) - 1, kCFStringEncodingUTF8)) {
qerror("memory allocation or string conversion error\n");
result = -1;
goto finish;
}
kxresult = KXKextManagerAddKextWithURL(aManager, kextURL, true, &theKext);
if (kxresult != kKXKextManagerErrorNone) {
result = 0;
qerror("can't add kernel extension %s (%s)",
name_buffer, KXKextManagerErrorStaticCStringForError(kxresult));
qerror(" (run %s on this kext with -t for diagnostic output)\n",
progname);
#if 0
if (do_tests && theKext && g_verbose_level >= kKXKextManagerLogLevelErrorsOnly) {
qerror("kernel extension problems:\n");
KXKextPrintDiagnostics(theKext, stderr);
}
continue;
#endif 0
}
if (kextNamesToUse && theKext &&
(kxresult == kKXKextManagerErrorNone || do_tests)) {
CFArrayAppendValue(kextNamesToUse, kextName);
}
}
finish:
if (kextURL) CFRelease(kextURL);
return result;
}
int fork_program(const char * argv0, char * const argv[], int delay, Boolean wait)
{
int result = -2;
int status;
pid_t pid;
switch (pid = fork()) {
case -1: goto finish;
break;
case 0: if (!wait) {
result = daemon(0, 0);
if (result == -1) {
goto finish;
}
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE);
}
if (delay) {
sleep(delay);
}
execv(argv0, argv);
exit(1);
default: waitpid(pid, &status, 0);
status = WEXITSTATUS(status);
if (wait) {
result = status;
} else if (status != 0) {
result = -1;
} else {
result = pid;
}
break;
}
finish:
return result;
}