18fae3551SRodney W. Grimes /* 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 48fae3551SRodney W. Grimes * Copyright (c) 1989, 1993 58fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 68fae3551SRodney W. Grimes * 78fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 88fae3551SRodney W. Grimes * Kevin Fall. 98fae3551SRodney W. Grimes * 108fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 118fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 128fae3551SRodney W. Grimes * are met: 138fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 158fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 168fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 178fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 198fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 208fae3551SRodney W. Grimes * without specific prior written permission. 218fae3551SRodney W. Grimes * 228fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 238fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 248fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 258fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 268fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 278fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 288fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 298fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 308fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 318fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 328fae3551SRodney W. Grimes * SUCH DAMAGE. 338fae3551SRodney W. Grimes */ 348fae3551SRodney W. Grimes 358fae3551SRodney W. Grimes #ifndef lint 367c9e694fSBruce Evans static const char copyright[] = 378fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 388fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 398fae3551SRodney W. Grimes #endif /* not lint */ 408fae3551SRodney W. Grimes 418fae3551SRodney W. Grimes #ifndef lint 427c9e694fSBruce Evans #if 0 438fae3551SRodney W. Grimes static char sccsid[] = "@(#)mknod.c 8.1 (Berkeley) 6/5/93"; 447c9e694fSBruce Evans #endif 45fbb3447fSPhilippe Charnier static const char rcsid[] = 467f3dea24SPeter Wemm "$FreeBSD$"; 478fae3551SRodney W. Grimes #endif /* not lint */ 488fae3551SRodney W. Grimes 498fae3551SRodney W. Grimes #include <sys/types.h> 508fae3551SRodney W. Grimes #include <sys/stat.h> 518fae3551SRodney W. Grimes 52fbb3447fSPhilippe Charnier #include <err.h> 537c9e694fSBruce Evans #include <errno.h> 547c9e694fSBruce Evans #include <stdio.h> 557c9e694fSBruce Evans #include <stdlib.h> 567c9e694fSBruce Evans #include <unistd.h> 572dc15252SDavid E. O'Brien #include <grp.h> 582dc15252SDavid E. O'Brien #include <pwd.h> 592dc15252SDavid E. O'Brien #include <string.h> 60fbb3447fSPhilippe Charnier 61fbb3447fSPhilippe Charnier static void 625224d0a1SXin LI usage(void) 63fbb3447fSPhilippe Charnier { 642dc15252SDavid E. O'Brien 652dc15252SDavid E. O'Brien (void)fprintf(stderr, 6604e532d5SEd Schouten "usage: mknod name\n" 6704e532d5SEd Schouten " mknod name [b | c] major minor [owner:group]\n"); 68fbb3447fSPhilippe Charnier exit(1); 69fbb3447fSPhilippe Charnier } 707c9e694fSBruce Evans 712dc15252SDavid E. O'Brien static u_long 725224d0a1SXin LI id(const char *name, const char *type) 732dc15252SDavid E. O'Brien { 742dc15252SDavid E. O'Brien u_long val; 752dc15252SDavid E. O'Brien char *ep; 762dc15252SDavid E. O'Brien 772dc15252SDavid E. O'Brien /* 782dc15252SDavid E. O'Brien * XXX 792dc15252SDavid E. O'Brien * We know that uid_t's and gid_t's are unsigned longs. 802dc15252SDavid E. O'Brien */ 812dc15252SDavid E. O'Brien errno = 0; 822dc15252SDavid E. O'Brien val = strtoul(name, &ep, 10); 832dc15252SDavid E. O'Brien if (errno) 842dc15252SDavid E. O'Brien err(1, "%s", name); 852dc15252SDavid E. O'Brien if (*ep != '\0') 862dc15252SDavid E. O'Brien errx(1, "%s: illegal %s name", name, type); 872dc15252SDavid E. O'Brien return (val); 882dc15252SDavid E. O'Brien } 892dc15252SDavid E. O'Brien 902dc15252SDavid E. O'Brien static gid_t 915224d0a1SXin LI a_gid(const char *s) 922dc15252SDavid E. O'Brien { 932dc15252SDavid E. O'Brien struct group *gr; 942dc15252SDavid E. O'Brien 952dc15252SDavid E. O'Brien if (*s == '\0') /* Argument was "uid[:.]". */ 962dc15252SDavid E. O'Brien errx(1, "group must be specified when the owner is"); 972dc15252SDavid E. O'Brien return ((gr = getgrnam(s)) == NULL) ? id(s, "group") : gr->gr_gid; 982dc15252SDavid E. O'Brien } 992dc15252SDavid E. O'Brien 1002dc15252SDavid E. O'Brien static uid_t 1015224d0a1SXin LI a_uid(const char *s) 1022dc15252SDavid E. O'Brien { 1032dc15252SDavid E. O'Brien struct passwd *pw; 1042dc15252SDavid E. O'Brien 1052dc15252SDavid E. O'Brien if (*s == '\0') /* Argument was "[:.]gid". */ 1062dc15252SDavid E. O'Brien errx(1, "owner must be specified when the group is"); 1072dc15252SDavid E. O'Brien return ((pw = getpwnam(s)) == NULL) ? id(s, "user") : pw->pw_uid; 1082dc15252SDavid E. O'Brien } 1092dc15252SDavid E. O'Brien 1107c9e694fSBruce Evans int 1115224d0a1SXin LI main(int argc, char **argv) 1128fae3551SRodney W. Grimes { 1137c9e694fSBruce Evans int range_error; 1142dc15252SDavid E. O'Brien uid_t uid; 1152dc15252SDavid E. O'Brien gid_t gid; 1162dc15252SDavid E. O'Brien mode_t mode; 1172dc15252SDavid E. O'Brien dev_t dev; 1182dc15252SDavid E. O'Brien char *cp, *endp; 1192dc15252SDavid E. O'Brien long mymajor, myminor; 1208fae3551SRodney W. Grimes 12104e532d5SEd Schouten if (argc != 2 && argc != 5 && argc != 6) 122fbb3447fSPhilippe Charnier usage(); 1238fae3551SRodney W. Grimes 12404e532d5SEd Schouten if (argc >= 5) { 1258fae3551SRodney W. Grimes mode = 0666; 1268fae3551SRodney W. Grimes if (argv[2][0] == 'c') 1278fae3551SRodney W. Grimes mode |= S_IFCHR; 1288fae3551SRodney W. Grimes else if (argv[2][0] == 'b') 1298fae3551SRodney W. Grimes mode |= S_IFBLK; 13086eaffafSPhilippe Charnier else 13186eaffafSPhilippe Charnier errx(1, "node must be type 'b' or 'c'"); 1328fae3551SRodney W. Grimes 1337c9e694fSBruce Evans errno = 0; 13495b9c18aSPoul-Henning Kamp mymajor = (long)strtoul(argv[3], &endp, 0); 13586eaffafSPhilippe Charnier if (endp == argv[3] || *endp != '\0') 13686eaffafSPhilippe Charnier errx(1, "%s: non-numeric major number", argv[3]); 1377c9e694fSBruce Evans range_error = errno; 1387c9e694fSBruce Evans errno = 0; 13995b9c18aSPoul-Henning Kamp myminor = (long)strtoul(argv[4], &endp, 0); 14086eaffafSPhilippe Charnier if (endp == argv[4] || *endp != '\0') 14186eaffafSPhilippe Charnier errx(1, "%s: non-numeric minor number", argv[4]); 1427c9e694fSBruce Evans range_error |= errno; 14395b9c18aSPoul-Henning Kamp dev = makedev(mymajor, myminor); 1441161d420SRebecca Cran if (range_error || major(dev) != mymajor || 14598397198SXin LI (long)(u_int)minor(dev) != myminor) 14686eaffafSPhilippe Charnier errx(1, "major or minor number too large"); 14704e532d5SEd Schouten } else { 14804e532d5SEd Schouten mode = 0666 | S_IFCHR; 14904e532d5SEd Schouten dev = 0; 15004e532d5SEd Schouten } 151ce6bb537SJoerg Wunsch 1522dc15252SDavid E. O'Brien uid = gid = -1; 1532dc15252SDavid E. O'Brien if (6 == argc) { 1542dc15252SDavid E. O'Brien /* have owner:group */ 1552dc15252SDavid E. O'Brien if ((cp = strchr(argv[5], ':')) != NULL) { 1562dc15252SDavid E. O'Brien *cp++ = '\0'; 1572dc15252SDavid E. O'Brien gid = a_gid(cp); 1582dc15252SDavid E. O'Brien } else 1592dc15252SDavid E. O'Brien usage(); 1602dc15252SDavid E. O'Brien uid = a_uid(argv[5]); 1612dc15252SDavid E. O'Brien } 1622dc15252SDavid E. O'Brien 16386eaffafSPhilippe Charnier if (mknod(argv[1], mode, dev) != 0) 16486eaffafSPhilippe Charnier err(1, "%s", argv[1]); 1652dc15252SDavid E. O'Brien if (6 == argc) 1662dc15252SDavid E. O'Brien if (chown(argv[1], uid, gid)) 1672dc15252SDavid E. O'Brien err(1, "setting ownership on %s", argv[1]); 1688fae3551SRodney W. Grimes exit(0); 1698fae3551SRodney W. Grimes } 170