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