/* mkstemp.c -- create a temporary file * * This code is Copyright (c) 2014 by the authors of nmh. * See the COPYRIGHT file in the root directory of the nmh * distribution for complete copyright information. */ /* define NMH to 0 to remove dependencies on nmh. */ #ifndef NMH # define NMH 1 #endif /* ! NMH */ #ifdef HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #if ! defined HAVE_MKSTEMPS # define HAVE_MKSTEMPS 0 #endif /* ! HAVE_MKSTEMPS */ char *build_template(const char *, const char *, const char *); void process_args(int, char **, const char **, const char **, const char **); /* * Use a template of the form: * [directory/][prefix]XXXXXX[suffix] * where some of those named components might be null. suffix is only * supported if HAVE_MKSTEMPS. */ int main(int argc, char *argv[]) { const char *directory = "", *prefix = "", *suffix = ""; size_t suffix_len; int fd; char *template; process_args(argc, argv, &directory, &prefix, &suffix); if ((template = build_template(directory, prefix, suffix)) == NULL) { return -1; } if ((suffix_len = strlen(suffix)) > 0) { # if HAVE_MKSTEMPS if ((fd = mkstemps(template, suffix_len)) < 0) { perror("mkstemps"); } # else /* ! HAVE_MKSTEMPS */ fd = 0; # endif /* ! HAVE_MKSTEMPS */ } else { if ((fd = mkstemp(template)) < 0) { perror("mkstemp"); } } if (fd >= 0) { (void) puts(template); (void) close(fd); } free(template); return fd >= 0 ? 0 : -1; } char * build_template(const char *directory, const char *prefix, const char *suffix) { const char pattern[] = "XXXXXX"; size_t len, directory_len, pathsep_len, prefix_len, suffix_len; char *template; directory_len = strlen(directory); if (directory_len > 0) { pathsep_len = 1; if (directory[directory_len - 1] == '/') { /* Will insert a '/' separately, so truncate the one provided in the directory name. */ --directory_len; } } else { pathsep_len = 0; } prefix_len = strlen(prefix); suffix_len = strlen(suffix); /* sizeof pattern includes its final NULL, so don't add another. */ len = directory_len + pathsep_len + prefix_len + sizeof pattern + suffix_len; if ((template = malloc(len))) { char *tp = template; (void) strncpy(tp, directory, directory_len); tp += directory_len; if (pathsep_len == 1) { *tp++ = '/'; } (void) strncpy(tp, prefix, prefix_len); tp += prefix_len; (void) strncpy(tp, pattern, sizeof pattern - 1); tp += sizeof pattern - 1; (void) strncpy(tp, suffix, suffix_len); /* tp += suffix_len; */ template[len-1] = '\0'; return template; } perror("malloc"); return NULL; } #if NMH #include #if HAVE_MKSTEMPS # define MHFIXMSG_SWITCHES \ X("directory", 0, DIRECTORYSW) \ X("prefix", 0, PREFIXSW) \ X("suffix", 0, SUFFIXSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) #else /* ! HAVE_MKSTEMPS */ # define MHFIXMSG_SWITCHES \ X("directory", 0, DIRECTORYSW) \ X("prefix", 0, PREFIXSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) #endif /* ! HAVE_MKSTEMPS */ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(MHFIXMSG); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(MHFIXMSG, switches); #undef X void process_args(int argc, char **argv, const char **directory, const char **prefix, const char **suffix) { char **argp, **arguments, *cp, buf[100]; # if ! HAVE_MKSTEMPS NMH_UNUSED(suffix); # endif /* ! HAVE_MKSTEMPS */ if (nmh_init(argv[0], 2)) { done(NOTOK); } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch(++cp, switches)) { case AMBIGSW: ambigsw(cp, switches); done(NOTOK); case UNKWNSW: inform("-%s unknown", cp); (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name); print_help(buf, switches, 1); done(NOTOK); case HELPSW: (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name); print_help(buf, switches, 1); done(OK); case VERSIONSW: print_version(invo_name); done(OK); case DIRECTORYSW: /* Allow the directory to start with '-'. */ if ((cp = *argp++) == NULL) { adios(NULL, "missing argument to %s", argp[-2]); } *directory = cp; continue; case PREFIXSW: /* Allow the prefix to start with '-'. */ if ((cp = *argp++) == NULL) { adios(NULL, "missing argument to %s", argp[-2]); } *prefix = cp; continue; # if HAVE_MKSTEMPS case SUFFIXSW: /* Allow the suffix to start with '-'. */ if ((cp = *argp++) == NULL) { adios(NULL, "missing argument to %s", argp[-2]); } *suffix = cp; continue; # endif /* HAVE_MKSTEMPS */ } } } } #else /* ! NMH */ void process_args(int argc, char **argv, const char **directory, const char **prefix, const char **suffix) { # if HAVE_MKSTEMPS const char usage[] = "usage: %s [-h] [-d directory] [-p prefix] [-s suffix]\n"; const char optstring[] = "d:hp:s:"; # else /* ! HAVE_MKSTEMPS */ const char usage[] = "usage: %s [-h] [-d directory] [-p prefix]\n"; const char optstring[] = "d:hp:"; # endif /* ! HAVE_MKSTEMPS */ int opt; while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { case 'd': *directory = optarg; break; case 'p': *prefix = optarg; break; case 's': *suffix = optarg; break; case 'h': (void) printf(usage, argv[0]); exit(0); default: (void) fprintf(stderr, usage, argv[0]); exit(-1); } } } #endif /* ! NMH */