@@ -0,0 +1,18 @@ | |||
DIRS := bin man | |||
INIT := $(notdir $(wildcard debian/*.init)) | |||
all: $(DIRS:%=all-%) | |||
all-%: | |||
$(MAKE) -C $* all | |||
clean: $(DIRS:%=clean-%) | |||
clean-%: | |||
$(MAKE) -C $* clean | |||
distclean: clean | |||
test: $(INIT:%=test-%) | |||
test-%: | |||
$(info checking $* ...) | |||
@dash -n debian/$* | |||
@checkbashisms -p debian/$* |
@@ -0,0 +1,33 @@ | |||
CFLAGS ?= -O2 -g -Wall | |||
LIBS_UDEV = $(shell pkg-config --libs libudev) | |||
LIBS_BLKID = $(shell pkg-config --libs blkid) | |||
ifdef USE_LIBPIPELINE | |||
LIBS_PIPELINE = $(shell pkg-config --libs libpipeline) | |||
CFLAGS += -DUSE_LIBPIPELINE | |||
endif | |||
PROGS = fll_fstab_generator fll_blockdev_detect | |||
all: $(PROGS) | |||
fll_fstab_cmdline.c: fll_fstab_generator.ggo | |||
gengetopt --input=$< --file-name=fll_fstab_cmdline \ | |||
--unamed-opts=DEVICES | |||
fll_fstab_cmdline.o: fll_fstab_cmdline.c | |||
$(CC) $(CFLAGS) -c -o $@ $< | |||
fll_fstab_generator: fll_fstab_cmdline.o | |||
$(CC) $(CFLAGS) $< -o $@ $@.c $(LIBS_UDEV) $(LIBS_BLKID) | |||
fll_blockdev_cmdline.c: fll_blockdev_detect.ggo | |||
gengetopt --input=$< --file-name=fll_blockdev_cmdline \ | |||
--unamed-opts=ARGS | |||
fll_blockdev_cmdline.o: fll_blockdev_cmdline.c | |||
$(CC) $(CFLAGS) -c -o $@ $< | |||
fll_blockdev_detect: fll_blockdev_cmdline.o | |||
$(CC) $(CFLAGS) $< -o $@ $@.c $(LIBS_UDEV) $(LIBS_PIPELINE) | |||
clean: | |||
$(RM) $(PROGS) *_cmdline.* |
@@ -0,0 +1,285 @@ | |||
/* | |||
* Copyright (C) 2010 Kel Modderman <kel@otaku42.de> | |||
* | |||
* 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 2 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, write to the Free Software Foundation, Inc., | |||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||
* | |||
*/ | |||
#ifndef _GNU_SOURCE | |||
#define _GNU_SOURCE 1 | |||
#endif | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <fcntl.h> | |||
#include <signal.h> | |||
#include <sys/select.h> | |||
#include <libudev.h> | |||
#ifdef USE_LIBPIPELINE | |||
#include <pipeline.h> | |||
#endif | |||
#include "fll_blockdev_cmdline.h" | |||
struct gengetopt_args_info opts; | |||
volatile sig_atomic_t timeout = 0; | |||
static void handle_timeout(int signum) | |||
{ | |||
timeout = 1; | |||
} | |||
static void setup_timeout_signal(unsigned int seconds) | |||
{ | |||
struct sigaction sa; | |||
sigemptyset(&sa.sa_mask); | |||
sa.sa_handler = handle_timeout; | |||
sigaction(SIGALRM, &sa, NULL); | |||
alarm(seconds); | |||
} | |||
static int device_removable(struct udev_device *device) | |||
{ | |||
struct udev_device *parent = device; | |||
const char *removable; | |||
do { | |||
removable = udev_device_get_sysattr_value(parent, | |||
"removable"); | |||
if (removable != NULL) | |||
return atoi(removable); | |||
parent = udev_device_get_parent_with_subsystem_devtype(parent, | |||
"block", | |||
"disk"); | |||
} while (parent != NULL); | |||
return 1; | |||
} | |||
static int print_device(struct udev_device *device) | |||
{ | |||
struct udev_list_entry *list_entry; | |||
struct udev_list_entry *first_list_entry; | |||
printf("--- %p ---\n", device); | |||
first_list_entry = udev_device_get_properties_list_entry(device); | |||
udev_list_entry_foreach(list_entry, first_list_entry) { | |||
printf("%s=\"%s\"\n", | |||
udev_list_entry_get_name(list_entry), | |||
udev_list_entry_get_value(list_entry)); | |||
} | |||
return 0; | |||
} | |||
#ifdef USE_LIBPIPELINE | |||
static int execp_device(struct udev_device *device) | |||
{ | |||
struct udev_list_entry *list_entry; | |||
struct udev_list_entry *first_list_entry; | |||
pipeline *pipe; | |||
pipecmd *cmd; | |||
int ret; | |||
pipe = pipeline_new(); | |||
cmd = pipecmd_new(opts.execp_arg); | |||
first_list_entry = udev_device_get_properties_list_entry(device); | |||
udev_list_entry_foreach(list_entry, first_list_entry) { | |||
pipecmd_setenv(cmd, udev_list_entry_get_name(list_entry), | |||
udev_list_entry_get_value(list_entry)); | |||
} | |||
pipeline_command(pipe, cmd); | |||
ret = pipeline_run(pipe); | |||
return !ret; | |||
} | |||
#else | |||
static int execp_device(struct udev_device *device) | |||
{ | |||
struct udev_list_entry *list_entry; | |||
struct udev_list_entry *first_list_entry; | |||
int ret; | |||
first_list_entry = udev_device_get_properties_list_entry(device); | |||
udev_list_entry_foreach(list_entry, first_list_entry) { | |||
setenv(udev_list_entry_get_name(list_entry), | |||
udev_list_entry_get_value(list_entry), 1); | |||
} | |||
ret = system(opts.execp_arg); | |||
udev_list_entry_foreach(list_entry, first_list_entry) { | |||
unsetenv(udev_list_entry_get_name(list_entry)); | |||
} | |||
return !ret; | |||
} | |||
#endif | |||
static int process_device(struct udev_device *device) | |||
{ | |||
if (opts.execp_given) | |||
return execp_device(device); | |||
else | |||
return print_device(device); | |||
} | |||
int main(int argc, char **argv) | |||
{ | |||
struct udev *udev; | |||
struct udev_monitor *udev_monitor; | |||
struct udev_enumerate *u_enum; | |||
struct udev_list_entry *u_list_ent; | |||
struct udev_list_entry *u_first_list_ent; | |||
fd_set readfds; | |||
int fd; | |||
int ret = 0; | |||
if (cmdline_parser(argc, argv, &opts) != 0) | |||
return 1; | |||
udev = udev_new(); | |||
if (udev == NULL) { | |||
fprintf(stderr, "Error: udev_new()\n"); | |||
cmdline_parser_free(&opts); | |||
return 1; | |||
} | |||
/* enumerate existing block devices */ | |||
u_enum = udev_enumerate_new(udev); | |||
if (u_enum == NULL) { | |||
fprintf(stderr, "Error: udev_enumerate_new(udev)\n"); | |||
cmdline_parser_free(&opts); | |||
udev_unref(udev); | |||
return 1; | |||
} | |||
udev_enumerate_add_match_subsystem(u_enum, "block"); | |||
udev_enumerate_add_match_property(u_enum, "DEVTYPE", "disk"); | |||
udev_enumerate_add_match_property(u_enum, "DEVTYPE", "partition"); | |||
udev_enumerate_scan_devices(u_enum); | |||
u_first_list_ent = udev_enumerate_get_list_entry(u_enum); | |||
udev_list_entry_foreach(u_list_ent, u_first_list_ent) { | |||
struct udev_device *device; | |||
struct udev *context; | |||
const char *name; | |||
context = udev_enumerate_get_udev(u_enum); | |||
name = udev_list_entry_get_name(u_list_ent); | |||
device = udev_device_new_from_syspath(context, name); | |||
if (device == NULL) | |||
continue; | |||
if (opts.removable_flag && !device_removable(device)) { | |||
udev_device_unref(device); | |||
continue; | |||
} | |||
ret = process_device(device); | |||
udev_device_unref(device); | |||
if (ret) | |||
break; | |||
} | |||
udev_enumerate_unref(u_enum); | |||
if (ret || !opts.monitor_flag) { | |||
cmdline_parser_free(&opts); | |||
udev_unref(udev); | |||
return !ret; | |||
} | |||
/* set an alarm to interupt the monitor loop */ | |||
setup_timeout_signal(opts.timeout_arg); | |||
/* monitor add|change of block devices until timeout period expires */ | |||
udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); | |||
if (udev_monitor == NULL) { | |||
fprintf(stderr, "Error: udev_monitor_new_from_netlink()\n"); | |||
cmdline_parser_free(&opts); | |||
udev_unref(udev); | |||
return 1; | |||
} | |||
if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, | |||
"block", | |||
"disk") < 0 || | |||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, | |||
"block", | |||
"partition") < 0) { | |||
fprintf(stderr, "Error: udev_monitor_filter_add_match_subsystem_devtype()\n"); | |||
cmdline_parser_free(&opts); | |||
udev_unref(udev); | |||
return 1; | |||
} | |||
if (udev_monitor_enable_receiving(udev_monitor) < 0) { | |||
fprintf(stderr, "Error: udev_monitor_enable_receiving()\n"); | |||
cmdline_parser_free(&opts); | |||
udev_unref(udev); | |||
return 1; | |||
} | |||
fd = udev_monitor_get_fd(udev_monitor); | |||
while (!timeout) { | |||
struct udev_device *device; | |||
const char *action; | |||
FD_ZERO(&readfds); | |||
FD_SET(fd, &readfds); | |||
if (select(fd + 1, &readfds, NULL, NULL, NULL) == -1) { | |||
if (errno != EINTR) | |||
fprintf(stderr, "Error: select(): %s\n", | |||
strerror(errno)); | |||
break; | |||
} | |||
if (FD_ISSET(fd, &readfds)) { | |||
device = udev_monitor_receive_device(udev_monitor); | |||
if (device == NULL) | |||
continue; | |||
action = udev_device_get_action(device); | |||
if (strcmp(action, "add") != 0 && | |||
strcmp(action, "change") != 0) { | |||
udev_device_unref(device); | |||
continue; | |||
} | |||
if (opts.removable_flag && !device_removable(device)) { | |||
udev_device_unref(device); | |||
continue; | |||
} | |||
ret = process_device(device); | |||
udev_device_unref(device); | |||
if (ret) | |||
break; | |||
} | |||
} | |||
udev_monitor_unref(udev_monitor); | |||
cmdline_parser_free(&opts); | |||
udev_unref(udev); | |||
return !ret; | |||
} |
@@ -0,0 +1,21 @@ | |||
package "fll_blockdev_detect" | |||
version "1.0" | |||
option "execp" e | |||
"execute this script for every block device detected" | |||
typestr="PROG" | |||
string optional | |||
option "monitor" m | |||
"monitor for block device add|change events" | |||
flag off | |||
option "removable" r | |||
"detect removable block devices" | |||
flag off | |||
option "timeout" t | |||
"time in seconds to monitor for add|change events" | |||
typestr="SECONDS" | |||
int optional | |||
default="30" |
@@ -0,0 +1,666 @@ | |||
/* | |||
* Copyright (C) 2010 Kel Modderman <kel@otaku42.de> | |||
* | |||
* 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 2 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, write to the Free Software Foundation, Inc., | |||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||
* | |||
*/ | |||
#ifndef _GNU_SOURCE | |||
#define _GNU_SOURCE 1 | |||
#endif | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <getopt.h> | |||
#include <fcntl.h> | |||
#include <mntent.h> | |||
#include <sys/ioctl.h> | |||
#include <sys/mount.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <sys/swap.h> | |||
#include <unistd.h> | |||
#include <libudev.h> | |||
#include <blkid/blkid.h> | |||
#include "fll_fstab_cmdline.h" | |||
struct gengetopt_args_info opts; | |||
FILE *fstab; | |||
int mounted; | |||
static int linux_filesystem(const char *fstype) | |||
{ | |||
if (strcmp(fstype, "swap") == 0) | |||
return 1; | |||
if (strcmp(fstype, "ext4") == 0) | |||
return 1; | |||
if (strcmp(fstype, "ext3") == 0) | |||
return 1; | |||
if (strcmp(fstype, "ext2") == 0) | |||
return 1; | |||
if (strcmp(fstype, "xfs") == 0) | |||
return 1; | |||
if (strcmp(fstype, "jfs") == 0) | |||
return 1; | |||
if (strcmp(fstype, "reiserfs") == 0) | |||
return 1; | |||
if (strcmp(fstype, "reiser4") == 0) | |||
return 1; | |||
if (strcmp(fstype, "btrfs") == 0) | |||
return 1; | |||
return 0; | |||
} | |||
static int device_flagged(struct udev_device *device, unsigned int flagged, | |||
char **a) | |||
{ | |||
struct udev_device *parent = device; | |||
struct udev_list_entry *u_list_ent; | |||
struct udev_list_entry *u_first_list_ent; | |||
const char *devnode; | |||
int i; | |||
if (!flagged) | |||
return 0; | |||
do { | |||
devnode = udev_device_get_devnode(parent); | |||
if (devnode == NULL) | |||
break; | |||
for (i = 0; i < flagged; ++i) { | |||
if (strcmp(devnode, a[i]) == 0) | |||
return 1; | |||
else if (strcmp(basename(devnode), a[i]) == 0) | |||
return 1; | |||
} | |||
u_first_list_ent = udev_device_get_devlinks_list_entry(parent); | |||
udev_list_entry_foreach(u_list_ent, u_first_list_ent) { | |||
devnode = udev_list_entry_get_name(u_list_ent); | |||
for (i = 0; i < flagged; ++i) { | |||
if (strcmp(devnode, a[i]) == 0) | |||
return 1; | |||
else if (strcmp(basename(devnode), a[i]) == 0) | |||
return 1; | |||
} | |||
} | |||
parent = udev_device_get_parent_with_subsystem_devtype(parent, | |||
"block", | |||
"disk"); | |||
} while (parent != NULL); | |||
return 0; | |||
} | |||
static int device_removable(struct udev_device *device) | |||
{ | |||
struct udev_device *parent = device; | |||
const char *removable; | |||
if (opts.removable_flag) | |||
return 0; | |||
do { | |||
removable = udev_device_get_sysattr_value(parent, | |||
"removable"); | |||
if (removable != NULL) | |||
return atoi(removable); | |||
parent = udev_device_get_parent_with_subsystem_devtype(parent, | |||
"block", | |||
"disk"); | |||
} while (parent != NULL); | |||
return 1; | |||
} | |||
static int device_devtype_disk(struct udev_device *device) | |||
{ | |||
const char *devtype; | |||
devtype = udev_device_get_devtype(device); | |||
if (devtype != NULL) | |||
return strcmp(devtype, "disk") == 0; | |||
return 0; | |||
} | |||
static int device_devmapper(struct udev_device *device) | |||
{ | |||
const char *devnode; | |||
devnode = udev_device_get_devnode(device); | |||
if (devnode != NULL) | |||
return strncmp(devnode, "/dev/mapper/", | |||
strlen("/dev/mapper/")) == 0; | |||
else | |||
return 0; | |||
} | |||
static char* device_vfstype(struct udev_device *device) | |||
{ | |||
const char *fstype; | |||
char *value; | |||
blkid_probe pr; | |||
uint64_t size; | |||
int fd; | |||
size_t len; | |||
int res; | |||
value = NULL; | |||
if (opts.blkid_flag) { | |||
fd = open(udev_device_get_devnode(device), O_RDONLY); | |||
if (fd < 0) | |||
return NULL; | |||
pr = blkid_new_probe(); | |||
if (pr == NULL) { | |||
fprintf(stderr, "Error: blkid_new_probe()\n"); | |||
close(fd); | |||
return NULL; | |||
} | |||
blkid_probe_set_request(pr, BLKID_PROBREQ_TYPE); | |||
if (ioctl(fd, BLKGETSIZE64, &size) != 0) | |||
size = 0; | |||
if (blkid_probe_set_device(pr, fd, 0, size) != 0 || | |||
blkid_do_safeprobe(pr) != 0 || | |||
blkid_probe_lookup_value(pr, "TYPE", &fstype, NULL) != 0) { | |||
blkid_free_probe(pr); | |||
close(fd); | |||
return NULL; | |||
} | |||
len = strlen(fstype) + 1; | |||
value = malloc(len); | |||
if (value == NULL) { | |||
blkid_free_probe(pr); | |||
close(fd); | |||
return NULL; | |||
} | |||
res = snprintf(value, len, "%s", fstype); | |||
if (res < 0 || (size_t) res >= len) { | |||
blkid_free_probe(pr); | |||
close(fd); | |||
return NULL; | |||
} | |||
else | |||
value[len - 1] = '\0'; | |||
blkid_free_probe(pr); | |||
close(fd); | |||
} | |||
else { | |||
fstype = udev_device_get_property_value(device, "ID_FS_TYPE"); | |||
if (fstype == NULL) | |||
return NULL; | |||
len = strlen(fstype) + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "%s", fstype); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
return value; | |||
} | |||
static char* device_spec(struct udev_device *device, char *fstype, int disk) | |||
{ | |||
struct udev_list_entry *u_list_ent; | |||
struct udev_list_entry *u_first_list_ent; | |||
const char *devnode; | |||
char *value; | |||
size_t len; | |||
int res; | |||
value = NULL; | |||
u_first_list_ent = udev_device_get_devlinks_list_entry(device); | |||
if (disk && (opts.labels_flag || opts.uuids_flag)) { | |||
udev_list_entry_foreach(u_list_ent, u_first_list_ent) { | |||
devnode = udev_list_entry_get_name(u_list_ent); | |||
if (opts.labels_flag && | |||
strncmp(devnode, "/dev/disk/by-label", | |||
strlen("/dev/disk/by-label")) == 0) { | |||
if (value != NULL) | |||
free(value); | |||
len = strlen("LABEL=") + 1; | |||
len += strlen(basename(devnode)); | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "LABEL=%s", | |||
basename(devnode)); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
if (opts.uuids_flag && | |||
strncmp(devnode, "/dev/disk/by-uuid", | |||
strlen("/dev/disk/by-uuid")) == 0) { | |||
if (value != NULL) | |||
free(value); | |||
len = strlen("UUID=") + 1; | |||
len += strlen(basename(devnode)); | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "UUID=%s", | |||
basename(devnode)); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
} | |||
} | |||
if (!disk || value == NULL) { | |||
devnode = udev_device_get_devnode(device); | |||
if (devnode == NULL) | |||
return NULL; | |||
len = strlen(devnode) + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "%s", devnode); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
return value; | |||
} | |||
static char* device_file(struct udev_device *device, int disk) | |||
{ | |||
struct udev_list_entry *u_list_ent; | |||
struct udev_list_entry *u_first_list_ent; | |||
FILE *fp; | |||
struct mntent *mnt; | |||
const char *devnode; | |||
const char *fstype; | |||
const char *partition; | |||
char *value; | |||
size_t len; | |||
int res; | |||
value = NULL; | |||
u_first_list_ent = udev_device_get_devlinks_list_entry(device); | |||
if (!opts.nomounts_flag) { | |||
fstype = udev_device_get_property_value(device, "ID_FS_TYPE"); | |||
fp = setmntent("/proc/mounts", "r"); | |||
for (;;) { | |||
if (fp == NULL || fstype == NULL) | |||
break; | |||
mnt = getmntent(fp); | |||
if (mnt == NULL) | |||
break; | |||
if (strcmp(fstype, mnt->mnt_type) != 0) | |||
continue; | |||
if (strcmp(udev_device_get_devnode(device), | |||
mnt->mnt_fsname) == 0) { | |||
len = strlen(mnt->mnt_dir) + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "%s", mnt->mnt_dir); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
mounted = 1; | |||
break; | |||
} | |||
udev_list_entry_foreach(u_list_ent, u_first_list_ent) { | |||
devnode = udev_list_entry_get_name(u_list_ent); | |||
if (strcmp(devnode, mnt->mnt_fsname) != 0) | |||
continue; | |||
len = strlen(mnt->mnt_dir) + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "%s", mnt->mnt_dir); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
mounted = 1; | |||
break; | |||
} | |||
} | |||
if (fp != NULL) | |||
endmntent(fp); | |||
} | |||
if (value == NULL) { | |||
if (!disk) { | |||
devnode = udev_device_get_devnode(device); | |||
len = strlen("/media/"); | |||
len += strlen(basename(devnode)) + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "/media/%s", | |||
basename(devnode)); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
else { | |||
partition = udev_device_get_sysattr_value(device, | |||
"partition"); | |||
if (partition != NULL) { | |||
len = strlen("/media/disk"); | |||
if (disk < 10) | |||
len += 1; | |||
else if (disk < 100) | |||
len += 2; | |||
else | |||
len += 3; | |||
len += strlen("part") + strlen(partition) + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, | |||
"/media/disk%dpart%s", | |||
disk, partition); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
else { | |||
len = strlen("/media/disk"); | |||
if (disk < 10) | |||
len += 1; | |||
else if (disk < 100) | |||
len += 2; | |||
else | |||
len += 3; | |||
len += 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "/media/disk%d", | |||
disk); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
} | |||
} | |||
return value; | |||
} | |||
static char* device_mntops(struct udev_device *device, char *fstype, char *dir) | |||
{ | |||
const char *str; | |||
char *value; | |||
size_t len; | |||
int res; | |||
value = NULL; | |||
if (mounted && linux_filesystem(fstype)) { | |||
if ((strcmp(fstype, "ext4") == 0) || | |||
(strcmp(fstype, "ext3") == 0) || | |||
(strcmp(fstype, "ext2") == 0)) | |||
str = "defaults,relatime,errors=remount-ro"; | |||
else | |||
str = "defaults,relatime"; | |||
len = strlen(str) + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "%s", str); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
else { | |||
if (linux_filesystem(fstype)) | |||
str = "users,rw,exec,relatime"; | |||
else if (strcmp(fstype, "ntfs") == 0) | |||
str = "users,ro,dmask=0022,fmask=0133,nls=utf8"; | |||
else if (strcmp(fstype, "msdos") == 0) | |||
str = "users,rw,quiet,umask=000,iocharset=utf8"; | |||
else if (strcmp(fstype, "vfat") == 0) | |||
str = "users,rw,quiet,umask=000,shortname=lower"; | |||
else if (strcmp(fstype, "hfsplus") == 0) | |||
str = "users,ro,exec"; | |||
else | |||
return NULL; | |||
len = strlen(str) + 1; | |||
if (opts.auto_flag) | |||
len += strlen("auto") + 1; | |||
else | |||
len += strlen("noauto") + 1; | |||
value = malloc(len); | |||
if (value == NULL) | |||
return NULL; | |||
res = snprintf(value, len, "%s,%s", | |||
opts.auto_flag ? "auto" : "noauto", str); | |||
if (res < 0 || (size_t) res >= len) | |||
return NULL; | |||
else | |||
value[len - 1] = '\0'; | |||
} | |||
return value; | |||
} | |||
static void print_mntent(const char *fs_spec, const char *fs_file, | |||
const char *fs_vfstype, const char *fs_mntops, | |||
int fs_freq, int fs_passno) | |||
{ | |||
fprintf(fstab, "%s %s %s %s %d %d\n", fs_spec, fs_file, fs_vfstype, | |||
fs_mntops, fs_freq, fs_passno); | |||
} | |||
static void process_disk(struct udev_device *device, int disk) | |||
{ | |||
char *fs_spec = NULL; | |||
char *fs_file = NULL; | |||
char *fs_vfstype = NULL; | |||
char *fs_mntops = NULL; | |||
int fs_pass = 0; | |||
mounted = 0; | |||
fs_vfstype = device_vfstype(device); | |||
if (fs_vfstype == NULL) | |||
goto end_process_disk; | |||
fs_spec = device_spec(device, fs_vfstype, disk); | |||
if (fs_spec == NULL) | |||
goto end_process_disk; | |||
if (strcmp(fs_vfstype, "swap") == 0) { | |||
if (opts.noswap_flag) | |||
goto end_process_disk; | |||
print_mntent(fs_spec, "none", fs_vfstype, "sw", 0, 0); | |||
if (opts.swapon_flag && | |||
swapon(udev_device_get_devnode(device), 0) == -1) { | |||
if (errno != EBUSY) | |||
fprintf(stderr, "Error: swapon(%s): %s\n", | |||
udev_device_get_devnode(device), | |||
strerror(errno)); | |||
} | |||
goto end_process_disk; | |||
} | |||
fs_file = device_file(device, disk); | |||
if (fs_file == NULL) | |||
goto end_process_disk; | |||
fs_mntops = device_mntops(device, fs_vfstype, fs_file); | |||
if (fs_mntops == NULL) | |||
goto end_process_disk; | |||
if (mounted) { | |||
if (strcmp(fs_file, "/") == 0) | |||
fs_pass = 1; | |||
else if (linux_filesystem(fs_vfstype)) | |||
fs_pass = 2; | |||
} | |||
if (opts.mkdir_flag && | |||
mkdir(fs_file, S_IRWXU | S_IRWXG | S_IRWXO) == -1) { | |||
if (errno != EEXIST) { | |||
fprintf(stderr, "Error: mkdir(%s): %s\n", fs_file, | |||
strerror(errno)); | |||
goto end_process_disk; | |||
} | |||
} | |||
print_mntent(fs_spec, fs_file, fs_vfstype, fs_mntops, 0, fs_pass); | |||
end_process_disk: | |||
if (fs_spec != NULL) | |||
free(fs_spec); | |||
if (fs_vfstype != NULL) | |||
free(fs_vfstype); | |||
if (fs_file != NULL) | |||
free(fs_file); | |||
if (fs_mntops != NULL) | |||
free(fs_mntops); | |||
} | |||
int main(int argc, char **argv) | |||
{ | |||
struct udev *udev; | |||
struct udev_enumerate *u_enum; | |||
struct udev_list_entry *u_list_ent; | |||
struct udev_list_entry *u_first_list_ent; | |||
int disk = 0; | |||
if (cmdline_parser(argc, argv, &opts) != 0) { | |||
fprintf(stderr, "Error: cmdline_parser(argc, argv, &opts)\n"); | |||
return 1; | |||
} | |||
if (opts.file_given) { | |||
fstab = fopen(opts.file_arg, "w"); | |||
if (fstab == NULL) { | |||
fprintf(stderr, "Error: fpopen(%s): %s\n", | |||
opts.file_arg, strerror(errno)); | |||
cmdline_parser_free(&opts); | |||
return 1; | |||
} | |||
} | |||
else | |||
fstab = stdout; | |||
udev = udev_new(); | |||
if (udev == NULL) { | |||
fprintf(stderr, "Error: udev_new()\n"); | |||
cmdline_parser_free(&opts); | |||
fclose(fstab); | |||
return 1; | |||
} | |||
u_enum = udev_enumerate_new(udev); | |||
if (u_enum == NULL) { | |||
fprintf(stderr, "Error: udev_enumerate_new(udev)\n"); | |||
cmdline_parser_free(&opts); | |||
fclose(fstab); | |||
udev_unref(udev); | |||
return 1; | |||
} | |||
udev_enumerate_add_match_subsystem(u_enum, "block"); | |||
udev_enumerate_add_match_property(u_enum, "DEVTYPE", "disk"); | |||
udev_enumerate_add_match_property(u_enum, "DEVTYPE", "partition"); | |||
udev_enumerate_scan_devices(u_enum); | |||
u_first_list_ent = udev_enumerate_get_list_entry(u_enum); | |||
udev_list_entry_foreach(u_list_ent, u_first_list_ent) { | |||
struct udev_device *device; | |||
struct udev *context; | |||
const char *name; | |||
context = udev_enumerate_get_udev(u_enum); | |||
name = udev_list_entry_get_name(u_list_ent); | |||
device = udev_device_new_from_syspath(context, name); | |||
if (device == NULL) | |||
continue; | |||
if (device_flagged(device, opts.ignore_given, | |||
opts.ignore_arg)) { | |||
udev_device_unref(device); | |||
continue; | |||
} | |||
else if (opts.inputs_num) { | |||
if (device_removable(device) || | |||
!device_flagged(device, opts.inputs_num, | |||
opts.inputs)) { | |||
udev_device_unref(device); | |||
continue; | |||
} | |||
} | |||
else if (device_removable(device)) { | |||
if (!device_flagged(device, opts.wanted_given, | |||
opts.wanted_arg)) { | |||
udev_device_unref(device); | |||
continue; | |||
} | |||
} | |||
if (device_devtype_disk(device)) | |||
disk++; | |||
if (device_devmapper(device)) | |||
process_disk(device, 0); | |||
else | |||
process_disk(device, disk); | |||
udev_device_unref(device); | |||
} | |||
udev_enumerate_unref(u_enum); | |||
udev_unref(udev); | |||
fclose(fstab); | |||
cmdline_parser_free(&opts); | |||
return 0; | |||
} |
@@ -0,0 +1,42 @@ | |||
package "fll_fstab_generator" | |||
version "1.0" | |||
option "auto" a | |||
"add \"auto\" to default mount options" | |||
flag off | |||
option "blkid" b | |||
"use blkid to query filesystem information" | |||
flag off | |||
option "file" f | |||
"write output to file" | |||
typestr="FILE" | |||
string optional | |||
option "ignore" i | |||
"ignore device(s) (may be specified multiple times)" | |||
typestr="DEVICE" | |||
string optional multiple | |||
option "labels" l | |||
"use volume labels to represent device" | |||
flag off | |||
option "mkdir" m | |||
"create mount point directories" | |||
flag off | |||
option "nomounts" n | |||
"do not attempt to detect existing mountpoints" | |||
flag off | |||
option "removable" r | |||
"include entries for removable devices" | |||
flag off | |||
option "noswap" N | |||
"do not include entries for swap devices" | |||
flag off | |||
option "swapon" s | |||
"activate detected swap partitions" | |||
flag off | |||
option "uuids" u | |||
"use UUIDs to represent device" | |||
flag off | |||
option "wanted" w | |||
"include removable device (may be specified multiple times)" | |||
typestr="DEVICE" | |||
string optional multiple |
@@ -0,0 +1,35 @@ | |||
#!/bin/sh | |||
[ -s /etc/default/distro ] && . /etc/default/distro | |||
case "${lang}" in | |||
cs_*) p="Stisknฤte prosรญm Enter pro aktivaci tรฉto konzole." ;; | |||
da_*) p="For at aktivere denne konsol, tast venligst retur." ;; | |||
de_*) p="Bitte drรผcken Sie die Eingabetaste, um diese Konsole zu aktivieren." ;; | |||
es_*) p="Por favor, pulse Intro para activar esta consola." ;; | |||
it_*) p="Premere Invio per attivare questo terminale." ;; | |||
ja_*) p="ใใฎใณใณใฝใผใซใใขใฏใใฃใใซใใใใEnterใๆผใใฆใใ ใใ" ;; | |||
nl_*) p="Druk op Enter om deze console te activeren." ;; | |||
pl_*) p="Naciลnij Enter aby aktywowaฤ tฤ konsolฤ." ;; | |||
pt_*) p="Por favor, pressione a tecla Enter para activar esta consola." ;; | |||
ro_*) p="Vฤ rog, apฤsศi tasta Enter pentru a activa aceastฤ consolฤ." ;; | |||
ru_*) p="ะะฐะถะผะธัะต Enter, ััะพะฑั ะฐะบัะธะฒะธัะพะฒะฐัั ััั ะบะพะฝัะพะปั." ;; | |||
*) p="Please press Enter to activate this console." ;; | |||
esac | |||
# Let user know this shell is no longer activatable when fll_login exits | |||
trap "echo ; echo ${0##*/} Terminated ; exit" TERM | |||
read -p "${p} " nothing | |||
if getent passwd "${FLL_LIVE_USER}" >/dev/null 2>&1; then | |||
FLL_LIVE_USER_HOME=$(getent passwd ${FLL_LIVE_USER} | cut -d\: -f 6) | |||
if [ ! -e "${FLL_LIVE_USER_HOME}/.hushlogin" ]; then | |||
:> "${FLL_LIVE_USER_HOME}/.hushlogin" | |||
chown "${FLL_LIVE_USER}:${FLL_LIVE_USER}" \ | |||
"${FLL_LIVE_USER_HOME}/.hushlogin" | |||
fi | |||
exec /bin/login -f "${FLL_LIVE_USER}" | |||
else | |||
exec /bin/login -f root | |||
fi |
@@ -0,0 +1,380 @@ | |||
#!/usr/bin/perl | |||
# | |||
# Copyright (C) 2007 - 2008 Kel Modderman <kel@otaku42.de> | |||
# | |||
# 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 2 | |||
# 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 package; if not, write to the Free Software | |||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |||
# MA 02110-1301, USA. | |||
# | |||
# On Debian GNU/Linux systems, the text of the GPL license can be | |||
# found in /usr/share/common-licenses/GPL. | |||
# Much information can be taken from: | |||
# http://wiki.debian.org/XStrikeForce/XSFTODO | |||
use warnings; | |||
use strict; | |||
use autouse 'Data::Dumper' => qw(Dumper); | |||
use File::Find; | |||
use FindBin qw($Bin); | |||
use Getopt::Long; | |||
use Tie::File; | |||
use Switch 'Perl6'; | |||
########################################################### | |||
# global vars | |||
my $verbosity = 0; | |||
my $xorg_conf = '/etc/X11/xorg.conf'; | |||
my $xorg_tmpl = "$Bin/../share/fll-live-xorgconfig/templates"; | |||
# used for counting line numbers | |||
my $n; | |||
# the array to be tied to xorg.conf | |||
my @x; | |||
# the x config structure, provide defaults here. overridden by GetOptions down below | |||
my %x = ( | |||
# global variable refs | |||
'output' => \$xorg_conf, | |||
'templates' => \$xorg_tmpl, | |||
'verbose' => \$verbosity, | |||
# screen | |||
'colordepth' => '24', | |||
# monitor | |||
'modes' => '1024x768 800x600 640x480', | |||
'modelines' => 1, | |||
'modelname' => 'Default Monitor', | |||
'horizsync' => '28-96', | |||
'vertrefresh' => '50-75', | |||
# extensions | |||
'composite' => 0, | |||
); | |||
########################################################### | |||
# internal functions | |||
# debugging function | |||
sub dbg { | |||
return unless $verbosity; | |||
# dump references, print everything else | |||
for (@_) { | |||
next unless defined; | |||
if (ref) { | |||
print STDERR Dumper($_); | |||
} | |||
else { | |||
print STDERR "$_\n"; | |||
} | |||
} | |||
} | |||
sub gtf_modelines { | |||
my @ml; | |||
# if no args are given to function, return a Modeline for each | |||
# element of our mode/frequency library | |||
my @f = @_ == 3 ? [ @_ ] : ( | |||
[ 640, 350, 85 ], [ 640, 400, 85 ], [ 640, 480, 60 ], | |||
[ 640, 480, 72 ], [ 640, 480, 75 ], [ 640, 480, 85 ], | |||
[ 640, 480, 100 ], [ 720, 400, 85 ], [ 768, 576, 60 ], | |||
[ 768, 576, 72 ], [ 768, 576, 75 ], [ 768, 576, 85 ], | |||
[ 768, 576, 100 ], [ 800, 600, 56 ], [ 800, 600, 60 ], | |||
[ 800, 600, 72 ], [ 800, 600, 75 ], [ 800, 600, 85 ], | |||
[ 800, 600, 100 ], [ 1024, 600, 60 ], [ 1024, 768, 60 ], | |||
[ 1024, 768, 70 ], [ 1024, 768, 75 ], [ 1024, 768, 85 ], | |||
[ 1024, 768, 100 ], [ 1152, 864, 75 ], [ 1152, 864, 60 ], | |||
[ 1152, 864, 85 ], [ 1152, 864, 100 ], [ 1152, 900, 77 ], | |||
[ 1152, 900, 66 ], [ 1280, 768, 60 ], [ 1280, 800, 60 ], | |||
[ 1280, 960, 60 ], [ 1280, 960, 72 ], [ 1280, 960, 75 ], | |||
[ 1280, 960, 85 ], [ 1280, 960, 100 ], [ 1280, 1024, 60 ], | |||
[ 1280, 1024, 67 ], [ 1280, 1024, 75 ], [ 1280, 1024, 76 ], | |||
[ 1280, 1024, 85 ], [ 1280, 1024, 100 ], [ 1368, 768, 60 ], | |||
[ 1440, 900, 60 ], [ 1400, 1050, 60 ], [ 1400, 1050, 72 ], | |||
[ 1400, 1050, 75 ], [ 1400, 1050, 85 ], [ 1400, 1050, 100 ], | |||
[ 1440, 900, 60 ], [ 1600, 1200, 60 ], [ 1600, 1200, 65 ], | |||
[ 1600, 1200, 70 ], [ 1600, 1200, 75 ], [ 1600, 1200, 85 ], | |||
[ 1600, 1200, 100 ], [ 1680, 1050, 60 ], [ 1792, 1344, 60 ], | |||
[ 1792, 1344, 75 ], [ 1856, 1392, 60 ], [ 1856, 1392, 75 ], | |||
[ 1920, 1200, 60 ], [ 1920, 1440, 60 ], [ 1920, 1440, 75 ], | |||
); | |||
for (@f) { | |||
open(my $fh, '-|', '/usr/bin/gtf', @{ $_ }) | |||
or die "cannot compute modeline with gtf: $!\n"; | |||
while (<$fh>) { | |||
chomp; | |||
next unless /^\s+(#|Modeline)/; | |||
s/^\s+/\t/; | |||
# strip the frequency marker for legacy Modeline entries | |||
# keep the marker for PrefferredMode entry (xrandr1.2) | |||
s/Modeline "(\d+x\d+)_[\d\.]+"/Modeline "$1"/ unless $x{'xrandr'}; | |||
push(@ml, $_); | |||
} | |||
close($fh); | |||
} | |||
return @ml; | |||
} | |||
sub get_template { | |||
my $file = shift; | |||
my @template; | |||
dbg "looking for template: $file"; | |||
find( | |||
sub { | |||
return if $File::Find::name =~ m|/\.svn/|; | |||
return unless -T $File::Find::name; | |||
if ($_ eq $file) { | |||
dbg "reading template: $file"; | |||
open(my $fh, '<', $File::Find::name) | |||
or die "cannot open template for reading: $!\n"; | |||
@template = <$fh>; | |||
close($fh); | |||
} | |||
}, | |||
$xorg_tmpl | |||
); | |||
chomp(@template); | |||
return @template; | |||
} | |||
# I have observed the Xserver using 1680x1200 when Modes | |||
# looked like: | |||
# Modes "1680x1050" "1600x1200" "1400x1050" ... | |||
# | |||
# Take the preferred resolution (first, or left most) as | |||
# returned by xresprobe and calculate its X and Y axes. | |||
# | |||
# Remove any mode in the remaining list with X or Y values | |||
# greater than that of the preferred resolution. | |||
# | |||
# given: | |||
# "1680x1050 1600x1200 1400x1050 1280x1024 ..." | |||
# return: | |||
# "1680x1050 1400x1050 1280x1024 ..." | |||
# | |||
sub sanitize_modes { | |||
my @modes = split(/\s+/, shift); | |||
my ($x_max, $y_max) = split(/x/, $modes[0]); | |||
dbg "MAX $x_max, $y_max"; | |||
for my $count (1..$#{modes}) { | |||
last unless $modes[$count]; | |||
my ($x_now, $y_now) = split(/x/, $modes[$count]); | |||
dbg "NOW $x_now, $y_now"; | |||
if ($x_now > $x_max or $y_now > $y_max) { | |||
dbg "REM $modes[$count]"; | |||
splice(@modes, $count, 1); | |||
redo; | |||
} | |||
} | |||
return "@modes"; | |||
} | |||
########################################################### | |||
# process cli args | |||
GetOptions( | |||
\%x, | |||
# mkxorgconfig control | |||
'output=s', | |||
'templates=s', | |||
'verbose|debug', | |||
# device | |||
'boardname=s', | |||
'busid=s', | |||
'driver=s', | |||
# monitor | |||
'colordepth=i', | |||
'modelname=s', | |||
'modelines!', | |||
'modes=s', | |||
'horizsync=s', | |||
'vertrefresh=s', | |||
# xrandr | |||
'xrandr', | |||
'mode=s', | |||
'rate=s', | |||
'virtual=s', | |||
# extensions | |||
'composite', | |||
); | |||
dbg \%x; | |||
# sanitize/postprocess input | |||
for my $key (keys %x) { | |||
my $invalid; | |||
given ($key) { | |||
when 'colordepth' { | |||
$x{$key} =~ /^(8|15|16|24)$/ or $invalid = $key; | |||
} | |||
when 'composite' { | |||
$x{$key} = $x{$key} ? 'on' : 'off'; | |||
} | |||
when 'mode' { | |||
$x{$key} =~ /^\d+x\d+$/ or $invalid = $key; | |||
} | |||
when 'modes' { | |||
for (split /\s+/, $x{$key}) { | |||
unless (/^\d+x\d+$/) { | |||
$invalid = $key; | |||
last; | |||
} | |||
} | |||
if (not $invalid) { | |||
$x{$key} = sanitize_modes($x{$key}); | |||
} | |||
} | |||
when 'rate' { | |||
$x{$key} =~ /^\d+(\.\d+)?$/ or $invalid = $key; | |||
} | |||
when 'virtual' { | |||
$x{$key} =~ /^\d+\s+\d+$/ or $invalid = $key; | |||
} | |||
} | |||
$invalid and warn "W: invalid --$invalid value: " . $x{$invalid} . "\n"; | |||
} | |||
########################################################### | |||
# read in the templates | |||
my @heading = get_template('heading'); | |||
my @serverlayout = get_template('serverlayout'); | |||
my @serverflags = get_template('serverflags'); | |||
my @monitor = get_template('monitor'); | |||
my @device = ($x{'driver'} or $x{'busid'} or $x{'boardname'}) ? get_template('device') : undef; | |||
my @screen = get_template('screen'); | |||
my @extensions = get_template('extensions'); | |||
########################################################### | |||
# monitor settings | |||
if ($x{'xrandr'}) { | |||
# http://bgoglin.livejournal.com/10423.html | |||
# force mode/resolution for self modesetting driver | |||
if ($x{'mode'}) { | |||
my @prefmode; | |||
if ($x{'rate'}) { | |||
# get Modeline from gtf, compute gtf args | |||
my ($x_axis, $y_axis) = split 'x', $x{'mode'}; | |||
@prefmode = gtf_modelines($x_axis, $y_axis, $x{'rate'}); | |||
# match Modeline mode_freq marker that gtf outputs | |||
for (@prefmode) { | |||
if (m/^\s+Modeline\s+"(.+)"\s+/) { | |||
push(@prefmode, "\tOption\t\t\"PreferredMode\"\t\t\"$1\""); | |||
last; | |||
} | |||
} | |||
} | |||
else { | |||
push(@prefmode, "\tOption\t\t\"PreferredMode\"\t\t\"" . $x{'mode'} . "\""); | |||
} | |||
dbg \@prefmode; | |||
splice(@monitor, -1, 0, @prefmode); | |||
} | |||
# http://bgoglin.livejournal.com/10214.html | |||
# * drop ModeLine, HorizSync and VertRefresh from the Monitor section | |||
delete $x{'horizsync'}; | |||
delete $x{'vertrefresh'}; | |||
# * drop Modes line from the Display subsection | |||
# the Virual option would go in place of the Modes option for xrandr1.2 style | |||
# Virtual specifies the dimensions of a large virtual screen in which you may | |||
# configure two sub-screens (dual monitor) | |||
$x{'modes'} = $x{'virtual'} ? "Virtual\t" . $x{'virtual'} : undef; | |||
} | |||
else { | |||
# wrap each mode in quotation marks | |||
($x{'modes'} = "Modes\t" . $x{'modes'}) =~ s/(\d+x\d+)/"$1"/g; | |||
# slice our Modeline library into the monitor section | |||
if ($x{'modelines'}) { | |||
# add large modeline table for legacy config | |||
splice(@monitor, -1, 0, gtf_modelines); | |||
} | |||
} | |||
########################################################### | |||
# tie @x to $xorg_conf, $x_o is the control object | |||
my $x_o = tie(@x, "Tie::File", $xorg_conf) | |||
or die "Cannot open $xorg_conf for writing: $!\n"; | |||
# lock it for writing | |||
$x_o->flock; | |||
# write the config | |||
@x = ( | |||
@heading, | |||
@serverlayout, | |||
@serverflags, | |||
@device, | |||
@monitor, | |||
@screen, | |||
@extensions, | |||
); | |||
########################################################### | |||
# post-process xorg.conf, substitute markers | |||
$n = 0; | |||
XCONF: while (defined $x[$n]) { | |||
my $line = \$x[$n]; | |||
dbg "$n: " . ${ $line }; | |||
given (${ $line }) { | |||
# substitute placeholders | |||
when m/@@\w+@@/ { | |||
if (${ $line } =~ m/@@(\w+)@@/ and $x{ lc($1) }) { | |||
dbg "Modifying line '$n': $1 => " . $x{ lc($1) }; | |||
my $sub = $x{ lc($1) }; | |||
${ $line } =~ s/@@\w+@@/$sub/; | |||
} | |||
else { | |||
dbg "Removing line '$n'"; | |||
splice(@x, $n, 1); | |||
redo XCONF if $x[$n]; | |||
} | |||
} | |||
# beautify, seperate each section with blank line | |||
when m/^EndSection$/ { | |||
dbg "Adding whitespace"; | |||
splice(@x, ++$n, 0, ''); | |||
} | |||
} | |||
} | |||
continue { | |||
$n++; | |||
} |
@@ -0,0 +1 @@ | |||
8 |
@@ -0,0 +1,78 @@ | |||
Source: fll-live-initscripts | |||
Section: misc | |||
Priority: optional | |||
Maintainer: Kel Modderman <kel@otaku42.de> | |||
Uploaders: Stefan Lippers-Hollmann <s.l-h@gmx.de>, | |||
Joaquim Boura <x-un-i@berlios.de>, | |||
Niall Walsh <niallwalsh@users.berlios.de> | |||
Build-Depends: debhelper (>= 8), | |||
asciidoc, | |||
docbook, | |||
gengetopt, | |||
xsltproc, | |||
docbook-xml, | |||
docbook-xsl, | |||
devscripts, | |||
pkg-config, | |||
libblkid-dev, | |||
libudev-dev, | |||
libxml2-utils | |||
Standards-Version: 3.9.2 | |||
Vcs-Svn: svn://svn.berlios.de/fullstory/fll-live-initscripts/trunk | |||
Vcs-Browser: http://svn.berlios.de/wsvn/fullstory/fll-live-initscripts/trunk/ | |||
Package: distro-defaults | |||
Architecture: all | |||
Depends: ${misc:Depends} | |||
Description: set various default options | |||
This seemingly empty package has much influence on the system and update | |||
behaviour of the fll live Linux utilities. It's configuration data is | |||
dynamically created at distro build time. | |||
Package: fll-live-initscripts | |||
Architecture: all | |||
Depends: ${misc:Depends}, | |||
adduser, | |||
console-setup, | |||
cpufrequtils, | |||
distro-defaults, | |||
eject, | |||
fll-live-utils, | |||
ifplugd, | |||
ceni, | |||
keyboard-configuration, | |||
lsb-base | |||
Recommends: tzdata | |||
Description: fll live media sysv initscripts | |||
A set of initscripts suitable for managing the SysV-Init boot sequence of the | |||
live media generated by code from the F.U.L.L.S.T.O.R.Y project. | |||
. | |||
This is a FULLSTORY live-only package and must not be installed to an | |||
ordinary system. | |||
Package: fll-live-xorgconfig | |||
Architecture: all | |||
Depends: ${misc:Depends}, | |||
distro-defaults, | |||
lsb-base, | |||
perl, | |||
libswitch-perl, | |||
xserver-xorg-core | |||
Recommends: kdm | gdm3 | lightdm (>= 1.0.2) | slim, | |||
xserver-xorg-input-vmmouse (>> 12.6.3) | |||
Description: fll live media xorg related tools | |||
A set of scripts to generate a Xorg configuration. | |||
. | |||
This is a FULLSTORY live-only package and must not be installed to an | |||
ordinary system. | |||
Package: fll-live-utils | |||
Architecture: any | |||
Depends: ${shlibs:Depends}, | |||
${misc:Depends}, | |||
udev | |||
Description: fll live utilities | |||
A set of tools for use by fll-live-initscripts. | |||
. | |||
This is a FULLSTORY live-only package and should not be installed to an | |||
ordinary system. |
@@ -0,0 +1,52 @@ | |||
This is fll-live-initramfs, written and maintained by Kel Modderman | |||
<kel@otaku42.de> on Tue, 29 May 2007 13:04:10 +1000. | |||
The original source can always be found at: | |||
http://developer.berlios.de/projects/fullstory | |||
Copyright: | |||
Copyright ยฉ 2007-2008 Kel Modderman <kel@otaku42.de> | |||
Copyright ยฉ 2007-2010 Stefan Lippers-Hollmann <s.l-h@gmx.net> | |||
./bin/fll_analyze_initscripts and ./bin/fll_xserver_discover were | |||
originally written by "locsmif". | |||
Copyright Holders: | |||
ยฉ 2006 M.L. de Boer a.k.a locsmif <locsmif@kanotix.com> | |||
ยฉ 2007 Michiel de Boer <locsmif@kanotix.com> | |||
Some code and concepts derived from initscripts-sidux-live. | |||
Copyright Holders: ยฉ Klaus Knopper <knopper@knopper.net> | |||
ยฉ Jรถrg Schirottke <master@kanotix.com> | |||
ยฉ Stefan Lippers-Hollmann <s.l-h@gmx.net> | |||
License: GPL | |||
http://sidux.com/debian/pool/main/i/initscripts-sidux-live/ | |||
./debian/fll-live-initscripts.fll-reboot.init was inspired by | |||
/etc/init.d/umountfs from initscripts (2.86.ds1-38). | |||
Copyright Holders: | |||
Copyright ยฉ 1997-2005 Miquel van Smoorenburg <miquels@cistron.nl> and | |||
Copyright ยฉ 2007-2008 Kel Modderman <kel@otaku42.de> | |||
Copyright ยฉ 2007-2010 Stefan Lippers-Hollmann <s.l-h@gmx.net> | |||
the members pkg-sysvinit project. | |||
License: GPL | |||
http://alioth.debian.org/projects/pkg-sysvinit/ | |||
copy_exec() in ./debian/fll-live-initscripts.fll-reboot.init was shamelessly | |||
adapted from initramfs-tools. | |||
Copyright Holders: | |||
Copyright ยฉ 2005-2006 Adam Conrad | |||
Copyright ยฉ 2006 Ben Collins | |||
Copyright ยฉ 2005-2007 David Hรคrdeman | |||
Copyright ยฉ 2005 Jeff Bailey | |||
Copyright ยฉ 2005-2007 maximilian attems | |||
Copyright ยฉ 2005-2006 Scott James Remnant | |||
Copyright ยฉ 2007-2008 Kel Modderman <kel@otaku42.de> | |||
Copyright ยฉ 2007-2010 Stefan Lippers-Hollmann <s.l-h@gmx.net> | |||
License: PUBLIC DOMAIN | |||
http://git.debian.org/?p=kernel/initramfs-tools.git;a=shortlog | |||
On Debian systems, the complete text of the GNU General Public License, | |||
version 2, can be found in `/usr/share/common-licenses/GPL-2'. | |||
The Debian packaging is ยฉ 2007, Kel Modderman <kel@otaku42.de> and | |||
is licensed under the GPL-2, see above. |
@@ -0,0 +1 @@ | |||
etc/insserv/overrides |
@@ -0,0 +1,112 @@ | |||
#!/bin/sh | |||
set -e | |||
# This script can be called in the following ways: | |||
# | |||
# After the package was installed: | |||
# <postinst> configure <old-version> | |||
# | |||
# | |||
# If prerm fails during upgrade or fails on failed upgrade: | |||
# <old-postinst> abort-upgrade <new-version> | |||
# | |||
# If prerm fails during deconfiguration of a package: | |||
# <postinst> abort-deconfigure in-favour <new-package> <version> | |||
# removing <old-package> <version> | |||
# | |||
# If prerm fails during replacement due to conflict: | |||
# <postinst> abort-remove in-favour <new-package> <version> | |||
chrooted() { | |||
# borrowed from udev's postinst | |||
if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then | |||
# the device number/inode pair of / is the same as that of | |||
# /sbin/init's root, so we're *not* in a chroot and hence | |||
# return false. | |||
return 1 | |||
fi | |||
return 0 | |||
} | |||
override_dm_lsb_defaults() { | |||
dmstart='5' | |||
dmstop='0 1 2 3 4 6' | |||
# Dump the LSB header to insserv override file | |||
sed -n '/^### BEGIN INIT INFO/,/^### END INIT INFO/p' ${1} > ${2} | |||
# Override Default-Start and Default-Stop | |||
sed -i -e 's/^\(# Default-Start:[[:space:]]\+\).*/\1'"${dmstart}"'/' \ | |||
-e 's/^\(# Default-Stop:[[:space:]]\+\).*/\1'"${dmstop}"'/' \ | |||
${2} | |||
echo '# Managed by the distro-defaults package.' >> ${2} | |||
} | |||
do_override() { | |||
# Usage: do_override kdm 5 | |||
[ -s /etc/init.d/${1} ] || return 0 | |||
echo "distro-defaults: overriding LSB init info for ${1} ..." 1>&2 | |||
override_dm_lsb_defaults /etc/init.d/${1} /etc/insserv/overrides/${1} | |||
} | |||
purge_conffile() { | |||
rm -f ${1} | |||
} | |||
case "$1" in | |||
configure) | |||
for dm in gdm3 kdm slim lightdm lxdm wdm xdm; do | |||
do_override "${dm}" | |||
done | |||
# gdm is no more | |||
if [ -f /etc/insserv/overrides/gdm ]; then | |||
purge_conffile /etc/insserv/overrides/gdm | |||
fi | |||
# Bug #487196 has been fixed in util-linux, remove now | |||
# obsolete LSB overrides | |||
if [ -f /etc/insserv/overrides/hwclock.sh ]; then | |||
purge_conffile /etc/insserv/overrides/hwclock.sh | |||
fi | |||
if [ -f /etc/insserv/overrides/hwclockfirst.sh ]; then | |||
purge_conffile /etc/insserv/overrides/hwclockfirst.sh | |||
fi | |||
if [ ! -f /etc/apt/sources.list ] && chrooted; then | |||
echo 'distro-defaults: creating /etc/apt/sources.list ...' 1>&2 | |||
cat > /etc/apt/sources.list \ | |||
<<EOF | |||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |||
# See sources.list(5) for more information, especialy remember that you can # | |||
# only use http, ftp or file URIs, CDROMs are managed through apt-cdrom. # | |||
# # | |||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |||
# Please use /etc/apt/sources.list.d/ instead of this file and create a # | |||
# separate *.list configuration file for each repository, containing the # | |||
# actual deb/deb-src desired suites and components for that repository. # | |||
# # | |||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |||
EOF | |||
fi | |||
;; | |||
triggered) | |||
shift | |||
for interest in "${@}"; do | |||
do_override "${interest#/etc/init.d/}" | |||
done | |||
;; | |||
abort-upgrade|abort-deconfigure|abort-remove) | |||
;; | |||
*) | |||
echo "$0 called with unknown argument \`$1'" 1>&2 | |||
exit 1 | |||
;; | |||
esac | |||
#DEBHELPER# | |||
exit 0 |
@@ -0,0 +1,57 @@ | |||
#!/bin/sh | |||
set -e | |||
# This script can be called in the following ways: | |||
# | |||
# After the package was removed: | |||
# <postrm> remove | |||
# | |||
# After the package was purged: | |||
# <postrm> purge | |||
# | |||
# After the package was upgraded: | |||
# <old-postrm> upgrade <new-version> | |||
# if that fails: | |||
# <new-postrm> failed-upgrade <old-version> | |||
# | |||
# | |||
# After all of the packages files have been replaced: | |||
# <postrm> disappear <overwriting-package> <version> | |||
# | |||
# | |||
# If preinst fails during install: | |||
# <new-postrm> abort-install | |||
# | |||
# If preinst fails during upgrade of removed package: | |||
# <new-postrm> abort-install <old-version> | |||
# | |||
# If preinst fails during upgrade: | |||
# <new-postrm> abort-upgrade <old-version> | |||
purge_conffile() { | |||
rm -f ${1} | |||
} | |||
case "$1" in | |||
remove) | |||
;; | |||
purge) | |||
purge_conffile /etc/default/distro | |||
for file in gdm3 kdm lxdm slim wdm xdm; do | |||
purge_conffile /etc/insserv/overrides/${file} | |||
done | |||
;; | |||
upgrade|failed-upgrade|disappear) | |||
;; | |||
abort-install|abort-upgrade) | |||
;; | |||
*) | |||
echo "$0 called with unknown argument \`$1'" 1>&2 | |||
exit 1 | |||
;; | |||
esac | |||
#DEBHELPER# | |||
exit 0 |
@@ -0,0 +1,7 @@ | |||
interest /etc/init.d/gdm3 | |||
interest /etc/init.d/xdm | |||
interest /etc/init.d/kdm | |||
interest /etc/init.d/lxdm | |||
interest /etc/init.d/slim | |||
interest /etc/init.d/wdm | |||
interest /etc/init.d/xdm |
@@ -0,0 +1 @@ | |||
etc/insserv/overrides |
@@ -0,0 +1,131 @@ | |||
#!/bin/sh | |||
### BEGIN INIT INFO | |||
# Provides: fll-adduser | |||
# Required-Start: keyboard-setup console-setup | |||
# Required-Stop: | |||
# Default-Start: S | |||
# Default-Stop: | |||
# Short-Description: add user to live system | |||
# Description: The purpose of fll-adduser is to add a user to the live | |||
# system and populate their /home. | |||
### END INIT INFO | |||
### | |||
# F.U.L.L.S.T.O.R.Y init script | |||
# | |||
# Copyright: (C) 2007 - 2008 Kel Modderman <kel@otaku42.de> | |||
# License: GPLv2 | |||
# | |||
# F.U.L.L.S.T.O.R.Y Project Homepage: | |||
# http://developer.berlios.de/projects/fullstory | |||
### | |||
PATH=/sbin:/usr/sbin:/bin:/usr/bin | |||
NAME="fll-adduser" | |||
### | |||
# source distro-defaults, no-op unless in live mode | |||
### | |||
FLL_DISTRO_MODE="installed" | |||
if [ -r /etc/default/distro ]; then | |||
. /etc/default/distro | |||
fi | |||
if [ "${FLL_DISTRO_MODE}" != "live" ]; then | |||
exit 0 | |||
fi | |||
### | |||
# VERBOSE setting and other rcS variables | |||
### | |||
#. /lib/init/vars.sh | |||
### | |||
# source lsb functions | |||
### | |||
. /lib/lsb/init-functions | |||
### | |||
# source fll functions | |||
### | |||
. /lib/init/fll | |||
### | |||
# cheatcode handling | |||
### | |||
if [ -f /proc/cmdline ]; then | |||
for param in $(cat /proc/cmdline); do | |||
case "${param}" in | |||
flldebug=*) | |||
if [ "${param#flldebug=}" = "${NAME#fll-}" ] || [ "${param#flldebug=}" = "all" ]; then | |||
fll_redirect | |||
fi | |||
;; | |||
username=*) | |||
FLL_LIVE_USER="${param#username=}" | |||
sed -i "s/^FLL_LIVE_USER=.*/FLL_LIVE_USER=\"${FLL_LIVE_USER}\"/" \ | |||
/etc/default/distro | |||
;; | |||
esac | |||
done | |||
fi | |||
add_live_user() { | |||
if getent passwd "${FLL_LIVE_USER}" >/dev/null 2>&1; then | |||
log_action_begin_msg " user '${FLL_LIVE_USER}' exists" | |||
return 0 | |||
fi | |||
log_action_begin_msg " adding user '${FLL_LIVE_USER}'" | |||
adduser --disabled-password --gecos "${FLL_LIVE_USER}" "${FLL_LIVE_USER}" >/dev/null | |||
} | |||
hack_sudoers() { | |||
if [ -e "/etc/sudoers.d/15_${FLL_DISTRO_NAME}" ]; then | |||
return 0 | |||
fi | |||
# append sudoers entry | |||
cat >> "/etc/sudoers.d/15_${FLL_DISTRO_NAME}" \ | |||
<<EOF | |||
# WARNING: This allows the unprivileged ${FLL_LIVE_USER} user to start commands as root | |||
# WARNING: This is totally insecure and (almost) makes ${FLL_LIVE_USER} a second root account. | |||
# WARNING: Never allow external access to the ${FLL_LIVE_USER} user!!! | |||
${FLL_LIVE_USER} ALL=(ALL:ALL) NOPASSWD: ALL | |||
EOF | |||
chmod 0440 "/etc/sudoers.d/15_${FLL_DISTRO_NAME}" | |||
} | |||
hack_bashrc() { | |||
FLL_LIVE_USER_HOME=$(getent passwd ${FLL_LIVE_USER} | cut -d\: -f 6) | |||
grep -s -q 'alias su' ${FLL_LIVE_USER_HOME}/.bashrc && return 0 | |||
printf "\nalias su='sudo su'\nalias sux='sudo sux'\n" \ | |||
>> ${FLL_LIVE_USER_HOME}/.bashrc | |||
} | |||
case "${1}" in | |||
start) | |||
log_daemon_msg "${NAME}" | |||
add_live_user | |||
hack_sudoers | |||
hack_bashrc | |||
log_end_msg 0 | |||
;; | |||
stop) | |||
;; | |||
restart|force-reload) | |||
echo "Error: argument '${1}' not supported" >&2 | |||
exit 3 | |||
;; | |||
*) | |||
echo "Usage: ${NAME} {start|stop}" >&2 | |||
exit 3 | |||
;; | |||
esac | |||
: |
@@ -0,0 +1,182 @@ | |||
#!/bin/sh | |||
### BEGIN INIT INFO | |||
# Provides: fll-desktop | |||
# Required-Start: fll-adduser | |||
# Required-Stop: | |||
# X-Start-Before: gdm3 kdm lxdm slim wdm xdm | |||
# Default-Start: 2 3 4 5 | |||
# Default-Stop: | |||
# Short-Description: configure window manager to be used on live system | |||
# Description: The purpose of this script is to configure a X window | |||
# manager. | |||
### END INIT INFO | |||
### | |||
# F.U.L.L.S.T.O.R.Y init script | |||
# | |||
# Copyright: (C) 2007 - 2008 Kel Modderman <kel@otaku42.de> | |||
# License: GPLv2 | |||
# | |||
# F.U.L.L.S.T.O.R.Y Project Homepage: | |||
# http://developer.berlios.de/projects/fullstory | |||
### | |||
PATH=/sbin:/usr/sbin:/bin:/usr/bin | |||
NAME="fll-desktop" | |||
### | |||
# source distro-defaults, no-op unless in live mode | |||
### | |||
FLL_DISTRO_MODE="installed" | |||
if [ -r /etc/default/distro ]; then | |||
. /etc/default/distro | |||
fi | |||
if [ "${FLL_DISTRO_MODE}" != "live" ]; then | |||
exit 0 | |||
fi | |||
### | |||
# VERBOSE setting and other rcS variables | |||
### | |||
#. /lib/init/vars.sh | |||
### | |||
# source lsb functions | |||
### | |||
. /lib/lsb/init-functions | |||
### | |||
# source fll functions | |||
### | |||
. /lib/init/fll | |||
### | |||
# cheatcode handling | |||
### | |||
if [ -f /proc/cmdline ]; then | |||
for param in $(cat /proc/cmdline); do | |||
case "${param}" in | |||
flldebug=*) | |||
if [ "${param#flldebug=}" = "${NAME#fll-}" ] || [ "${param#flldebug=}" = "all" ]; then | |||
fll_redirect | |||
fi | |||
;; | |||
desktop=*) | |||
DESKTOP="${param#desktop=}" | |||
;; | |||
esac | |||
done | |||
fi | |||
if [ -z "${DESKTOP}" ]; then | |||
[ -x "/usr/bin/icewm" ] && DESKTOP="icewm" # sixth choice | |||
[ -x "/usr/bin/startfluxbox" ] && DESKTOP="fluxbox" # fifth choice | |||
[ -x "/usr/bin/startlxde" ] && \ | |||
[ -x "/usr/bin/openbox" ] && DESKTOP="lxde" # fourth choice | |||
[ -x "/usr/bin/xfwm4" ] && DESKTOP="xfce" # third choice | |||
[ -x "/usr/bin/metacity" ] && DESKTOP="gnome" # second choice | |||
[ -x "/usr/bin/kwin" ] && DESKTOP="kde" # first choice, if installed and desktop= is empty | |||
# none of the major desktop environments is installed, don't interfere | |||
# with ordinary priorities. | |||
[ -z "${DESKTOP}" ] && exit 0 | |||
fi | |||
do_start() { | |||
FLL_LIVE_USER_GROUP=$(getent passwd ${FLL_LIVE_USER} | cut -d\: -f 4) | |||
FLL_LIVE_USER_HOME=$(getent passwd ${FLL_LIVE_USER} | cut -d\: -f 6) | |||
log_daemon_msg "${NAME}" | |||
case "${DESKTOP}" in | |||
flux*) | |||
WM="/usr/bin/startfluxbox" | |||
;; | |||
gnome) | |||
WM="/usr/bin/metacity" | |||
;; | |||
icewm) | |||
WM="/usr/bin/icewm" | |||
;; | |||
kde) | |||
WM="/usr/bin/kwin" | |||
;; | |||
lxde) | |||
WM="/usr/bin/openbox" | |||
;; | |||
xfce*) | |||
WM="/usr/bin/xfwm4" | |||
;; | |||
*) | |||
log_action_msg " desktop '${DESKTOP}' is not available" | |||
log_end_msg 0 | |||
return 1 | |||
;; | |||
esac | |||
if [ -x "${WM}" ]; then | |||
case "${WM}" in | |||
"/usr/bin/kwin") | |||
if [ -r /usr/share/xsessions/kde.desktop ] && \ | |||
[ ! -r /usr/share/xsessions/kde-plasma.desktop ]; then | |||
XSESSION="kde" | |||
else | |||
XSESSION="kde-plasma" | |||
fi | |||
;; | |||
"/usr/bin/metacity") | |||
XSESSION="gnome" | |||
;; | |||
"/usr/bin/startfluxbox") | |||
XSESSION="fluxbox" | |||
;; | |||
"/usr/bin/xfwm4") | |||
XSESSION="xfce" | |||
;; | |||
"/usr/bin/icewm") | |||
XSESSION="IceWM" | |||
;; | |||
"/usr/bin/openbox") | |||
XSESSION="LXDE" | |||
;; | |||
esac | |||
log_action_begin_msg " setting up window manager '${WM}'" | |||
echo "[Desktop]" > ${FLL_LIVE_USER_HOME}/.dmrc | |||
echo "Session=${XSESSION}" >> ${FLL_LIVE_USER_HOME}/.dmrc | |||
chown "${FLL_LIVE_USER}:${FLL_LIVE_USER_GROUP}" "${FLL_LIVE_USER_HOME}/.dmrc" | |||
update-alternatives --set x-window-manager "${WM}" >/dev/null | |||
log_end_msg "${?}" | |||
return 0 | |||
else | |||
log_action_msg " desktop '${DESKTOP}' is not available" | |||
log_end_msg 0 | |||
return 1 | |||
fi | |||
} | |||
case "${1}" in | |||
start) | |||
do_start | |||
;; | |||
stop) | |||
;; | |||
restart|force-reload) | |||
echo "Error: argument '${1}' not supported" >&2 | |||
exit 3 | |||
;; | |||
kde|gnome|flux*|xfce*|icewm|lxde) | |||
DESKTOP="${1}" | |||
do_start | |||
;; | |||
*) | |||
echo "Usage: ${NAME} {start|stop}" >&2 | |||
exit 3 | |||
;; | |||
esac | |||
: |
@@ -0,0 +1,114 @@ | |||
#!/bin/sh | |||
### BEGIN INIT INFO | |||
# Provides: fll-fstab | |||
# Required-Start: mountdevsubfs | |||
# Required-Stop: | |||
# Should-Start: lvm2 | |||
# X-Start-Before: mountall | |||
# Default-Start: S | |||
# Default-Stop: | |||
# Short-Description: generates /etc/fstab | |||
# Description: The purpose of fll-fstab is to generate /etc/fstab via | |||
# fll_fstab_generator(8). | |||
### END INIT INFO | |||
### | |||
# F.U.L.L.S.T.O.R.Y init script | |||
# | |||