Date: Tue, 30 Aug 2005 02:47:24 GMT From: soc-tyler <soc-tyler@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 82813 for review Message-ID: <200508300247.j7U2lO2s023026@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=82813 Change 82813 by soc-tyler@soc-tyler_launchd on 2005/08/30 02:46:50 Merge zarzycki@'s developmental changes (i.e. experiemental code from Cupertino) to take advantage of some of the features "im bau." Affected files ... .. //depot/projects/soc2005/launchd/launchctl/launchctl.c#12 edit .. //depot/projects/soc2005/launchd/launchd.c#16 edit Differences ... ==== //depot/projects/soc2005/launchd/launchctl/launchctl.c#12 (text+ko) ==== @@ -41,6 +41,7 @@ #include <sys/event.h> #include <sys/resource.h> #include <sys/param.h> +#include <sys/wait.h> #include <netinet/in.h> #include <errno.h> #include <unistd.h> @@ -81,16 +82,17 @@ static void distill_config_file(launch_data_t); static void sock_dict_cb(launch_data_t what, const char *key, void *context); static void sock_dict_edit_entry(launch_data_t tmp, const char *key, launch_data_t fdarray, launch_data_t thejob); -static void readpath(const char *, launch_data_t, launch_data_t, bool editondisk, bool load); +static void readpath(const char *, launch_data_t, launch_data_t, bool editondisk, bool load, bool forceload); static int _fd(int); static int demux_cmd(int argc, char *const argv[]); static void submit_job_pass(launch_data_t jobs); +static void do_mgroup_join(int fd, int family, int socktype, int protocol, const char *mgroup); // Mac OS X/Darwin related functions (for backwards compat.) #ifdef _BUILD_DARWIN_ static launch_data_t CF2launch_data(const void *); static launch_data_t read_plist_file(const char *file, bool editondisk, bool load); -static const void *CreateMyPropertyListFromFile(const char *); +static CFPropertyListRef CreateMyPropertyListFromFile(const char *); static void WriteMyPropertyListToFile(CFPropertyListRef, const char *); static launch_data_t do_rendezvous_magic(const struct addrinfo *res, const char *serv); #endif @@ -102,7 +104,8 @@ static int load_and_unload_cmd(int argc, char *const argv[]); //static int reload_cmd(int argc, char *const argv[]); -static int start_and_stop_cmd(int argc, char *const argv[]); +static int start_stop_remove_cmd(int argc, char *const argv[]); +static int submit_cmd(int argc, char *const argv[]); static int list_cmd(int argc, char *const argv[]); static int setenv_cmd(int argc, char *const argv[]); @@ -127,8 +130,10 @@ { "load", load_and_unload_cmd, "Load configuration files and/or directories" }, { "unload", load_and_unload_cmd, "Unload configuration files and/or directories" }, // { "reload", reload_cmd, "Reload configuration files and/or directories" }, - { "start", start_and_stop_cmd, "Start specified jobs" }, - { "stop", start_and_stop_cmd, "Stop specified jobs" }, + { "start", start_stop_remove_cmd, "Start specified job" }, + { "stop", start_stop_remove_cmd, "Stop specified job" }, + { "submit", submit_cmd, "Submit a job from the command line" }, + { "remove", start_stop_remove_cmd, "Remove specified job" }, { "list", list_cmd, "List jobs and information about jobs" }, { "setenv", setenv_cmd, "Set an environmental variable in launchd" }, { "unsetenv", unsetenv_cmd, "Unset an environmental variable in launchd" }, @@ -144,22 +149,25 @@ { "umask", umask_cmd, "Change launchd's umask" }, { "help", help_cmd, "This help output" }, {"exit", exit_cmd, "Exit launchctl" }, + {"quit", exit_cmd, "Quit launchctl"}, }; -int main(int argc, char *const argv[]) -{ - bool istty = isatty(STDIN_FILENO); +static bool istty = false; + +int main(int argc, char *const argv[]) { char *l; if (argc > 1) exit(demux_cmd(argc - 1, argv + 1)); + istty = isatty(STDIN_FILENO); + if (NULL == readline) { fprintf(stderr, "missing library: readline\n"); exit(EXIT_FAILURE); } - while ((l = readline(istty ? "launchctl% " : NULL))) { + while ((l = readline(istty ? "launchd% " : NULL))) { char *inputstring = l, *argv2[100], **ap = argv2; int i = 0; @@ -415,31 +423,75 @@ return res; } -static void readfile(const char *what, launch_data_t pass1, launch_data_t pass2, bool editondisk, bool load) +static void readfile(const char *what, launch_data_t pass1, launch_data_t pass2, bool editondisk, bool load, bool forceload) { - launch_data_t tmpd, thejob; + char ourhostname[1024]; + launch_data_t tmpd, thejob, tmpa; bool job_disabled = false; + size_t i, c; + gethostname(ourhostname, sizeof(ourhostname)); +#ifndef _BUILD_DARWIN_ if (NULL == (thejob = read_conf_file(what, editondisk, load))) { - fprintf(stderr, "%s: no plist was returned for: %s\n", getprogname(), what); + fprintf(stderr, "%s: no config file was returned for: %s\n", getprogname(), what); return; } +#endif +#ifdef _BUILD_DARWIN_ + if (NULL == (thejob = read_plist_file(what, editondisk, load))) { + fprintf(stderr, "%s: no plist was returned for: %s\n", getprogname(), what); + return; + } +#endif - if ((tmpd = launch_data_dict_lookup(thejob, LAUNCH_JOBKEY_DISABLED))) - job_disabled = launch_data_get_bool(tmpd); + if (NULL == launch_data_dict_lookup(thejob, LAUNCH_JOBKEY_LABEL)) { + fprintf(stderr, "%s: missing the Label key: %s\n", getprogname(), what); + goto out_bad; + } + + if (NULL != (tmpa = launch_data_dict_lookup(thejob, LAUNCH_JOBKEY_LIMITLOADFROMHOSTS))) { + c = launch_data_array_get_count(tmpa); + + for (i = 0; i < c; i++) { + launch_data_t oai = launch_data_array_get_index(tmpa, i); + if (!strcasecmp(ourhostname, launch_data_get_string(oai))) + goto out_bad; + } + } + + if (NULL != (tmpa = launch_data_dict_lookup(thejob, LAUNCH_JOBKEY_LIMITLOADTOHOSTS))) { + c = launch_data_array_get_count(tmpa); + + for (i = 0; i < c; i++) { + launch_data_t oai = launch_data_array_get_index(tmpa, i); + if (!strcasecmp(ourhostname, launch_data_get_string(oai))) + break; + } + + if (i == c) + goto out_bad; + } + + if ((tmpd = launch_data_dict_lookup(thejob, LAUNCH_JOBKEY_DISABLED))) + job_disabled = launch_data_get_bool(tmpd); + + if (forceload) + job_disabled = false; + + if (job_disabled && load) + goto out_bad; - if (job_disabled && load) { - launch_data_free(thejob); - return; - } + if (delay_to_second_pass(thejob)) + launch_data_array_append(pass2, thejob); + else + launch_data_array_append(pass1, thejob); - if (delay_to_second_pass(thejob)) - launch_data_array_append(pass2, thejob); - else - launch_data_array_append(pass1, thejob); + return; +out_bad: + launch_data_free(thejob); } -static void readpath(const char *what, launch_data_t pass1, launch_data_t pass2, bool editondisk, bool load) +static void readpath(const char *what, launch_data_t pass1, launch_data_t pass2, bool editondisk, bool load, bool forceload) { char buf[MAXPATHLEN]; struct stat sb; @@ -450,7 +502,7 @@ return; if (S_ISREG(sb.st_mode) && !(sb.st_mode & S_IWOTH)) { - readfile(what, pass1, pass2, editondisk, load); + readfile(what, pass1, pass2, editondisk, load, forceload); } else { if ((d = opendir(what)) == NULL) { fprintf(stderr, "%s: opendir() failed to open the directory\n", getprogname()); @@ -462,7 +514,7 @@ continue; snprintf(buf, sizeof(buf), "%s/%s", what, de->d_name); - readfile(buf, pass1, pass2, editondisk, load); + readfile(buf, pass1, pass2, editondisk, load, forceload); } closedir(d); } @@ -578,7 +630,7 @@ launch_data_array_append(fdarray, val); } else { launch_data_t rnames = NULL; - const char *node = NULL, *serv = NULL; + const char *node = NULL, *serv = NULL, *mgroup = NULL; char servnbuf[50]; struct addrinfo hints, *res0, *res; int gerr, sock_opt = 1; @@ -592,6 +644,8 @@ if ((val = launch_data_dict_lookup(tmp, LAUNCH_JOBSOCKETKEY_NODENAME))) node = launch_data_get_string(val); + if ((val = launch_data_dict_lookup(tmp, LAUNCH_JOBSOCKETKEY_MULTICASTGROUP))) + mgroup = launch_data_get_string(val); if ((val = launch_data_dict_lookup(tmp, LAUNCH_JOBSOCKETKEY_SERVICENAME))) { if (LAUNCH_DATA_INTEGER == launch_data_get_type(val)) { sprintf(servnbuf, "%lld", launch_data_get_integer(val)); @@ -635,14 +689,24 @@ fprintf(stderr, "setsockopt(IPV6_V6ONLY): %m"); return; } - if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt, sizeof(sock_opt)) == -1) { - fprintf(stderr, "socket(): %s\n", strerror(errno)); - return; - } + if (mgroup) { + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, (void *)&sock_opt, sizeof(sock_opt)) == -1) { + fprintf(stderr, "setsockopt(SO_REUSEPORT): %s\n", strerror(errno)); + return; + } + } else { + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt, sizeof(sock_opt)) == -1) { + fprintf(stderr, "setsockopt(SO_REUSEADDR): %s\n", strerror(errno)); + return; + } + } if (bind(sfd, res->ai_addr, res->ai_addrlen) == -1) { fprintf(stderr, "bind(): %s\n", strerror(errno)); return; } + if (mgroup) { + do_mgroup_join(sfd, res->ai_family, res->ai_socktype, res->ai_protocol, mgroup); + } if ((res->ai_socktype == SOCK_STREAM || res->ai_socktype == SOCK_SEQPACKET) && listen(sfd, SOMAXCONN) == -1) { fprintf(stderr, "listen(): %s\n", strerror(errno)); @@ -698,6 +762,45 @@ } } +static void do_mgroup_join(int fd, int family, int socktype, int protocol, const char *mgroup) { + struct addrinfo hints, *res0, *res; + struct ip_mreq mreq; + struct ipv6_mreq m6req; int gerr; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_flags |= AI_PASSIVE; + hints.ai_family = family; + hints.ai_socktype = socktype; + hints.ai_protocol = protocol; + if ((gerr = getaddrinfo(mgroup, NULL, &hints, &res0)) != 0) { + fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(gerr)); + return; + } + + for (res = res0; res; res = res->ai_next) { + if (AF_INET == family) { memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr = ((struct sockaddr_in *)res->ai_addr)->sin_addr; + if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) { fprintf(stderr, "setsockopt(IP_ADD_MEMBERSHIP): %s\n", strerror(errno)); + continue; + } break; + } else if (AF_INET6 == family) { + memset(&m6req, 0, sizeof(m6req)); + m6req.ipv6mr_multiaddr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; + if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &m6req, sizeof(m6req)) == -1) { + fprintf(stderr, "setsockopt(IPV6_JOIN_GROUP): %s\n", strerror(errno)); + continue; + } + break; + } else { + fprintf(stderr, "unknown family during multicast group bind!\n"); + break; + } } + + freeaddrinfo(res0); +} + + #ifdef _BUILD_DARWIN_ static launch_data_t do_rendezvous_magic(const struct addrinfo *res, const char *serv) { @@ -730,7 +833,7 @@ return NULL; } -static const void *CreateMyPropertyListFromFile(const char *posixfile) +static CFPropertyListRef CreateMyPropertyListFromFile(const char *posixfile) { CFPropertyListRef propertyList; CFStringRef errorString; @@ -738,7 +841,7 @@ SInt32 errorCode; CFURLRef fileURL; - fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, posixfile, strlen(posixfile), false); + fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)posixfile, strlen(posixfile), false); if (!fileURL) fprintf(stderr, "%s: CFURLCreateFromFileSystemRepresentation(%s) failed\n", getprogname(), posixfile); if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &errorCode)) @@ -756,7 +859,7 @@ CFURLRef fileURL; SInt32 errorCode; - fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, posixfile, strlen(posixfile), false); + fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)posixfile, strlen(posixfile), false); if (!fileURL) fprintf(stderr, "%s: CFURLCreateFromFileSystemRepresentation(%s) failed\n", getprogname(), posixfile); resourceData = CFPropertyListCreateXMLData(kCFAllocatorDefault, plist); @@ -777,7 +880,7 @@ launch_data_free(ik); } -static launch_data_t CF2launch_data(const void *cfr) +static launch_data_t CF2launch_data(CFTypeRef cfr) { launch_data_t r; CFTypeID cft = CFGetTypeID(cfr); @@ -794,7 +897,7 @@ CFIndex i, ac = CFArrayGetCount(cfr); r = launch_data_alloc(LAUNCH_DATA_ARRAY); for (i = 0; i < ac; i++) { - const void *v = CFArrayGetValueAtIndex(cfr, i); + CFTypeRef v = CFArrayGetValueAtIndex(cfr, i); if (v) { launch_data_t iv = CF2launch_data(v); launch_data_array_set_index(r, iv, i); @@ -811,7 +914,6 @@ double d; CFNumberType cfnt = CFNumberGetType(cfr); switch (cfnt) { - case kCFNumberSInt8Type: case kCFNumberSInt16Type: case kCFNumberSInt32Type: case kCFNumberSInt64Type: @@ -853,18 +955,24 @@ where = stderr; fprintf(where, "usage: %s <subcommand>\n", getprogname()); + for (i = 0; i < (sizeof cmds / sizeof cmds[0]); i++) { - l = strlen(cmds[i].name); - if (l > cmdwidth) - cmdwidth = l; - } - for (i = 0; i < (sizeof cmds / sizeof cmds[0]); i++) - fprintf(where, "\t%-*s\t%s\n", cmdwidth, cmds[i].name, cmds[i].desc); + l = strlen(cmds[i].name); + if (l > cmdwidth) + cmdwidth = l; + } + + for (i = 0; i < (sizeof cmds / sizeof cmds[0]); i++) { + if (cmds[i].func == exit_cmd && istty == false) + continue; + fprintf(where, "\t%-*s\t%s\n", cmdwidth, cmds[i].name, cmds[i].desc); + } return 0; } -static int exit_cmd(int argc, char *const argv[]) { +static int exit_cmd(int argc __attribute__((unused)), char *const argv[] __attribute__((unused))) +{ exit(EXIT_SUCCESS); return 0; // god help us if we get here ;) @@ -883,22 +991,22 @@ int i, ch; bool wflag = false; bool lflag = false; + bool Fflag = false; if (!strcmp(argv[0], "load")) lflag = true; - while ((ch = getopt(argc, argv, "w")) != -1) { - switch (ch) { - case 'w': - wflag = true; - break; - default: - fprintf(stderr, "usage: %s load [-w] paths...\n", getprogname()); - return 1; - } - } - argc -= optind; - argv += optind; + while ((ch = getopt(argc, argv, "wF")) != -1) { + switch (ch) { + case 'w': wflag = true; break; + case 'F': Fflag = true; break; + default: + fprintf(stderr, "usage: %s load [-wF] paths...\n", getprogname()); + return 1; + } + } + argc -= optind; + argv += optind; if (argc == 0) { fprintf(stderr, "usage: %s load [-w] paths...\n", getprogname()); @@ -917,7 +1025,7 @@ pass2 = launch_data_alloc(LAUNCH_DATA_ARRAY); for (i = 0; i < argc; i++) - readpath(argv[i], pass1, pass2, wflag, lflag); + readpath(argv[i], pass1, pass2, wflag, lflag, Fflag); if (0 == launch_data_array_get_count(pass1) && 0 == launch_data_array_get_count(pass2)) { fprintf(stderr, "nothing found to %s\n", lflag ? "load" : "unload"); @@ -998,15 +1106,18 @@ launch_data_free(msg); } -static int start_and_stop_cmd(int argc, char *const argv[]) +static int start_stop_remove_cmd(int argc, char *const argv[]) { launch_data_t resp, msg; const char *lmsgcmd = LAUNCH_KEY_STOPJOB; int e, r = 0; - if (!strcmp(argv[0], "start")) + if (0 == strcmp(argv[0], "start")) lmsgcmd = LAUNCH_KEY_STARTJOB; + if (0 == strcmp(argv[0], "remove")) + lmsgcmd = LAUNCH_KEY_REMOVEJOB; + if (argc != 2) { fprintf(stderr, "usage: %s %s <job label>\n", getprogname(), argv[0]); return 1; @@ -1037,48 +1148,65 @@ static void print_jobs(launch_data_t j __attribute__((unused)), const char *label, void *context __attribute__((unused))) { - fprintf(stdout, "%s\n", label); + launch_data_t pido = launch_data_dict_lookup(j, LAUNCH_JOBKEY_PID); + launch_data_t stato = launch_data_dict_lookup(j, LAUNCH_JOBKEY_LASTEXITSTATUS); + + if (pido) { + fprintf(stdout, "%lld\t-\t%s\n", launch_data_get_integer(pido), label); + } else if (stato) { + int wstatus = (int)launch_data_get_integer(stato); + if (WIFEXITED(wstatus)) { + fprintf(stdout, "-\t%d\t%s\n", WEXITSTATUS(wstatus), label); + } else if (WIFSIGNALED(wstatus)) { + fprintf(stdout, "-\t-%d\t%s\n", WTERMSIG(wstatus), label); + } else { + fprintf(stdout, "-\t???\t%s\n", label); + } + } else { + fprintf(stdout, "-\t-\t%s\n", label); + } } static int list_cmd(int argc, char *const argv[]) { launch_data_t resp, msg; - int ch, r = 0; - bool vflag = false; + int ch, r = 0; + bool vflag = false; - while ((ch = getopt(argc, argv, "v")) != -1) { - switch (ch) { - case 'v': - vflag = true; - break; - default: - fprintf(stderr, "usage: %s list [-v]\n", getprogname()); - return 1; - } - } + while ((ch = getopt(argc, argv, "v")) != -1) { + switch (ch) { + case 'v': + vflag = true; + break; + default: + fprintf(stderr, "usage: %s list [-v]\n", getprogname()); + return 1; + } + } - if (vflag) { - fprintf(stderr, "usage: %s list: \"-v\" flag not implemented yet\n", getprogname()); - return 1; - } + if (vflag) { + fprintf(stderr, "usage: %s list: \"-v\" flag not implemented yet\n", getprogname()); + return 1; + } - msg = launch_data_new_string(LAUNCH_KEY_GETJOBS); - resp = launch_msg(msg); - launch_data_free(msg); + msg = launch_data_new_string(LAUNCH_KEY_GETJOBS); + resp = launch_msg(msg); + launch_data_free(msg); - if (resp == NULL) { - fprintf(stderr, "launch_msg(): %s\n", strerror(errno)); - return 1; - } else if (launch_data_get_type(resp) == LAUNCH_DATA_DICTIONARY) { - launch_data_dict_iterate(resp, print_jobs, NULL); - } else { - fprintf(stderr, "%s %s returned unknown response\n", getprogname(), argv[0]); - r = 1; - } + if (resp == NULL) { + fprintf(stderr, "launch_msg(): %s\n", strerror(errno)); + return 1; + } else if (launch_data_get_type(resp) == LAUNCH_DATA_DICTIONARY) { + fprintf(stdout, "PID\tStatus\tLabel\n"); + launch_data_dict_iterate(resp, print_jobs, NULL); + } else { + fprintf(stderr, "%s %s returned unknown response\n", getprogname(), argv[0]); + r = 1; + } - launch_data_free(resp); + launch_data_free(resp); - return r; + return r; } static int stdio_cmd(int argc, char *const argv[]) @@ -1420,48 +1548,108 @@ static int umask_cmd(int argc, char *const argv[]) { launch_data_t resp, msg; - bool badargs = false; - char *endptr; - long m = 0; - int r = 0; + bool badargs = false; + char *endptr; + long m = 0; + int r = 0; + + if (argc == 2) { + m = strtol(argv[1], &endptr, 8); + if (*endptr != '\0' || m > 0777) + badargs = true; + } + + if (argc > 2 || badargs) { + fprintf(stderr, "usage: %s %s <mask>\n", getprogname(), argv[0]); + return 1; + } + + + if (argc == 1) { + msg = launch_data_new_string(LAUNCH_KEY_GETUMASK); + } else { + msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY); + launch_data_dict_insert(msg, launch_data_new_integer(m), LAUNCH_KEY_SETUMASK); + } + resp = launch_msg(msg); + launch_data_free(msg); + + if (resp == NULL) { + fprintf(stderr, "launch_msg(): %s\n", strerror(errno)); + return 1; + } else if (launch_data_get_type(resp) == LAUNCH_DATA_STRING) { + fprintf(stderr, "%s %s error: %s\n", getprogname(), argv[0], launch_data_get_string(resp)); + r = 1; + } else if (launch_data_get_type(resp) != LAUNCH_DATA_INTEGER) { + fprintf(stderr, "%s %s returned unknown response\n", getprogname(), argv[0]); + r = 1; + } else if (argc == 1) { + fprintf(stdout, "%o\n", (unsigned int)launch_data_get_integer(resp)); + } + + launch_data_free(resp); + + return r; +} + +static int submit_cmd(int argc, char *const argv[]) +{ + launch_data_t msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY); + launch_data_t job = launch_data_alloc(LAUNCH_DATA_DICTIONARY); + launch_data_t resp, largv = launch_data_alloc(LAUNCH_DATA_ARRAY); + int ch, i, r = 0; + + launch_data_dict_insert(job, launch_data_new_bool(false), LAUNCH_JOBKEY_ONDEMAND); + + while ((ch = getopt(argc, argv, "l:p:o:e:")) != -1) { + switch (ch) { + case 'l': + launch_data_dict_insert(job, launch_data_new_string(optarg), LAUNCH_JOBKEY_LABEL); + break; + case 'p': + launch_data_dict_insert(job, launch_data_new_string(optarg), LAUNCH_JOBKEY_PROGRAM); + break; + case 'o': + launch_data_dict_insert(job, launch_data_new_string(optarg), LAUNCH_JOBKEY_STANDARDOUTPATH); + break; + case 'e': + launch_data_dict_insert(job, launch_data_new_string(optarg), LAUNCH_JOBKEY_STANDARDERRORPATH); + break; + default: + fprintf(stderr, "usage: %s submit ...\n", getprogname()); + return 1; + } + } + argc -= optind; + argv += optind; - if (argc == 2) { - m = strtol(argv[1], &endptr, 8); - if (*endptr != '\0' || m > 0777) - badargs = true; - } + for (i = 0; argv[i]; i++) { + launch_data_array_append(largv, launch_data_new_string(argv[i])); + } - if (argc > 2 || badargs) { - fprintf(stderr, "usage: %s %s <mask>\n", getprogname(), argv[0]); - return 1; - } + launch_data_dict_insert(job, largv, LAUNCH_JOBKEY_PROGRAMARGUMENTS); + launch_data_dict_insert(msg, job, LAUNCH_KEY_SUBMITJOB); - if (argc == 1) { - msg = launch_data_new_string(LAUNCH_KEY_GETUMASK); - } else { - msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY); - launch_data_dict_insert(msg, launch_data_new_integer(m), LAUNCH_KEY_SETUMASK); - } - resp = launch_msg(msg); - launch_data_free(msg); + resp = launch_msg(msg); + launch_data_free(msg); - if (resp == NULL) { - fprintf(stderr, "launch_msg(): %s\n", strerror(errno)); - return 1; - } else if (launch_data_get_type(resp) == LAUNCH_DATA_STRING) { - fprintf(stderr, "%s %s error: %s\n", getprogname(), argv[0], launch_data_get_string(resp)); - r = 1; - } else if (launch_data_get_type(resp) != LAUNCH_DATA_INTEGER) { - fprintf(stderr, "%s %s returned unknown response\n", getprogname(), argv[0]); - r = 1; - } else if (argc == 1) { - fprintf(stdout, "%o\n", (unsigned int)launch_data_get_integer(resp)); - } + if (resp == NULL) { + fprintf(stderr, "launch_msg(): %s\n", strerror(errno)); + return 1; + } else if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) { + errno = launch_data_get_errno(resp); + if (errno) { + fprintf(stderr, "%s %s error: %s\n", getprogname(), argv[0], strerror(errno)); + r = 1; + } + } else { + fprintf(stderr, "%s %s error: %s\n", getprogname(), argv[0], "unknown response"); + } - launch_data_free(resp); + launch_data_free(resp); - return r; + return r; } static int getrusage_cmd(int argc, char *const argv[]) ==== //depot/projects/soc2005/launchd/launchd.c#16 (text+ko) ==== @@ -110,6 +110,7 @@ TAILQ_ENTRY(jobcb) tqe; launch_data_t ldj; pid_t p; + int last_exit_status; int execfd; time_t start_time; size_t failed_exits; @@ -167,6 +168,7 @@ static void job_reap(struct jobcb *j); static void job_remove(struct jobcb *j); static void job_set_alarm(struct jobcb *j); +static launch_data_t job_export(struct jobcb *j); static void job_callback(void *obj, struct kevent *kev); static void job_log(struct jobcb *j, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); static void job_log_error(struct jobcb *j, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); @@ -347,7 +349,7 @@ init_pre_kevent(); } else { if (TAILQ_EMPTY(&jobs) && TAILQ_EMPTY(&connections)) { - /* launched on demand */ + /* liblaunch will restart launchd if we're needed again */ timeoutp = &timeout; } else if (shutdown_in_progress && total_children == 0) { exit(EXIT_SUCCESS); @@ -885,6 +887,24 @@ kill(j->p, SIGTERM); } +static launch_data_t job_export(struct jobcb *j) +{ + launch_data_t tmp, r = launch_data_copy(j->ldj); + + if (r) { + tmp = launch_data_new_integer(j->last_exit_status); + if (tmp) + launch_data_dict_insert(r, tmp, LAUNCH_JOBKEY_LASTEXITSTATUS); + if (j->p) { + tmp = launch_data_new_integer(j->p); + if (tmp) + launch_data_dict_insert(r, tmp, LAUNCH_JOBKEY_PID); + } + } + + return r; +} + static void job_remove(struct jobcb *j) { launch_data_t tmp; @@ -1263,7 +1283,7 @@ if (which) { TAILQ_FOREACH(j, &jobs, tqe) { if (!strcmp(which, j->label)) - resp = launch_data_copy(j->ldj); + resp = job_export(j); } if (resp == NULL) resp = launch_data_new_errno(ESRCH); @@ -1271,7 +1291,7 @@ resp = launch_data_alloc(LAUNCH_DATA_DICTIONARY); TAILQ_FOREACH(j, &jobs, tqe) { - tmp = launch_data_copy(j->ldj); + tmp = job_export(j); launch_data_dict_insert(resp, tmp, j->label); } } @@ -1483,6 +1503,7 @@ } total_children--; + j->last_exit_status = status; j->p = 0; } @@ -1539,8 +1560,8 @@ startnow = false; } } - } else if (kev->filter == EVFILT_TIMER && kev->fflags & NOTE_ABSOLUTE) { - job_set_alarm(j); + } else if (kev->filter == EVFILT_TIMER && (void *)kev->ident == j->start_cal_interval) { + job_set_alarm(j); } else if (kev->filter == EVFILT_VNODE) { size_t i; const char *thepath = NULL; @@ -1606,6 +1627,7 @@ } } + static void job_start(struct jobcb *j) { int spair[2]; @@ -2416,43 +2438,48 @@ * 1 5 4 4 * 5 1 -4 7 + -4 */ - if (delta > 0) - otherlatertm.tm_mday += delta; - else if (delta < 0) - otherlatertm.tm_mday += 7 + delta; - else if (-1 != j->start_cal_interval->tm_hour && otherlatertm.tm_hour <= nowtm->tm_hour) - otherlatertm.tm_mday += 7; - else if (-1 != j->start_cal_interval->tm_min && otherlatertm.tm_min <= nowtm->tm_min) - otherlatertm.tm_hour++; - else - otherlatertm.tm_min++; + if (delta > 0) { + otherlatertm.tm_mday += delta; + } else if (delta < 0) { + otherlatertm.tm_mday += 7 + delta; + } else if (-1 != j->start_cal_interval->tm_hour && otherlatertm.tm_hour <= nowtm->tm_hour) { + otherlatertm.tm_mday += 7; + } else if (-1 != j->start_cal_interval->tm_min && otherlatertm.tm_min <= nowtm->tm_min) { + otherlatertm.tm_hour++; + } else { + otherlatertm.tm_min++; + } - otherlater = mktime(&otherlatertm); + otherlater = mktime(&otherlatertm); } - if (-1 != j->start_cal_interval->tm_mon && latertm.tm_mon <= nowtm->tm_mon) { - latertm.tm_year++; - } else if (-1 != j->start_cal_interval->tm_mday && latertm.tm_mday <= nowtm->tm_mday) { - latertm.tm_mon++; - } else if (-1 != j->start_cal_interval->tm_hour && latertm.tm_hour <= nowtm->tm_hour) { - latertm.tm_mday++; - } else if (-1 != j->start_cal_interval->tm_min && latertm.tm_min <= nowtm->tm_min) { - latertm.tm_hour++; - } else { - latertm.tm_min++; - } + if (-1 != j->start_cal_interval->tm_mon && latertm.tm_mon <= nowtm->tm_mon) { + latertm.tm_year++; + } else if (-1 != j->start_cal_interval->tm_mday && latertm.tm_mday <= nowtm->tm_mday) { + latertm.tm_mon++; + } else if (-1 != j->start_cal_interval->tm_hour && latertm.tm_hour <= nowtm->tm_hour) { + latertm.tm_mday++; + } else if (-1 != j->start_cal_interval->tm_min && latertm.tm_min <= nowtm->tm_min) { + latertm.tm_hour++; + } else { + latertm.tm_min++; + } + + later = mktime(&latertm); - later = mktime(&latertm); + if (otherlater) { + if (-1 != j->start_cal_interval->tm_mday) + later = later < otherlater ? later : otherlater; + else + later = otherlater; + } - if (otherlater) { - if (-1 != j->start_cal_interval->tm_mday) - later = later < otherlater ? later : otherlater; - else - later = otherlater; - } + if (-1 == kevent_mod((uintptr_t)j->start_cal_interval, EVFILT_TIMER, EV_ADD, NOTE_ABSOLUTE|NOTE_SECONDS, later, &j->kqjob_callback)) { + job_log_error(j, LOG_ERR, "adding kevent alarm"); + } else { + job_log(j, LOG_INFO, "scheduled to run again at %s", ctime(&later)); + } - if (-1 == kevent_mod((uintptr_t)j->start_cal_interval, EVFILT_TIMER, EV_ADD, NOTE_ABSOLUTE|NOTE_SECONDS, later, &j->kqjob_callback)) - job_log_error(j, LOG_ERR, "adding kevent alarm"); } static void job_log_error(struct jobcb *j, int pri, const char *msg, ...)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200508300247.j7U2lO2s023026>