Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

LD_PRELOAD trick for completing command options



Hiya,

I'm just submitting this idea in case nobody had it before:

what about adding a small LD_PRELOAD wrapper for the getopts and
getopt_long functions in the installation of zsh (on systems
that support it) that could be used by the completion system for
the completion of options:

The completion system could do some nm -D to check whether the
command uses getopt or getopt_long, check that the command is
not setuid/setgid, and run the command with
LD_PRELOAD=/that/wrapper cmd, and parse the output from the
wrapper.

Maybe not something to do for every command, but for commands
for which we don't have a completion yet and know that doing
this hack won't harm.

Something like:

$ LD_PRELOAD=./a.so w -: 3>&1
hlusfVo
$ LD_PRELOAD=./a.so who -: 3>&1
abdlmpqrstuwHT
all:0:a
boot:0:b
count:0:q
dead:0:d
heading:0:H
ips:0:
login:0:l
lookup:0:
message:0:T
mesg:0:T
process:0:p
runlevel:0:r
short:0:s
time:0:t
users:0:u
writable:0:T
help:0:
version:0:


#define _GNU_SOURCE
#include <stdlib.h>
#include <getopt.h>
#include <stdio.h>
#include <string.h>

int getopt_long(int argc, char * const argv[],
		const char *optstring,
		const struct option *longopts, int *longindex) {
  FILE* f = fdopen(3, "w");

  if (!f)
    exit(111);

  fprintf(f, "%s\n", optstring);
  while (longopts->name) {
    int val = longopts->val;

    fprintf(f, "%s:%d:", longopts->name, longopts->has_arg);
    if (longopts->flag == NULL &&
	val > 0 &&
	val <= 0xFF &&
	val != ':' &&
	strchr(optstring, val))
      fprintf(f, "%c\n", val);
    else
      fprintf(f, "\n");
    longopts++;
  }

  exit(112);
}

int getopt(int argc, char * const argv[],
	   const char *optstring) {
  FILE* f = fdopen(3, "w");

  if (!f)
    exit(111);

  fprintf(f, "%s\n", optstring);
  exit(112);
}

Cheers,
Stéphane



Messages sorted by: Reverse Date, Date, Thread, Author