1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /* Copyright (c) 1987, 1988 Microsoft Corporation */
31 /* All Rights Reserved */
32
33 /*
34 * mknod - build special file
35 *
36 * mknod name [ b ] [ c ] major minor
37 * mknod name p (named pipe)
38 *
39 * MODIFICATION HISTORY
40 * M000 11 Apr 83 andyp 3.0 upgrade
41 * - (Mostly uncommented). Picked up 3.0 source.
42 * - Added header. Changed usage message. Replaced hard-coded
43 * makedev with one from <sys/types.h>.
44 * - Added mechanism for creating name space files.
45 * - Added some error checks.
46 * - Semi-major reorganition.
47 */
48
49 #include <sys/types.h>
50 #include <stdio.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <errno.h>
54 #include <sys/stat.h>
55 #include <sys/mkdev.h>
56
57 #define ACC 0666
58
59 static int domk(const char *path, const mode_t mode, const dev_t arg);
60 static long number(const char *s);
61 static void usage(void);
62
63 int
main(int argc,char ** argv)64 main(int argc, char **argv)
65 {
66 mode_t mode;
67 dev_t arg;
68 major_t majno;
69 minor_t minno;
70
71 if (argc < 3 || argc > 5)
72 usage();
73
74 if (argv[2][1] != '\0')
75 usage();
76
77 if (argc == 3) {
78 switch (argv[2][0]) {
79 case 'p':
80 mode = S_IFIFO;
81 arg = 0; /* (not used) */
82 break;
83 default:
84 usage();
85 /* NO RETURN */
86 }
87 } else if (argc == 5) {
88 switch (argv[2][0]) {
89 case 'b':
90 mode = S_IFBLK;
91 break;
92 case 'c':
93 mode = S_IFCHR;
94 break;
95 default:
96 usage();
97 }
98 majno = (major_t)number(argv[3]);
99 if (majno == (major_t)-1 || majno > MAXMAJ) {
100 (void) fprintf(stderr, "mknod: invalid major number "
101 "'%s' - valid range is 0-%lu\n", argv[3], MAXMAJ);
102 return (2);
103 }
104 minno = (minor_t)number(argv[4]);
105 if (minno == (minor_t)-1 || minno > MAXMIN) {
106 (void) fprintf(stderr, "mknod: invalid minor number "
107 "'%s' - valid range is 0-%lu\n", argv[4], MAXMIN);
108 return (2);
109 }
110 arg = makedev(majno, minno);
111 } else
112 usage();
113
114 return (domk(argv[1], (mode | ACC), arg) ? 2 : 0);
115 }
116
117 static int
domk(const char * path,const mode_t mode,const dev_t arg)118 domk(const char *path, const mode_t mode, const dev_t arg)
119 {
120 int ec;
121
122 if ((ec = mknod(path, mode, arg)) == -1) {
123 perror("mknod");
124 } else {
125 /* chown() return deliberately ignored */
126 (void) chown(path, getuid(), getgid());
127 }
128 return (ec);
129 }
130
131 static long
number(const char * s)132 number(const char *s)
133 {
134 long n;
135
136 errno = 0;
137 n = strtol(s, NULL, 0);
138 if (errno != 0 || n < 0)
139 return (-1);
140 return (n);
141 }
142
143 static void
usage(void)144 usage(void)
145 {
146 (void) fprintf(stderr, "usage: mknod name [ b/c major minor ] [ p ]\n");
147 exit(2);
148 }
149