/** * mds — A micro-display server * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) * * 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 . */ #include "mds-server.h" #include "config.h" #include #include #include #include #include /** * Number of elements in `argv` */ static int argc; /** * Command line arguments */ static char** argv; /** * Entry point of the server * * @param argc_ Number of elements in `argv_` * @param argv_ Command line arguments * @return Non-zero on error */ int main(int argc_, char** argv_) { char* unparsed_args[ARGC_LIMIT + LIBEXEC_ARGC_EXTRA_LIMIT + 1]; int i; int is_respawn = -1; int socket_fd = -1; int unparsed_args_ptr = 0; argc = argc_; argv = argv_; /* Drop privileges like it's hot. */ if ((geteuid() == getuid() ? 0 : seteuid(getuid())) || (getegid() == getgid() ? 0 : setegid(getgid()))) { perror(*argv); return 1; } /* Sanity check the number of command line arguments. */ if (argc > ARGC_LIMIT + LIBEXEC_ARGC_EXTRA_LIMIT) { fprintf(stderr, "%s: that number of arguments is ridiculous, I will not allow it.\n", *argv); return 1; } /* Parse command line arguments. */ for (i = 1; i < argc; i++) { char* arg = argv[i]; if (!strcmp(arg, "--initial-spawn")) /* Initial spawn? */ if (is_respawn == 1) { fprintf(stderr, "%s: conflicting arguments %s and %s cannot be combined.\n", *argv, "--initial-spawn", "--respawn"); return 1; } else is_respawn = 0; else if (!strcmp(arg, "--respawn")) /* Respawning after crash? */ if (is_respawn == 0) { fprintf(stderr, "%s: conflicting arguments %s and %s cannot be combined.\n", *argv, "--initial-spawn", "--respawn"); return 1; } else is_respawn = 1; else if (strstr(arg, "--socket-fd=") == arg) /* Socket file descriptor. */ { long int r; char* endptr; if (socket_fd != -1) { fprintf(stderr, "%s: duplicate declaration of %s.\n", *argv, "--socket-fd"); return -1; } arg += strlen("--socket-fd="); r = strtol(arg, &endptr, 10); if ((*argv == '\0') || isspace(*argv) || (endptr - arg != (ssize_t)strlen(arg)) || (r < 0) || (r > INT_MAX)) { fprintf(stderr, "%s: invalid value for %s: %s.\n", *argv, "--socket-fd", arg); return 1; } socket_fd = (int)r; } else /* Not recognised, it is probably for another server. */ unparsed_args[unparsed_args_ptr++] = arg; } unparsed_args[unparsed_args_ptr] = NULL; /* Check that manditory arguments have been specified. */ if (is_respawn < 0) { fprintf(stderr, "%s: missing state argument, require either %s or %s.\n", *argv, "--initial-spawn", "--respawn"); return 1; } if (socket_fd < 0) { fprintf(stderr, "%s: missing socket file descriptor argument.\n", *argv); return 1; } return 0; }