]> git.saurik.com Git - apple/launchd.git/blob - launchd/src/register_mach_bootstrap_servers.c
launchd-106.tar.gz
[apple/launchd.git] / launchd / src / register_mach_bootstrap_servers.c
1 #include <CoreFoundation/CoreFoundation.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <mach/mach.h>
5 #include <mach/mach_error.h>
6 #include <servers/bootstrap.h>
7 #include <unistd.h>
8 #include <dirent.h>
9 #include <pwd.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 static void regServ(uid_t u, bool on_demand, bool is_kunc, const char *serv_name, const char *serv_cmd);
14 static void handleConfigFile(const char *file);
15 static CFPropertyListRef CreateMyPropertyListFromFile(const char *posixfile);
16
17 int main(int argc, char *argv[])
18 {
19 DIR *d;
20 struct dirent *de;
21 struct stat sb;
22
23 if (argc != 2) {
24 fprintf(stderr, "usage: %s: <configdir|configfile>\n", getprogname());
25 exit(EXIT_FAILURE);
26 }
27
28 stat(argv[1], &sb);
29
30 if (S_ISREG(sb.st_mode)) {
31 handleConfigFile(argv[1]);
32 exit(EXIT_SUCCESS);
33 }
34
35 if (getenv("SECURITYSESSIONID")) {
36 if (fork() == 0) {
37 const char *h = getenv("HOME");
38 struct passwd *pwe = getpwuid(getuid());
39 char *buf;
40 asprintf(&buf, "%s/%s", h ? h : pwe->pw_dir, "Library/LaunchAgents");
41 execlp("launchctl", "launchctl", "load", buf, "/Library/LaunchAgents", "/System/Library/LaunchAgents", NULL);
42 exit(EXIT_SUCCESS);
43 }
44 }
45
46 if ((d = opendir(argv[1])) == NULL) {
47 fprintf(stderr, "%s: opendir() failed to open the directory\n", getprogname());
48 exit(EXIT_FAILURE);
49 }
50
51 while ((de = readdir(d)) != NULL) {
52 if ((de->d_name[0] != '.')) {
53 char *foo;
54 if (asprintf(&foo, "%s/%s", argv[1], de->d_name))
55 handleConfigFile(foo);
56 free(foo);
57 }
58 }
59
60 exit(EXIT_SUCCESS);
61 }
62
63 static void handleConfigFile(const char *file)
64 {
65 bool on_demand = true, is_kunc = false;
66 uid_t u = getuid();
67 struct passwd *pwe;
68 char usr[4096];
69 char serv_name[4096];
70 char serv_cmd[4096];
71 CFPropertyListRef plist = CreateMyPropertyListFromFile(file);
72
73 if (plist) {
74 if (CFDictionaryContainsKey(plist, CFSTR("Username"))) {
75 const void *v = CFDictionaryGetValue(plist, CFSTR("Username"));
76
77 if (v) CFStringGetCString(v, usr, sizeof(usr), kCFStringEncodingUTF8);
78 else goto out;
79
80 if ((pwe = getpwnam(usr))) {
81 u = pwe->pw_uid;
82 } else {
83 fprintf(stderr, "%s: user not found\n", getprogname());
84 goto out;
85 }
86 }
87 if (CFDictionaryContainsKey(plist, CFSTR("OnDemand"))) {
88 const void *v = CFDictionaryGetValue(plist, CFSTR("OnDemand"));
89 if (v)
90 on_demand = CFBooleanGetValue(v);
91 else goto out;
92 }
93 if (CFDictionaryContainsKey(plist, CFSTR("ServiceName"))) {
94 const void *v = CFDictionaryGetValue(plist, CFSTR("ServiceName"));
95
96 if (v) CFStringGetCString(v, serv_name, sizeof(serv_name), kCFStringEncodingUTF8);
97 else goto out;
98 }
99 if (CFDictionaryContainsKey(plist, CFSTR("Command"))) {
100 const void *v = CFDictionaryGetValue(plist, CFSTR("Command"));
101
102 if (v) CFStringGetCString(v, serv_cmd, sizeof(serv_cmd), kCFStringEncodingUTF8);
103 else goto out;
104 }
105 if (CFDictionaryContainsKey(plist, CFSTR("isKUNCServer"))) {
106 const void *v = CFDictionaryGetValue(plist, CFSTR("isKUNCServer"));
107 if (v && CFBooleanGetValue(v)) is_kunc = true;
108 else goto out;
109 }
110 regServ(u, on_demand, is_kunc, serv_name, serv_cmd);
111 goto out_good;
112 out:
113 fprintf(stdout, "%s: failed to register: %s\n", getprogname(), file);
114 out_good:
115 CFRelease(plist);
116 } else {
117 fprintf(stderr, "%s: no plist was returned for: %s\n", getprogname(), file);
118 }
119 }
120
121 static void regServ(uid_t u, bool on_demand, bool is_kunc, const char *serv_name, const char *serv_cmd)
122 {
123 kern_return_t kr;
124 mach_port_t msr, msv, mhp;
125
126 if ((kr = bootstrap_create_server(bootstrap_port, (char*)serv_cmd, u, on_demand, &msr)) != KERN_SUCCESS) {
127 fprintf(stderr, "%s: bootstrap_create_server(): %d\n", getprogname(), kr);
128 return;
129 }
130 if ((kr = bootstrap_create_service(msr, (char*)serv_name, &msv)) != KERN_SUCCESS) {
131 fprintf(stderr, "%s: bootstrap_register(): %d\n", getprogname(), kr);
132 return;
133 }
134 if (is_kunc) {
135 mhp = mach_host_self();
136 if ((kr = host_set_UNDServer(mhp, msv)) != KERN_SUCCESS) {
137 fprintf(stderr, "%s: host_set_UNDServer(): %s\n", getprogname(), mach_error_string(kr));
138 return;
139 }
140 mach_port_deallocate(mach_task_self(), mhp);
141 }
142 }
143
144 static CFPropertyListRef CreateMyPropertyListFromFile(const char *posixfile)
145 {
146 CFPropertyListRef propertyList;
147 CFStringRef errorString;
148 CFDataRef resourceData;
149 SInt32 errorCode;
150 CFURLRef fileURL;
151
152 fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, posixfile, strlen(posixfile), false);
153 if (!fileURL)
154 fprintf(stderr, "%s: CFURLCreateFromFileSystemRepresentation(%s) failed\n", getprogname(), posixfile);
155 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &errorCode))
156 fprintf(stderr, "%s: CFURLCreateDataAndPropertiesFromResource(%s) failed: %d\n", getprogname(), posixfile, (int)errorCode);
157 propertyList = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, &errorString);
158 if (!propertyList) {
159 fprintf(stderr, "%s: propertyList is NULL\n", getprogname());
160 if (errorString)
161 CFRelease(errorString);
162 }
163 if (resourceData)
164 CFRelease(resourceData);
165 if (fileURL)
166 CFRelease(fileURL);
167
168 return propertyList;
169 }