vm-file-editor.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include <sys/stat.h>
  2. #include <sys/wait.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <fcntl.h>
  7. #include <unistd.h>
  8. #include <ioall.h>
  9. #include "dvm2.h"
  10. char *get_filename()
  11. {
  12. char buf[DVM_FILENAME_SIZE];
  13. static char retname[sizeof(buf) + sizeof("/tmp/")];
  14. int i;
  15. if (!read_all(0, buf, sizeof(buf)))
  16. exit(1);
  17. if (index(buf, '/')) {
  18. fprintf(stderr, "filename contains /");
  19. exit(1);
  20. }
  21. for (i=0; i < DVM_FILENAME_SIZE && buf[i]!=0; i++) {
  22. // replace some characters with _ (eg mimeopen have problems with some of them)
  23. if (index(" !?\"#$%^&*()[]<>;`~", buf[i]))
  24. buf[i]='_';
  25. }
  26. snprintf(retname, sizeof(retname), "/tmp/%s", buf);
  27. return retname;
  28. }
  29. void copy_file(char *filename)
  30. {
  31. int fd = open(filename, O_WRONLY | O_CREAT, 0600);
  32. if (fd < 0) {
  33. perror("open file");
  34. exit(1);
  35. }
  36. if (!copy_fd_all(fd, 0))
  37. exit(1);
  38. close(fd);
  39. }
  40. void send_file_back(char * filename)
  41. {
  42. int fd = open(filename, O_RDONLY);
  43. if (fd < 0) {
  44. perror("open file");
  45. exit(1);
  46. }
  47. if (!copy_fd_all(1, fd))
  48. exit(1);
  49. close(fd);
  50. }
  51. int
  52. main()
  53. {
  54. struct stat stat_pre, stat_post, session_stat;
  55. char *filename = get_filename();
  56. int child, status, log_fd;
  57. char var[1024], val[4096];
  58. FILE *env_file;
  59. FILE *waiter_pidfile;
  60. copy_file(filename);
  61. if (stat(filename, &stat_pre)) {
  62. perror("stat pre");
  63. exit(1);
  64. }
  65. // wait for X server to starts (especially in DispVM)
  66. if (stat("/tmp/qubes-session-env", &session_stat)) {
  67. switch (child = fork()) {
  68. case -1:
  69. perror("fork");
  70. exit(1);
  71. case 0:
  72. waiter_pidfile = fopen("/tmp/qubes-session-waiter", "a");
  73. if (waiter_pidfile == NULL) {
  74. perror("fopen waiter_pidfile");
  75. exit(1);
  76. }
  77. fprintf(waiter_pidfile, "%d\n", getpid());
  78. fclose(waiter_pidfile);
  79. // check the second time, to prevent race
  80. if (stat("/tmp/qubes-session-env", &session_stat)) {
  81. // wait for qubes-session notify
  82. pause();
  83. }
  84. exit(0);
  85. default:
  86. waitpid(child, &status, 0);
  87. if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
  88. //propagate exit code from child
  89. exit(WEXITSTATUS(status));
  90. }
  91. }
  92. }
  93. switch (child = fork()) {
  94. case -1:
  95. perror("fork");
  96. exit(1);
  97. case 0:
  98. close(0);
  99. env_file = fopen("/tmp/qubes-session-env", "r");
  100. while(fscanf(env_file, "%1024[^=]=%4096[^\n]\n", var, val) == 2) {
  101. setenv(var, val, 1);
  102. }
  103. fclose(env_file);
  104. log_fd = open("/tmp/mimeopen.log", O_CREAT | O_APPEND, 0666);
  105. if (log_fd == -1) {
  106. perror("open /tmp/mimeopen.log");
  107. exit(1);
  108. }
  109. dup2(log_fd, 1);
  110. dup2(log_fd, 2);
  111. close(log_fd);
  112. setenv("HOME", "/home/user", 1);
  113. setenv("DISPLAY", ":0", 1);
  114. execl("/usr/bin/mimeopen", "mimeopen", "-n", filename, (char*)NULL);
  115. perror("execl");
  116. exit(1);
  117. default:
  118. waitpid(child, &status, 0);
  119. if (status != 0) {
  120. char cmd[512];
  121. #ifdef USE_KDIALOG
  122. snprintf(cmd, sizeof(cmd),
  123. "HOME=/home/user DISPLAY=:0 /usr/bin/kdialog --sorry 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
  124. ("HOME=/home/user DISPLAY=:0 /usr/bin/kdialog --sorry 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
  125. #else
  126. snprintf(cmd, sizeof(cmd),
  127. "HOME=/home/user DISPLAY=:0 /usr/bin/zenity --error --text 'Unable to handle mimetype of the requested file (exit status: %d)!' > /tmp/kdialog.log 2>&1 </dev/null", status);
  128. #endif
  129. system(cmd);
  130. }
  131. }
  132. if (stat(filename, &stat_post)) {
  133. perror("stat post");
  134. exit(1);
  135. }
  136. if (stat_pre.st_mtime != stat_post.st_mtime)
  137. send_file_back(filename);
  138. return 0;
  139. }