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_OK) { 96 fprintf(stderr, "%s: Starting job \"%s\" failed: %s\n", kProgramName, 97 name, strerror(status)); 98 exit(EXIT_FAILURE); 99 } 100 } 101 102 103 static void 104 stop_job(const char* name) 105 { 106 BLaunchRoster roster; 107 status_t status = roster.Stop(name); 108 if (status != B_OK) { 109 fprintf(stderr, "%s: Stopping job \"%s\" failed: %s\n", kProgramName, 110 name, strerror(status)); 111 exit(EXIT_FAILURE); 112 } 113 } 114 115 116 static void 117 enable_job(const char* name, bool enable) 118 { 119 BLaunchRoster roster; 120 status_t status = roster.SetEnabled(name, enable); 121 if (status != B_OK) { 122 fprintf(stderr, "%s: %s job \"%s\" failed: %s\n", kProgramName, 123 enable ? "Enabling" : "Disabling", name, strerror(status)); 124 exit(EXIT_FAILURE); 125 } 126 } 127 128 129 static void 130 usage(int status) 131 { 132 fprintf(stderr, "Usage: %s <command>\n" 133 "Where <command> is one of:\n" 134 " list - Lists all jobs (the default command)\n" 135 " list-targets - Lists all targets\n" 136 "The following <command>s have a <name> argument:\n" 137 " start - Starts a job\n" 138 " stop - Stops a running job\n" 139 " info - Shows info for a job/target\n", 140 kProgramName); 141 142 exit(status); 143 } 144 145 146 int 147 main(int argc, char** argv) 148 { 149 const char* command = "list"; 150 bool verbose = false; 151 152 int c; 153 while ((c = getopt_long(argc, argv, "hv", kLongOptions, NULL)) != -1) { 154 switch (c) { 155 case 0: 156 break; 157 case 'h': 158 usage(0); 159 break; 160 case 'v': 161 verbose = true; 162 break; 163 default: 164 usage(1); 165 break; 166 } 167 } 168 169 if (argc - optind >= 1) 170 command = argv[optind]; 171 172 if (strcmp(command, "list") == 0) { 173 list_jobs(verbose); 174 } else if (strcmp(command, "list-targets") == 0) { 175 list_targets(verbose); 176 } else if (argc == optind + 1) { 177 // For convenience (the "info" command can be omitted) 178 get_info(command); 179 } else { 180 // All commands that need a name following 181 182 const char* name = argv[argc - 1]; 183 184 if (strcmp(command, "info") == 0) { 185 get_info(name); 186 } else if (strcmp(command, "start") == 0) { 187 start_job(name); 188 } else if (strcmp(command, "stop") == 0) { 189 stop_job(name); 190 } else if (strcmp(command, "enable") == 0) { 191 enable_job(name, true); 192 } else if (strcmp(command, "disable") == 0) { 193 enable_job(name, false); 194 } else { 195 fprintf(stderr, "%s: Unknown command \"%s\".\n", kProgramName, 196 command); 197 } 198 } 199 return 0; 200 } 201