/* * Hot Beverage Companion – server module * * Copyright (C) 2017-2018 Gediminas Jakutis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "net.h" #include "ui.h" struct settings { struct timespec period; enum uitype ui; unsigned short int port; }; static int init(int *argc, char ***argv, const struct settings * const settings); static struct settings parseargs(int argc, char **argv); static enum uitype identify_ui(const char * const s, const char * const name); static struct timespec calc_period(const char * const s); static size_t printhelp(const char * const name) __attribute__((noreturn)); int main(int argc, char **argv) { struct settings settings; int ret; int nd; settings = parseargs(argc, argv); nd = init(&argc, &argv, &settings); if (nd == ERROR) { ret = nd; goto fail; } ret = ui_startloop(); fail: net_close(nd); return ret; } static int init(int *argc, char ***argv, const struct settings * const settings) { int ret = A_OK; int nd; nd = net_init(settings->port); if (nd == ERROR) { ret = nd; goto fail; } ret = ui_init(argc, argv, settings->ui, nd, settings->period); if (ret == ERROR) { net_close(nd); goto fail; } fail: return ret; } static struct settings parseargs(int argc, char **argv) { /* collection of defaults */ struct settings ret = {{0, 200 * 1000 * 1000}, /* 200 ms */ ui_curses, 2191}; ssize_t i; if (argc == 1) { return ret; } for (i = 1; i < argc; ++i) { if (!(strncmp(argv[i], "--period=", 8))) { ret.period = strlen(argv[i]) > 9 ? calc_period(argv[i] + 9) : (struct timespec) {0, printhelp(*argv)}; } else if (!(strncmp(argv[i], "--ui=", 5))) { ret.ui = strlen(argv[i]) > 5 ? identify_ui(argv[i] + 5, *argv) : printhelp(*argv); } else if (!(strncmp(argv[i], "--port=", 7))) { ret.port = strlen(argv[i]) > 7 ? strtoul(argv[i] + 7, NULL, 10) : printhelp(*argv); } else { printhelp(*argv); } } return ret; } static enum uitype identify_ui(const char * const s, const char * const name) { static const struct uituple { char *name; enum uitype type; } uilist[] = {{"none", ui_none}, {"file", ui_file}, {"curses", ui_curses}, {"gtk", ui_gtk}}; size_t i; int found = 0; enum uitype ret = ui_none; for (i = 0; i < arrsize(uilist); ++i) { if (!strcmp(s, uilist[i].name)) { found = 1; ret = uilist[i].type; } } if (!found) { printhelp(name); } return ret; } static struct timespec calc_period(const char * const s) { /* TODO: stub! */ return (struct timespec) {0, 200 * 1000 * 1000}; } static size_t printhelp(const char * const name) { printf( "This is a coffeetemp companion application\n" "\n" "usage:\t%s [options]\n" "\n" "Options:\n" " --period= set network polling rate to milliseconds (default: 200)\n" " --ui= set the UI frontend (default: curses)\n" " * possible choices: [none, file, curses, gtk]\n" " --port= set the listening port number to \n" "\n" "In case more than one same option is provided, the last one take precedence\n" "\n", name); exit(EXIT_FAILURE); return 0; }