123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <regex.h>
- #include <unistd.h>
- #include <wait.h>
- // 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.
- char* regex_sub_v(regex_t regex, char* string, char** subs){
- regmatch_t match[1];
- if (regexec(®ex, string, 1, match, 0) == 0){
- char* newstring;
- char* rec_string;
- if ( subs[0] != NULL ){
- newstring=malloc(sizeof(char)*(strlen(subs[0]) + strlen(string) + match[0].rm_eo - match[0].rm_so));
- memset(newstring, '\0', sizeof(char)*strlen(newstring));
- strncpy(newstring, string, match[0].rm_so);
- strcat(newstring, subs[0]);
- rec_string = regex_sub_v(regex,string+match[0].rm_eo, subs+1);
- }
- else {
- newstring=malloc(sizeof(char)*(strlen(string)+match[0].rm_eo - match[0].rm_so));
- memset(newstring, '\0', sizeof(char)*strlen(newstring));
- strncpy(newstring, string, match[0].rm_so);
- rec_string = regex_sub_v(regex,string+match[0].rm_eo, NULL);
- }
- char* ret_string = malloc (sizeof(char)*(strlen(newstring)+strlen(rec_string)));
- memset(ret_string, '\0', strlen(ret_string));
- strcpy(ret_string, newstring);
- strcat(ret_string, rec_string);
- free(newstring);
- return ret_string;
- }
- return string;
- }
- int main(int argc, char** argv){
- //Initialization and reading arguments
-
- int do_fork = 1;
- while(1){
- if (argv[1] == NULL) {
- fprintf(stderr, "No file specified\n");
- return 1;
- }
-
- if (strncmp(argv[1], "-h", 2) == 0){
- 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");
- return 0;
- }
-
- if (strncmp(argv[1], "--no-fork", 9) == 0){
- do_fork = 0;
- argv++;
- argc--;
- continue;
- }
- break;
- }
- // parse arg 1=target app to open
- int applen=strlen(argv[1]);
- char* application = malloc(sizeof(char)*applen);
- strcpy(application, argv[1]);
- // generate target paths: ~/.local/share/applications/app, /usr/local/share/applications/app, /usr/share/applications/app
- char* home = getenv("HOME");
- char* xdg_home=malloc(sizeof(char)*(strlen(home)+applen+strlen("/.local/share/applications/")));
- strcpy(xdg_home, home);
- xdg_home=strcat(xdg_home, "/.local/share/applications/");
- xdg_home=strcat(xdg_home, application);
- char* usr_local = malloc(sizeof(char)*(strlen("/usr/local/share/applications/")+applen));
- strcpy(usr_local, "/usr/local/share/applications/");
- usr_local = strcat(usr_local, application);
- char* usr_share = malloc(sizeof(char)*(strlen("/usr/share/applications/")+applen));
- strcpy(usr_share, "/usr/share/applications/");
- usr_share = strcat(usr_share, application);
- //Try to open paths in the following order: app, ~/.local/share/applications/app, /usr/local/share/applications/app, /usr/share/applications/app
- char* paths[]={application, xdg_home, usr_local, usr_share};
- FILE* file;
- for (int i=0; i<4; i++){
- printf("Trying to open %s\n", paths[i]);
- file = fopen(paths[i], "r");
- if (file != NULL){
- break;
- }
- }
- free(xdg_home);
- free(usr_local);
- free(usr_share);
- if (file == NULL){
- fprintf(stderr, "Could not find app %s\n", application);
- return 2;
- }
- //Parsing and validating .desktop file
-
- char* line;
- size_t size1=0;
- ssize_t size2;
- size2 = getline(&line, &size1, file);
- char dsk_ntr[17];
- strcpy(dsk_ntr, "[Desktop Entry]\n");
- if (strcmp(line, dsk_ntr) != 0){
- fprintf(stderr, "%s is not a valid application\n", application);
- return 3;
- }
- regex_t exec_regex;
- regcomp(&exec_regex, "^Exec=",0);
- regex_t term_regex;
- regcomp(&term_regex, "^Terminal=",0);
- char* exec = NULL;
- char* termline = NULL;
- while ( getline(&line, &size1, file) > 0){
- if(regexec(&exec_regex, line, 0, NULL, 0) == 0){
- if (exec != NULL) free(exec);
- exec=malloc(sizeof(char)*strlen(line));
- strcpy(exec,line);
- }
- else if(regexec(&term_regex, line, 0, NULL, 0) == 0){
- if (termline != NULL) free(termline);
- termline=malloc(sizeof(char)*strlen(line));
- strcpy(termline,line);
- }
- }
- fclose(file);
- regfree(&exec_regex);
- regfree(&exec_regex);
- if (exec == NULL){
- fprintf(stderr, "%s is not a valid application\n", application);
- return 3;
- }
- //Generating command to execute
-
- char* exec2=malloc(sizeof(char)*strlen(exec));
- strncpy(exec2, exec+5, strlen(exec)-5);
- free(exec);
- regmatch_t match[1];
- regex_t substitute;
- regcomp(&substitute, "%[FfkKuU]", 0);
- exec2=regex_sub_v(substitute,exec2,argv+2);
- regfree(&substitute);
- if (termline != NULL) {
- regex_t isterminal;
- regcomp(&isterminal, "[tT]rue", 0);
- if (regexec(&isterminal, termline, 0, NULL, 0) == 0){
- char* termname=getenv("DEFAULT_TERM");
- if (termname == NULL || strlen(termname) <= 1){
- termname="xterm -e";
- }
- char* tempexec = malloc((strlen(exec2)+strlen(termname)+1)*sizeof(char));
- memset(tempexec, '\0', sizeof(char)*strlen(tempexec));
- strcpy(tempexec, termname);
- strcat(tempexec, " ");
- strcat(tempexec, exec2);
- free(exec2);
- exec2=tempexec;
- }
- }
- //Run generated command in a forked process and concurrently return
- char* args[4]={"sh", "-c", exec2, NULL};
- if ( do_fork == 1){
- pid_t pid = fork();
- if (pid == 0) {
- if (execvp(args[0], args) == -1) {
- printf("Something went wrong\n");
- return 1;
- }
- }
- }
- else{
- if(execvp(args[0], args)== -1){
- printf("Something went wrong\n");
- }
- }
- free(application);
- free(exec2);
- free(termline);
- return 0;
- }
|