/* Copyright (c) 2026 The Solidite Developers
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero 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 Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>. */

#include <bitset>
#include <iostream>
#include <vector>

#include <cstddef>
#include <cstdint>
#include <cstring>

#include <libintl.h>
#include <signal.h>

/* Questionably IEEE Std 1003.1-2024 and XSI conformant
 * needs testing */

constexpr char SIGNALS_LIST[] = "SIGHUP SIGINT SIGQUIT SIGABRT SIGKILL SIGALRM"
                                " SIGTERM\n";

int main(int argc, char* argv[]) {
  // locale work
  std::locale::global(std::locale(""));
  std::cerr.imbue(std::locale()); 

  std::bitset<2> options = 0b00;
  // options[0]=skip next arg from being processed
  // options[1]=stop processing arguments (-- encountered)
  std::vector<std::size_t> pids;
  int signal = 15;

  for (int i = 1; i < argc; ++i) {
    if (options.test(0) == 1) {
      options.reset(0);
      continue;
    } else if (std::strcmp(argv[i], "--") == 0 && options.test(1) == 0) {
      options.set(1);
      continue;
    } else if (options.test(1) == 1) {
      pids.push_back(std::atoi(argv[i]));
      continue;
    }

    if (std::strcmp(argv[i], "-l") == 0 && argv[i + 1] == nullptr) {
      std::cout << SIGNALS_LIST;
      return 0;
    } else if (std::strcmp(argv[i], "-l") == 0) {
      switch (std::atoi(argv[i + 1])) {
        case 0:
          std::cout << "0\n";
          options.set(0);
          break;
        case 1:
          std::cout << "HUP\n";
          options.set(0);
          break;
        case 2:
          std::cout << "INT\n";
          options.set(0);
          break;
        case 3:
          std::cout << "QUIT\n";
          options.set(0);
          break;
        case 6:
          std::cout << "ABRT\n";
          options.set(0);
          break;
        case 9:
          std::cout << "KILL\n";
          options.set(0);
          break;
        case 14:
          std::cout << "ALRM\n";
          options.set(0);
          break;
        case 15:
          std::cout << "TERM\n";
          options.set(0);
          break;
        default:
          std::cerr << "bad signal\n";
          options.set(0);
          break;
      }
    } else if (std::strcmp(argv[i], "-s") == 0) {
      if (argv[i + 1] == nullptr) {
        std::cerr << "signal name required after -s\n";
        continue;
      }
      if (std::strcmp(argv[i + 1], "0") == 0) {
        signal = 0;
      } else if (std::strcmp(argv[i + 1], "HUP") == 0) {
        signal = 1;
      } else if (std::strcmp(argv[i + 1], "INT") == 0) {
        signal = 2;
      } else if (std::strcmp(argv[i + 1], "QUIT") == 0) {
        signal = 3;
      } else if (std::strcmp(argv[i + 1], "ABRT") == 0) {
        signal = 6;
      } else if (std::strcmp(argv[i + 1], "KILL") == 0) {
        signal = 9;
      } else if (std::strcmp(argv[i + 1], "ALRM") == 0) {
        signal = 14;
      } else if (std::strcmp(argv[i + 1], "TERM") == 0) {
        signal = 15;
      } else {
        std::cerr << "bad signal name\n";
      }
      options.set(0);
      continue;
    } else if (std::strcmp(argv[i], "-0") == 0) {
      signal = 0;
    } else if (std::strcmp(argv[i], "-1") == 0) {
      signal = 1;
    } else if (std::strcmp(argv[i], "-2") == 0) {
      signal = 2;
    } else if (std::strcmp(argv[i], "-3") == 0) {
      signal = 3;
    } else if (std::strcmp(argv[i], "-6") == 0) {
      signal = 6;
    } else if (std::strcmp(argv[i], "-9") == 0) {
      signal = 9;
    } else if (std::strcmp(argv[i], "-14") == 0) {
      signal = 14;
    } else if (std::strcmp(argv[i], "-15") == 0) {
      signal = 15;
    } else if (std::strcmp(argv[i], "-UP") == 0) {
      signal = 1;
    } else if (std::strcmp(argv[i], "-INT") == 0) {
      signal = 2;
    } else if (std::strcmp(argv[i], "-QUIT") == 0) {
      signal = 3;
    } else if (std::strcmp(argv[i], "-ABRT") == 0) {
      signal = 6;
    } else if (std::strcmp(argv[i], "-KILL") == 0) {
      signal = 9;
    } else if (std::strcmp(argv[i], "-ALRM") == 0) {
      signal = 14;
    } else if (std::strcmp(argv[i], "-TERM") == 0) {
      signal =  15;
    } else {
      pids.push_back(std::atoi(argv[i]));
    }
  }
  for (std::size_t pid : pids) {
    kill(pid, signal); 
  }
  return 0;
}
