From 92de5eb1655e39fce165d18e44bc40b4fbb1b05b Mon Sep 17 00:00:00 2001 From: SCOTT-HAMILTON Date: Thu, 30 Jul 2020 14:51:45 +0200 Subject: [PATCH 1/4] start working on dbus interface --- Makefile | 6 ++++ config.mk | 2 ++ dbus/org.instantos.instantLOCK.xml | 41 ++++++++++++++++++++++++++ dbus/org.instantos.instantlock.service | 3 ++ 4 files changed, 52 insertions(+) create mode 100644 dbus/org.instantos.instantLOCK.xml create mode 100644 dbus/org.instantos.instantlock.service diff --git a/Makefile b/Makefile index 20f9b8c..fb8f4e0 100644 --- a/Makefile +++ b/Makefile @@ -54,11 +54,17 @@ install: all @mkdir -p ${DESTDIR}${MANPREFIX}/man1 @sed "s/VERSION/${VERSION}/g" ${DESTDIR}${MANPREFIX}/man1/instantlock.1 @chmod 644 ${DESTDIR}${MANPREFIX}/man1/instantlock.1 + @echo installing dbus service and interface to ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR} + @install -Dm 644 dbus/org.instantos.instantlock.service ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR}/org.instantos.instantlock.service + @install -Dm 644 dbus/org.instantos.instantLOCK.xml ${DESTDIR}${DBUS_INTERFACES_INSTALL_DIR}/org.instantos.instantLOCK.xml uninstall: @echo removing executable file from ${DESTDIR}${PREFIX}/bin @rm -f ${DESTDIR}${PREFIX}/bin/instantlock @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 @rm -f ${DESTDIR}${MANPREFIX}/man1/instantlock.1 + @echo uninstalling dbus service and interface from ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR} + @rm -f ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR}/org.instantos.instantlock.service + @rm -f ${DESTDIR}${DBUS_INTERFACES_INSTALL_DIR}/org.instantos.instantLOCK.xml .PHONY: all options clean dist install uninstall diff --git a/config.mk b/config.mk index f440999..6d39148 100644 --- a/config.mk +++ b/config.mk @@ -6,6 +6,8 @@ VERSION = 1.4 # paths PREFIX = /usr MANPREFIX = ${PREFIX}/share/man +DBUS_SERVICES_INSTALL_DIR = ${PREFIX}/share/dbus-1/services +DBUS_INTERFACES_INSTALL_DIR = ${PREFIX}/share/dbus-1/interfaces X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib diff --git a/dbus/org.instantos.instantLOCK.xml b/dbus/org.instantos.instantLOCK.xml new file mode 100644 index 0000000..55e0bd4 --- /dev/null +++ b/dbus/org.instantos.instantLOCK.xml @@ -0,0 +1,41 @@ + + + + + + + + + + The message to print. + + + + + Locks the screen. + + + + + + + + Emitted if the user locked the screen. + + + + + + + Emitted if the user successfully unlocked the screen. + + + + + diff --git a/dbus/org.instantos.instantlock.service b/dbus/org.instantos.instantlock.service new file mode 100644 index 0000000..6443a27 --- /dev/null +++ b/dbus/org.instantos.instantlock.service @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.instantos.instantLOCK +Exec=@Prefix@/bin/instantlock --dbus From 24d470845a3810c2bb0853c3f95f46401a48f8dd Mon Sep 17 00:00:00 2001 From: SCOTT-HAMILTON Date: Thu, 6 Aug 2020 12:03:13 +0200 Subject: [PATCH 2/4] Move to argtable3 argument parser --- Makefile | 5 +- arg.h | 65 ------ config.def.h | 7 +- config.mk | 6 +- instantlock.c | 623 +++++++------------------------------------------- lock.h | 528 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 628 insertions(+), 606 deletions(-) delete mode 100644 arg.h create mode 100644 lock.h diff --git a/Makefile b/Makefile index fb8f4e0..ddb0106 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ all: options instantlock options: @echo instantlock build options: @echo "CFLAGS = ${CFLAGS}" + @echo "CPPFLAGS = ${CPPFLAGS}" @echo "LDFLAGS = ${LDFLAGS}" @echo "CC = ${CC}" @@ -18,7 +19,7 @@ options: @echo CC $< @${CC} -c ${CFLAGS} $< -${OBJ}: config.h config.mk arg.h util.h +${OBJ}: config.h config.mk lock.h util.h config.h: @echo creating $@ from config.def.h @@ -36,7 +37,7 @@ dist: clean @echo creating dist tarball @mkdir -p instantlock-${VERSION} @cp -R LICENSE Makefile README instantlock.1 config.mk \ - ${SRC} explicit_bzero.c config.def.h arg.h util.h instantlock-${VERSION} + ${SRC} explicit_bzero.c config.def.h lock.h util.h instantlock-${VERSION} @tar -cf instantlock-${VERSION}.tar instantlock-${VERSION} @gzip instantlock-${VERSION}.tar @rm -rf instantlock-${VERSION} diff --git a/arg.h b/arg.h deleted file mode 100644 index 0b23c53..0000000 --- a/arg.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - for (brk_ = 0, argv[0]++, argv_ = argv;\ - argv[0][0] && !brk_;\ - argv[0]++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][0];\ - switch (argc_) - -/* Handles obsolete -NUM syntax */ -#define ARGNUM case '0':\ - case '1':\ - case '2':\ - case '3':\ - case '4':\ - case '5':\ - case '6':\ - case '7':\ - case '8':\ - case '9' - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX)) - -#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][1] != '\0')?\ - (&argv[0][1]) :\ - (argc--, argv++, argv[0]))) - -#define LNGARG() &argv[0][0] - -#endif diff --git a/config.def.h b/config.def.h index ffc2930..164799f 100644 --- a/config.def.h +++ b/config.def.h @@ -1,3 +1,6 @@ +#ifndef CONFIG_DEF_H +#define CONFIG_DEF_H + /* user and group to drop privileges to */ static const char *user = "nobody"; static const char *group = "nobody"; @@ -22,4 +25,6 @@ static int onebutton = 0; static const char * text_color = "#ffffff"; /* text size (must be a valid size) */ -static const char * font_name = "10x20"; \ No newline at end of file +static const char * font_name = "10x20"; + +#endif //CONFIG_DEF_H diff --git a/config.mk b/config.mk index 6d39148..865255a 100644 --- a/config.mk +++ b/config.mk @@ -8,13 +8,15 @@ PREFIX = /usr MANPREFIX = ${PREFIX}/share/man DBUS_SERVICES_INSTALL_DIR = ${PREFIX}/share/dbus-1/services DBUS_INTERFACES_INSTALL_DIR = ${PREFIX}/share/dbus-1/interfaces +ARGTABLE3_INCLUDE_DIR = ${PREFIX}/usr/include +ARGTABLE3_LIB_DIR = ${PREFIX}/usr/lib X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib # includes and libs -INCS = -I. -I/usr/include -I${X11INC} -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lXinerama +INCS = -I. -I/usr/include -I${X11INC} -I${ARGTABLE3_INCLUDE_DIR} +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -L${ARGTABLE3_LIB_DIR} -lX11 -lXext -lXrandr -lXinerama -largtable3 # flags CPPFLAGS += -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/instantlock.c b/instantlock.c index 7029175..40d0c42 100644 --- a/instantlock.c +++ b/instantlock.c @@ -1,558 +1,109 @@ /* See LICENSE file for license details. */ -#define _XOPEN_SOURCE 500 -#if HAVE_SHADOW_H -#include -#endif -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include -#include -#include -#include - -#include "arg.h" -#include "util.h" - -char *argv0; - -/* global count to prevent repeated error messages */ -int count_error = 0; - -enum { - INIT, - INPUT, - FAILED, - NUMCOLS -}; - -struct lock { - int screen; - Window root, win; - Pixmap pmap; - unsigned long colors[NUMCOLS]; -}; - -struct xrandr { - int active; - int evbase; - int errbase; -}; - -#include "config.h" - -static void -die(const char *errstr, ...) -{ - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); -} - -#ifdef __linux__ -#include -#include - -static void -dontkillme(void) -{ - FILE *f; - const char oomfile[] = "/proc/self/oom_score_adj"; - - if (!(f = fopen(oomfile, "w"))) { - if (errno == ENOENT) - return; - die("instantlock: fopen %s: %s\n", oomfile, strerror(errno)); - } - fprintf(f, "%d", OOM_SCORE_ADJ_MIN); - if (fclose(f)) { - if (errno == EACCES) - die("instantlock: unable to disable OOM killer. " - "Make sure to suid or sgid instantlock.\n"); - else - die("instantlock: fclose %s: %s\n", oomfile, strerror(errno)); - } -} -#endif - -static void -writemessage(Display *dpy, Window win, int screen) -{ - int len, line_len, width, height, s_width, s_height, i, j, k, tab_replace, tab_size; - XGCValues gr_values; - XFontStruct *fontinfo; - XColor color, dummy; - XineramaScreenInfo *xsi; - GC gc; - fontinfo = XLoadQueryFont(dpy, font_name); - - if (fontinfo == NULL) { - if (count_error == 0) { - fprintf(stderr, "instantlock: Unable to load font \"%s\"\n", font_name); - fprintf(stderr, "instantlock: Try listing fonts with 'instantlock -f'\n"); - count_error++; - } - return; - } - - tab_size = 8 * XTextWidth(fontinfo, " ", 1); - - XAllocNamedColor(dpy, DefaultColormap(dpy, screen), - text_color, &color, &dummy); - - gr_values.font = fontinfo->fid; - gr_values.foreground = color.pixel; - gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values); - - /* To prevent "Uninitialized" warnings. */ - xsi = NULL; - - /* - * Start formatting and drawing text - */ - - len = strlen(message); - - /* Max max line length (cut at '\n') */ - line_len = 0; - k = 0; - for (i = j = 0; i < len; i++) { - if (message[i] == '\n') { - if (i - j > line_len) - line_len = i - j; - k++; - i++; - j = i; - } - } - /* If there is only one line */ - if (line_len == 0) - line_len = len; - - if (XineramaIsActive(dpy)) { - xsi = XineramaQueryScreens(dpy, &i); - s_width = xsi[0].width; - s_height = xsi[0].height; - } else { - s_width = DisplayWidth(dpy, screen); - s_height = DisplayHeight(dpy, screen); - } - - height = s_height*3/7 - (k*20)/3; - width = (s_width - XTextWidth(fontinfo, message, line_len))/2; - - /* Look for '\n' and print the text between them. */ - for (i = j = k = 0; i <= len; i++) { - /* i == len is the special case for the last line */ - if (i == len || message[i] == '\n') { - tab_replace = 0; - while (message[j] == '\t' && j < i) { - tab_replace++; - j++; - } - - XDrawString(dpy, win, gc, width + tab_size*tab_replace, height + 20*k, message + j, i - j); - while (i < len && message[i] == '\n') { - i++; - j = i; - k++; - } - } - } - - /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ - if (XineramaIsActive(dpy) && xsi != NULL) - XFree(xsi); -} - - - -static const char * -gethash(void) -{ - const char *hash; - struct passwd *pw; - - /* Check if the current user has a password entry */ - errno = 0; - if (!(pw = getpwuid(getuid()))) { - if (errno) - die("instantlock: getpwuid: %s\n", strerror(errno)); - else - die("instantlock: cannot retrieve password entry\n"); - } - hash = pw->pw_passwd; - -#if HAVE_SHADOW_H - if (!strcmp(hash, "x")) { - struct spwd *sp; - if (!(sp = getspnam(pw->pw_name))) - die("instantlock: getspnam: cannot retrieve shadow entry. " - "Make sure to suid or sgid instantlock.\n"); - hash = sp->sp_pwdp; - } -#else - if (!strcmp(hash, "*")) { -#ifdef __OpenBSD__ - if (!(pw = getpwuid_shadow(getuid()))) - die("instantlock: getpwnam_shadow: cannot retrieve shadow entry. " - "Make sure to suid or sgid instantlock.\n"); - hash = pw->pw_passwd; -#else - die("instantlock: getpwuid: cannot retrieve shadow entry. " - "Make sure to suid or sgid instantlock.\n"); -#endif /* __OpenBSD__ */ - } -#endif /* HAVE_SHADOW_H */ - - return hash; -} - -static void -readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, - const char *hash) -{ - XRRScreenChangeNotifyEvent *rre; - char buf[32], passwd[256], *inputhash; - char tmpmessage[300] = "entering password : "; - int num, screen, running, failure, oldc; - unsigned int len, color; - int i; - KeySym ksym; - XEvent ev; - - len = 0; - running = 1; - failure = 0; - oldc = INIT; - - while (running && !XNextEvent(dpy, &ev)) { - if (ev.type == KeyPress) { - if (onebutton) { - running = 0; - } - explicit_bzero(&buf, sizeof(buf)); - num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); - if (IsKeypadKey(ksym)) { - if (ksym == XK_KP_Enter) - ksym = XK_Return; - else if (ksym >= XK_KP_0 && ksym <= XK_KP_9) - ksym = (ksym - XK_KP_0) + XK_0; - } - if (IsFunctionKey(ksym) || - IsKeypadKey(ksym) || - IsMiscFunctionKey(ksym) || - IsPFKey(ksym) || - IsPrivateKeypadKey(ksym)) - continue; - switch (ksym) { - case XK_Return: - if (onebutton) { - running = 0; - break; - } - passwd[len] = '\0'; - errno = 0; - if (!(inputhash = crypt(passwd, hash))) - fprintf(stderr, "instantlock: crypt: %s\n", strerror(errno)); - else - running = !!strcmp(inputhash, hash); - if (running) { - XBell(dpy, 100); - failure = 1; - } - explicit_bzero(&passwd, sizeof(passwd)); - len = 0; - break; - case XK_Escape: - explicit_bzero(&passwd, sizeof(passwd)); - len = 0; - break; - case XK_BackSpace: - if (len) - passwd[--len] = '\0'; - break; - default: - if (num && !iscntrl((int)buf[0]) && - (len + num < sizeof(passwd))) { - memcpy(passwd + len, buf, num); - len += num; - } - break; - } - color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); - if (color == INPUT) { - message = tmpmessage; - for (int i = 0; i < strlen(passwd); i++) - { - tmpmessage[i + 20] = '.'; - tmpmessage[i + 21] = '\0'; - } - } - if (running /* && oldc != color */) { - for (screen = 0; screen < nscreens; screen++) { - XSetWindowBackground(dpy, - locks[screen]->win, - locks[screen]->colors[color]); - XClearWindow(dpy, locks[screen]->win); - writemessage(dpy, locks[screen]->win, screen); - } - oldc = color; - } - } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) { - rre = (XRRScreenChangeNotifyEvent*)&ev; - for (screen = 0; screen < nscreens; screen++) { - if (locks[screen]->win == rre->window) { - if (rre->rotation == RR_Rotate_90 || - rre->rotation == RR_Rotate_270) - XResizeWindow(dpy, locks[screen]->win, - rre->height, rre->width); - else - XResizeWindow(dpy, locks[screen]->win, - rre->width, rre->height); - XClearWindow(dpy, locks[screen]->win); - break; - } - } - } else { - for (screen = 0; screen < nscreens; screen++) - XRaiseWindow(dpy, locks[screen]->win); - } - } -} - -static struct lock * -lockscreen(Display *dpy, struct xrandr *rr, int screen) -{ - char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, ptgrab, kbgrab; - struct lock *lock; - XColor color, dummy; - XSetWindowAttributes wa; - Cursor invisible; - - if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock)))) - return NULL; - - lock->screen = screen; - lock->root = RootWindow(dpy, lock->screen); - - for (i = 0; i < NUMCOLS; i++) { - XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), - colorname[i], &color, &dummy); - lock->colors[i] = color.pixel; - } - - /* init */ - wa.override_redirect = 1; - wa.background_pixel = lock->colors[INIT]; - lock->win = XCreateWindow(dpy, lock->root, 0, 0, - DisplayWidth(dpy, lock->screen), - DisplayHeight(dpy, lock->screen), - 0, DefaultDepth(dpy, lock->screen), - CopyFromParent, - DefaultVisual(dpy, lock->screen), - CWOverrideRedirect | CWBackPixel, &wa); - lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); - invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, - &color, &color, 0, 0); - XDefineCursor(dpy, lock->win, invisible); - - /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ - for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) { - if (ptgrab != GrabSuccess) { - ptgrab = XGrabPointer(dpy, lock->root, False, - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask, GrabModeAsync, - GrabModeAsync, None, invisible, CurrentTime); - } - if (kbgrab != GrabSuccess) { - kbgrab = XGrabKeyboard(dpy, lock->root, True, - GrabModeAsync, GrabModeAsync, CurrentTime); - } - - /* input is grabbed: we can lock the screen */ - if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { - XMapRaised(dpy, lock->win); - if (rr->active) - XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); - - XSelectInput(dpy, lock->root, SubstructureNotifyMask); - return lock; - } - - /* retry on AlreadyGrabbed but fail on other errors */ - if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) || - (kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess)) - break; - - usleep(100000); - } - - /* we couldn't grab all input: fail out */ - if (ptgrab != GrabSuccess) - fprintf(stderr, "instantlock: unable to grab mouse pointer for screen %d\n", - screen); - if (kbgrab != GrabSuccess) - fprintf(stderr, "instantlock: unable to grab keyboard for screen %d\n", - screen); - return NULL; -} - -static void -monitorreset(Display* dpy, CARD16 standby, CARD16 suspend, CARD16 off) -{ - DPMSSetTimeouts(dpy, standby, suspend, off); - DPMSForceLevel(dpy, DPMSModeOn); - XFlush(dpy); -} - -static void -usage(void) -{ - die("usage: instantlock [-v] [-f] [-m message] [cmd [arg ...]]\n"); -} +#include "lock.h" int main(int argc, char **argv) { - struct xrandr rr; - struct lock **locks; - struct passwd *pwd; - struct group *grp; - uid_t duid; - gid_t dgid; - const char *hash; Display *dpy; - int i, s, nlocks, nscreens; - CARD16 standby, suspend, off; - int count_fonts; char **font_names; + int count_fonts; + int oneButton = onebutton; + int runCommand = 0; + const char* lock_message = message; + struct arg_lit *help, *version, *fonts, *anyKey; + struct arg_str *message, *command; + struct arg_end *end; + + + void* argtable[] = { + help = arg_litn(NULL, "help", 0, 1, "display this help and exit"), + version = arg_litn("v", "version", 0, 1, "print instantlock version"), + fonts = arg_litn("f", "fonts", 0, 1, "list available fonts"), + anyKey = arg_litn("o", NULL, 0, 1, "press any key"), + message = arg_str0("m", "message", "MESSAGE", "display the specified message"), + command = arg_strn(NULL, NULL, "COMMAND [ARGS ...]",0,argc+2,NULL), + end = arg_end(20) + }; + + int nerrors; + int exitcode = 0; + char progname[] = "instantlock"; + + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) + { + /* NULL entries were detected, some allocations must have failed */ + printf("%s: insufficient memory\n",progname); + exitcode = 1; + goto exit; + } - ARGBEGIN { - case 'v': - fprintf(stderr, "instantlock-"VERSION"\n"); - return 0; - case 'm': - message = EARGF(usage()); - break; - case 'o': - onebutton = 1; - message = "Press key to Unlock"; - break; - case 'f': + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout, argtable, "\n"); + printf("Demonstrate command-line parsing in argtable3.\n\n"); + arg_print_glossary(stdout, argtable, " %-25s %s\n"); + exitcode = 0; + goto exit; + } + + if (command->count > 0) + runCommand = 1; + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout, end, progname); + printf("Try '%s --help' for more information.\n", progname); + exitcode = 1; + goto exit; + } + if (version->count > 0) + { + fputs("instantlock-"VERSION"\n", stderr); + exitcode = 0; + goto exit; + } + if (message->count > 0) + { + lock_message = message->sval[0]; + } + if (anyKey->count > 0) + { + oneButton = 1; + lock_message = "Press key to Unlock"; + } + if (fonts->count > 0) + { if (!(dpy = XOpenDisplay(NULL))) die("instantlock: cannot open display\n"); font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts); + int i = 0; for (i=0; ipw_uid; - errno = 0; - if (!(grp = getgrnam(group))) - die("instantlock: getgrnam %s: %s\n", group, - errno ? strerror(errno) : "group entry not found"); - dgid = grp->gr_gid; - -#ifdef __linux__ - dontkillme(); -#endif - - hash = gethash(); - errno = 0; - if (!crypt("", hash)) - die("instantlock: crypt: %s\n", strerror(errno)); - - if (!(dpy = XOpenDisplay(NULL))) - die("instantlock: cannot open display\n"); - - /* drop privileges */ - if (setgroups(0, NULL) < 0) - die("instantlock: setgroups: %s\n", strerror(errno)); - if (setgid(dgid) < 0) - die("instantlock: setgid: %s\n", strerror(errno)); - if (setuid(duid) < 0) - die("instantlock: setuid: %s\n", strerror(errno)); - - /* check for Xrandr support */ - rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); - - /* get number of screens in display "dpy" and blank them */ - nscreens = ScreenCount(dpy); - if (!(locks = calloc(nscreens, sizeof(struct lock *)))) - die("instantlock: out of memory\n"); - for (nlocks = 0, s = 0; s < nscreens; s++) { - if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) { - writemessage(dpy, locks[s]->win, s); - nlocks++; - } else { - break; - } + exitcode = 0; + goto exit; } - XSync(dpy, 0); - - /* did we manage to lock everything? */ - if (nlocks != nscreens) - return 1; - - /* DPMS-magic to disable the monitor */ - if (!DPMSCapable(dpy)) - die("instantlock: DPMSCapable failed\n"); - if (!DPMSEnable(dpy)) - die("instantlock: DPMSEnable failed\n"); - if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off)) - die("instantlock: DPMSGetTimeouts failed\n"); - if (!standby || !suspend || !off) - /* set values if there arent some */ - standby = suspend = off = 300; - - DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime); - XFlush(dpy); - - /* run post-lock command */ - if (argc > 0) { - switch (fork()) { - case -1: - die("instantlock: fork failed: %s\n", strerror(errno)); - case 0: - monitorreset(dpy, standby, suspend, off); - - if (close(ConnectionNumber(dpy)) < 0) - die("instantlock: close: %s\n", strerror(errno)); - execvp(argv[0], argv); - fprintf(stderr, "instantlock: execvp %s: %s\n", argv[0], strerror(errno)); - _exit(1); - } + if (command->count > 0) { + runCommand = 1; } - /* everything is now blank. Wait for the correct password */ - readpw(dpy, &rr, locks, nscreens, hash); + fprintf(stderr, "lock message : %s\n", lock_message); + fprintf(stderr, "oneButton : %d\n", oneButton); + fprintf(stderr, "runCommand : %d\n", runCommand); - /* reset DPMS values to inital ones */ - monitorreset(dpy, standby, suspend, off); + lock(lock_message, oneButton, runCommand, argv); - return 0; +exit: + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); + return exitcode; } diff --git a/lock.h b/lock.h new file mode 100644 index 0000000..458b53e --- /dev/null +++ b/lock.h @@ -0,0 +1,528 @@ +#ifndef LOCK_H +#define LOCK_H + +/* See LICENSE file for license details. */ + +#define _XOPEN_SOURCE 500 +#if HAVE_SHADOW_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "util.h" + +char *argv0; + +/* global count to prevent repeated error messages */ +int count_error = 0; + +enum { + INIT, + INPUT, + FAILED, + NUMCOLS +}; + +struct lock { + int screen; + Window root, win; + Pixmap pmap; + unsigned long colors[NUMCOLS]; +}; + +struct xrandr { + int active; + int evbase; + int errbase; +}; + +#include "config.h" + +static void +die(const char *errstr, ...) +{ + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + +#ifdef __linux__ +#include +#include + +static void +dontkillme(void) +{ + FILE *f; + const char oomfile[] = "/proc/self/oom_score_adj"; + + if (!(f = fopen(oomfile, "w"))) { + if (errno == ENOENT) + return; + die("instantlock: fopen %s: %s\n", oomfile, strerror(errno)); + } + fprintf(f, "%d", OOM_SCORE_ADJ_MIN); + if (fclose(f)) { + if (errno == EACCES) + die("instantlock: unable to disable OOM killer. " + "Make sure to suid or sgid instantlock.\n"); + else + die("instantlock: fclose %s: %s\n", oomfile, strerror(errno)); + } +} +#endif + +static void +writemessage(Display *dpy, Window win, int screen, const char* message) +{ + int len, line_len, width, height, s_width, s_height, i, j, k, tab_replace, tab_size; + XGCValues gr_values; + XFontStruct *fontinfo; + XColor color, dummy; + XineramaScreenInfo *xsi; + GC gc; + fontinfo = XLoadQueryFont(dpy, font_name); + + if (fontinfo == NULL) { + if (count_error == 0) { + fprintf(stderr, "instantlock: Unable to load font \"%s\"\n", font_name); + fprintf(stderr, "instantlock: Try listing fonts with 'instantlock -f'\n"); + count_error++; + } + return; + } + + tab_size = 8 * XTextWidth(fontinfo, " ", 1); + + XAllocNamedColor(dpy, DefaultColormap(dpy, screen), + text_color, &color, &dummy); + + gr_values.font = fontinfo->fid; + gr_values.foreground = color.pixel; + gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values); + + /* To prevent "Uninitialized" warnings. */ + xsi = NULL; + + /* + * Start formatting and drawing text + */ + + len = strlen(message); + + /* Max max line length (cut at '\n') */ + line_len = 0; + k = 0; + for (i = j = 0; i < len; i++) { + if (message[i] == '\n') { + if (i - j > line_len) + line_len = i - j; + k++; + i++; + j = i; + } + } + /* If there is only one line */ + if (line_len == 0) + line_len = len; + + if (XineramaIsActive(dpy)) { + xsi = XineramaQueryScreens(dpy, &i); + s_width = xsi[0].width; + s_height = xsi[0].height; + } else { + s_width = DisplayWidth(dpy, screen); + s_height = DisplayHeight(dpy, screen); + } + + height = s_height*3/7 - (k*20)/3; + width = (s_width - XTextWidth(fontinfo, message, line_len))/2; + + /* Look for '\n' and print the text between them. */ + for (i = j = k = 0; i <= len; i++) { + /* i == len is the special case for the last line */ + if (i == len || message[i] == '\n') { + tab_replace = 0; + while (message[j] == '\t' && j < i) { + tab_replace++; + j++; + } + + XDrawString(dpy, win, gc, width + tab_size*tab_replace, height + 20*k, message + j, i - j); + while (i < len && message[i] == '\n') { + i++; + j = i; + k++; + } + } + } + + /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ + if (XineramaIsActive(dpy) && xsi != NULL) + XFree(xsi); +} + + + +static const char * +gethash(void) +{ + const char *hash; + struct passwd *pw; + + /* Check if the current user has a password entry */ + errno = 0; + if (!(pw = getpwuid(getuid()))) { + if (errno) + die("instantlock: getpwuid: %s\n", strerror(errno)); + else + die("instantlock: cannot retrieve password entry\n"); + } + hash = pw->pw_passwd; + +#if HAVE_SHADOW_H + if (!strcmp(hash, "x")) { + struct spwd *sp; + if (!(sp = getspnam(pw->pw_name))) + die("instantlock: getspnam: cannot retrieve shadow entry. " + "Make sure to suid or sgid instantlock.\n"); + hash = sp->sp_pwdp; + } +#else + if (!strcmp(hash, "*")) { +#ifdef __OpenBSD__ + if (!(pw = getpwuid_shadow(getuid()))) + die("instantlock: getpwnam_shadow: cannot retrieve shadow entry. " + "Make sure to suid or sgid instantlock.\n"); + hash = pw->pw_passwd; +#else + die("instantlock: getpwuid: cannot retrieve shadow entry. " + "Make sure to suid or sgid instantlock.\n"); +#endif /* __OpenBSD__ */ + } +#endif /* HAVE_SHADOW_H */ + + return hash; +} + +static void +readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, + const char *hash, int oneButton, const char* lock_message) +{ + XRRScreenChangeNotifyEvent *rre; + char buf[32], passwd[256], *inputhash; + char tmpmessage[300] = "entering password : "; + int num, screen, running, failure; + unsigned int len, color; + KeySym ksym; + XEvent ev; + + len = 0; + running = 1; + failure = 0; + + while (running && !XNextEvent(dpy, &ev)) { + if (ev.type == KeyPress) { + if (oneButton) { + running = 0; + } + explicit_bzero(&buf, sizeof(buf)); + num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); + if (IsKeypadKey(ksym)) { + if (ksym == XK_KP_Enter) + ksym = XK_Return; + else if (ksym >= XK_KP_0 && ksym <= XK_KP_9) + ksym = (ksym - XK_KP_0) + XK_0; + } + if (IsFunctionKey(ksym) || + IsKeypadKey(ksym) || + IsMiscFunctionKey(ksym) || + IsPFKey(ksym) || + IsPrivateKeypadKey(ksym)) + continue; + switch (ksym) { + case XK_Return: + if (oneButton) { + running = 0; + break; + } + passwd[len] = '\0'; + errno = 0; + if (!(inputhash = crypt(passwd, hash))) + fprintf(stderr, "instantlock: crypt: %s\n", strerror(errno)); + else + running = !!strcmp(inputhash, hash); + if (running) { + XBell(dpy, 100); + failure = 1; + } + explicit_bzero(&passwd, sizeof(passwd)); + len = 0; + break; + case XK_Escape: + explicit_bzero(&passwd, sizeof(passwd)); + len = 0; + break; + case XK_BackSpace: + if (len) + passwd[--len] = '\0'; + break; + default: + if (num && !iscntrl((int)buf[0]) && + (len + num < sizeof(passwd))) { + memcpy(passwd + len, buf, num); + len += num; + } + break; + } + color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); + if (color == INPUT) { + lock_message = tmpmessage; + for (int i = 0; i < strlen(passwd); i++) + { + tmpmessage[i + 20] = '.'; + tmpmessage[i + 21] = '\0'; + } + } + if (running) { + for (screen = 0; screen < nscreens; screen++) { + XSetWindowBackground(dpy, + locks[screen]->win, + locks[screen]->colors[color]); + XClearWindow(dpy, locks[screen]->win); + writemessage(dpy, locks[screen]->win, screen, lock_message); + } + } + } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) { + rre = (XRRScreenChangeNotifyEvent*)&ev; + for (screen = 0; screen < nscreens; screen++) { + if (locks[screen]->win == rre->window) { + if (rre->rotation == RR_Rotate_90 || + rre->rotation == RR_Rotate_270) + XResizeWindow(dpy, locks[screen]->win, + rre->height, rre->width); + else + XResizeWindow(dpy, locks[screen]->win, + rre->width, rre->height); + XClearWindow(dpy, locks[screen]->win); + break; + } + } + } else { + for (screen = 0; screen < nscreens; screen++) + XRaiseWindow(dpy, locks[screen]->win); + } + } +} + +static struct lock * +lockscreen(Display *dpy, struct xrandr *rr, int screen) +{ + char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; + int i, ptgrab, kbgrab; + struct lock *lock; + XColor color, dummy; + XSetWindowAttributes wa; + Cursor invisible; + + if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock)))) + return NULL; + + lock->screen = screen; + lock->root = RootWindow(dpy, lock->screen); + + for (i = 0; i < NUMCOLS; i++) { + XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), + colorname[i], &color, &dummy); + lock->colors[i] = color.pixel; + } + + /* init */ + wa.override_redirect = 1; + wa.background_pixel = lock->colors[INIT]; + lock->win = XCreateWindow(dpy, lock->root, 0, 0, + DisplayWidth(dpy, lock->screen), + DisplayHeight(dpy, lock->screen), + 0, DefaultDepth(dpy, lock->screen), + CopyFromParent, + DefaultVisual(dpy, lock->screen), + CWOverrideRedirect | CWBackPixel, &wa); + lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); + invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, + &color, &color, 0, 0); + XDefineCursor(dpy, lock->win, invisible); + + /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ + for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) { + if (ptgrab != GrabSuccess) { + ptgrab = XGrabPointer(dpy, lock->root, False, + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask, GrabModeAsync, + GrabModeAsync, None, invisible, CurrentTime); + } + if (kbgrab != GrabSuccess) { + kbgrab = XGrabKeyboard(dpy, lock->root, True, + GrabModeAsync, GrabModeAsync, CurrentTime); + } + + /* input is grabbed: we can lock the screen */ + if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { + XMapRaised(dpy, lock->win); + if (rr->active) + XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); + + XSelectInput(dpy, lock->root, SubstructureNotifyMask); + return lock; + } + + /* retry on AlreadyGrabbed but fail on other errors */ + if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) || + (kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess)) + break; + + usleep(100000); + } + + /* we couldn't grab all input: fail out */ + if (ptgrab != GrabSuccess) + fprintf(stderr, "instantlock: unable to grab mouse pointer for screen %d\n", + screen); + if (kbgrab != GrabSuccess) + fprintf(stderr, "instantlock: unable to grab keyboard for screen %d\n", + screen); + return NULL; +} + +static void +monitorreset(Display* dpy, CARD16 standby, CARD16 suspend, CARD16 off) +{ + DPMSSetTimeouts(dpy, standby, suspend, off); + DPMSForceLevel(dpy, DPMSModeOn); + XFlush(dpy); +} + +static int lock(const char* lock_message, int oneButton, int runCommand, char*const* argv) { + CARD16 standby, suspend, off; + Display *dpy; + const char *hash; + gid_t dgid; + int s, nlocks, nscreens; + struct group *grp; + struct lock **locks; + struct passwd *pwd; + struct xrandr rr; + uid_t duid; + + /* validate drop-user and -group */ + errno = 0; + if (!(pwd = getpwnam(user))) + die("instantlock: getpwnam %s: %s\n", user, + errno ? strerror(errno) : "user entry not found"); + duid = pwd->pw_uid; + errno = 0; + if (!(grp = getgrnam(group))) + die("instantlock: getgrnam %s: %s\n", group, + errno ? strerror(errno) : "group entry not found"); + dgid = grp->gr_gid; + +#ifdef __linux__ + dontkillme(); +#endif + + hash = gethash(); + errno = 0; + if (!crypt("", hash)) + die("instantlock: crypt: %s\n", strerror(errno)); + + if (!(dpy = XOpenDisplay(NULL))) + die("instantlock: cannot open display\n"); + + /* drop privileges */ + if (setgroups(0, NULL) < 0) + die("instantlock: setgroups: %s\n", strerror(errno)); + if (setgid(dgid) < 0) + die("instantlock: setgid: %s\n", strerror(errno)); + if (setuid(duid) < 0) + die("instantlock: setuid: %s\n", strerror(errno)); + + /* check for Xrandr support */ + rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); + + /* get number of screens in display "dpy" and blank them */ + nscreens = ScreenCount(dpy); + if (!(locks = calloc(nscreens, sizeof(struct lock *)))) + die("instantlock: out of memory\n"); + for (nlocks = 0, s = 0; s < nscreens; s++) { + if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) { + writemessage(dpy, locks[s]->win, s, lock_message); + nlocks++; + } else { + break; + } + } + XSync(dpy, 0); + + /* did we manage to lock everything? */ + if (nlocks != nscreens) + return 1; + + /* DPMS-magic to disable the monitor */ + if (!DPMSCapable(dpy)) + die("instantlock: DPMSCapable failed\n"); + if (!DPMSEnable(dpy)) + die("instantlock: DPMSEnable failed\n"); + if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off)) + die("instantlock: DPMSGetTimeouts failed\n"); + if (!standby || !suspend || !off) + /* set values if there arent some */ + standby = suspend = off = 300; + + DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime); + XFlush(dpy); + + /* run post-lock command */ + if (runCommand) { + switch (fork()) { + case -1: + die("instantlock: fork failed: %s\n", strerror(errno)); + case 0: + monitorreset(dpy, standby, suspend, off); + + if (close(ConnectionNumber(dpy)) < 0) + die("instantlock: close: %s\n", strerror(errno)); + execvp(argv[0], argv); + fprintf(stderr, "instantlock: execvp %s: %s\n", argv[0], strerror(errno)); + _exit(1); + } + } + + /* everything is now blank. Wait for the correct password */ + readpw(dpy, &rr, locks, nscreens, hash, oneButton, lock_message); + + /* reset DPMS values to inital ones */ + monitorreset(dpy, standby, suspend, off); + + return 0; +} + +#endif //LOCK_H From bf84f3af80fd5f4f349cf5483806e90796a59c02 Mon Sep 17 00:00:00 2001 From: SCOTT-HAMILTON Date: Sat, 8 Aug 2020 17:06:06 +0200 Subject: [PATCH 3/4] DBus Service Implementation using gdbus. --- Makefile | 2 +- config.mk | 6 +- dbus/org.instantos.instantLOCK.xml | 5 + dbusadapter.c | 190 +++++++++++++++++++++++++++++ dbusadapter.h | 7 ++ instantlock.c | 10 +- lock.h | 2 +- 7 files changed, 217 insertions(+), 5 deletions(-) create mode 100644 dbusadapter.c create mode 100644 dbusadapter.h diff --git a/Makefile b/Makefile index ddb0106..d11f8ef 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ include config.mk -SRC = instantlock.c ${COMPATSRC} +SRC = instantlock.c dbusadapter.c ${COMPATSRC} OBJ = ${SRC:.c=.o} all: options instantlock diff --git a/config.mk b/config.mk index 865255a..71db600 100644 --- a/config.mk +++ b/config.mk @@ -10,13 +10,15 @@ DBUS_SERVICES_INSTALL_DIR = ${PREFIX}/share/dbus-1/services DBUS_INTERFACES_INSTALL_DIR = ${PREFIX}/share/dbus-1/interfaces ARGTABLE3_INCLUDE_DIR = ${PREFIX}/usr/include ARGTABLE3_LIB_DIR = ${PREFIX}/usr/lib +GLIB2_CFLAGS = `pkg-config --cflags glib-2.0` `pkg-config --cflags gio-unix-2.0` +GLIB2_LDFLAGS = `pkg-config --libs glib-2.0` `pkg-config --libs gio-unix-2.0` X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib # includes and libs -INCS = -I. -I/usr/include -I${X11INC} -I${ARGTABLE3_INCLUDE_DIR} -LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -L${ARGTABLE3_LIB_DIR} -lX11 -lXext -lXrandr -lXinerama -largtable3 +INCS = -I. -I/usr/include -I${X11INC} -I${ARGTABLE3_INCLUDE_DIR} ${GLIB2_CFLAGS} +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -L${ARGTABLE3_LIB_DIR} ${GLIB2_LDFLAGS} -lX11 -lXext -lXrandr -lXinerama -largtable3 # flags CPPFLAGS += -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/dbus/org.instantos.instantLOCK.xml b/dbus/org.instantos.instantLOCK.xml index 55e0bd4..748178d 100644 --- a/dbus/org.instantos.instantLOCK.xml +++ b/dbus/org.instantos.instantLOCK.xml @@ -16,6 +16,11 @@ The message to print. + + + Press any key to unlock. + + Locks the screen. diff --git a/dbusadapter.c b/dbusadapter.c new file mode 100644 index 0000000..4608984 --- /dev/null +++ b/dbusadapter.c @@ -0,0 +1,190 @@ +#include +#include +#include +#include + +#ifdef G_OS_UNIX +#include +/* For STDOUT_FILENO */ +#include +#endif + +#include "lock.h" + +/* ---------------------------------------------------------------------------------------------------- */ + +static GDBusNodeInfo *introspection_data = NULL; + +/* Introspection data for the service we are exporting */ +static const gchar introspection_xml[] = +" " +" " +" " +" " +" " +" The message to print." +" " +" " +" " +" " +" Press any key to unlock." +" " +" " +" " +" " +" Locks the screen." +" " +" " +" " +" " +" " +" " +" Emitted if the user locked the screen." +" " +" " +" " +" " +" " +" " +" Emitted if the user successfully unlocked the screen." +" " +" " +" " +" " +" "; + +/* ---------------------------------------------------------------------------------------------------- */ + + static void +handle_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + if (g_strcmp0 (method_name, "Lock") == 0) + { + const gchar *message; + gboolean oneKey; + g_variant_get (parameters, "(sb)", &message, &oneKey); + fprintf(stderr, "Received Lock Call with args : message `%s`, oneKey : `%d`\n", message, oneKey); + lock(message, oneKey, 0, NULL); + + } else { + fprintf(stderr, "Unknown method name : %s\n", method_name); + } +/* ERROR */ +/* g_dbus_method_invocation_return_dbus_error (invocation, */ +/* "org.gtk.GDBus.NotOnUnix", */ +/* "Your OS does not support file descriptor passing"); */ +} + +static GVariant * +handle_get_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + GVariant *ret; + + ret = NULL; + /* ret = g_variant_new_string ("DeLorean"); */ + + return ret; +} + + static gboolean +handle_set_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **error, + gpointer user_data) +{ + return TRUE; +} + + +/* for now */ +static const GDBusInterfaceVTable interface_vtable = +{ + handle_method_call, + handle_get_property, + handle_set_property +}; + +/* ---------------------------------------------------------------------------------------------------- */ + + static void +on_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + guint registration_id; + + registration_id = g_dbus_connection_register_object (connection, + "/org/instantos/InstantLock", + introspection_data->interfaces[0], + &interface_vtable, + NULL, /* user_data */ + NULL, /* user_data_free_func */ + NULL); /* GError** */ + g_assert (registration_id > 0); + +} + + static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + fprintf(stderr, "[log] Name `%s` acquired\n", name); +} + + static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + fprintf(stderr, "[log] Name `%s` lost\n", name); + exit (1); +} + +void +dbus_listen () +{ + guint owner_id; + GMainLoop *loop; + + /* We are lazy here - we don't want to manually provide + * the introspection data structures - so we just build + * them from XML. + */ + introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); + g_assert (introspection_data != NULL); + + owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + "org.instantos.instantLock", + G_BUS_NAME_OWNER_FLAGS_NONE, + on_bus_acquired, + on_name_acquired, + on_name_lost, + NULL, + NULL); + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + g_bus_unown_name (owner_id); + + g_dbus_node_info_unref (introspection_data); +} + diff --git a/dbusadapter.h b/dbusadapter.h new file mode 100644 index 0000000..42d920d --- /dev/null +++ b/dbusadapter.h @@ -0,0 +1,7 @@ +#ifndef DBUSADAPTER_H +#define DBUSADAPTER_H + +void +dbus_listen(); + +#endif //DBUSADAPTER_H diff --git a/instantlock.c b/instantlock.c index 40d0c42..790ca3e 100644 --- a/instantlock.c +++ b/instantlock.c @@ -4,6 +4,7 @@ #include #include "lock.h" +#include "dbusadapter.h" int main(int argc, char **argv) { @@ -13,7 +14,7 @@ main(int argc, char **argv) { int oneButton = onebutton; int runCommand = 0; const char* lock_message = message; - struct arg_lit *help, *version, *fonts, *anyKey; + struct arg_lit *help, *version, *fonts, *anyKey, *dbus; struct arg_str *message, *command; struct arg_end *end; @@ -23,6 +24,7 @@ main(int argc, char **argv) { version = arg_litn("v", "version", 0, 1, "print instantlock version"), fonts = arg_litn("f", "fonts", 0, 1, "list available fonts"), anyKey = arg_litn("o", NULL, 0, 1, "press any key"), + dbus = arg_litn("d", "dbus", 0, 1, "run the dbus service"), message = arg_str0("m", "message", "MESSAGE", "display the specified message"), command = arg_strn(NULL, NULL, "COMMAND [ARGS ...]",0,argc+2,NULL), end = arg_end(20) @@ -93,6 +95,12 @@ main(int argc, char **argv) { exitcode = 0; goto exit; } + if (dbus->count > 0) { + dbus_listen(); + exitcode = 0; + goto exit; + } + if (command->count > 0) { runCommand = 1; } diff --git a/lock.h b/lock.h index 458b53e..3c7ab1b 100644 --- a/lock.h +++ b/lock.h @@ -31,7 +31,7 @@ char *argv0; /* global count to prevent repeated error messages */ -int count_error = 0; +static int count_error = 0; enum { INIT, From ae4f32f4ee281f6926ae9efe3b6593fb32139638 Mon Sep 17 00:00:00 2001 From: SCOTT-HAMILTON Date: Sun, 16 Aug 2020 19:31:52 +0200 Subject: [PATCH 4/4] Update --- Makefile | 4 +++- config.mk | 1 + dbus/instantlock-dbus.conf | 22 ++++++++++++++++++++++ dbusadapter.c | 5 +++-- 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 dbus/instantlock-dbus.conf diff --git a/Makefile b/Makefile index d11f8ef..ed09e67 100644 --- a/Makefile +++ b/Makefile @@ -55,9 +55,10 @@ install: all @mkdir -p ${DESTDIR}${MANPREFIX}/man1 @sed "s/VERSION/${VERSION}/g" ${DESTDIR}${MANPREFIX}/man1/instantlock.1 @chmod 644 ${DESTDIR}${MANPREFIX}/man1/instantlock.1 - @echo installing dbus service and interface to ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR} + @echo installing dbus service, interface and config @install -Dm 644 dbus/org.instantos.instantlock.service ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR}/org.instantos.instantlock.service @install -Dm 644 dbus/org.instantos.instantLOCK.xml ${DESTDIR}${DBUS_INTERFACES_INSTALL_DIR}/org.instantos.instantLOCK.xml + @install -Dm 644 dbus/instantlock-dbus.conf ${DESTDIR}${DBUS_CONFIG_INSTALL_DIR}/instantlock-dbus.conf uninstall: @echo removing executable file from ${DESTDIR}${PREFIX}/bin @@ -67,5 +68,6 @@ uninstall: @echo uninstalling dbus service and interface from ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR} @rm -f ${DESTDIR}${DBUS_SERVICES_INSTALL_DIR}/org.instantos.instantlock.service @rm -f ${DESTDIR}${DBUS_INTERFACES_INSTALL_DIR}/org.instantos.instantLOCK.xml + @rm -f ${DESTDIR}${DBUS_CONFIG_INSTALL_DIR}/instantlock-dbus.conf .PHONY: all options clean dist install uninstall diff --git a/config.mk b/config.mk index 71db600..b489434 100644 --- a/config.mk +++ b/config.mk @@ -8,6 +8,7 @@ PREFIX = /usr MANPREFIX = ${PREFIX}/share/man DBUS_SERVICES_INSTALL_DIR = ${PREFIX}/share/dbus-1/services DBUS_INTERFACES_INSTALL_DIR = ${PREFIX}/share/dbus-1/interfaces +DBUS_CONFIG_INSTALL_DIR = ${PREFIX}/etc/dbus-1/system.d ARGTABLE3_INCLUDE_DIR = ${PREFIX}/usr/include ARGTABLE3_LIB_DIR = ${PREFIX}/usr/lib GLIB2_CFLAGS = `pkg-config --cflags glib-2.0` `pkg-config --cflags gio-unix-2.0` diff --git a/dbus/instantlock-dbus.conf b/dbus/instantlock-dbus.conf new file mode 100644 index 0000000..f0766c2 --- /dev/null +++ b/dbus/instantlock-dbus.conf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dbusadapter.c b/dbusadapter.c index 4608984..4f31dc8 100644 --- a/dbusadapter.c +++ b/dbusadapter.c @@ -171,9 +171,10 @@ dbus_listen () introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (introspection_data != NULL); - owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + owner_id = g_bus_own_name ( + G_BUS_TYPE_SYSTEM, "org.instantos.instantLock", - G_BUS_NAME_OWNER_FLAGS_NONE, + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, on_bus_acquired, on_name_acquired, on_name_lost,