ly/src/desktop.c

181 lines
3.6 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include "lang.h"
#include "config.h"
#include "utils.h"
#include "desktop.h"
#define LY_XSESSION_EXEC "Exec="
#define LY_XSESSION_NAME "Name="
// searches a folder
short get_desktops(char* sessions_dir, struct delist_t* list, int* remote_count, short x)
{
/* xsession */
FILE* file;
DIR* dir;
struct dirent* dir_info;
/* buffers */
char path[LY_LIM_PATH];
char* name;
char* command;
int count = *remote_count;
if(access(sessions_dir, F_OK) == -1 )
{
return -1;
}
/* reads xorg's desktop environments entries */
dir = opendir(sessions_dir);
/* exits if the folder can't be read */
if(!dir)
{
error_print(LY_ERR_DELIST);
end_list(list, count);
return -2;
}
/* cycles through the folder */
while((dir_info = readdir(dir)))
{
/* gets rid of ".", ".." and ".*" files */
if((dir_info->d_name)[0] == '.')
{
continue;
}
/* opens xsession file */
snprintf(path, sizeof(path), "%s/%s", sessions_dir,
dir_info->d_name);
file = fopen(path, "r");
/* stops the entire procedure if the file can't be read */
if(!file)
{
error_print(LY_ERR_DELIST);
closedir(dir);
break;
}
/* reads xsession file */
name = NULL;
command = NULL;
get_props(file, &name, &command);
/* frees memory when the entries are incomplete */
if((name && !command) || (!name && command))
{
free(name ? name : command);
break;
}
/* adds the new entry to the list */
list->names = realloc(list->names,
(count + 2) * (sizeof * (list->names)));
list->names[count] = name;
list->props = realloc(list->props,
(count + 1) * (sizeof * (list->props)));
list->props[count].cmd = command;
list->props[count].type = x ? xorg : wayland;
++count;
fclose(file);
}
closedir(dir);
*remote_count = count;
return 0;
}
/* returns a list containing all the DE for all the display servers */
struct delist_t* list_de(void)
{
/* de list */
int count = 2;
short errors = 0;
struct delist_t* list = init_list(count);
if(get_desktops(LY_PATH_XSESSIONS, list, &count, true) != 0)
{
++errors;
}
if(get_desktops(LY_PATH_WSESSIONS, list, &count, false))
{
++errors;
}
if(errors > 1) {
return NULL;
}
end_list(list, count);
return list;
}
/* writes default entries to the DE list */
struct delist_t* init_list(int count)
{
struct delist_t* list = malloc(sizeof * list);
list->names = malloc((count + 1) * (sizeof * (list->names)));
list->names[0] = strdup(LY_LANG_SHELL);
list->names[1] = strdup(LY_LANG_XINITRC);
list->props = malloc(count * (sizeof * (list->props)));
list->props[0].cmd = strdup("");
list->props[0].type = shell;
list->props[1].cmd = strdup(LY_CMD_XINITRC);
list->props[1].type = xinitrc;
return list;
}
void end_list(struct delist_t* list, int count)
{
list->names[count] = NULL;
list->count = count;
}
/* extracts the name and command of a DE from its .desktop file */
void get_props(FILE* file, char** name, char** command)
{
char line[LY_LIM_LINE_FILE];
while(fgets(line, sizeof(line), file))
{
if(!strncmp(LY_XSESSION_NAME, line, (sizeof(LY_XSESSION_NAME) - 1)))
{
*name = strdup(trim(line + (sizeof(LY_XSESSION_NAME) - 1)));
}
else if(!strncmp(LY_XSESSION_EXEC, line,
(sizeof(LY_XSESSION_EXEC) - 1)))
{
*command = strdup(trim(line + (sizeof(LY_XSESSION_EXEC) - 1)));
}
if(*name && *command)
{
break;
}
}
}
void free_list(struct delist_t* list)
{
int count;
for(count = 0; count < list->count; ++count)
{
free(list->names[count]);
free(list->props[count].cmd);
}
free(list->names);
free(list->props);
free(list);
}