main.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <regex.h>
  5. #include <unistd.h>
  6. #include <wait.h>
  7. // replaces the matches with the compiled regex in the string with the substrings in subs. If there are more matches than substring, the excess matches are replaced with nothing.
  8. char* regex_sub_v(regex_t regex, char* string, char** subs){
  9. regmatch_t match[1];
  10. if (regexec(&regex, string, 1, match, 0) == 0){
  11. char* newstring;
  12. char* rec_string;
  13. if ( subs[0] != NULL ){
  14. newstring=malloc(sizeof(char)*(strlen(subs[0]) + strlen(string) + match[0].rm_eo - match[0].rm_so));
  15. memset(newstring, '\0', sizeof(char)*strlen(newstring));
  16. strncpy(newstring, string, match[0].rm_so);
  17. strcat(newstring, subs[0]);
  18. rec_string = regex_sub_v(regex,string+match[0].rm_eo, subs+1);
  19. }
  20. else {
  21. newstring=malloc(sizeof(char)*(strlen(string)+match[0].rm_eo - match[0].rm_so));
  22. memset(newstring, '\0', sizeof(char)*strlen(newstring));
  23. strncpy(newstring, string, match[0].rm_so);
  24. rec_string = regex_sub_v(regex,string+match[0].rm_eo, NULL);
  25. }
  26. char* ret_string = malloc (sizeof(char)*(strlen(newstring)+strlen(rec_string)));
  27. memset(ret_string, '\0', strlen(ret_string));
  28. strcpy(ret_string, newstring);
  29. strcat(ret_string, rec_string);
  30. free(newstring);
  31. return ret_string;
  32. }
  33. return string;
  34. }
  35. int main(int argc, char** argv){
  36. //Initialization and reading arguments
  37. int do_fork = 1;
  38. while(1){
  39. if (argv[1] == NULL) {
  40. fprintf(stderr, "No file specified\n");
  41. return 1;
  42. }
  43. if (strncmp(argv[1], "-h", 2) == 0){
  44. printf("Usage:\ndot-desktop [OPTIONS] application [application args]\n\nOptions:\n-h\t\tPrint help.\n--no-fork\tDon't fork launched process to the background.\n\nSet the DEFAULT_TERM environment variable to choose which terminal emulator to open apps it, defaults to 'xterm -e' if unset.\n");
  45. return 0;
  46. }
  47. if (strncmp(argv[1], "--no-fork", 9) == 0){
  48. do_fork = 0;
  49. argv++;
  50. argc--;
  51. continue;
  52. }
  53. break;
  54. }
  55. // parse arg 1=target app to open
  56. int applen=strlen(argv[1]);
  57. char* application = malloc(sizeof(char)*applen);
  58. strcpy(application, argv[1]);
  59. // generate target paths: ~/.local/share/applications/app, /usr/local/share/applications/app, /usr/share/applications/app
  60. char* home = getenv("HOME");
  61. char* xdg_home=malloc(sizeof(char)*(strlen(home)+applen+strlen("/.local/share/applications/")));
  62. strcpy(xdg_home, home);
  63. xdg_home=strcat(xdg_home, "/.local/share/applications/");
  64. xdg_home=strcat(xdg_home, application);
  65. char* usr_local = malloc(sizeof(char)*(strlen("/usr/local/share/applications/")+applen));
  66. strcpy(usr_local, "/usr/local/share/applications/");
  67. usr_local = strcat(usr_local, application);
  68. char* usr_share = malloc(sizeof(char)*(strlen("/usr/share/applications/")+applen));
  69. strcpy(usr_share, "/usr/share/applications/");
  70. usr_share = strcat(usr_share, application);
  71. //Try to open paths in the following order: app, ~/.local/share/applications/app, /usr/local/share/applications/app, /usr/share/applications/app
  72. char* paths[]={application, xdg_home, usr_local, usr_share};
  73. FILE* file;
  74. for (int i=0; i<4; i++){
  75. printf("Trying to open %s\n", paths[i]);
  76. file = fopen(paths[i], "r");
  77. if (file != NULL){
  78. break;
  79. }
  80. }
  81. free(xdg_home);
  82. free(usr_local);
  83. free(usr_share);
  84. if (file == NULL){
  85. fprintf(stderr, "Could not find app %s\n", application);
  86. return 2;
  87. }
  88. //Parsing and validating .desktop file
  89. char* line;
  90. size_t size1=0;
  91. ssize_t size2;
  92. size2 = getline(&line, &size1, file);
  93. char dsk_ntr[17];
  94. strcpy(dsk_ntr, "[Desktop Entry]\n");
  95. if (strcmp(line, dsk_ntr) != 0){
  96. fprintf(stderr, "%s is not a valid application\n", application);
  97. return 3;
  98. }
  99. regex_t exec_regex;
  100. regcomp(&exec_regex, "^Exec=",0);
  101. regex_t term_regex;
  102. regcomp(&term_regex, "^Terminal=",0);
  103. char* exec = NULL;
  104. char* termline = NULL;
  105. while ( getline(&line, &size1, file) > 0){
  106. if(regexec(&exec_regex, line, 0, NULL, 0) == 0){
  107. if (exec != NULL) free(exec);
  108. exec=malloc(sizeof(char)*strlen(line));
  109. strcpy(exec,line);
  110. }
  111. else if(regexec(&term_regex, line, 0, NULL, 0) == 0){
  112. if (termline != NULL) free(termline);
  113. termline=malloc(sizeof(char)*strlen(line));
  114. strcpy(termline,line);
  115. }
  116. }
  117. fclose(file);
  118. regfree(&exec_regex);
  119. regfree(&exec_regex);
  120. if (exec == NULL){
  121. fprintf(stderr, "%s is not a valid application\n", application);
  122. return 3;
  123. }
  124. //Generating command to execute
  125. char* exec2=malloc(sizeof(char)*strlen(exec));
  126. strncpy(exec2, exec+5, strlen(exec)-5);
  127. free(exec);
  128. regmatch_t match[1];
  129. regex_t substitute;
  130. regcomp(&substitute, "%[FfkKuU]", 0);
  131. exec2=regex_sub_v(substitute,exec2,argv+2);
  132. regfree(&substitute);
  133. if (termline != NULL) {
  134. regex_t isterminal;
  135. regcomp(&isterminal, "[tT]rue", 0);
  136. if (regexec(&isterminal, termline, 0, NULL, 0) == 0){
  137. char* termname=getenv("DEFAULT_TERM");
  138. if (termname == NULL || strlen(termname) <= 1){
  139. termname="xterm -e";
  140. }
  141. char* tempexec = malloc((strlen(exec2)+strlen(termname)+1)*sizeof(char));
  142. memset(tempexec, '\0', sizeof(char)*strlen(tempexec));
  143. strcpy(tempexec, termname);
  144. strcat(tempexec, " ");
  145. strcat(tempexec, exec2);
  146. free(exec2);
  147. exec2=tempexec;
  148. }
  149. }
  150. //Run generated command in a forked process and concurrently return
  151. char* args[4]={"sh", "-c", exec2, NULL};
  152. if ( do_fork == 1){
  153. pid_t pid = fork();
  154. if (pid == 0) {
  155. if (execvp(args[0], args) == -1) {
  156. printf("Something went wrong\n");
  157. return 1;
  158. }
  159. }
  160. }
  161. else{
  162. if(execvp(args[0], args)== -1){
  163. printf("Something went wrong\n");
  164. }
  165. }
  166. free(application);
  167. free(exec2);
  168. free(termline);
  169. return 0;
  170. }