1 /* 2 * Copyright 2015, 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 usage(int status) 118 { 119 fprintf(stderr, "Usage: %s <command>\n" 120 "Where <command> is one of:\n" 121 " list - Lists all jobs (the default command)\n" 122 " list-targets - Lists all targets\n" 123 "The following <command>s have a <name> argument:\n" 124 " start - Starts a job\n" 125 " stop - Stops a running job\n" 126 " info - Shows info for a job/target\n", 127 kProgramName); 128 129 exit(status); 130 } 131 132 133 int 134 main(int argc, char** argv) 135 { 136 const char* command = "list"; 137 bool verbose = false; 138 139 int c; 140 while ((c = getopt_long(argc, argv, "hv", kLongOptions, NULL)) != -1) { 141 switch (c) { 142 case 0: 143 break; 144 case 'h': 145 usage(0); 146 break; 147 case 'v': 148 verbose = true; 149 break; 150 default: 151 usage(1); 152 break; 153 } 154 } 155 156 if (argc - optind >= 1) 157 command = argv[optind]; 158 159 if (strcmp(command, "list") == 0) { 160 list_jobs(verbose); 161 } else if (strcmp(command, "list-targets") == 0) { 162 list_targets(verbose); 163 } else { 164 // All commands that need a name following 165 if (argc == optind + 1) 166 usage(1); 167 168 const char* name = argv[argc - 1]; 169 170 if (strcmp(command, "info") == 0) { 171 get_info(name); 172 } else if (strcmp(command, "start") == 0) { 173 start_job(name); 174 } else if (strcmp(command, "stop") == 0) { 175 stop_job(name); 176 } else { 177 fprintf(stderr, "%s: Unknown command \"%s\".\n", kProgramName, 178 command); 179 } 180 } 181 return 0; 182 } 183