1 /* $OpenBSD: mknod.c,v 1.16 2007/12/30 13:52:40 sobrado 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 #ifndef lint 37 static char copyright[] = 38 "@(#) Copyright (c) 1989, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"; 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)mknod.c 8.1 (Berkeley) 6/5/93"; 45 #else 46 static char rcsid[] = "$OpenBSD: mknod.c,v 1.16 2007/12/30 13:52:40 sobrado Exp $"; 47 #endif 48 #endif /* not lint */ 49 50 #include <sys/types.h> 51 #include <sys/stat.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 #include <locale.h> 57 #include <err.h> 58 59 extern char *__progname; 60 61 int domknod(char **, mode_t); 62 int domkfifo(char **, mode_t); 63 void usage(int); 64 65 int 66 main(int argc, char *argv[]) 67 { 68 int ch, ismkfifo = 0; 69 void *set = NULL; 70 mode_t mode = 0; 71 72 setlocale (LC_ALL, ""); 73 74 if (strcmp(__progname, "mkfifo") == 0) 75 ismkfifo = 1; 76 77 while ((ch = getopt(argc, argv, "m:")) != -1) 78 switch(ch) { 79 case 'm': 80 if (!(set = setmode(optarg))) { 81 errx(1, "invalid file mode."); 82 /* NOTREACHED */ 83 } 84 85 /* 86 * In symbolic mode strings, the + and - operators are 87 * interpreted relative to an assumed initial mode of 88 * a=rw. 89 */ 90 mode = getmode(set, DEFFILEMODE); 91 free(set); 92 break; 93 case '?': 94 default: 95 usage(ismkfifo); 96 } 97 argc -= optind; 98 argv += optind; 99 100 if (argv[0] == NULL) 101 usage(ismkfifo); 102 if (!ismkfifo) { 103 if (argc == 2 && argv[1][0] == 'p') { 104 ismkfifo = 2; 105 argc--; 106 argv[1] = NULL; 107 } else if (argc != 4) { 108 usage(ismkfifo); 109 /* NOTREACHED */ 110 } 111 } 112 113 /* 114 * If the user specified a mode via `-m', don't allow the umask 115 * to modified it. If no `-m' flag was specified, the default 116 * mode is the value of the bitwise inclusive or of S_IRUSR, 117 * S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH as modified by 118 * the umask. 119 */ 120 if (set) 121 (void)umask(0); 122 else 123 mode = DEFFILEMODE; 124 125 if (ismkfifo) 126 exit(domkfifo(argv, mode)); 127 else 128 exit(domknod(argv, mode)); 129 } 130 131 int 132 domknod(char **argv, mode_t mode) 133 { 134 dev_t dev; 135 char *endp; 136 u_int major, minor; 137 138 if (argv[1][0] == 'c') 139 mode |= S_IFCHR; 140 else if (argv[1][0] == 'b') 141 mode |= S_IFBLK; 142 else { 143 errx(1, "node must be type 'b' or 'c'."); 144 /* NOTREACHED */ 145 } 146 147 major = (long)strtoul(argv[2], &endp, 0); 148 if (endp == argv[2] || *endp != '\0') { 149 errx(1, "non-numeric major number."); 150 /* NOTREACHED */ 151 } 152 minor = (long)strtoul(argv[3], &endp, 0); 153 if (endp == argv[3] || *endp != '\0') { 154 errx(1, "non-numeric minor number."); 155 /* NOTREACHED */ 156 } 157 dev = makedev(major, minor); 158 if (major(dev) != major || minor(dev) != minor) { 159 errx(1, "major or minor number too large"); 160 /* NOTREACHED */ 161 } 162 if (mknod(argv[0], mode, dev) < 0) { 163 err(1, "%s", argv[0]); 164 /* NOTREACHED */ 165 } 166 return(0); 167 } 168 169 int 170 domkfifo(char **argv, mode_t mode) 171 { 172 int rv; 173 174 for (rv = 0; *argv; ++argv) { 175 if (mkfifo(*argv, mode) < 0) { 176 warn("%s", *argv); 177 rv = 1; 178 } 179 } 180 return(rv); 181 } 182 183 void 184 usage(int ismkfifo) 185 { 186 187 if (ismkfifo == 1) 188 (void)fprintf(stderr, "usage: %s [-m mode] fifo_name ...\n", 189 __progname); 190 else { 191 (void)fprintf(stderr, 192 "usage: %s [-m mode] name [b | c] major minor\n", 193 __progname); 194 (void)fprintf(stderr, " %s [-m mode] name p\n", 195 __progname); 196 } 197 exit(1); 198 } 199