#include #include #include #include #include #include #include #include #include #include #include static const char *argv0 = NULL; static void regServ(uid_t u, bool on_demand, bool is_kunc, const char *serv_name, const char *serv_cmd); static void handleConfigFile(const char *file); static CFPropertyListRef CreateMyPropertyListFromFile(const char *posixfile); #ifdef BUILD_LIB #include "initng.h" static int register_per_user_mach_bootstrap_servers_main(int argc, char *argv[]); static int register_per_user_mach_bootstrap_servers_main(int argc, char *argv[]) #else int main(int argc, char *argv[]) #endif { DIR *d; struct dirent *de; struct stat sb; argv0 = argv[0]; if (argc != 2) { fprintf(stderr, "usage: %s: \n", argv0); exit(EXIT_FAILURE); } stat(argv[1], &sb); if (S_ISREG(sb.st_mode)) { handleConfigFile(argv[1]); exit(EXIT_SUCCESS); } if ((d = opendir(argv[1])) == NULL) { fprintf(stderr, "%s: opendir() failed to open the directory\n", argv0); exit(EXIT_FAILURE); } while ((de = readdir(d)) != NULL) { if ((de->d_name[0] != '.')) { char *foo; if (asprintf(&foo, "%s/%s", argv[1], de->d_name)) handleConfigFile(foo); free(foo); } } exit(EXIT_SUCCESS); } static void handleConfigFile(const char *file) { bool on_demand = true, is_kunc = false; uid_t u = getuid(); struct passwd *pwe; char usr[4096]; char serv_name[4096]; char serv_cmd[4096]; CFPropertyListRef plist = CreateMyPropertyListFromFile(file); if (u == 0) u = geteuid(); if (plist) { if (CFDictionaryContainsKey(plist, CFSTR("Username"))) { const void *v = CFDictionaryGetValue(plist, CFSTR("Username")); if (v) CFStringGetCString(v, usr, sizeof(usr), kCFStringEncodingUTF8); else goto out; if ((pwe = getpwnam(usr))) { u = pwe->pw_uid; } else { fprintf(stderr, "%s: user not found\n", argv0); goto out; } } if (CFDictionaryContainsKey(plist, CFSTR("OnDemand"))) { const void *v = CFDictionaryGetValue(plist, CFSTR("OnDemand")); if (v) on_demand = CFBooleanGetValue(v); else goto out; } if (CFDictionaryContainsKey(plist, CFSTR("ServiceName"))) { const void *v = CFDictionaryGetValue(plist, CFSTR("ServiceName")); if (v) CFStringGetCString(v, serv_name, sizeof(serv_name), kCFStringEncodingUTF8); else goto out; } if (CFDictionaryContainsKey(plist, CFSTR("Command"))) { const void *v = CFDictionaryGetValue(plist, CFSTR("Command")); if (v) CFStringGetCString(v, serv_cmd, sizeof(serv_cmd), kCFStringEncodingUTF8); else goto out; } if (CFDictionaryContainsKey(plist, CFSTR("isKUNCServer"))) { const void *v = CFDictionaryGetValue(plist, CFSTR("isKUNCServer")); if (v && CFBooleanGetValue(v)) is_kunc = true; else goto out; } regServ(u, on_demand, is_kunc, serv_name, serv_cmd); goto out_good; out: fprintf(stdout, "%s: failed to register: %s\n", argv0, file); out_good: CFRelease(plist); } else { fprintf(stderr, "%s: no plist was returned for: %s\n", argv0, file); } } static void regServ(uid_t u, bool on_demand, bool is_kunc, const char *serv_name, const char *serv_cmd) { kern_return_t kr; mach_port_t msr, msv, mhp; if ((kr = bootstrap_create_server(bootstrap_port, (char*)serv_cmd, u, on_demand, &msr)) != KERN_SUCCESS) { fprintf(stderr, "%s: bootstrap_create_server(): %d\n", argv0, kr); return; } if ((kr = bootstrap_create_service(msr, (char*)serv_name, &msv)) != KERN_SUCCESS) { fprintf(stderr, "%s: bootstrap_register(): %d\n", argv0, kr); return; } if (is_kunc) { mhp = mach_host_self(); if ((kr = host_set_UNDServer(mhp, msv)) != KERN_SUCCESS) { fprintf(stderr, "%s: host_set_UNDServer(): %s\n", argv0, mach_error_string(kr)); return; } mach_port_deallocate(mach_task_self(), mhp); } } static CFPropertyListRef CreateMyPropertyListFromFile(const char *posixfile) { CFPropertyListRef propertyList; CFStringRef errorString; CFDataRef resourceData; SInt32 errorCode; CFURLRef fileURL; fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, posixfile, strlen(posixfile), false); if (!fileURL) fprintf(stderr, "%s: CFURLCreateFromFileSystemRepresentation(%s) failed\n", argv0, posixfile); if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &errorCode)) fprintf(stderr, "%s: CFURLCreateDataAndPropertiesFromResource(%s) failed: %d\n", argv0, posixfile, (int)errorCode); propertyList = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, &errorString); if (!propertyList) fprintf(stderr, "%s: propertyList is NULL\n", argv0); CFRelease(resourceData); return propertyList; } #ifdef BUILD_LIB int __register_per_user_mach_bootstrap_servers(void) { char *av[] = { "/usr/libexec/register_mach_bootstrap_servers", "/etc/mach_init_per_user.d", NULL }; pid_t p = fork(); if (p == -1) return 1; if (p == 0) { register_per_user_mach_bootstrap_servers_main(2, av); exit(EXIT_SUCCESS); } return 0; } #endif