Lift the current argument limit (see BUGS section) and simplify the parsing logic by turning `xidle -program "/bin/prog args"' into `xidle prog args' where normal argv is used instead of an strsep(3) routine.
Search PATH with execvp(3), drop unused status parameter from wait(2) while here. Merge `fopts' and `opts' since there is no need to split `-display' parsing from the rest, so XrmParseCommand(3) is called once still handling display setup first. Users would have to adjust their xidle invocations but the change is trivial and introduces nice improvements, so that's reasonble; I'd put a note into current.html. Feedback? Objections? OK? PS: This diff applies cleanly against -CURRENT and is independent from my earlier ones and but will conflict diff-wise. Index: xidle.1 =================================================================== RCS file: /cvs/xenocara/app/xidle/xidle.1,v retrieving revision 1.5 diff -u -p -r1.5 xidle.1 --- xidle.1 6 Sep 2018 07:21:34 -0000 1.5 +++ xidle.1 4 Nov 2018 01:43:21 -0000 @@ -23,7 +23,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 20, 2005 +.Dd $Mdocdate: November 4 2018 $ .Dt XIDLE 1 .Os .Sh NAME @@ -36,8 +36,8 @@ .Op Fl delay Ar secs .Op Fl display Ar display .Op Fl no | nw | ne | sw | se -.Op Fl program Ar path .Op Fl timeout Ar secs +.Op Ar program Op Ar args .Ek .Sh DESCRIPTION .Nm @@ -45,6 +45,8 @@ uses the .Xr XScreenSaver 3 extension to receive inactivity events when a timeout is specified, running a specific program after the elapsed time. +The default is +.Xr xlock 1 . .Nm will also run the program if it is sent a .Dv SIGUSR1 @@ -71,14 +73,6 @@ Set the position to one of none, northwe respectively. If no position is specified, the default is northwest. -.It Fl program Ar path -Specify the full pathname of the program to run on any of the -aforementioned events. -Arguments to the program may also be specified, separated by whitespace. -If -.Fl program -is not specified, the default is -.Xr xlock 1 . .It Fl timeout Ar secs Set the timeout to the specified number of seconds. If @@ -129,8 +123,7 @@ Run using the flying bats mode if no activity is detected in 300 seconds or the pointer sits in the southwest corner for more than 5 seconds: .Bd -literal -offset indent -$ xidle -delay 5 -sw -program "/usr/X11R6/bin/xlock -mode bat" \e - -timeout 300 +$ xidle -delay 5 -sw xlock -mode bat -timeout 300 .Ed .Sh SEE ALSO .Xr xlock 1 , @@ -142,7 +135,3 @@ The program was written by .An Federico Schwindt Aq Mt fg...@openbsd.org as an xautolock replacement. -.Sh BUGS -The maximum number of arguments for -.Fl program , -including the executable file, is currently set to 9. Index: xidle.c =================================================================== RCS file: /cvs/xenocara/app/xidle/xidle.c,v retrieving revision 1.6 diff -u -p -r1.6 xidle.c --- xidle.c 6 Sep 2018 07:21:34 -0000 1.6 +++ xidle.c 4 Nov 2018 02:46:19 -0000 @@ -75,14 +75,10 @@ struct xinfo { struct xinfo x; -static XrmOptionDescRec fopts[] = { - { "-display", ".display", XrmoptionSepArg, (caddr_t)NULL }, -}; - static XrmOptionDescRec opts[] = { { "-area", ".area", XrmoptionSepArg, (caddr_t)NULL }, { "-delay", ".delay", XrmoptionSepArg, (caddr_t)NULL }, - { "-program", ".program", XrmoptionSepArg, (caddr_t)NULL }, + { "-display", ".display", XrmoptionSepArg, (caddr_t)NULL }, { "-timeout", ".timeout", XrmoptionSepArg, (caddr_t)NULL }, { "-no", ".position", XrmoptionNoArg, (caddr_t)"no" }, @@ -94,13 +90,12 @@ static XrmOptionDescRec opts[] = { extern char *__progname; -void action(struct xinfo *, char **); +void action(struct xinfo *, char *const []); void close_x(struct xinfo *); Bool getres(XrmValue *, const XrmDatabase, const char *, const char *); void init_x(struct xinfo *, int, int, int); void handler(int); -void parse_opts(int, char **, Display **, int *, int *, int *, int *, - char **); +void parse_opts(int, char **[], Display **, int *, int *, int *, int *); int str2pos(const char *); __dead void usage(void); @@ -108,9 +103,10 @@ __dead void usage(void); __dead void usage() { - fprintf(stderr, "Usage:\n%s %s\n", __progname, - "[-area pixels] [-delay secs] [-display host:dpy] " - "[-no | -ne | -nw | -se | -sw]\n [-program path] [-timeout secs]"); + fprintf(stderr, + "usage:\t%s [-area pixels] [-delay secs] [-display host:dpy]\n" + "\t [-no | -ne | -nw | -se | -sw] [-timeout secs] " + "[program [args]]\n", __progname); exit(1); } @@ -180,10 +176,8 @@ close_x(struct xinfo *xi) void -action(struct xinfo *xi, char **args) +action(struct xinfo *xi, char *const args[]) { - int dumb; - switch (fork()) { case -1: err(1, "fork"); @@ -191,12 +185,12 @@ action(struct xinfo *xi, char **args) case 0: setsid(); - execv(*args, args); + execvp(*args, args); exit(1); /* NOTREACHED */ default: - wait(&dumb); + wait(NULL); XSync(xi->dpy, True); break; } @@ -256,19 +250,24 @@ getres(XrmValue *value, const XrmDatabas void -parse_opts(int argc, char **argv, Display **dpy, int *area, int *delay, - int *timeout, int *position, char **args) +parse_opts(int argc, char **argvp[], Display **dpy, int *area, int *delay, + int *timeout, int *position) { - char **ap, *program = PATH_PROG; char *display, *p; XrmDatabase tdb, rdb = NULL; XrmValue value; XrmInitialize(); - /* Get display to open. */ - XrmParseCommand(&rdb, fopts, sizeof(fopts) / sizeof(fopts[0]), - __progname, &argc, argv); + /* Get command line values. */ + XrmParseCommand(&rdb, opts, sizeof(opts) / sizeof(opts[0]), + __progname, &argc, *argvp); + if (argc > 1) { + (*argvp)++; + if ((*argvp)[0][0] == '-') + usage(); + } else + (*argvp)[0] = PATH_PROG; display = (getres(&value, rdb, "display", "Display") == True) ? (char *)value.addr : NULL; @@ -292,15 +291,8 @@ parse_opts(int argc, char **argv, Displa XrmMergeDatabases(tdb, &rdb); } - /* Get remaining command line values. */ - XrmParseCommand(&rdb, opts, sizeof(opts) / sizeof(opts[0]), - __progname, &argc, argv); - if (argc > 1) { - usage(); - /* NOTREACHED */ - } if (getres(&value, rdb, "area", "Area")) { - *area = strtol((char *)value.addr, &p, 10); + *area = strtol((char *)value.addr, &p, 9); if (*p || *area < 1) { fail: errx(1, "illegal value -- %s", (char *)value.addr); /* NOTREACHED */ @@ -321,24 +313,12 @@ fail: errx(1, "illegal value -- %s", ( if (*p || *timeout < 0) goto fail; } - if (getres(&value, rdb, "program", "Program")) { - /* Should be the last :) */ - program = (char *)value.addr; - } - - for (ap = args; ap < &args[9] && - (*ap = strsep(&program, " ")) != NULL;) { - if (**ap != '\0') - ap++; - } - *ap = NULL; } int main(int argc, char **argv) { - char *args[10]; int area = 2, delay = 2, timeout = 0; int position = north|west; int fd; @@ -346,14 +326,12 @@ main(int argc, char **argv) bzero(&x, sizeof(struct xinfo)); - - parse_opts(argc, argv, &x.dpy, &area, &delay, &timeout, - &position, args); + parse_opts(argc, &argv, &x.dpy, &area, &delay, &timeout, &position); #ifdef DEBUG printf("Area: %d\nDelay: %d\nPosition: %d\nTimeout: %d\n" "Program: \"%s\"\n", - area, delay, position, timeout, args[0]); + area, delay, position, timeout, argv[0]); #endif init_x(&x, position, area, timeout); @@ -415,7 +393,7 @@ main(int argc, char **argv) close_x(&x); exit(0); } else if (ev.xclient.message_type == XIDLE_LOCK) - action(&x, args); + action(&x, argv); break; case EnterNotify: @@ -433,7 +411,7 @@ main(int argc, char **argv) ev.xcrossing.x_root > x.coord_x + area || ev.xcrossing.y_root > x.coord_y + area) break; - action(&x, args); + action(&x, argv); break; default: @@ -449,7 +427,7 @@ main(int argc, char **argv) * switching or a locking program? */ if (timeout > 0 && se->forced == False) - action(&x, args); + action(&x, argv); } break; } =================================================================== Stats: --- 65 lines 1991 chars Stats: +++ 32 lines 1156 chars Stats: -33 lines Stats: -835 chars