1 /* $OpenBSD: mknod.c,v 1.18 2010/03/27 09:10:02 jmc Exp $ */ 2 /* $NetBSD: mknod.c,v 1.8 1995/08/11 00:08:18 jtc Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Kevin Fall. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <locale.h> 43 #include <err.h> 44 45 extern char *__progname; 46 47 int domknod(char **, mode_t); 48 int domkfifo(char **, mode_t); 49 void usage(int); 50 51 int 52 main(int argc, char *argv[]) 53 { 54 int ch, ismkfifo = 0; 55 void *set = NULL; 56 mode_t mode = 0; 57 58 setlocale (LC_ALL, ""); 59 60 if (strcmp(__progname, "mkfifo") == 0) 61 ismkfifo = 1; 62 63 while ((ch = getopt(argc, argv, "m:")) != -1) 64 switch(ch) { 65 case 'm': 66 if (!(set = setmode(optarg))) { 67 errx(1, "invalid file mode."); 68 /* NOTREACHED */ 69 } 70 71 /* 72 * In symbolic mode strings, the + and - operators are 73 * interpreted relative to an assumed initial mode of 74 * a=rw. 75 */ 76 mode = getmode(set, DEFFILEMODE); 77 free(set); 78 break; 79 case '?': 80 default: 81 usage(ismkfifo); 82 } 83 argc -= optind; 84 argv += optind; 85 86 if (argv[0] == NULL) 87 usage(ismkfifo); 88 if (!ismkfifo) { 89 if (argc == 2 && argv[1][0] == 'p') { 90 ismkfifo = 2; 91 argc--; 92 argv[1] = NULL; 93 } else if (argc != 4) { 94 usage(ismkfifo); 95 /* NOTREACHED */ 96 } 97 } 98 99 /* 100 * If the user specified a mode via `-m', don't allow the umask 101 * to modified it. If no `-m' flag was specified, the default 102 * mode is the value of the bitwise inclusive or of S_IRUSR, 103 * S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH as modified by 104 * the umask. 105 */ 106 if (set) 107 (void)umask(0); 108 else 109 mode = DEFFILEMODE; 110 111 if (ismkfifo) 112 exit(domkfifo(argv, mode)); 113 else 114 exit(domknod(argv, mode)); 115 } 116 117 int 118 domknod(char **argv, mode_t mode) 119 { 120 dev_t dev; 121 char *endp; 122 u_int major, minor; 123 124 if (argv[1][0] == 'c') 125 mode |= S_IFCHR; 126 else if (argv[1][0] == 'b') 127 mode |= S_IFBLK; 128 else { 129 errx(1, "node must be type 'b' or 'c'."); 130 /* NOTREACHED */ 131 } 132 133 major = (long)strtoul(argv[2], &endp, 0); 134 if (endp == argv[2] || *endp != '\0') { 135 errx(1, "non-numeric major number."); 136 /* NOTREACHED */ 137 } 138 minor = (long)strtoul(argv[3], &endp, 0); 139 if (endp == argv[3] || *endp != '\0') { 140 errx(1, "non-numeric minor number."); 141 /* NOTREACHED */ 142 } 143 dev = makedev(major, minor); 144 if (major(dev) != major || minor(dev) != minor) { 145 errx(1, "major or minor number too large"); 146 /* NOTREACHED */ 147 } 148 if (mknod(argv[0], mode, dev) < 0) { 149 err(1, "%s", argv[0]); 150 /* NOTREACHED */ 151 } 152 return(0); 153 } 154 155 int 156 domkfifo(char **argv, mode_t mode) 157 { 158 int rv; 159 160 for (rv = 0; *argv; ++argv) { 161 if (mkfifo(*argv, mode) < 0) { 162 warn("%s", *argv); 163 rv = 1; 164 } 165 } 166 return(rv); 167 } 168 169 void 170 usage(int ismkfifo) 171 { 172 173 if (ismkfifo == 1) 174 (void)fprintf(stderr, "usage: %s [-m mode] fifo_name ...\n", 175 __progname); 176 else { 177 (void)fprintf(stderr, 178 "usage: %s [-m mode] name b|c major minor\n", 179 __progname); 180 (void)fprintf(stderr, " %s [-m mode] name p\n", 181 __progname); 182 } 183 exit(1); 184 } 185