aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFRIGN <dev@frign.de>2016-08-22 00:25:21 +0200
committerMarkus Teich <markus.teich@stusta.mhn.de>2016-08-22 23:22:20 +0200
commit3bb868e40873c568acdec74f7783c77f063aa396 (patch)
tree2f6f2406770cb9e5795832dcace37ac536469341
parenta7afade1701a809f6a33b53525d59dd29b38d381 (diff)
Refactor main()
- Add arg.h and fix usage Given slock is suid we don't want to have half-measures in place to parse the arguments in case the code is changed in the future with somebody not paying enough attention. Also, fix the usage string output to be more consistent across the suckless toolbase and make it reflect the manpage entry. - Comments Use proper block comments and add/change them where necessary to help in studying the code. - Error messages Consistently prepend them with "slock:" and fix wording and do a proper cleanup before quitting (XCloseDisplay and free the locks), making the die() semantics consistent with st's. - getpwuid() error reporting Properly present an error message if getpwuid() fails. - fork() error reporting Properly present an error message if fork() fails. If we cannot close the connection within the fork context we abort the operation and report an error. - execvp() error handling If execvp fails, we cannot call die() afterwards as this implies calling exit(). We must use _exit() to prevent the libc from doing now "illegal" cleanup-work.
-rw-r--r--arg.h65
-rw-r--r--slock.c85
2 files changed, 119 insertions, 31 deletions
diff --git a/arg.h b/arg.h
new file mode 100644
index 0000000..0b23c53
--- /dev/null
+++ b/arg.h
@@ -0,0 +1,65 @@
1/*
2 * Copy me if you can.
3 * by 20h
4 */
5
6#ifndef ARG_H__
7#define ARG_H__
8
9extern char *argv0;
10
11/* use main(int argc, char *argv[]) */
12#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
13 argv[0] && argv[0][0] == '-'\
14 && argv[0][1];\
15 argc--, argv++) {\
16 char argc_;\
17 char **argv_;\
18 int brk_;\
19 if (argv[0][1] == '-' && argv[0][2] == '\0') {\
20 argv++;\
21 argc--;\
22 break;\
23 }\
24 for (brk_ = 0, argv[0]++, argv_ = argv;\
25 argv[0][0] && !brk_;\
26 argv[0]++) {\
27 if (argv_ != argv)\
28 break;\
29 argc_ = argv[0][0];\
30 switch (argc_)
31
32/* Handles obsolete -NUM syntax */
33#define ARGNUM case '0':\
34 case '1':\
35 case '2':\
36 case '3':\
37 case '4':\
38 case '5':\
39 case '6':\
40 case '7':\
41 case '8':\
42 case '9'
43
44#define ARGEND }\
45 }
46
47#define ARGC() argc_
48
49#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
50
51#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
52 ((x), abort(), (char *)0) :\
53 (brk_ = 1, (argv[0][1] != '\0')?\
54 (&argv[0][1]) :\
55 (argc--, argv++, argv[0])))
56
57#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
58 (char *)0 :\
59 (brk_ = 1, (argv[0][1] != '\0')?\
60 (&argv[0][1]) :\
61 (argc--, argv++, argv[0])))
62
63#define LNGARG() &argv[0][0]
64
65#endif
diff --git a/slock.c b/slock.c
index a00fbb9..210d5c8 100644
--- a/slock.c
+++ b/slock.c
@@ -23,8 +23,11 @@
23#include <bsd_auth.h> 23#include <bsd_auth.h>
24#endif 24#endif
25 25
26#include "arg.h"
26#include "util.h" 27#include "util.h"
27 28
29char *argv0;
30
28enum { 31enum {
29 INIT, 32 INIT,
30 INPUT, 33 INPUT,
@@ -54,7 +57,6 @@ die(const char *errstr, ...)
54{ 57{
55 va_list ap; 58 va_list ap;
56 59
57 fputs("slock: ", stderr);
58 va_start(ap, errstr); 60 va_start(ap, errstr);
59 vfprintf(stderr, errstr, ap); 61 vfprintf(stderr, errstr, ap);
60 va_end(ap); 62 va_end(ap);
@@ -280,8 +282,7 @@ lockscreen(Display *dpy, int screen)
280static void 282static void
281usage(void) 283usage(void)
282{ 284{
283 fprintf(stderr, "usage: slock [-v|POST_LOCK_CMD]\n"); 285 die("usage: slock [-v | cmd [arg ...]]\n");
284 exit(1);
285} 286}
286 287
287int 288int
@@ -290,64 +291,86 @@ main(int argc, char **argv) {
290 const char *pws; 291 const char *pws;
291#endif 292#endif
292 Display *dpy; 293 Display *dpy;
293 int screen; 294 int s, nlocks;
294 295
295 if ((argc >= 2) && !strcmp("-v", argv[1])) 296 ARGBEGIN {
296 die("version %s, © 2006-2016 slock engineers\n", VERSION); 297 case 'v':
297 298 fprintf(stderr, "slock-"VERSION"\n");
298 /* treat first argument starting with a '-' as option */ 299 return 0;
299 if ((argc >= 2) && argv[1][0] == '-') 300 default:
300 usage(); 301 usage();
302 } ARGEND
301 303
302#ifdef __linux__ 304#ifdef __linux__
303 dontkillme(); 305 dontkillme();
304#endif 306#endif
305 307
306 if (!getpwuid(getuid())) 308 /* Check if the current user has a password entry */
307 die("no passwd entry for you\n"); 309 errno = 0;
310 if (!getpwuid(getuid())) {
311 if (errno == 0)
312 die("slock: no password entry for current user\n");
313 else
314 die("slock: getpwuid: %s\n", strerror(errno));
315 }
308 316
309#ifndef HAVE_BSD_AUTH 317#ifndef HAVE_BSD_AUTH
310 pws = getpw(); 318 pws = getpw();
311#endif 319#endif
312 320
313 if (!(dpy = XOpenDisplay(0))) 321 if (!(dpy = XOpenDisplay(NULL)))
314 die("cannot open display\n"); 322 die("slock: cannot open display\n");
323
324 /* check for Xrandr support */
315 rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase); 325 rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase);
316 /* Get the number of screens in display "dpy" and blank them all. */ 326
327 /* get number of screens in display "dpy" and blank them */
317 nscreens = ScreenCount(dpy); 328 nscreens = ScreenCount(dpy);
318 if (!(locks = malloc(sizeof(Lock*) * nscreens))) 329 if (!(locks = malloc(sizeof(Lock *) * nscreens))) {
319 die("Out of memory.\n"); 330 XCloseDisplay(dpy);
320 int nlocks = 0; 331 die("slock: out of memory\n");
321 for (screen = 0; screen < nscreens; screen++) { 332 }
322 if ((locks[screen] = lockscreen(dpy, screen)) != NULL) 333 for (nlocks = 0, s = 0; s < nscreens; s++) {
334 if ((locks[s] = lockscreen(dpy, s)) != NULL)
323 nlocks++; 335 nlocks++;
324 } 336 }
325 XSync(dpy, False); 337 XSync(dpy, 0);
326 338
327 /* Did we actually manage to lock something? */ 339 /* did we actually manage to lock anything? */
328 if (nlocks == 0) { /* nothing to protect */ 340 if (nlocks == 0) {
341 /* nothing to protect */
329 free(locks); 342 free(locks);
330 XCloseDisplay(dpy); 343 XCloseDisplay(dpy);
331 return 1; 344 return 1;
332 } 345 }
333 346
334 if (argc >= 2 && fork() == 0) { 347 /* run post-lock command */
335 if (dpy) 348 if (argc > 0) {
336 close(ConnectionNumber(dpy)); 349 switch (fork()) {
337 execvp(argv[1], argv+1); 350 case -1:
338 die("execvp %s failed: %s\n", argv[1], strerror(errno)); 351 free(locks);
352 XCloseDisplay(dpy);
353 die("slock: fork failed: %s\n", strerror(errno));
354 case 0:
355 if (close(ConnectionNumber(dpy)) < 0)
356 die("slock: close: %s\n", strerror(errno));
357 execvp(argv[0], argv);
358 fprintf(stderr, "slock: execvp %s: %s\n", argv[0],
359 strerror(errno));
360 _exit(1);
361 }
339 } 362 }
340 363
341 /* Everything is now blank. Now wait for the correct password. */ 364 /* everything is now blank. Wait for the correct password */
342#ifdef HAVE_BSD_AUTH 365#ifdef HAVE_BSD_AUTH
343 readpw(dpy); 366 readpw(dpy);
344#else 367#else
345 readpw(dpy, pws); 368 readpw(dpy, pws);
346#endif 369#endif
347 370
348 /* Password ok, unlock everything and quit. */ 371 /* password ok, unlock everything and quit */
349 for (screen = 0; screen < nscreens; screen++) 372 for (s = 0; s < nscreens; s++)
350 unlockscreen(dpy, locks[screen]); 373 unlockscreen(dpy, locks[s]);
351 374
352 free(locks); 375 free(locks);
353 XCloseDisplay(dpy); 376 XCloseDisplay(dpy);