diff options
Diffstat (limited to 'src/cg-base.c')
-rw-r--r-- | src/cg-base.c | 927 |
1 files changed, 0 insertions, 927 deletions
diff --git a/src/cg-base.c b/src/cg-base.c deleted file mode 100644 index 9f77937..0000000 --- a/src/cg-base.c +++ /dev/null @@ -1,927 +0,0 @@ -/** - * cg-tools -- Cooperative gamma-enabled tools - * Copyright (C) 2016, 2018 Mattias Andrée (maandree@kth.se) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include "cg-base.h" - -#include <libclut.h> - -#include <alloca.h> -#include <errno.h> -#include <inttypes.h> -#include <poll.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - - - -/** - * The process's name - */ -const char* argv0 = NULL; - -/** - * The libcoopgamma context - */ -libcoopgamma_context_t cg; - -/** - * The names of the selected CRTC:s - */ -char** crtcs = NULL; - -/** - * Gamma ramp updates for each CRTC - */ -filter_update_t* crtc_updates = NULL; - -/** - * CRTC and monitor information about - * each selected CRTC and connect monitor - */ -libcoopgamma_crtc_info_t* crtc_info = NULL; - -/** - * The number of selected CRTC:s - */ -size_t crtcs_n = 0; - -/** - * The number of filters - */ -size_t filters_n = 0; - - -/** - * Contexts for asynchronous ramp updates - */ -static libcoopgamma_async_context_t* asyncs = NULL; - -/** - * The number of pending receives - */ -static size_t pending_recvs = 0; - -/** - * Whether message must be flushed - */ -static int flush_pending = 0; - - - -/** - * Data used to sort CRTC:s - */ -struct crtc_sort_data -{ - /** - * The gamma ramp type - */ - libcoopgamma_depth_t depth; - - /** - * Should be 0 - */ - int __padding; - - /** - * The size of the red gamma ramp - */ - size_t red_size; - - /** - * The size of the green gamma ramp - */ - size_t green_size; - - /** - * The size of the blue gamma ramp - */ - size_t blue_size; - - /** - * The index of the CRTC - */ - size_t index; -}; - - - -/** - * Compare two strings - * - * @param a Return -1 if this string is `NULL` or less than `b` - * @param b Return +1 if this string is less than `a` - * @return See `a` and `b`, 0 is returned if `a` and `b` are equal - */ -static int nulstrcmp(const char *a, const char *b) -{ - return (a == NULL) ? -1 : strcmp(a, b); -} - - -/** - * Compare two instances of `crtc_sort_data` - * - * @param a_ Return -1 if this one is lower - * @param b_ Return +1 if this one is higher - * @return See `a_` and `b_`, only -1 or +1 can be returned - */ -static int crtc_sort_data_cmp(const void* a_, const void* b_) -{ - const struct crtc_sort_data* a = a_; - const struct crtc_sort_data* b = b_; - int cmp = memcmp(a, b, sizeof(*a) - sizeof(a->index)); - return cmp ? cmp : a->index < b->index ? -1 : +1; -} - - -/** - * Make elements in `crtc_updates` slaves where appropriate - * - * @return Zero on success, -1 on error - */ -int make_slaves(void) -{ - struct crtc_sort_data* data; - size_t i, j, n = 0, master = 0, master_i; - - data = alloca(filters_n * sizeof(*data)); - memset(data, 0, filters_n * sizeof(*data)); - for (i = 0; i < filters_n; i++) - { - if (!(crtc_info[crtc_updates[i].crtc].supported)) - continue; - - data[n].depth = crtc_updates[i].filter.depth; - data[n].red_size = crtc_updates[i].filter.ramps.u8.red_size; - data[n].green_size = crtc_updates[i].filter.ramps.u8.green_size; - data[n].blue_size = crtc_updates[i].filter.ramps.u8.blue_size; - data[n].index = i; - n++; - } - - qsort(data, n, sizeof(*data), crtc_sort_data_cmp); - if (n == 0) - return 0; - - master_i = data[0].index; - for (i = 1; i < n; i++) - if (memcmp(data + i, data + master, sizeof(*data) - sizeof(data->index))) - { - if (master + 1 < i) - { - crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); - if (crtc_updates[master_i].slaves == NULL) - return -1; - for (j = 1; master + j < i; j++) - crtc_updates[master_i].slaves[j - 1] = data[master + j].index; - } - master = i; - master_i = data[master].index; - } - else - { - libcoopgamma_ramps_destroy(&(crtc_updates[data[i].index].filter.ramps.u8)); - crtc_updates[data[i].index].master = 0; - crtc_updates[data[i].index].filter.ramps.u8 = crtc_updates[master_i].filter.ramps.u8; - } - - if (master + 1 < i) - { - crtc_updates[master_i].slaves = calloc(i - master, sizeof(size_t)); - if (crtc_updates[master_i].slaves == NULL) - return -1; - for (j = 1; master + j < i; j++) - crtc_updates[master_i].slaves[j - 1] = data[master + j].index; - } - - return 0; -} - - -/** - * Update a filter and synchronise calls - * - * @param index The index of the CRTC - * @param timeout The number of milliseconds a call to `poll` may block, - * -1 if it may block forever - * @return 1: Success, no pending synchronisations - * 0: Success, with still pending synchronisations - * -1: Error, `errno` set - * -2: Error, `cg.error` set - * - * @throws EINTR Call to `poll` was interrupted by a signal - * @throws EAGAIN Call to `poll` timed out - */ -int update_filter(size_t index, int timeout) -{ - filter_update_t* filter = crtc_updates + index; - - if (!(filter->synced) || filter->failed) - abort(); - - pending_recvs += 1; - - if (libcoopgamma_set_gamma_send(&(filter->filter), &cg, asyncs + index) < 0) - switch (errno) - { - case EINTR: - case EAGAIN: -#if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: -#endif - flush_pending = 1; - break; - default: - return -1; - } - - filter->synced = 0; - return synchronise(timeout); -} - - -/** - * Synchronised calls - * - * @param timeout The number of milliseconds a call to `poll` may block, - * -1 if it may block forever - * @return 1: Success, no pending synchronisations - * 0: Success, with still pending synchronisations - * -1: Error, `errno` set - * -2: Error, `cg.error` set - * - * @throws EINTR Call to `poll` was interrupted by a signal - * @throws EAGAIN Call to `poll` timed out - */ -int synchronise(int timeout) -{ - struct pollfd pollfd; - size_t selected; - - pollfd.fd = cg.fd; - pollfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; - if (flush_pending > 0) - pollfd.events |= POLLOUT; - - pollfd.revents = 0; - if (poll(&pollfd, (nfds_t)1, timeout) < 0) - return -1; - - if (pollfd.revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) - { - if (libcoopgamma_flush(&cg) < 0) - goto sync; - flush_pending = 0; - } - - if ((timeout < 0) && (pending_recvs > 0)) - if (!(pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI))) - { - pollfd.revents = 0; - if (poll(&pollfd, (nfds_t)1, -1) < 0) - return -1; - } - - sync: - if (pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLERR | POLLHUP | POLLNVAL)) - for (;;) - { - if (libcoopgamma_synchronise(&cg, asyncs, filters_n, &selected) < 0) - { - if (errno == 0) - continue; - else - goto fail; - } - if (crtc_updates[selected].synced) - continue; - crtc_updates[selected].synced = 1; - pending_recvs -= 1; - if (libcoopgamma_set_gamma_recv(&cg, asyncs + selected) < 0) - { - if (cg.error.server_side) - { - crtc_updates[selected].error = cg.error; - crtc_updates[selected].failed = 1; - memset(&(cg.error), 0, sizeof(cg.error)); - } - else - goto cg_fail; - } - } - - return pending_recvs == 0; - cg_fail: - return -2; - fail: - switch (errno) - { - case EINTR: - case EAGAIN: -#if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: -#endif - return pending_recvs == 0; - default: - return -1; - } -} - - -/** - * Initialise the process, specifically - * reset the signal mask and signal handlers - * - * @return Zero on success, -1 on error - */ -static int initialise_proc(void) -{ - sigset_t sigmask; - int sig; - - for (sig = 1; sig < _NSIG; sig++) - if (signal(sig, SIG_DFL) == SIG_ERR) - if (sig == SIGCHLD) - return -1; - - if (sigemptyset(&sigmask) < 0) - return -1; - if (sigprocmask(SIG_SETMASK, &sigmask, NULL) < 0) - return -1; - - return 0; -} - - -/** - * Print, to stdout, a list of all - * recognised adjustment methods - * - * @return Zero on success, -1 on error - */ -static int list_methods(void) -{ - char** list; - size_t i; - - list = libcoopgamma_get_methods(); - if (list == NULL) - return -1; - for (i = 0; list[i]; i++) - printf("%s\n", list[i]); - free(list); - if (fflush(stdout) < 0) - return -1; - - return 0; -} - - -/** - * Print, to stdout, a list of all CRTC:s - * - * A connection to the coopgamma server - * must have been made - * - * @return Zero on success, -1 on error, -2 - * on libcoopgamma error - */ -static int list_crtcs(void) -{ - char** list; - size_t i; - - list = libcoopgamma_get_crtcs_sync(&cg); - if (list == NULL) - return -2; - for (i = 0; list[i]; i++) - printf("%s\n", list[i]); - free(list); - if (fflush(stdout) < 0) - return -1; - - return 0; -} - - -/** - * Fill the list of CRTC information - * - * @return Zero on success, -1 on error, -2 - * on libcoopgamma error - */ -static int get_crtc_info(void) -{ - size_t i, unsynced = 0, selected; - char* synced; - int need_flush = 0; - struct pollfd pollfd; - - synced = alloca(crtcs_n * sizeof(*synced)); - memset(synced, 0, crtcs_n * sizeof(*synced)); - - i = 0; - pollfd.fd = cg.fd; - pollfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; - - while ((unsynced > 0) || (i < crtcs_n)) - { - wait: - if (i < crtcs_n) - pollfd.events |= POLLOUT; - else - pollfd.events &= ~POLLOUT; - - pollfd.revents = 0; - if (poll(&pollfd, (nfds_t)1, -1) < 0) - goto fail; - - if (pollfd.revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) - { - if (need_flush && (libcoopgamma_flush(&cg) < 0)) - goto send_fail; - need_flush = 0; - for (; i < crtcs_n; i++) - if (unsynced++, libcoopgamma_get_gamma_info_send(crtcs[i], &cg, asyncs + i) < 0) - goto send_fail; - goto send_done; - send_fail: - switch (errno) - { - case EINTR: - case EAGAIN: -#if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: -#endif - i++; - need_flush = 1; - break; - default: - goto fail; - } - } - send_done: - - if ((unsynced == 0) && (i == crtcs_n)) - break; - - if (pollfd.revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) - while (unsynced > 0) - switch (libcoopgamma_synchronise(&cg, asyncs, i, &selected)) - { - case 0: - if (synced[selected]) - { - libcoopgamma_skip_message(&cg); - break; - } - synced[selected] = 1; - unsynced -= 1; - if (libcoopgamma_get_gamma_info_recv(crtc_info + selected, &cg, asyncs + selected) < 0) - goto cg_fail; - break; - case -1: - switch (errno) - { - case 0: - break; - case EINTR: - case EAGAIN: -#if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: -#endif - goto wait; - default: - goto fail; - } - break; - } - } - - return 0; - fail: - return -1; - cg_fail: - return -2; -} - - -/** - * -M METHOD - * Select adjustment method. If METHOD is "?", - * available methods will be printed to stdout. - * - * -S SITE - * Select site (display server instance). - * - * -c CRTC - * Select CRT controller. If CRTC is "?", CRTC:s - * will be printed to stdout. - * - * This option can be used multiple times. If it - * is not used at all, all CRTC:s will be selected. - * - * -p PRIORITY - * Select the priority for the filter, this should - * be a signed two's-complement integer. If - * PRIORITY is "?", the default priority for the - * program is printed to stdout. - * - * -R RULE - * The rule of the filter, that is, the last part - * of the class which is its identifier. If RULE - * is "?" the default rule is printed to stdout, - * if RULE is "??" the default class is printed - * to stdout. - * - * @param argc The number of command line arguments - * @param argv The command line arguments - * @return 0 on success, 1 on error - */ -int main(int argc, char* argv[]) -{ - int stage = 0; - int dealloc_crtcs = 0; - int rc = 0; - char* method = NULL; - char* site = NULL; - size_t crtc_i = 0; - int64_t priority = default_priority; - char* prio = NULL; - char* rule = NULL; - char* class = default_class; - char** classes = NULL; - size_t classes_n = 0; - int explicit_crtcs = 0; - int have_crtc_q = 0; - size_t i, filter_i; - - argv0 = *argv++, argc--; - - if (initialise_proc() < 0) - goto fail; - - crtcs = alloca(argc * sizeof(*crtcs)); - - for (; *argv; argv++, argc--) - { - char* args = *argv; - char opt[3]; - if (!strcmp(args, "--")) - { - argv++, argc--; - break; - } - opt[0] = *args++; - opt[2] = '\0'; - if ((*opt != '-') && (*opt != '+')) - break; - while (*args) - { - char* arg; - int at_end; - opt[1] = *args++; - arg = args; - if ((at_end = !*arg)) - arg = argv[1]; - if (!strcmp(opt, "-M")) - { - if ((method != NULL) || ((method = arg) == NULL)) - usage(); - } - else if (!strcmp(opt, "-S")) - { - if ((site != NULL) || ((site = arg) == NULL)) - usage(); - } - else if (!strcmp(opt, "-c")) - { - if (arg == NULL) - usage(); - crtcs[crtc_i++] = arg; - explicit_crtcs = 1; - if (!have_crtc_q && !strcmp(arg, "?")) - have_crtc_q = 1; - } - else if (!strcmp(opt, "-p")) - { - if ((prio != NULL) || ((prio = arg) == NULL)) - usage(); - } - else if (!strcmp(opt, "-R")) - { - if ((rule != NULL) || ((rule = arg) == NULL)) - usage(); - } - else - switch (handle_opt(opt, arg)) - { - case 0: - goto next_opt; - case 1: - break; - default: - goto fail; - } - argv += at_end; - argc -= at_end; - break; - next_opt:; - } - } - - crtcs_n = crtc_i; - crtcs[crtc_i] = NULL; - if (!have_crtc_q && nulstrcmp(method, "?") && - nulstrcmp(rule, "?") && nulstrcmp(rule, "??") && - ((default_priority == NO_DEFAULT_PRIORITY) || nulstrcmp(prio, "?"))) - if (handle_args(argc, argv, prio) < 0) - goto fail; - - if (default_priority != NO_DEFAULT_PRIORITY) - { - if (!nulstrcmp(prio, "?")) - { - printf("%" PRIi64 "\n", priority); - return 0; - } - else if (prio != NULL) - { - char *end; - errno = 0; - priority = (int64_t)strtoll(prio, &end, 10); - if (errno || *end || !*prio) - usage(); - } - } - - if (!nulstrcmp(rule, "??")) - { - size_t i; - if (*class_suffixes == NULL) - printf("%s\n", class); - else - for (i = 0; class_suffixes[i] != NULL; i++) - printf("%s%s\n", class, class_suffixes[i]); - return 0; - } - else if (!nulstrcmp(rule, "?")) - { - printf("%s\n", strstr(strstr(class, "::") + 2, "::") + 2); - return 0; - } - else if (rule != NULL) - { - char* p = strstr(strstr(class, "::") + 2, "::") + 2; - size_t n = (size_t)(p - class); - class = alloca(strlen(rule) + n + (size_t)1); - memcpy(class, default_class, n); - strcpy(class + n, rule); - if (strchr(class, '\n')) - { - fprintf(stderr, "%s: LF character is not allowed in the filter's class\n", argv0); - goto custom_fail; - } - } - - if (!nulstrcmp(method, "?")) - { - if (list_methods() < 0) - goto fail; - return 0; - } - - if (libcoopgamma_context_initialise(&cg) < 0) - goto fail; - stage++; - if (libcoopgamma_connect(method, site, &cg) < 0) - { - fprintf(stderr, "%s: server failed to initialise\n", argv0); - goto custom_fail; - } - stage++; - - if (have_crtc_q) - switch (list_crtcs()) - { - case 0: - goto done; - case -1: - goto fail; - default: - goto cg_fail; - } - - if (crtcs_n == 0) - { - crtcs = libcoopgamma_get_crtcs_sync(&cg); - if (crtcs == NULL) - goto cg_fail; - dealloc_crtcs = 1; - for (; crtcs[crtcs_n] != NULL; crtcs_n++); - } - - if (crtcs_n == 0) - { - fprintf(stderr, "%s: no CRTC:s are available\n", argv0); - goto custom_fail; - } - - if (*class_suffixes == NULL) - { - classes = &class; - classes_n = 1; - } - else - { - size_t len = strlen(class); - while (class_suffixes[classes_n]) - classes_n++; - classes = alloca(classes_n * sizeof(*classes)); - for (i = 0; i < classes_n; i++) - { - classes[i] = alloca(len + strlen(class_suffixes[i]) + sizeof(":")); - stpcpy(stpcpy(stpcpy(classes[i], class), ":"), class_suffixes[i]); - } - } - filters_n = classes_n * crtcs_n; - - crtc_info = alloca(crtcs_n * sizeof(*crtc_info)); - memset(crtc_info, 0, crtcs_n * sizeof(*crtc_info)); - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) - if (libcoopgamma_crtc_info_initialise(crtc_info + crtc_i) < 0) - goto cg_fail; - - if (libcoopgamma_set_nonblocking(&cg, 1) < 0) - goto fail; - - asyncs = alloca(filters_n * sizeof(*asyncs)); - memset(asyncs, 0, filters_n * sizeof(*asyncs)); - for (filter_i = 0; filter_i < filters_n; filter_i++) - if (libcoopgamma_async_context_initialise(asyncs + filter_i) < 0) - goto fail; - - switch (get_crtc_info()) - { - case 0: - break; - case -1: - goto fail; - case -2: - goto cg_fail; - } - - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) - { - if (explicit_crtcs && !(crtc_info[crtc_i].supported)) - fprintf(stderr, "%s: warning: gamma adjustments not supported on CRTC: %s\n", - argv0, crtcs[crtc_i]); - if (crtc_info[crtc_i].cooperative == 0) - fprintf(stderr, "%s: warning: cooperative gamma server not running for CRTC: %s\n", - argv0, crtcs[crtc_i]); - } - - crtc_updates = alloca(filters_n * sizeof(*crtc_updates)); - memset(crtc_updates, 0, filters_n * sizeof(*crtc_updates)); - for (filter_i = i = 0; i < classes_n; i++) - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++, filter_i++) - { - if (libcoopgamma_filter_initialise(&(crtc_updates[filter_i].filter)) < 0) - goto fail; - if (libcoopgamma_error_initialise(&(crtc_updates[filter_i].error)) < 0) - goto fail; - crtc_updates[filter_i].crtc = crtc_i; - crtc_updates[filter_i].synced = 1; - crtc_updates[filter_i].failed = 0; - crtc_updates[filter_i].master = 1; - crtc_updates[filter_i].slaves = NULL; - crtc_updates[filter_i].filter.crtc = crtcs[crtc_i]; - crtc_updates[filter_i].filter.class = classes[i]; - crtc_updates[filter_i].filter.priority = priority; - crtc_updates[filter_i].filter.depth = crtc_info[crtc_i].depth; - crtc_updates[filter_i].filter.ramps.u8.red_size = crtc_info[crtc_i].red_size; - crtc_updates[filter_i].filter.ramps.u8.green_size = crtc_info[crtc_i].green_size; - crtc_updates[filter_i].filter.ramps.u8.blue_size = crtc_info[crtc_i].blue_size; - switch (crtc_updates[filter_i].filter.depth) - { -#define X(CONST, MEMBER, MAX, TYPE)\ - case CONST:\ - libcoopgamma_ramps_initialise(&(crtc_updates[filter_i].filter.ramps.MEMBER));\ - libclut_start_over(&(crtc_updates[filter_i].filter.ramps.MEMBER), MAX, TYPE, 1, 1, 1);\ - break; -LIST_DEPTHS -#undef X - default: - fprintf(stderr, "%s: internal error: gamma ramp type is unrecognised: %i\n", - argv0, crtc_updates[filter_i].filter.depth); - goto custom_fail; - } - } - - switch (start()) - { - case 0: - break; - case -1: - goto fail; - case -2: - goto cg_fail; - case -3: - goto custom_fail; - } - - for (filter_i = 0; filter_i < filters_n; filter_i++) - if (crtc_updates[filter_i].failed) - { - const char* side = cg.error.server_side ? "server" : "client"; - const char* crtc = crtc_updates[filter_i].filter.crtc; - if (cg.error.custom) - { - if ((cg.error.number != 0) && (cg.error.description != NULL)) - fprintf(stderr, "%s: %s-side error number %" PRIu64 " for CRTC %s: %s\n", - argv0, side, cg.error.number, crtc, cg.error.description); - else if (cg.error.number != 0) - fprintf(stderr, "%s: %s-side error number %" PRIu64 " for CRTC %s\n", - argv0, side, cg.error.number, crtc); - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", argv0, side, crtc, cg.error.description); - } - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", argv0, side, crtc, cg.error.description); - else - fprintf(stderr, "%s: %s-side error for CRTC %s: %s\n", argv0, side, crtc, strerror(cg.error.number)); - } - - done: - if (dealloc_crtcs) - free(crtcs); - if (crtc_info != NULL) - for (crtc_i = 0; crtc_i < crtcs_n; crtc_i++) - libcoopgamma_crtc_info_destroy(crtc_info + crtc_i); - if (asyncs != NULL) - for (filter_i = 0; filter_i < filters_n; filter_i++) - libcoopgamma_async_context_destroy(asyncs + filter_i); - if (stage >= 1) - libcoopgamma_context_destroy(&cg, stage >= 2); - if (crtc_updates != NULL) - for (filter_i = 0; filter_i < filters_n; filter_i++) - { - if (crtc_updates[filter_i].master == 0) - memset(&(crtc_updates[filter_i].filter.ramps.u8), 0, sizeof(crtc_updates[filter_i].filter.ramps.u8)); - crtc_updates[filter_i].filter.crtc = NULL; - crtc_updates[filter_i].filter.class = NULL; - libcoopgamma_filter_destroy(&(crtc_updates[filter_i].filter)); - libcoopgamma_error_destroy(&(crtc_updates[filter_i].error)); - free(crtc_updates[filter_i].slaves); - } - return rc; - - custom_fail: - rc = 1; - goto done; - - fail: - rc = 1; - if (errno) - perror(argv0); - goto done; - - cg_fail: - rc = 1; - { - const char* side = cg.error.server_side ? "server" : "client"; - if (cg.error.custom) - { - if ((cg.error.number != 0) && (cg.error.description != NULL)) - fprintf(stderr, "%s: %s-side error number %" PRIu64 ": %s\n", - argv0, side, cg.error.number, cg.error.description); - else if (cg.error.number != 0) - fprintf(stderr, "%s: %s-side error number %" PRIu64 "\n", argv0, side, cg.error.number); - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description); - } - else if (cg.error.description != NULL) - fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description); - else - fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, strerror(cg.error.number)); - } - goto done; -} - |