1 /* 2 * Copyright 2015-2016, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 /*! The launch_daemon's companion command line tool. */ 8 9 10 #include <LaunchRoster.h> 11 #include <StringList.h> 12 13 #include <getopt.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <errno.h> 18 19 20 static struct option const kLongOptions[] = { 21 {"verbose", no_argument, 0, 'v'}, 22 {"help", no_argument, 0, 'h'}, 23 {NULL} 24 }; 25 26 extern const char *__progname; 27 static const char *kProgramName = __progname; 28 29 30 static void 31 list_jobs(bool verbose) 32 { 33 BLaunchRoster roster; 34 BStringList jobs; 35 status_t status = roster.GetJobs(NULL, jobs); 36 if (status != B_OK) { 37 fprintf(stderr, "%s: Could not get job listing: %s\n", kProgramName, 38 strerror(status)); 39 exit(EXIT_FAILURE); 40 } 41 42 for (int32 i = 0; i < jobs.CountStrings(); i++) 43 puts(jobs.StringAt(i).String()); 44 } 45 46 47 static void 48 list_targets(bool verbose) 49 { 50 BLaunchRoster roster; 51 BStringList targets; 52 status_t status = roster.GetTargets(targets); 53 if (status != B_OK) { 54 fprintf(stderr, "%s: Could not get target listing: %s\n", kProgramName, 55 strerror(status)); 56 exit(EXIT_FAILURE); 57 } 58 59 for (int32 i = 0; i < targets.CountStrings(); i++) 60 puts(targets.StringAt(i).String()); 61 } 62 63 64 static void 65 get_info(const char* name) 66 { 67 BLaunchRoster roster; 68 BMessage info; 69 status_t targetStatus = roster.GetTargetInfo(name, info); 70 if (targetStatus == B_OK) { 71 printf("Target: %s\n", name); 72 info.PrintToStream(); 73 } 74 75 info.MakeEmpty(); 76 status_t jobStatus = roster.GetJobInfo(name, info); 77 if (jobStatus == B_OK) { 78 printf("Job: %s\n", name); 79 info.PrintToStream(); 80 } 81 82 if (jobStatus != B_OK && targetStatus != B_OK) { 83 fprintf(stderr, "%s: Could not get target or job info for \"%s\": " 84 "%s\n", kProgramName, name, strerror(jobStatus)); 85 exit(EXIT_FAILURE); 86 } 87 } 88 89 90 static void 91 start_job(const char* name) 92 { 93 BLaunchRoster roster; 94 status_t status = roster.Start(name); 95 if (status == B_NAME_NOT_FOUND) 96 status = roster.Target(name); 97 98 if (status != B_OK) { 99 fprintf(stderr, "%s: Starting job \"%s\" failed: %s\n", kProgramName, 100 name, strerror(status)); 101 exit(EXIT_FAILURE); 102 } 103 } 104 105 106 static void 107 stop_job(const char* name) 108 { 109 BLaunchRoster roster; 110 status_t status = roster.Stop(name); 111 if (status == B_NAME_NOT_FOUND) 112 status = roster.StopTarget(name); 113 114 if (status != B_OK) { 115 fprintf(stderr, "%s: Stopping job \"%s\" failed: %s\n", kProgramName, 116 name, strerror(status)); 117 exit(EXIT_FAILURE); 118 } 119 } 120 121 122 static void 123 restart_job(const char* name) 124 { 125 stop_job(name); 126 start_job(name); 127 } 128 129 130 static void 131 enable_job(const char* name, bool enable) 132 { 133 BLaunchRoster roster; 134 status_t status = roster.SetEnabled(name, enable); 135 if (status != B_OK) { 136 fprintf(stderr, "%s: %s job \"%s\" failed: %s\n", kProgramName, 137 enable ? "Enabling" : "Disabling", name, strerror(status)); 138 exit(EXIT_FAILURE); 139 } 140 } 141 142 143 static void 144 usage(int status) 145 { 146 fprintf(stderr, "Usage: %s <command>\n" 147 "Where <command> is one of:\n" 148 " list - Lists all jobs (the default command)\n" 149 " list-targets - Lists all targets\n" 150 "The following <command>s have a <name> argument:\n" 151 " start - Starts a job/target\n" 152 " stop - Stops a running job/target\n" 153 " restart - Restarts a running job/target\n" 154 " info - Shows info for a job/target\n", 155 kProgramName); 156 157 exit(status); 158 } 159 160 161 int 162 main(int argc, char** argv) 163 { 164 const char* command = "list"; 165 bool verbose = false; 166 167 int c; 168 while ((c = getopt_long(argc, argv, "hv", kLongOptions, NULL)) != -1) { 169 switch (c) { 170 case 0: 171 break; 172 case 'h': 173 usage(0); 174 break; 175 case 'v': 176 verbose = true; 177 break; 178 default: 179 usage(1); 180 break; 181 } 182 } 183 184 if (argc - optind >= 1) 185 command = argv[optind]; 186 187 if (strcmp(command, "list") == 0) { 188 list_jobs(verbose); 189 } else if (strcmp(command, "list-targets") == 0) { 190 list_targets(verbose); 191 } else if (argc == optind + 1) { 192 // For convenience (the "info" command can be omitted) 193 get_info(command); 194 } else { 195 // All commands that need a name following 196 197 const char* name = argv[argc - 1]; 198 199 if (strcmp(command, "info") == 0) { 200 get_info(name); 201 } else if (strcmp(command, "start") == 0) { 202 start_job(name); 203 } else if (strcmp(command, "stop") == 0) { 204 stop_job(name); 205 } else if (strcmp(command, "restart") == 0) { 206 restart_job(name); 207 } else if (strcmp(command, "enable") == 0) { 208 enable_job(name, true); 209 } else if (strcmp(command, "disable") == 0) { 210 enable_job(name, false); 211 } else { 212 fprintf(stderr, "%s: Unknown command \"%s\".\n", kProgramName, 213 command); 214 } 215 } 216 return 0; 217 } 218