diff options
| author | Mattias Andrée <maandree@operamail.com> | 2014-10-28 10:23:34 +0100 | 
|---|---|---|
| committer | Mattias Andrée <maandree@operamail.com> | 2014-10-28 10:23:34 +0100 | 
| commit | d374a86d6f91c927e749de0ae992ffc8c6cd0a45 (patch) | |
| tree | 52752362fddf321a6b02d3d8aa04b078e5a23d2b /src | |
| parent | m doc (diff) | |
| download | scrotty-d374a86d6f91c927e749de0ae992ffc8c6cd0a45.tar.gz scrotty-d374a86d6f91c927e749de0ae992ffc8c6cd0a45.tar.bz2 scrotty-d374a86d6f91c927e749de0ae992ffc8c6cd0a45.tar.xz | |
implement --exec
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/scrotty.c | 94 | 
1 files changed, 89 insertions, 5 deletions
| diff --git a/src/scrotty.c b/src/scrotty.c index c7e98ee..bb8e886 100644 --- a/src/scrotty.c +++ b/src/scrotty.c @@ -320,7 +320,7 @@ static int evaluate(char* restrict buf, size_t n, const char* restrict pattern,    char* fmt;    time_t t;    struct tm tm; - +      /* Expand '$' and '\'. */    while ((c = *pattern++))      { @@ -380,18 +380,80 @@ static int evaluate(char* restrict buf, size_t n, const char* restrict pattern,  /** + * Run a command for an image + *  + * @param   flatten_args  The arguments to run, 255 delimits the arguments + * @return                Zero on success -1 on error + */ +static int exec_image(char* flatten_args) +{ +  char** args; +  char* arg; +  size_t i, arg_count = 1; +  pid_t pid, reaped; +  int status; +   +  /* Count arguments. */ +  for (i = 0; flatten_args[i]; i++) +    if (flatten_args[i] == 255) +      arg_count++; +   +  /* Allocate argument array. */ +  args = alloca((arg_count + 1) * sizeof(char*)); +   +  /* Unflatten argument array. */ +  for (arg = flatten_args, i = 0;;) +    { +      args[i++] = arg; +      arg = strchr(arg, 255); +      if (arg == NULL) +	break; +      *arg++ = '\0'; +    } +  args[i] = NULL; + +  /* Fork process. */ +  pid = fork(); +  if (pid == -1) +    return -1; + +  /* Child process: */ +  if (pid == 0) +    { +      execvp(*args, args); +      perror(execname); +      exit(1); +      return -1; +    } +   +  /* Parent process: */ +   +  /* Wait for child to exit. */ +  for (reaped = 0; reaped != pid;) +    if (reaped = waitpid(pid, &status, 0), reaped < 0) +      return -1; +   +  /* Return successfully if and only if `the child` did. */ +  return status == 0 ? 0 : -1; +} + + +/**   * Take a screenshot of a framebuffer   *    * @param   fbno         The number of the framebuffer   * @param   filepattern  The pattern for the filename, `NULL` for default   * @return               Zero on success, -1 on error, 1 if the framebuffer does not exist   */ -static int save_fb(int fbno, const char* filepattern) +static int save_fb(int fbno, const char* filepattern, const char* execpattern)  {    char fbpath[PATH_MAX];    char imgpath[PATH_MAX]; +  char* execargs = NULL; +  char* old;    long width, height; -  int i; +  size_t size = PATH_MAX; +  int i, saved_errno;    /* Get pathname for framebuffer, and stop if we have read all existing ones. */    sprintf(fbpath, DEVDIR "/fb%i", fbno); @@ -422,7 +484,29 @@ static int save_fb(int fbno, const char* filepattern)    if (save(fbpath, imgpath, fbno, width, height) < 0)      return -1;    fprintf(stderr, "Saved framebuffer %i to %s\n", fbno, imgpath); -  return 0; +   +  /* Should we run a command over the image? */ +  if (execpattern == NULL) +    return 0; +   +  /* Get execute arguments. */ + retry: +  execargs = realloc(old = execargs, size * sizeof(char)); +  if (execargs == NULL) +    return saved_errno = errno, free(old), errno = saved_errno, -1; +  if (evaluate(execargs, size, execpattern, fbno, width, height, imgpath) < 0) +    { +      if ((errno != ENAMETOOLONG) || ((size >> 8) <= PATH_MAX)) +	return -1; +      size <<= 1; +      goto retry; +    } +   +  /* Run command over image. */ +  i = exec_image(execargs); +  saved_errno = errno; +  free(execargs); +  return errno = saved_errno, i;  } @@ -567,7 +651,7 @@ int main(int argc, char* argv[])    /* Take a screenshot of each framebuffer. */    for (fbno = 0;; fbno++)      { -      r = save_fb(fbno, filepattern < 0 ? NULL : argv[filepattern]); +      r = save_fb(fbno, filepattern < 0 ? NULL : argv[filepattern], exec < 0 ? NULL : argv[exec]);        if (r < 0)  return perror(execname), 1;        if (r > 0)  break;      } | 
