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