]> diplodocus.org Git - nmh/blob - uip/mkstemp.c
oauth.c: Alter permissions from 0755 to 0644.
[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 <stdbool.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 static char *build_template(const char *, const char *, const char *);
27 static 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 {
39 const char *directory = "", *prefix = "", *suffix = "";
40 size_t suffix_len;
41 int fd;
42 char *template;
43
44 process_args(argc, argv, &directory, &prefix, &suffix);
45 if ((template = build_template(directory, prefix, suffix)) == NULL) {
46 return 1;
47 }
48
49 if ((suffix_len = strlen(suffix)) > 0) {
50 # if HAVE_MKSTEMPS
51 if ((fd = mkstemps(template, suffix_len)) < 0) { perror("mkstemps"); }
52 # else /* ! HAVE_MKSTEMPS */
53 fd = 0;
54 # endif /* ! HAVE_MKSTEMPS */
55 } else {
56 if ((fd = mkstemp(template)) < 0) { perror("mkstemp"); }
57 }
58
59 if (fd >= 0) {
60 (void) puts(template);
61 (void) close(fd);
62 }
63
64 free(template);
65
66 return fd >= 0 ? 0 : 1;
67 }
68
69
70 static char *
71 build_template(const char *directory, const char *prefix, const char *suffix)
72 {
73 const char pattern[] = "XXXXXX";
74 size_t len, directory_len, pathsep_len, prefix_len, suffix_len;
75 char *template;
76
77 directory_len = strlen(directory);
78 if (directory_len > 0) {
79 pathsep_len = 1;
80 if (directory[directory_len - 1] == '/') {
81 /* Will insert a '/' separately, so truncate the one provided
82 in the directory name. */
83 --directory_len;
84 }
85 } else {
86 pathsep_len = 0;
87 }
88 prefix_len = strlen(prefix);
89 suffix_len = strlen(suffix);
90 /* sizeof pattern includes its final NULL, so don't add another. */
91 len = directory_len + pathsep_len + prefix_len + sizeof pattern +
92 suffix_len;
93
94 if ((template = malloc(len))) {
95 char *tp = template;
96
97 (void) strncpy(tp, directory, directory_len);
98 tp += directory_len;
99
100 if (pathsep_len == 1) { *tp++ = '/'; }
101
102 (void) strncpy(tp, prefix, prefix_len);
103 tp += prefix_len;
104
105 (void) strncpy(tp, pattern, sizeof pattern - 1);
106 tp += sizeof pattern - 1;
107
108 (void) strncpy(tp, suffix, suffix_len);
109 /* tp += suffix_len; */
110
111 template[len-1] = '\0';
112
113 return template;
114 }
115
116 perror("malloc");
117 return NULL;
118 }
119
120
121 #if NMH
122 #include "h/mh.h"
123 #include "sbr/getarguments.h"
124 #include "sbr/smatch.h"
125 #include "sbr/ambigsw.h"
126 #include "sbr/print_version.h"
127 #include "sbr/print_help.h"
128 #include "sbr/error.h"
129 #include "h/done.h"
130 #include "h/utils.h"
131
132 #if HAVE_MKSTEMPS
133 # define MHFIXMSG_SWITCHES \
134 X("directory", 0, DIRECTORYSW) \
135 X("prefix", 0, PREFIXSW) \
136 X("suffix", 0, SUFFIXSW) \
137 X("version", 0, VERSIONSW) \
138 X("help", 0, HELPSW)
139 #else /* ! HAVE_MKSTEMPS */
140 # define MHFIXMSG_SWITCHES \
141 X("directory", 0, DIRECTORYSW) \
142 X("prefix", 0, PREFIXSW) \
143 X("version", 0, VERSIONSW) \
144 X("help", 0, HELPSW)
145 #endif /* ! HAVE_MKSTEMPS */
146
147 #define X(sw, minchars, id) id,
148 DEFINE_SWITCH_ENUM(MHFIXMSG);
149 #undef X
150
151 #define X(sw, minchars, id) { sw, minchars, id },
152 DEFINE_SWITCH_ARRAY(MHFIXMSG, switches);
153 #undef X
154
155 static void
156 process_args(int argc, char **argv, const char **directory,
157 const char **prefix, const char **suffix)
158 {
159 char **argp, **arguments, *cp, buf[100];
160 # if ! HAVE_MKSTEMPS
161 NMH_UNUSED(suffix);
162 # endif /* ! HAVE_MKSTEMPS */
163
164 if (nmh_init(argv[0], true, false)) { done(1); }
165 arguments = getarguments (invo_name, argc, argv, 1);
166 argp = arguments;
167
168 /*
169 * Parse arguments
170 */
171 while ((cp = *argp++)) {
172 if (*cp == '-') {
173 switch (smatch(++cp, switches)) {
174 case AMBIGSW:
175 ambigsw(cp, switches);
176 done(1);
177 case UNKWNSW:
178 inform("-%s unknown", cp);
179 (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name);
180 print_help(buf, switches, 1);
181 done(1);
182 case HELPSW:
183 (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name);
184 print_help(buf, switches, 1);
185 done(OK);
186 case VERSIONSW:
187 print_version(invo_name);
188 done(OK);
189
190 case DIRECTORYSW:
191 /* Allow the directory to start with '-'. */
192 if ((cp = *argp++) == NULL) {
193 die("missing argument to %s", argp[-2]);
194 }
195 *directory = cp;
196 continue;
197
198 case PREFIXSW:
199 /* Allow the prefix to start with '-'. */
200 if ((cp = *argp++) == NULL) {
201 die("missing argument to %s", argp[-2]);
202 }
203 *prefix = cp;
204 continue;
205
206 # if HAVE_MKSTEMPS
207 case SUFFIXSW:
208 /* Allow the suffix to start with '-'. */
209 if ((cp = *argp++) == NULL) {
210 die("missing argument to %s", argp[-2]);
211 }
212 *suffix = cp;
213 continue;
214 # endif /* HAVE_MKSTEMPS */
215 }
216 }
217 }
218 }
219 #else /* ! NMH */
220 static void
221 process_args(int argc, char **argv, const char **directory,
222 const char **prefix, const char **suffix)
223 {
224 # if HAVE_MKSTEMPS
225 const char usage[] =
226 "usage: %s [-h] [-d directory] [-p prefix] [-s suffix]\n";
227 const char optstring[] = "d:hp:s:";
228 # else /* ! HAVE_MKSTEMPS */
229 const char usage[] = "usage: %s [-h] [-d directory] [-p prefix]\n";
230 const char optstring[] = "d:hp:";
231 # endif /* ! HAVE_MKSTEMPS */
232 int opt;
233
234 while ((opt = getopt(argc, argv, optstring)) != -1) {
235 switch (opt) {
236 case 'd':
237 *directory = optarg;
238 break;
239 case 'p':
240 *prefix = optarg;
241 break;
242 case 's':
243 *suffix = optarg;
244 break;
245 case 'h':
246 (void) printf(usage, argv[0]);
247 exit(0);
248 default:
249 (void) fprintf(stderr, usage, argv[0]);
250 exit(1);
251 }
252 }
253 }
254 #endif /* ! NMH */