Compare commits

...

3 Commits

Author SHA1 Message Date
Sasha Koshka 45425c91d1 Decouple screenshot script from Xmd, Xmd session from Mwm 2024-01-17 11:30:25 -05:00
Sasha Koshka b341fbe6ca Separated session scripts from utility scripts 2024-01-17 11:12:05 -05:00
Sasha Koshka 51278b9d8f Read from /dev instead of lsblk 2023-12-12 02:12:50 -05:00
6 changed files with 126 additions and 131 deletions

View File

@ -49,6 +49,11 @@ in their respective subdirectories:
## Session
Xmd includes a startup script and assorted "glue code" to facilitate using it as
a desktop environment. It can be installed using `./install.sh` in the `session`
Xmd includes several scripts to facilitate using it as a desktop environment. It
can be installed using `./install.sh` in the `session` directory.
## Glue
Xmd includes some utility scripts to provide a standard interface for things
like screenshotting. These can be installed using `./install.sh` in the `glue`
directory.

3
glue/install.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
. ../scripts/flags.sh
cp src/* "$PREFIX/bin"

View File

@ -1,5 +1,7 @@
#!/bin/sh
export XMD_SESSION_PID="$$"
export XMD_USERDIR="${HOME}/.Xmd"
mkdir -p "${XMD_USERDIR}"
@ -26,4 +28,4 @@ else
echo "!!! cant find $startupDir"
fi
exec mwm
sleep infinity

8
session/src/xmd-end-session Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
if [ -z "$XMD_SESSION_PID" ]; then
echo "ERR session is not running (\$XMD_SESSION_PID not set)"
exit 1
fi
kill "$XMD_SESSION_PID"

View File

@ -12,6 +12,9 @@
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
@ -45,6 +48,7 @@ typedef enum {
typedef struct {
Widget widget;
DeviceKind kind;
Bool orphaned;
String name;
String mountPoint;
String label;
@ -52,6 +56,7 @@ typedef struct {
void loadIconPixmaps (void);
void refreshDevices (void);
void refreshDisks (void);
Device * DeviceNew (String name, DeviceKind kind);
void DeviceDelete (ConstString name);
void DeviceFree (Device *this);
@ -101,145 +106,116 @@ void loadIconPixmaps (void) {
dev(TTY, tty);
}
Bool markDevice (XmdStringMap *map, ConstString key, void *value, void *data) {
(void)(map);
(void)(key);
(void)(data);
Device *this = value;
this->orphaned = True;
return True;
}
Bool transferDevice (XmdStringMap *map, ConstString key, void *value, void *data) {
(void)(map);
(void)(key);
(void)(data);
Device *this = value;
if (this->orphaned) {
DeviceFree(this);
} else {
XmdStringMapSet(devices, key, value);
}
return True;
}
void refreshDevices (void) {
XtUnmanageChild(container);
pid_t child = 0;
FILE *stream = XmdVaPipedExecPath (
"lsblk", &child, "r",
"", "-P", "-o", "NAME,TYPE,MOUNTPOINTS,LABEL", NULL);
if (stream == NULL) {
/* TODO error */
return;
}
Device *device = NULL;
while (readBlockDevice(stream, &device) != EOF) {
/* do something with device? */
}
fclose(stream);
waitpid(child, NULL, 0);
/* pre-mark all devices as orphaned */
XmdStringMapIterate(devices, markDevice, NULL);
/* refresh devices by category */
refreshDisks();
/* create a new map, only moving over extant devices */
XmdStringMap *oldMap = devices;
devices = XmdStringMapNew();
XmdStringMapIterate(oldMap, transferDevice, NULL);
XmdStringMapFree(oldMap);
XtManageChild(container);
}
int readBlockDevice (FILE *stream, Device **device) {
DeviceKind kind = DeviceKindGeneric;
String name = NULL;
String mountPoint = NULL;
String label = NULL;
int ch = 0;
while (1) {
String key = NULL;
String value = NULL;
ch = readLsblkPair(stream, &key, &value);
if (strcmp(key, "NAME") == 0) {
XtFree(name);
name = value;
} else if (strcmp(key, "TYPE") == 0) {
if (strcmp(value, "disk") == 0) {
kind = DeviceKindDisk;
} else if (strcmp(value, "rom") == 0) {
kind = DeviceKindRom;
} else if (strcmp(value, "part") == 0) {
kind = DeviceKindFilesystem;
}
XtFree(value);
} else if (strcmp(key, "MOUNTPOINTS") == 0) {
XtFree(mountPoint);
mountPoint = value;
} else if (strcmp(key, "LABEL") == 0) {
XtFree(label);
label = value;
} else {
XtFree(value);
}
XtFree(key);
while ((ch = fgetc(stream)) == ' ');
if (ch == EOF || ch == '\n') break;
ungetc(ch, stream);
}
if (name != NULL) {
*device = XmdStringMapGet(devices, name);
if (*device == NULL) {
*device = DeviceNew(name, kind);
} else {
DeviceSetKind(*device, kind);
}
DeviceSetMountPoint(*device, mountPoint);
DeviceSetLabel(*device, label);
}
XtFree(name);
XtFree(mountPoint);
XtFree(label);
return ch;
String diskName (ConstString directory, ConstString name) {
char fullpath[PATH_MAX];
snprintf(fullpath, XtNumber(fullpath), "%s/%s", directory, name);
char resolved[PATH_MAX];
return XtNewString(basename(realpath(fullpath, resolved)));
}
int readLsblkPair (FILE *stream, String *key, String *value) {
int ch = 0;
int escapeCh = 0;
char null = 0;
void refreshDisks (void) {
/* get disks */
ConstString disksById = "/dev/disk/by-id";
ConstString disksByLabel = "/dev/disk/by-label";
ConstString disksByPartuuid = "/dev/disk/by-partuuid";
*key = NULL;
*value = NULL;
XmdBuffer *keyBuffer = XmdBufferNew(char);
while (isalpha(ch = fgetc(stream))) XmdBufferPush(keyBuffer, &ch);
XmdBufferPush(keyBuffer, &null);
*key = XmdBufferBreak(keyBuffer);
fgetc(stream); /* skip = */
XmdBuffer *valueBuffer = XmdBufferNew(char);
enum {
stateGetString,
stateGetEscape,
} state = stateGetString;
while (1) {
ch = fgetc(stream);
if (ch == EOF) goto end;
switch (state) {
case stateGetString:
switch (ch) {
case '"': goto end;
case '\\': state = stateGetEscape; break;
default: XmdBufferPush(valueBuffer, &ch); break;
}
break;
case stateGetEscape:
ch = fgetc(stream); /* skip x */
int digit = tolower(ch);
if (
(digit < '0' || digit > '9') &&
(digit < 'a' || digit > 'f')
) {
ungetc(ch, stream);
XmdBufferPush(valueBuffer, &escapeCh);
state = stateGetString;
break;
}
digit -= '0';
if (digit > 9) digit -= 'a' - '9' - 1;
escapeCh *= 16;
escapeCh += digit;
break;
struct dirent **entries = NULL;
int entriesCount = scandir(disksById, &entries, NULL, alphasort);
if (entriesCount < 0) {
/* TODO error message */
return;
}
for (int index = 0; index < entriesCount; index ++) {
struct dirent *entry = entries[index];
if (entry->d_name[0] == '.') {
XtFree((char *)(entry));
continue;
}
String deviceName = diskName(disksById, entry->d_name);
XtFree((char *)(entry));
Device *device = XmdStringMapGet(devices, deviceName);
if (device == NULL) {
device = DeviceNew(deviceName, DeviceKindDisk);
} else {
device->orphaned = False;
DeviceSetKind(device, DeviceKindDisk);
}
XtFree(deviceName);
}
end:
XmdBufferPush(valueBuffer, &null);
*value = XmdBufferBreak(valueBuffer);
if (strlen(*value) == 0) {
XtFree(*value);
*value = NULL;
XtFree((char *)(entries));
/* determine disk types */
DIR *dir = opendir(disksByPartuuid);
if (dir == NULL) {
/* TODO error message */
return;
}
return ch;
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] == '.') continue;
String deviceName = diskName(disksByPartuuid, entry->d_name);
Device *device = XmdStringMapGet(devices, deviceName);
if (device != NULL) DeviceSetKind(device, DeviceKindFilesystem);
XtFree(deviceName);
}
closedir(dir);
/* determine partition labels */
dir = opendir(disksByLabel);
if (dir == NULL) {
/* TODO error message */
return;
}
while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] == '.') continue;
String deviceName = diskName(disksByLabel, entry->d_name);
Device *device = XmdStringMapGet(devices, deviceName);
if (device != NULL) DeviceSetLabel(device, entry->d_name);
XtFree(deviceName);
}
closedir(dir);
}
Device *DeviceNew (String name, DeviceKind kind) {
@ -247,10 +223,11 @@ Device *DeviceNew (String name, DeviceKind kind) {
this->mountPoint = NULL;
this->label = NULL;
this->name = XtNewString(name);
this->orphaned = False;
XmString string = XmStringCreateLocalized(name);
this->widget = XtVaCreateManagedWidget (
"device", xmIconGadgetClass, container,
XmNalignment, XmALIGNMENT_CENTER,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNlabelString, string,
NULL);
XmStringFree(string);