1 /* Unix "yes" command */
2 
3 #define EX_UTILS_NO_USE_INPUT 1
4 
5 #include "ex_utils.h"
6 
7 #include <limits.h>
8 
9 #define OUT_DEF_NUM 2 /* how many lines to add at once, by default */
10 
11 #define OUT_LIM_DEF_NUM 0 /* how many lines to do in total, by default */
12 
13 #define OUT_PTR 1 /* copy ptr's to data */
14 #define OUT_BUF 2 /* copy data to */
15 #define OUT_REF 3 /* copy data once, to coalese */
16 
17 #define MAX_W_DATA_INCORE (1024 * 128)
18 
19 static unsigned int sz = MAX_W_DATA_INCORE;
20 
main(int argc,char * argv[])21 int main(int argc, char *argv[])
22 { /* This is "yes", without any command line options */
23   Vstr_base *cmd_line = NULL;
24   Vstr_base *s1 = ex_init(&cmd_line);
25   int count = 1; /* skip program name */
26   unsigned int out_type = OUT_PTR;
27   unsigned int out_num = OUT_DEF_NUM;
28   unsigned int lim_num = OUT_LIM_DEF_NUM;
29   const char *out_filename = NULL;
30   int out_fd = -1;
31 
32   while (count < argc)
33   { /* quick hack getopt_long */
34     if (!strcmp("--", argv[count]))
35     {
36       ++count;
37       break;
38     }
39     else if (!strcmp("--ptr", argv[count]))
40       out_type = OUT_PTR;
41     else if (!strcmp("--buf", argv[count]))
42       out_type = OUT_BUF;
43     else if (!strcmp("--ref", argv[count]))
44       out_type = OUT_REF;
45     EX_UTILS_GETOPT_NUM("sz",    sz);
46     EX_UTILS_GETOPT_NUM("num",   out_num);
47     EX_UTILS_GETOPT_NUM("limit", lim_num);
48     EX_UTILS_GETOPT_NUM("lim",   lim_num);
49     EX_UTILS_GETOPT_CSTR("file",  out_filename);
50     else if (!strcmp("--version", argv[count]))
51     {
52       vstr_add_fmt(s1, 0, "%s", "\
53 yes 1.0.0\n\
54 Written by James Antill\n\
55 \n\
56 Uses Vstr string library.\n\
57 ");
58       goto out;
59     }
60     else if (!strcmp("--help", argv[count]))
61     {
62       vstr_add_fmt(s1, 0, "%s", "\
63 Usage: yes [STRING]...\n\
64    or: yes OPTION\n\
65 Repeatedly output a line with all specified STRING(s), or `y'.\n\
66 \n\
67       --help     display this help and exit\n\
68       --version  output version information and exit\n\
69       --ptr      output using pointers to data\n\
70       --buf      output using copies of data\n\
71       --ref      output using single copy of data, with references\n\
72       --num      number of times to add the line, between output calls\n\
73       --sz       output maximum size, lower bound\n\
74       --         Use rest of cmd line input regardless of if it's an option\n\
75 \n\
76 Report bugs to James Antill <james@and.org>.\n\
77 ");
78       goto out;
79     }
80     else
81       break;
82     ++count;
83   }
84 
85   if (count >= argc)
86     VSTR_ADD_CSTR_PTR(cmd_line, cmd_line->len, "y");
87 
88   {
89     int added = FALSE;
90 
91     while (count < argc)
92     {
93       if (added) /* already done one argument */
94         VSTR_ADD_CSTR_PTR(cmd_line, cmd_line->len, " ");
95       VSTR_ADD_CSTR_PTR(cmd_line, cmd_line->len, argv[count]);
96 
97       ++count;
98       added = TRUE;
99     }
100   }
101 
102   VSTR_ADD_CSTR_PTR(cmd_line, cmd_line->len, "\n");
103 
104   if (0)
105   { ASSERT(FALSE); }
106   else if (out_type == OUT_PTR)
107   { /* do nothing */ }
108   else if (out_type == OUT_BUF)
109   {
110     size_t len = cmd_line->len;
111     vstr_add_vstr(cmd_line, len, cmd_line, 1, len, VSTR_TYPE_ADD_ALL_BUF);
112     vstr_del(cmd_line, 1, len);
113   }
114   else if (out_type == OUT_REF)
115   {
116     size_t len = cmd_line->len;
117     vstr_add_vstr(cmd_line, len, cmd_line, 1, len, VSTR_TYPE_ADD_ALL_REF);
118     vstr_del(cmd_line, 1, len);
119   }
120   else
121     errx(EXIT_SUCCESS, "INTERNAL ERROR ... bad out_type");
122 
123   if (cmd_line->conf->malloc_bad)
124     errno = ENOMEM, err(EXIT_SUCCESS, "Creating output string: %m\n");
125 
126   if (!out_num)
127     ++out_num;
128 
129   if (!out_filename)
130     out_fd = 1;
131   else
132     out_fd = io_open(out_filename);
133 
134   /* BEG: main loop */
135 
136   do
137   {
138     count = out_num;
139 
140     while ((s1->len < sz) && (--count >= 0))
141       vstr_add_vstr(s1, s1->len, cmd_line, 1, cmd_line->len, VSTR_TYPE_ADD_DEF);
142 
143     if ((io_put(s1, out_fd) == IO_BLOCK) && (s1->len >= sz))
144       io_block(-1, out_fd);
145 
146     /* 0 == infinity */
147     if    (lim_num == 1) break;
148     if    (lim_num >  1) --lim_num;
149   } while (TRUE);
150 
151  out:
152   io_put_all(s1, out_fd);
153 
154   exit (ex_exit(s1, cmd_line));
155 }
156