]> diplodocus.org Git - nmh/blob - uip/mkstemp.c
Changed unused symbol that gen-ctype-checked creates with NDEBUG
[nmh] / uip / mkstemp.c
1 /*
2 * mkstemp.c -- create a temporary file
3 *
4 * This code is Copyright (c) 2014 by the authors of nmh.
5 * See the COPYRIGHT file in the root directory of the nmh
6 * distribution for complete copyright information.
7 */
8
9 /* define NMH to 0 to remove dependencies on nmh. */
10 #ifndef NMH
11 # define NMH 1
12 #endif /* ! NMH */
13
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif /* HAVE_CONFIG_H */
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <stdio.h>
21
22 #if ! defined HAVE_MKSTEMPS
23 # define HAVE_MKSTEMPS 0
24 #endif /* ! HAVE_MKSTEMPS */
25
26 char *build_template(const char *, const char *, const char *);
27 void process_args(int, char **, const char **, const char **, const char **);
28
29 /*
30 * Use a template of the form:
31 * [directory/][prefix]XXXXXX[suffix]
32 * where some of those named components might be null. suffix is only
33 * supported if HAVE_MKSTEMPS.
34 */
35
36 int
37 main(int argc, char *argv[]) {
38 const char *directory = "", *prefix = "", *suffix = "";
39 size_t suffix_len;
40 int fd;
41 char *template;
42
43 process_args(argc, argv, &directory, &prefix, &suffix);
44 if ((template = build_template(directory, prefix, suffix)) == NULL) {
45 return -1;
46 }
47
48 if ((suffix_len = strlen(suffix)) > 0) {
49 # if HAVE_MKSTEMPS
50 if ((fd = mkstemps(template, suffix_len)) < 0) { perror("mkstemps"); }
51 # endif /* HAVE_MKSTEMPS */
52 } else {
53 if ((fd = mkstemp(template)) < 0) { perror("mkstemp"); }
54 }
55
56 if (fd >= 0) {
57 (void) puts(template);
58 (void) close(fd);
59 }
60
61 free(template);
62
63 return fd >= 0 ? 0 : -1;
64 }
65
66
67 char *
68 build_template(const char *directory, const char *prefix, const char *suffix) {
69 const char pattern[] = "XXXXXX";
70 size_t len, directory_len, pathsep_len, prefix_len, suffix_len;
71 char *template;
72
73 directory_len = strlen(directory);
74 if (directory_len > 0) {
75 pathsep_len = 1;
76 if (directory[directory_len - 1] == '/') {
77 /* Will insert a '/' separately, so truncate the one provided
78 in the directory name. */
79 --directory_len;
80 }
81 } else {
82 pathsep_len = 0;
83 }
84 prefix_len = strlen(prefix);
85 suffix_len = strlen(suffix);
86 /* sizeof pattern includes its final NULL, so don't add another. */
87 len = directory_len + pathsep_len + prefix_len + sizeof pattern +
88 suffix_len;
89
90 if ((template = malloc(len))) {
91 char *tp = template;
92
93 (void) strncpy(tp, directory, directory_len);
94 tp += directory_len;
95
96 if (pathsep_len == 1) { *tp++ = '/'; }
97
98 (void) strncpy(tp, prefix, prefix_len);
99 tp += prefix_len;
100
101 (void) strncpy(tp, pattern, sizeof pattern - 1);
102 tp += sizeof pattern - 1;
103
104 (void) strncpy(tp, suffix, suffix_len);
105 tp += suffix_len;
106
107 template[len-1] = '\0';
108
109 return template;
110 } else {
111 perror("malloc");
112 return NULL;
113 }
114 }
115
116
117 #if NMH
118 #include <h/mh.h>
119
120 #if HAVE_MKSTEMPS
121 # define MHFIXMSG_SWITCHES \
122 X("directory", 0, DIRECTORYSW) \
123 X("prefix", 0, PREFIXSW) \
124 X("suffix", 0, SUFFIXSW) \
125 X("version", 0, VERSIONSW) \
126 X("help", 0, HELPSW)
127 #else /* ! HAVE_MKSTEMPS */
128 # define MHFIXMSG_SWITCHES \
129 X("directory", 0, DIRECTORYSW) \
130 X("prefix", 0, PREFIXSW) \
131 X("version", 0, VERSIONSW) \
132 X("help", 0, HELPSW)
133 #endif /* ! HAVE_MKSTEMPS */
134
135 #define X(sw, minchars, id) id,
136 DEFINE_SWITCH_ENUM(MHFIXMSG);
137 #undef X
138
139 #define X(sw, minchars, id) { sw, minchars, id },
140 DEFINE_SWITCH_ARRAY(MHFIXMSG, switches);
141 #undef X
142
143 void
144 process_args(int argc, char **argv, const char **directory,
145 const char **prefix, const char **suffix) {
146 char **argp, **arguments, *cp, buf[100];
147 # if ! HAVE_MKSTEMPS
148 NMH_UNUSED(suffix);
149 # endif /* ! HAVE_MKSTEMPS */
150
151 if (nmh_init(argv[0], 1)) { done(NOTOK); }
152 arguments = getarguments (invo_name, argc, argv, 1);
153 argp = arguments;
154
155 /*
156 * Parse arguments
157 */
158 while ((cp = *argp++)) {
159 if (*cp == '-') {
160 switch (smatch(++cp, switches)) {
161 case AMBIGSW:
162 ambigsw(cp, switches);
163 done(NOTOK);
164 case UNKWNSW:
165 advise (NULL, "-%s unknown", cp);
166 (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name);
167 print_help(buf, switches, 1);
168 done(NOTOK);
169 case HELPSW:
170 (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name);
171 print_help(buf, switches, 1);
172 done(OK);
173 case VERSIONSW:
174 print_version(invo_name);
175 done(OK);
176
177 case DIRECTORYSW:
178 /* Allow the directory to start with '-'. */
179 if ((cp = *argp++) == NULL) {
180 adios(NULL, "missing argument to %s", argp[-2]);
181 }
182 *directory = cp;
183 continue;
184
185 case PREFIXSW:
186 /* Allow the prefix to start with '-'. */
187 if ((cp = *argp++) == NULL) {
188 adios(NULL, "missing argument to %s", argp[-2]);
189 }
190 *prefix = cp;
191 continue;
192
193 # if HAVE_MKSTEMPS
194 case SUFFIXSW:
195 /* Allow the suffix to start with '-'. */
196 if ((cp = *argp++) == NULL) {
197 adios(NULL, "missing argument to %s", argp[-2]);
198 }
199 *suffix = cp;
200 continue;
201 # endif /* HAVE_MKSTEMPS */
202 }
203 }
204 }
205 }
206 #else /* ! NMH */
207 void
208 process_args(int argc, char **argv, const char **directory,
209 const char **prefix, const char **suffix) {
210 # if HAVE_MKSTEMPS
211 const char usage[] =
212 "usage: %s [-h] [-d directory] [-p prefix] [-s suffix]\n";
213 const char optstring[] = "d:hp:s:";
214 # else /* ! HAVE_MKSTEMPS */
215 const char usage[] = "usage: %s [-h] [-d directory] [-p prefix]\n";
216 const char optstring[] = "d:hp:";
217 # endif /* ! HAVE_MKSTEMPS */
218 int opt;
219
220 while ((opt = getopt(argc, argv, optstring)) != -1) {
221 switch (opt) {
222 case 'd':
223 *directory = optarg;
224 break;
225 case 'p':
226 *prefix = optarg;
227 break;
228 case 's':
229 *suffix = optarg;
230 break;
231 case 'h':
232 (void) printf(usage, argv[0]);
233 exit(0);
234 default:
235 (void) fprintf(stderr, usage, argv[0]);
236 exit(-1);
237 }
238 }
239 }
240 #endif /* ! NMH */