/* yes - output a string repeatedly until killed This is the yes utility
Copyright (C) 1991-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */ The GNUv3 license
/* David MacKenzie <djm@gnu.ai.mit.edu> */
#include <config.h> Provides system specific information
#include <stdio.h> Provides standard I/O capability
#include <sys/types.h> Provides system data types
#include <getopt.h> ...!includes auto-comment...
#include "system.h" ...!includes auto-comment...
#include "error.h" ...!includes auto-comment...
#include "full-write.h" ...!includes auto-comment...
#include "long-options.h" ...!includes auto-comment...
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "yes" Line 31
#define AUTHORS proper_name ("David MacKenzie") Line 33
static struct option const long_options[] = Line 35
{
{NULL, 0, NULL, 0} Line 37
}; Block 1
void Line 40
usage (int status) Line 41
{
if (status != EXIT_SUCCESS) Line 43
emit_try_help (); ...!common auto-comment...
else Line 45
{
printf (_("\ Line 47
Usage: %s [STRING]...\n\ Line 48
or: %s OPTION\n\ Line 49
"), Line 50
program_name, program_name); Line 51
fputs (_("\ Line 53
Repeatedly output a line with all specified STRING(s), or 'y'.\n\ Line 54
\n\
"), stdout); Line 56
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 57
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 58
emit_ancillary_info (PROGRAM_NAME); Line 59
}
exit (status); Line 61
} Block 2
int
main (int argc, char **argv) Line 65
{
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
atexit (close_stdout); Close stdout on exit (see gnulib)
parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version, ...!common auto-comment...
usage, AUTHORS, (char const *) NULL); Line 76
if (getopt_long (argc, argv, "+", long_options, NULL) != -1) Line 77
usage (EXIT_FAILURE); Line 78
char **operands = argv + optind; Line 80
char **operand_lim = argv + argc; Line 81
if (optind == argc) Line 82
*operand_lim++ = bad_cast ("y"); Line 83
/* Buffer data locally once, rather than having the
large overhead of stdio buffering each item. */
size_t bufalloc = 0; Line 87
bool reuse_operand_strings = true; Line 88
for (char **operandp = operands; operandp < operand_lim; operandp++) Line 89
{
size_t operand_len = strlen (*operandp); Line 91
bufalloc += operand_len + 1; Line 92
if (operandp + 1 < operand_lim Line 93
&& *operandp + operand_len + 1 != operandp[1]) Line 94
reuse_operand_strings = false; Line 95
}
/* Improve performance by using a buffer size greater than BUFSIZ / 2. */
if (bufalloc <= BUFSIZ / 2) Line 99
{
bufalloc = BUFSIZ; Line 101
reuse_operand_strings = false; Line 102
}
/* Fill the buffer with one copy of the output. If possible, reuse
the operands strings; this wins when the buffer would be large. */
char *buf = reuse_operand_strings ? *operands : xmalloc (bufalloc); Line 107
size_t bufused = 0; Line 108
for (char **operandp = operands; operandp < operand_lim; operandp++) Line 109
{
size_t operand_len = strlen (*operandp); Line 111
if (! reuse_operand_strings) Line 112
memcpy (buf + bufused, *operandp, operand_len); Line 113
bufused += operand_len; Line 114
buf[bufused++] = ' '; Line 115
}
buf[bufused - 1] = '\n'; Line 117
/* If a larger buffer was allocated, fill it by repeating the buffer
contents. */
size_t copysize = bufused; Line 121
for (size_t copies = bufalloc / copysize; --copies; ) Line 122
{
memcpy (buf + bufused, buf, copysize); Line 124
bufused += copysize; Line 125
}
/* Repeatedly output the buffer until there is a write error; then fail. */
while (full_write (STDOUT_FILENO, buf, bufused) == bufused) Line 129...!syscalls auto-comment...
continue; Line 130
error (0, errno, _("standard output")); Line 131
return EXIT_FAILURE; Line 132
}