/*
* xcfg | simple xorg configuration tool
* MatterLinux 2024 (https://matterlinux.xyz)
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "util.h"
#include "log.h"
#define _(x) gettext(x)
int ask(char* text, ITEM** items, int sz) {
attron(COLOR_PAIR(1) | A_BOLD);
mvprintw(1, 1, "%s", text);
char line[strlen(text)+5];
int i = 0;
for (; i < strlen(text); i++){
line[i] = '#';
}
line[i] = '\0';
mvprintw(2, 1, "%s", line);
attroff(COLOR_PAIR(1) | A_BOLD);
refresh();
WINDOW* swin = newwin(LINES-3, COLS-1, 3, 1);
keypad(swin, TRUE);
MENU* menu = new_menu((ITEM **)items);
set_menu_win(menu, swin);
set_menu_sub(menu, swin);
set_menu_mark(menu, ">");
post_menu(menu);
wrefresh(swin);
bool done = false;
int indx = 0, c = 0;
while((c = wgetch(swin))){
switch(c){
case KEY_DOWN:
if (indx != (sz+1))
indx++;
menu_driver(menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
if (indx != 0)
indx--;
menu_driver(menu, REQ_UP_ITEM);
break;
case '\n':
done = true;
break;
}
wrefresh(swin);
if(done)
break;
}
free_menu(menu);
return indx;
}
bool add_startx(){
bool ret = false;
char* profile = ".bash_profile";
char* shellenv = getenv("SHELL");
if (NULL != shellenv && endswith(shellenv, "zsh"))
profile = ".zshrc";
char profile_file[PATH_MAX];
if(!joinhome(profile_file, profile)){
error(_("Failed to get the home directory"));
return ret;
}
FILE* pf = fopen(profile_file, "r");
if(NULL==pf){
error(_("Failed to open %s for reading"), profile_file);
return ret;
}
char* line = NULL, *all = NULL;
int indx = 0;
size_t sz, len;
while((sz = getline(&line, &len, pf)) != -1) {
if(strcmp(line, "#auto-startx \n")==0){
ret = true;
goto END;
}
if (NULL == all){
all = malloc(sz);
for(int i = 0; i < sz; i++){
all[indx] = line[i];
indx++;
}
}else {
all = realloc(all, indx+sz);
for(int i = 0; i < sz; i++){
all[indx] = line[i];
indx++;
}
}
}
char* startx = AUTOSTARTX;
all = realloc(all, indx+strlen(startx)+10);
for(int i = 0; i < strlen(startx); i++){
all[indx] = startx[i];
indx++;
}
fclose(pf);
pf = fopen(profile_file, "w");
if(NULL==pf){
error(_("Failed to open %s for writing"), profile_file);
goto END;
}
all[indx] = '\0';
if(fwrite(all, 1, indx, pf)<=0)
error(_("Failed to write to %s"), profile_file);
ret = true;
END:
free(all);
free(line);
fclose(pf);
return ret;
}
int main(int argc, char** argv, char** envp){
signal(SIGINT, SIG_IGN);
setlocale(LC_ALL, "");
textdomain("mp");
struct Desktop desktops[] = {
{
.name="XFCE4",
.desc="Lightweight desktop environment for UNIX-like operating systems",
.pkg="xfce4",
.cmd="startxfce4",
},
{
.name="bspwm",
.desc="Tiling window manager based on binary space partitioning",
.pkg="bspwm",
.cmd="bspwm"
}
};
char* mpi_path = check_path("mp-install");
if(NULL==mpi_path){
error(_("mp is not installed!"));
return EXIT_FAILURE;
}
free(mpi_path);
char* doas_path = check_path("doas");
if(NULL==doas_path) {
doas_path = check_path("sudo");
if(NULL==doas_path){
error(_("Install doas or sudo to use this script"));
free(mpi_path);
return EXIT_FAILURE;
}
}
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
init_pair(1, COLOR_BLUE, COLOR_BLUE);
int sz = sizeof(desktops)/sizeof(struct Desktop);
ITEM** items = (ITEM **)malloc(sizeof(ITEM *)*(sz+1));
for(int i = 0; i < sz; i++)
items[i] = new_item(desktops[i].name, desktops[i].desc);
int indx = ask(_("Choose a desktop enviroment"), items, sz);
for (int i = 0; i < sz; i++)
free_item(items[i]);
free(items);
clear();
char* yn[] = {_("Yes"), _("No")};
sz = sizeof(yn)/sizeof(char*);
items = (ITEM **)malloc(sizeof(ITEM *)*(sz+1));
for(int i = 0; i < sz; i++)
items[i] = new_item(yn[i], "");
bool autox = ask(_("Add auto-startx to shell configuration?"), items, sz) == 0;
for (int i = 0; i < sz; i++)
free_item(items[i]);
free(items);
clear();
clear();
endwin();
if(autox && !add_startx())
goto FAIL;
info(_("Installing %s"), desktops[indx].name, mpi_path);
char* args[] = {
doas_path, "mp-install", desktops[indx].pkg, NULL
};
pid_t pid;
if(posix_spawn(&pid, doas_path, NULL, NULL, args, envp) != 0) {
error(_("Installation failed"));
goto FAIL;
}
int status;
waitpid(pid, &status, 0);
if(status!=0){
error(_("Installation failed"));
goto FAIL;
}
char xinitrc[PATH_MAX];
if(!joinhome(xinitrc, ".xinitrc")){
error(_("Failed to get the home directory"));
goto FAIL;
}
FILE* xf = fopen(xinitrc, "w");
if(fwrite(xinitrc, 1, strlen(desktops[indx].cmd), xf)<0){
error(_("Failed to write to %s"), xinitrc);
fclose(xf);
goto FAIL;
}
success(_("Configuration has been saved!"));
fclose(xf);
free(doas_path);
return EXIT_SUCCESS;
FAIL:
free(doas_path);
return EXIT_FAILURE;
}