diff options
-rw-r--r-- | src/scrotty.c | 551 |
1 files changed, 309 insertions, 242 deletions
diff --git a/src/scrotty.c b/src/scrotty.c index 7a0e31b..8a45b24 100644 --- a/src/scrotty.c +++ b/src/scrotty.c @@ -74,69 +74,77 @@ static const char* inttable[] = /** - * `argv[0]` from `main` + * `argv[0]` from `main`. */ -static const char* execname; +static const char *execname; /** * Arguments for `convert`, * the output file should be printed into `convert_args[2]`. * `NULL` is `convert` shall not be used. */ -static char** convert_args = NULL; +static char **convert_args = NULL; /** * Create an PNM-file that is sent to `convert` for convertion - * to a compressed format, or directly to a file + * to a compressed format, or directly to a file. * - * @param fbname The framebuffer device - * @param width The width of the image - * @param height The height of the image + * @param fbname The framebuffer device. + * @param width The width of the image. + * @param height The height of the image. * @param fd The file descriptor connected to `convert`'s stdin - * @return Zero on success, -1 on error + * @return Zero on success, -1 on error. */ -static int save_pnm(const char* fbpath, long width, long height, int fd) +static int +save_pnm (const char *fbpath, long width, long height, int fd) { char buf[PATH_MAX]; - FILE* file; - int saved_errno, fbfd, r, g, b; + FILE *file = NULL; + int fbfd = 1; + int r, g, b; ssize_t got, off; + uint32_t *pixel; + int saved_errno; /* Open the framebuffer device for reading. */ - if (fbfd = open(fbpath, O_RDONLY), fbfd < 0) - return -1; + fbfd = open (fbpath, O_RDONLY); + if (fbfd == -1) + goto fail; /* Create a FILE*, for writing, for the image file. */ - file = fdopen(fd, "w"); + file = fdopen (fd, "w"); if (file == NULL) - return saved_errno = errno, close(fbfd), errno = saved_errno, -1; + goto fail; /* The PNM image should begin with `P3\n%{width} %{height}\n%{colour max=255}\n`. ('\n' and ' ' can be exchanged at will.) */ - fprintf(file, "P3\n%li %li\n255\n", width, height); + if (fprintf (file, "P3\n%li %li\n255\n", width, height) < 0) + goto fail; /* Convert raw framebuffer data into an PNM image. */ for (off = 0;;) { /* Read data from the framebuffer, we may have up to 3 bytes buffered. */ - got = read(fbfd, buf + off, sizeof(buf) - (size_t)off * sizeof(char)); + got = read (fbfd, buf + off, sizeof (buf) - (size_t)off * sizeof (char)); if (got < 0) - return saved_errno = errno, fclose(file), close(fbfd), errno = saved_errno, -1; - if (got += off, got == 0) + goto fail; + if (got == 0) break; + got += off; /* Convert read pixels. */ for (off = 0; off < got; off += 4) { /* A pixel in the framebuffer is formatted as `%{blue}%{green}%{red}%{x}` in big-endian binary, or `%{x}%{red}%{green}%{blue}` in little-endian binary. */ - uint32_t* pixel = (uint32_t*)(buf + off); + pixel = (uint32_t *)(buf + off); r = (*pixel >> 16) & 255; g = (*pixel >> 8) & 255; b = (*pixel >> 0) & 255; /* A pixel in the PNM image is formatted as `%{red} %{green} %{blue} ` in text. */ - fprintf(file, "%s%s%s", inttable[r], inttable[g], inttable[b]); + if (fprintf (file, "%s%s%s", inttable[r], inttable[g], inttable[b]) < 0) + goto fail; } /* If we read a whole number of pixels, reset the buffer, otherwise, @@ -144,7 +152,7 @@ static int save_pnm(const char* fbpath, long width, long height, int fd) if (off != got) { off -= 4; - memcpy(buf, buf + off, (size_t)(got - off) * sizeof(char)); + memcpy (buf, buf + off, (size_t)(got - off) * sizeof (char)); off = got - off; } else @@ -152,74 +160,89 @@ static int save_pnm(const char* fbpath, long width, long height, int fd) } /* Close files and return successfully. */ - fflush(file); - fclose(file); - close(fbfd); + fflush (file); + fclose (file); + close (fbfd); return 0; + + fail: + saved_errno = errno; + if (file != NULL) + fclose (file); + if (fbfd >= 0) + close (fbfd); + errno = saved_errno; + return -1; } /** - * Create an image of a framebuffer + * Create an image of a framebuffer. * - * @param fbname The framebuffer device - * @param imgname The pathname of the output image - * @param width The width of the image - * @param height The height of the image - * @return Zero on success, -1 on error + * @param fbname The framebuffer device. + * @param imgname The pathname of the output image. + * @param width The width of the image. + * @param height The height of the image. + * @return Zero on success, -1 on error. */ -static int save(const char* fbpath, const char* imgpath, long width, long height) +static int +save (const char *fbpath, const char *imgpath, long width, long height) { - int pipe_rw[2]; - pid_t pid, reaped; - int saved_errno, status, fd; + int pipe_rw[2] = { -1, -1 }; + pid_t pid; + int status; + int fd = -1; + int saved_errno; if (convert_args == NULL) goto no_convert; /* Create a pipe that for sending data into the `convert` program. */ - if (pipe(pipe_rw) < 0) - return -1; + if (pipe (pipe_rw) < 0) + goto fail; /* Fork the process, the child will exec. `convert`. */ - if (pid = fork(), pid == -1) - return saved_errno = errno, close(pipe_rw[0]), close(pipe_rw[1]), errno = saved_errno, -1; + pid = fork (); + if (pid == -1) + goto fail; /* Child process: */ if (pid == 0) { /* Close the write-end of the pipe. */ - close(pipe_rw[1]); + close (pipe_rw[1]); /* Turn the read-end of the into stdin. */ if (pipe_rw[0] != STDIN_FILENO) { - close(STDIN_FILENO); - dup2(pipe_rw[0], STDIN_FILENO); - close(pipe_rw[0]); + close (STDIN_FILENO); + if (dup2 (pipe_rw[0], STDIN_FILENO) == -1) + goto child_fail; + close (pipe_rw[0]); } /* Exec. `convert` to convert the PNM-image we create to a compressed image. */ - sprintf(convert_args[2], "%s", imgpath); - execvp("convert", convert_args); + sprintf (convert_args[2], "%s", imgpath); + execvp ("convert", convert_args); + + child_fail: perror(execname); - exit(1); + _exit(1); } /* Parent process: */ /* Close the read-end of the pipe. */ - close(pipe_rw[0]); + close (pipe_rw[0]), pipe_rw[0] = -1; /* Create a PNM-image of the framebuffer. */ - if (save_pnm(fbpath, width, height, pipe_rw[1]) < 0) - return saved_errno = errno, close(pipe_rw[1]), errno = saved_errno, -1; + if (save_pnm (fbpath, width, height, pipe_rw[1]) < 0) + goto fail; /* Close the write-end of the pipe. */ - close(pipe_rw[1]); + close (pipe_rw[1]), pipe_rw[1] = -1; /* Wait for `convert` to exit. */ - for (reaped = 0; reaped != pid;) - if (reaped = waitpid(pid, &status, 0), reaped < 0) - return -1; + if (waitpid (pid, &status, 0) < 0) + goto fail; /* Return successfully if and only if `convert` did. */ return status == 0 ? 0 : -1; @@ -229,65 +252,88 @@ static int save(const char* fbpath, const char* imgpath, long width, long height no_convert: /* Open output file. */ - if (fd = open(imgpath, O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), fd == -1) - return -1; + if (fd = open (imgpath, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), fd == -1) + goto fail; /* Save image. */ - if (save_pnm(fbpath, width, height, fd) < 0) - return saved_errno = errno, close(fd), errno = saved_errno, -1; + if (save_pnm (fbpath, width, height, fd) < 0) + goto fail; - close(fd); + close (fd); return 0; + + fail: + saved_errno = errno; + if (pipe_rw[0] >= 0) + close (pipe_rw[0]); + if (pipe_rw[1] >= 0) + close (pipe_rw[1]); + if (fd >= 0) + close (fd); + errno = saved_errno; + return -1; } /** - * Get the dimensions of the framebuffer + * Get the dimensions of the framebuffer. * - * @param fbno The number of the framebuffer - * @param width Output parameter for the width of the image - * @param height Output parameter for the height of the image - * @return Zero on success, -1 on error + * @param fbno The number of the framebuffer. + * @param width Output parameter for the width of the image. + * @param height Output parameter for the height of the image. + * @return Zero on success, -1 on error. */ -static int measure(int fbno, long* width, long* height) +static int +measure (int fbno, long *width, long *height) { char buf[PATH_MAX]; - char* delim; - int sizefd, saved_errno; + char *delim; + int sizefd = -1; ssize_t got; + int saved_errno; /* Open the file with the framebuffer's dimensions. */ - sprintf(buf, SYSDIR "/class/graphics/fb%i/virtual_size", fbno); - if (sizefd = open(buf, O_RDONLY), sizefd < 0) - return -1; + sprintf (buf, SYSDIR "/class/graphics/fb%i/virtual_size", fbno); + sizefd = open (buf, O_RDONLY); + if (sizefd == -1) + goto fail; /* Get the dimensions of the framebuffer. */ - if (got = read(sizefd, buf, sizeof(buf) / sizeof(char) - 1), got < 0) - return saved_errno = errno, close(sizefd), errno = saved_errno, -1; - close(sizefd); + got = read (sizefd, buf, sizeof (buf) / sizeof (char) - 1); + if (got < 0) + goto fail; + close (sizefd); /* The read content is formated as `%{width},%{height}\n`, convert it to `%{width}\0%{height}\0` and parse it. */ buf[got] = '\0'; - delim = strchr(buf, ','); + delim = strchr (buf, ','); *delim++ = '\0'; - *width = atol(buf); - *height = atol(delim); + *width = atol (buf); + *height = atol (delim); return 0; + + fail: + saved_errno = errno; + if (sizefd >= 0) + close (sizefd); + errno = saved_errno; + return -1; } /** - * Duplicate all '%':s in a buffer until the first occurrence of a zero byte + * Duplicate all '%':s in a buffer until the first occurrence of a zero byte. * - * @param buf The buffer - * @param n The size of the buffer - * @return -1 if the buffer is too small, otherwise - * the new position of the first zero byte + * @param buf The buffer. + * @param n The size of the buffer. + * @return -1 if the buffer is too small, otherwise. + * the new position of the first zero byte. */ -static ssize_t duplicate_percents(char* restrict buf, size_t n) +static ssize_t +duplicate_percents (char *restrict buf, size_t n) { size_t p = 0, pi, pc = 0, i; @@ -303,8 +349,8 @@ static ssize_t duplicate_percents(char* restrict buf, size_t n) /* Duplicate all '%':s. */ for (pi = 0; pi < pc; pi++) { - p = (size_t)(strchr(buf + p, '%') - buf); - memmove(buf + p + 1, buf + p, (i - (p - pi)) * sizeof(char)); + p = (size_t)(strchr (buf + p, '%') - buf); + memmove (buf + p + 1, buf + p, (i - (p - pi)) * sizeof (char)); p += 2; } @@ -313,24 +359,24 @@ static ssize_t duplicate_percents(char* restrict buf, size_t n) /** - * Parse and evaluate a --exec argument or filename pattern + * Parse and evaluate a --exec argument or filename pattern. * * If `path != NULL` than all non-escaped spaces in * `pattern` will be stored as 255-bytes in `buf`. * - * @param buf The output buffer - * @param n The size of `buf` - * @param pattern The pattern to evaluate - * @param fbno The index of the framebuffer - * @param width The width of the image/framebuffer - * @param height The height of the image/framebuffer - * @param path The filename of the saved image, `NULL` during the evaluation of the filename pattern - * @return Zero on success, -1 on error + * @param buf The output buffer. + * @param n The size of `buf`. + * @param pattern The pattern to evaluate. + * @param fbno The index of the framebuffer. + * @param width The width of the image/framebuffer. + * @param height The height of the image/framebuffer. + * @param path The filename of the saved image, `NULL` during the evaluation of the filename pattern. + * @return Zero on success, -1 on error. */ -static int evaluate(char* restrict buf, size_t n, const char* restrict pattern, - int fbno, long width, long height, const char* restrict path) +static int evaluate (char *restrict buf, size_t n, const char *restrict pattern, + int fbno, long width, long height, const char *restrict path) { -#define p(format, value) r = snprintf(buf + i, n - i, format "%zn", value, &j) +#define P(format, value) r = snprintf (buf + i, n - i, format "%zn", value, &j) size_t i = 0; ssize_t j = 0; @@ -349,20 +395,20 @@ static int evaluate(char* restrict buf, size_t n, const char* restrict pattern, if (path == NULL) if ((c == 'f') || (c == 'n')) continue; - if (c == 'i') p("%i", fbno); - else if (c == 'f') p("%s", path); - else if (c == 'n') p("%s", strrchr(path, '/') ? (strrchr(path, '/') + 1) : path); - else if (c == 'p') p("%ju", (uintmax_t)width * (uintmax_t)height); - else if (c == 'w') p("%li", width); - else if (c == 'h') p("%li", height); + if (c == 'i') P ("%i", fbno); + else if (c == 'f') P ("%s", path); + else if (c == 'n') P ("%s", strrchr (path, '/') ? (strrchr (path, '/') + 1) : path); + else if (c == 'p') P ("%ju", (uintmax_t)width * (uintmax_t)height); + else if (c == 'w') P ("%li", width); + else if (c == 'h') P ("%li", height); else if (c == '$') r = 0, j = 1, buf[i] = '$'; else continue; if ((r < 0) || (j <= 0)) return -1; if ((c == 'f') || (c == 'n')) - if (j = duplicate_percents(buf + i, n - i), j < 0) - return errno = ENAMETOOLONG, -1; + if (j = duplicate_percents (buf + i, n - i), j < 0) + goto enametoolong; i += (size_t)j; } else if (backslash) buf[i++] = (c == 'n' ? '\n' : c), backslash = 0; @@ -374,30 +420,37 @@ static int evaluate(char* restrict buf, size_t n, const char* restrict pattern, else buf[i++] = c; if (i >= n) - return errno = ENAMETOOLONG, -1; + goto enametoolong; } buf[i] = '\0'; /* Check whether there are any '%' to expand. */ - if (strchr(buf, '%') == NULL) + if (strchr (buf, '%') == NULL) return 0; /* Copy the buffer so we can reuse the buffer and use its old content for the format. */ - fmt = alloca((strlen(buf) + 1) * sizeof(char)); - memcpy(fmt, buf, (strlen(buf) + 1) * sizeof(char)); + fmt = alloca ((strlen (buf) + 1) * sizeof (char)); + memcpy (fmt, buf, (strlen (buf) + 1) * sizeof (char)); /* Expand '%'. */ - t = time(NULL); - localtime_r(&t, &tm); + t = time (NULL); + localtime_r (&t, &tm); +#ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wformat-nonliteral" - if (strftime(buf, n, fmt, &tm) == 0) +#endif + if (strftime (buf, n, fmt, &tm) == 0) + goto enametoolong; /* No errors are defined for `strftime`. */ +#ifdef __GNUC__ # pragma GCC diagnostic pop - return errno = ENAMETOOLONG, -1; +#endif return 0; -#undef p + enametoolong: + return errno = ENAMETOOLONG, -1; + +#undef P } @@ -407,12 +460,13 @@ static int evaluate(char* restrict buf, size_t n, const char* restrict pattern, * @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) +static int +exec_image (char *flatten_args) { - char** args; - char* arg; + char **args; + char *arg; size_t i, arg_count = 1; - pid_t pid, reaped; + pid_t pid; int status; /* Count arguments. */ @@ -421,39 +475,37 @@ static int exec_image(char* flatten_args) arg_count++; /* Allocate argument array. */ - args = alloca((arg_count + 1) * sizeof(char*)); + args = alloca ((arg_count + 1) * sizeof (char*)); /* Unflatten argument array. */ for (arg = flatten_args, i = 0;;) { args[i++] = arg; - arg = strchr(arg, 255); + arg = strchr (arg, 255); if (arg == NULL) break; *arg++ = '\0'; } args[i] = NULL; - + /* Fork process. */ - pid = fork(); + pid = fork (); if (pid == -1) return -1; /* Child process: */ if (pid == 0) { - execvp(*args, args); - perror(execname); - exit(1); - return -1; + execvp (*args, args); + perror (execname); + _exit (1); } /* Parent process: */ /* Wait for child to exit. */ - for (reaped = 0; reaped != pid;) - if (reaped = waitpid(pid, &status, 0), reaped < 0) - return -1; + if (waitpid(pid, &status, 0) < 0) + return -1; /* Return successfully if and only if `the child` did. */ return status == 0 ? 0 : -1; @@ -461,54 +513,55 @@ static int exec_image(char* flatten_args) /** - * Take a screenshot of a framebuffer + * Take a screenshot of a framebuffer. * - * @param fbno The number of the framebuffer - * @param raw Save in PNM rather than in PNG? - * @param filepattern The pattern for the filename, `NULL` for default + * @param fbno The number of the framebuffer. + * @param raw Save in PNM rather than in PNG?. + * @param filepattern The pattern for the filename, `NULL` for default. * @param execpattern The pattern for the command to run to - * process the image, `NULL` for default - * @return Zero on success, -1 on error, 1 if the framebuffer does not exist + * process the image, `NULL` for default. + * @return Zero on success, -1 on error, 1 if the framebuffer does not exist. */ -static int save_fb(int fbno, int raw, const char* filepattern, const char* execpattern) +static int +save_fb (int fbno, int raw, const char *filepattern, const char *execpattern) { char fbpath[PATH_MAX]; char imgpath[PATH_MAX]; - char* execargs = NULL; - char* old; + char *execargs = NULL; + void *new; long width, height; 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); - if (access(fbpath, F_OK)) + sprintf (fbpath, DEVDIR "/fb%i", fbno); + if (access (fbpath, F_OK)) return 1; /* Get the size of the framebuffer. */ - if (measure(fbno, &width, &height) < 0) - return -1; + if (measure (fbno, &width, &height) < 0) + goto fail; /* Get output pathname. */ if (filepattern == NULL) { - sprintf(imgpath, "fb%i.%s", fbno, (raw ? "pnm" : "png")); - if (access(imgpath, F_OK) == 0) + sprintf (imgpath, "fb%i.%s", fbno, (raw ? "pnm" : "png")); + if (access (imgpath, F_OK) == 0) for (i = 2;; i++) { - sprintf(imgpath, "fb%i.%s.%i", fbno, (raw ? "pnm" : "png"), i); - if (access(imgpath, F_OK)) + sprintf (imgpath, "fb%i.%s.%i", fbno, (raw ? "pnm" : "png"), i); + if (access (imgpath, F_OK)) break; } } else - if (evaluate(imgpath, (size_t)PATH_MAX, filepattern, fbno, width, height, NULL) < 0) + if (evaluate (imgpath, (size_t)PATH_MAX, filepattern, fbno, width, height, NULL) < 0) return -1; /* Take a screenshot of the current framebuffer. */ - if (save(fbpath, imgpath, width, height) < 0) - return -1; - fprintf(stderr, "Saved framebuffer %i to %s\n", fbno, imgpath); + if (save (fbpath, imgpath, width, height) < 0) + goto fail; + fprintf (stderr, "Saved framebuffer %i to %s\n", fbno, imgpath); /* Should we run a command over the image? */ if (execpattern == NULL) @@ -516,82 +569,87 @@ static int save_fb(int fbno, int raw, const char* filepattern, const char* execp /* Get execute arguments. */ retry: - execargs = realloc(old = execargs, size * sizeof(char)); + new = realloc (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) + goto fail; + execargs = new; + if (evaluate (execargs, size, execpattern, fbno, width, height, imgpath) < 0) { if ((errno != ENAMETOOLONG) || ((size >> 8) <= PATH_MAX)) - return -1; + goto fail; size <<= 1; goto retry; } /* Run command over image. */ - i = exec_image(execargs); + if (exec_image (execargs) < 0) + goto fail; + free (execargs); + return 0; + + fail: saved_errno = errno; - free(execargs); - return errno = saved_errno, i; + free (execargs); + errno = saved_errno; + return -1; } -#define p(...) if (printf(__VA_ARGS__) < 0) return -1; - - /** - * Print usage information + * Print usage information. * - * @return Zero on success, -1 on error + * @return Zero on success, -1 on error. */ -static int print_help(void) +static int +print_help(void) { - p("SYNOPSIS\n"); - p("\t%s [options...] [filename-pattern] [-- options-for-convert...]\n", execname); - p("\n"); - p("OPTIONS\n"); - p("\t--help Print usage information.\n"); - p("\t--version Print program name and version.\n"); - p("\t--copyright Print copyright information.\n"); - p("\t--raw Save in PNM rather than in PNG.\n"); - p("\t--exec CMD Command to run for each saved image.\n"); - p("\n"); - p("SPECIAL STRINGS\n"); - p("\tBoth the --exec and filename-pattern parameters can take format specifiers\n"); - p("\tthat are expanded by scrotty when encountered. There are two types of format\n"); - p("\tspecifier. Characters preceded by a '%%' are interpretted by strftime(3).\n"); - p("\tSee `man strftime` for examples. These options may be used to refer to the\n"); - p("\tcurrent date and time. The second kind are internal to scrotty and are prefixed\n"); - p("\tby '$' or '\\'. The following specifiers are recognised:\n"); - p("\n"); - p("\t\n"); - p("\t$i framebuffer index\n"); - p("\t$f image filename/pathname (ignored when used in filename-pattern)\n"); - p("\t$n image filename (ignored when used in filename-pattern)\n"); - p("\t$p image width multiplied by image height\n"); - p("\t$w image width\n"); - p("\t$h image height\n"); - p("\t$$ expands to a literal '$'\n"); - p("\t\\n expands to a new line\n"); - p("\t\\\\ expands to a literal '\\'\n"); - p("\t\\ expands to a literal ' ' (the string is a backslash followed by a space)\n"); - p("\n"); - p("\tA space that is not prefixed by a backslash in --exec is interpreted as an\n"); - p("\targument delimiter. This is the case even at the beginning and end of the\n"); - p("\tstring and if a space was the previous character in the string.\n"); - p("\n"); - return 0; + return printf ("SYNOPSIS\n" + "\t%s [options...] [filename-pattern] [-- options-for-convert...]\n" + "\n" + "OPTIONS\n" + "\t--help Print usage information.\n" + "\t--version Print program name and version.\n" + "\t--copyright Print copyright information.\n" + "\t--raw Save in PNM rather than in PNG.\n" + "\t--exec CMD Command to run for each saved image.\n" + "\n" + "SPECIAL STRINGS\n" + "\tBoth the --exec and filename-pattern parameters can take format specifiers\n" + "\tthat are expanded by scrotty when encountered. There are two types of format\n" + "\tspecifier. Characters preceded by a '%%' are interpretted by strftime(3).\n" + "\tSee `man strftime` for examples. These options may be used to refer to the\n" + "\tcurrent date and time. The second kind are internal to scrotty and are prefixed\n" + "\tby '$' or '\\'. The following specifiers are recognised:\n" + "\n" + "\t\n" + "\t$i framebuffer index\n" + "\t$f image filename/pathname (ignored when used in filename-pattern)\n" + "\t$n image filename (ignored when used in filename-pattern)\n" + "\t$p image width multiplied by image height\n" + "\t$w image width\n" + "\t$h image height\n" + "\t$$ expands to a literal '$'\n" + "\t\\n expands to a new line\n" + "\t\\\\ expands to a literal '\\'\n" + "\t\\ expands to a literal ' ' (the string is a backslash followed by a space)\n" + "\n" + "\tA space that is not prefixed by a backslash in --exec is interpreted as an\n" + "\targument delimiter. This is the case even at the beginning and end of the\n" + "\tstring and if a space was the previous character in the string.\n" + "\n", + execname) < 0 ? -1 : 0; } /** - * Print program name and version + * Print program name and version. * - * @return Zero on success, -1 on error + * @return Zero on success, -1 on error. */ -static int print_version(void) +static int +print_version (void) { - p("%s %s\n", PROGRAM_NAME, PROGRAM_VERSION); - return 0; + return printf ("%s %s\n", PROGRAM_NAME, PROGRAM_VERSION) < 0 ? -1 : 0; } @@ -600,30 +658,28 @@ static int print_version(void) * * @return Zero on success, -1 on error */ -static int print_copyright(void) +static int +print_copyright (void) { - p("scrotty -- Screenshot program for Linux's TTY\n"); - p("Copyright (C) 2014, 2015 Mattias Andrée (maandree@member.fsf.org)\n"); - p("\n"); - p("This program is free software: you can redistribute it and/or modify\n"); - p("it under the terms of the GNU General Public License as published by\n"); - p("the Free Software Foundation, either version 3 of the License, or\n"); - p("(at your option) any later version.\n"); - p("\n"); - p("This program is distributed in the hope that it will be useful,\n"); - p("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); - p("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); - p("GNU General Public License for more details.\n"); - p("\n"); - p("You should have received a copy of the GNU General Public License\n"); - p("along with this program. If not, see <http://www.gnu.org/licenses/>.\n"); - return 0; + return printf ("scrotty -- Screenshot program for Linux's TTY\n" + "Copyright (C) 2014, 2015 Mattias Andrée (maandree@member.fsf.org)\n" + "\n" + "This program is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program. If not, see <http://www.gnu.org/licenses/>.\n" + ) < 0 ? -1 : 0; } -#undef p - - /** * Take a screenshot of all framebuffers * @@ -631,48 +687,52 @@ static int print_copyright(void) * @param argv Command line arguments * @return Zero on and only on success */ -int main(int argc, char* argv[]) +int main +(int argc, char *argv[]) { +#define EXIT_USAGE(MSG) \ + return fprintf (stderr, "%s: %s. Type `%s --help` for help.\n", execname, MSG, execname), 1 + int fbno, r, i, dash = argc, exec = -1, help = 0; int raw = 0, version = 0, copyright = 0, filepattern = -1; static char convert_args_0[] = "convert"; static char convert_args_1[] = DEVDIR "/stdin"; static char convert_args_2[PATH_MAX]; - execname = *argv; + execname = argc ? *argv : "scrotty"; /* Parse command line. */ for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "--help")) help = 1; - else if (!strcmp(argv[i], "--version")) version = 1; - else if (!strcmp(argv[i], "--copyright")) copyright = 1; - else if (!strcmp(argv[i], "--raw")) raw = 1; - else if (!strcmp(argv[i], "--exec")) exec = ++i; - else if (!strcmp(argv[i], "--")) + if (!strcmp (argv[i], "--help")) help = 1; + else if (!strcmp (argv[i], "--version")) version = 1; + else if (!strcmp (argv[i], "--copyright")) copyright = 1; + else if (!strcmp (argv[i], "--raw")) raw = 1; + else if (!strcmp (argv[i], "--exec")) exec = ++i; + else if (!strcmp (argv[i], "--")) { dash = i + 1; break; } else if ((argv[i][0] == '-') || (filepattern != -1)) - return fprintf(stderr, "Unrecognised option. Type `%s --help` for help.\n", execname), 1; + EXIT_USAGE ("Unrecognised option."); else filepattern = i; } /* Check that --exec is valid. */ if (exec == argc) - return fprintf(stderr, "--exec has no argument. Type `%s --help` for help.\n", execname), 1; + EXIT_USAGE ("--exec has no argument."); - /* Was --help, --version or --copyright used? */ - if (help) return -(print_help()); - if (version) return -(print_version()); - if (copyright) return -(print_copyright()); + /* Was --help, --version, or --copyright used? */ + if (help) return -(print_help ()); + if (version) return -(print_version ()); + if (copyright) return -(print_copyright ()); /* Create arguments for `convert`. */ if ((!raw) || (dash < argc)) { - convert_args = alloca((size_t)(4 + (argc - dash)) * sizeof(char*)); + convert_args = alloca ((size_t)(4 + (argc - dash)) * sizeof (char*)); convert_args[0] = convert_args_0; convert_args[1] = convert_args_1; convert_args[2] = convert_args_2; @@ -684,13 +744,20 @@ int main(int argc, char* argv[]) /* Take a screenshot of each framebuffer. */ for (fbno = 0;; fbno++) { - r = save_fb(fbno, raw, - (filepattern < 0 ? NULL : argv[filepattern]), - (exec < 0 ? NULL : argv[exec])); - if (r < 0) return perror(execname), 1; - if (r > 0) break; + r = save_fb (fbno, raw, + (filepattern < 0 ? NULL : argv[filepattern]), + (exec < 0 ? NULL : argv[exec])); + if (r < 0) + goto fail; + if (r > 0) + break; } return 0; + + fail: + return perror (execname), 1; + +#undef EXIT_USAGE } |