soap.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /* See LICENSE file for copyright and license details. */
  2. #define _XOPEN_SOURCE 700
  3. #include <sys/stat.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <regex.h>
  7. typedef struct {
  8. const char *regex;
  9. const char *action;
  10. } Pair;
  11. #include "config.h"
  12. #define LEN(x) (sizeof(x) / sizeof(*x))
  13. int strncmp(const char *s1, const char *s2, size_t n)
  14. {
  15. while (n && *s1) {
  16. if (*s1 != *s2) return 0;
  17. s1++, s2++, n--;
  18. }
  19. return 1;
  20. }
  21. int main(int argc, char *argv[])
  22. {
  23. struct stat s;
  24. regex_t regex;
  25. const char *act = NULL, fileURI[] = "file://";
  26. size_t g, h, i, len = LEN(fileURI) - 1;
  27. char cmd[BUFSIZ + 32], sharg[BUFSIZ];
  28. /* we only take one argument */
  29. if (argc != 2) return EXIT_FAILURE;
  30. /* file:// URI - strip it off */
  31. if (strncmp(argv[1], fileURI, len)) argv[1] += len;
  32. /* is this a directory */
  33. if ((!lstat(((char *)argv[1]) + len, &s) || !lstat(argv[1], &s)) && S_ISDIR(s.st_mode)) act = dircmd;
  34. /* make arg shell-ready, strong quote, escape single quotes, and null terminate */
  35. sharg[0] = '\'';
  36. for (g = 0, h = 1; argv[1][g] && h < BUFSIZ - 6; g++, h++) {
  37. sharg[h] = argv[1][g];
  38. if (argv[1][g] == '\'') {
  39. sharg[++h] = '\\';
  40. sharg[++h] = '\'';
  41. sharg[++h] = '\'';
  42. }
  43. }
  44. sharg[h] = '\'';
  45. sharg[++h] = '\0';
  46. if (act) goto run; /* opening a directory */
  47. /* check regex and launch action if it matches argv[1] */
  48. for (i = 0; i < sizeof(pairs) / sizeof(*pairs); i++) {
  49. if (regcomp(&regex, pairs[i].regex, REG_EXTENDED|REG_NOSUB)) {
  50. fprintf(stderr, "invalid regex: %s\n", pairs[i].regex);
  51. break;
  52. }
  53. if (!regexec(&regex, argv[1], 0, NULL, 0)) {
  54. act = pairs[i].action;
  55. regfree(&regex);
  56. goto run;
  57. }
  58. regfree(&regex);
  59. }
  60. act = "/usr/bin/xdg-open %s"; /* fall back to xdg-open */
  61. run:
  62. snprintf(cmd, sizeof(cmd), act, sharg); // NOLINT
  63. system(cmd);
  64. return EXIT_SUCCESS;
  65. }