source: rtems/cpukit/libmisc/shell/main_mknod.c @ 8e686a24

4.104.115
Last change on this file since 8e686a24 was 8e686a24, checked in by Chris Johns <chrisj@…>, on Oct 8, 2009 at 9:31:40 PM

2009-10-09 Chris Johns <chrisj@…>

  • libmisc/shell/main_mknod.c: Fixed build problem with networking disabled.
  • Property mode set to 100644
File size: 10.4 KB
Line 
1/*      $NetBSD: mknod.c,v 1.39 2009/02/13 01:37:23 lukem Exp $ */
2
3/*-
4 * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#if HAVE_NBTOOL_CONFIG_H
33#include "nbtool_config.h"
34#endif
35
36#if 0
37#ifndef lint
38__COPYRIGHT("@(#) Copyright (c) 1998\
39 The NetBSD Foundation, Inc.  All rights reserved.");
40__RCSID("$NetBSD: mknod.c,v 1.39 2009/02/13 01:37:23 lukem Exp $");
41#endif /* not lint */
42#endif
43
44#include <rtems.h>
45#include <rtems/shell.h>
46#include <rtems/shellconfig.h>
47#define __need_getopt_newlib
48#include <getopt.h>
49
50#include <sys/cdefs.h>
51
52#include <sys/types.h>
53#include <sys/stat.h>
54#include <sys/param.h>
55#if !HAVE_NBTOOL_CONFIG_H && defined(KERN_DRIVERS)
56#include <sys/sysctl.h>
57#endif
58
59#include <err.h>
60#include <errno.h>
61#include <limits.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <unistd.h>
65#include <pwd.h>
66#include <grp.h>
67#include <string.h>
68#include <ctype.h>
69
70#include "mknod-pack_dev.h"
71
72#include <setjmp.h>
73
74typedef struct {
75  int exit_code;
76  jmp_buf exit_jmp;
77} rtems_shell_mknod_globals;
78
79#define exit_jump &(globals->exit_jmp)
80
81#define exit(ec) rtems_shell_mknod_exit(globals, ec)
82
83static int gid_name(const char *, gid_t *);
84static portdev_t callPack(rtems_shell_mknod_globals* globals,
85                          pack_t *, int, u_long *);
86
87static int      main_mknod(rtems_shell_mknod_globals*, int, char *[]);
88static  void    usage(rtems_shell_mknod_globals* );
89
90static void
91rtems_shell_mknod_exit (rtems_shell_mknod_globals* globals, int code)
92{
93  globals->exit_code = code;
94  longjmp (globals->exit_jmp, 1);
95}
96
97#include "mknod-pack_dev.c"
98
99int
100rtems_shell_main_mknod(int argc, char *argv[])
101{
102  rtems_shell_mknod_globals  mknod_globals;
103  rtems_shell_mknod_globals* globals = &mknod_globals;
104  memset (globals, 0, sizeof (mknod_globals));
105  mknod_globals.exit_code = 1;
106  if (setjmp (mknod_globals.exit_jmp) == 0)
107    return main_mknod (globals, argc, argv);
108  return mknod_globals.exit_code;
109}
110
111#define getprogname() "mknod"
112
113#ifdef KERN_DRIVERS
114#error invalid for RTEMS
115static struct kinfo_drivers *kern_drivers;
116static int num_drivers;
117
118static void get_device_info(void);
119static void print_device_info(char **);
120static int major_from_name(const char *, mode_t);
121#endif
122
123#define MAXARGS 3               /* 3 for bsdos, 2 for rest */
124
125int
126main_mknod(rtems_shell_mknod_globals* globals, int argc, char **argv)
127{
128        char    *name, *p;
129        mode_t   mode;
130        portdev_t        dev;
131        pack_t  *pack;
132        u_long   numbers[MAXARGS];
133        int      n, ch, fifo, hasformat;
134        int      r_flag = 0;            /* force: delete existing entry */
135#ifdef KERN_DRIVERS
136        int      l_flag = 0;            /* list device names and numbers */
137        int      major;
138#endif
139#if RTEMS_REMOVED
140        void    *modes = 0;
141#endif
142        uid_t    uid = -1;
143        gid_t    gid = -1;
144        int      rval;
145
146        struct getopt_data getopt_reent;
147        memset(&getopt_reent, 0, sizeof(getopt_data));
148
149        dev = 0;
150        fifo = hasformat = 0;
151        pack = pack_native;
152
153#ifdef KERN_DRIVERS
154        while ((ch = getopt(argc, argv, "lrRF:g:m:u:")) != -1) {
155#else
156        while ((ch = getopt_r(argc, argv, "rRF:g:m:u:", &getopt_reent)) != -1) {
157#endif
158                switch (ch) {
159
160#ifdef KERN_DRIVERS
161                case 'l':
162                        l_flag = 1;
163                        break;
164#endif
165
166                case 'r':
167                        r_flag = 1;
168                        break;
169
170                case 'R':
171                        r_flag = 2;
172                        break;
173
174                case 'F':
175                        pack = pack_find(getopt_reent.optarg);
176                        if (pack == NULL)
177                                errx(exit_jump, 1, "invalid format: %s", getopt_reent.optarg);
178                        hasformat++;
179                        break;
180
181                case 'g':
182                        if (getopt_reent.optarg[0] == '#') {
183                                gid = strtol(getopt_reent.optarg + 1, &p, 10);
184                                if (*p == 0)
185                                        break;
186                        }
187                        if (gid_name(getopt_reent.optarg, &gid) == 0)
188                                break;
189                        gid = strtol(getopt_reent.optarg, &p, 10);
190                        if (*p == 0)
191                                break;
192                        errx(exit_jump, 1, "%s: invalid group name", getopt_reent.optarg);
193
194                case 'm':
195#if RTEMS_REMOVED
196                        modes = setmode(getopt_reent.optarg);
197                        if (modes == NULL)
198#endif
199                                err(exit_jump, 1, "Cannot set file mode `%s'", getopt_reent.optarg);
200                        break;
201
202                case 'u':
203                        if (getopt_reent.optarg[0] == '#') {
204                                uid = strtol(getopt_reent.optarg + 1, &p, 10);
205                                if (*p == 0)
206                                        break;
207                        }
208#if RTEMS_REMOVED
209                        if (uid_from_user(getopt_reent.optarg, &uid) == 0)
210                                break;
211#endif
212                        uid = strtol(getopt_reent.optarg, &p, 10);
213                        if (*p == 0)
214                                break;
215                        errx(exit_jump, 1, "%s: invalid user name", getopt_reent.optarg);
216
217                default:
218                case '?':
219                        usage(globals);
220                }
221        }
222        argc -= getopt_reent.optind;
223        argv += getopt_reent.optind;
224
225#ifdef KERN_DRIVERS
226        if (l_flag) {
227                print_device_info(argv);
228                return 0;
229        }
230#endif
231
232        if (argc < 2 || argc > 10)
233                usage(globals);
234
235        name = *argv;
236        argc--;
237        argv++;
238
239        umask(mode = umask(0));
240        mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mode;
241
242        if (argv[0][1] != '\0')
243                goto badtype;
244        switch (*argv[0]) {
245        case 'c':
246                mode |= S_IFCHR;
247                break;
248
249        case 'b':
250                mode |= S_IFBLK;
251                break;
252
253        case 'p':
254                if (hasformat)
255                        errx(exit_jump, 1, "format is meaningless for fifos");
256                mode |= S_IFIFO;
257                fifo = 1;
258                break;
259
260        default:
261 badtype:
262                errx(exit_jump, 1, "node type must be 'b', 'c' or 'p'.");
263        }
264        argc--;
265        argv++;
266
267        if (fifo) {
268                if (argc != 0)
269                        usage(globals);
270        } else {
271                if (argc < 1 || argc > MAXARGS)
272                        usage(globals);
273        }
274
275        for (n = 0; n < argc; n++) {
276                errno = 0;
277                numbers[n] = strtoul(argv[n], &p, 0);
278                if (*p == 0 && errno == 0)
279                        continue;
280#ifdef KERN_DRIVERS
281                if (n == 0) {
282                        major = major_from_name(argv[0], mode);
283                        if (major != -1) {
284                                numbers[0] = major;
285                                continue;
286                        }
287                        if (!isdigit(*(unsigned char *)argv[0]))
288                                errx(1, "unknown driver: %s", argv[0]);
289                }
290#endif
291                errx(exit_jump, 1, "invalid number: %s", argv[n]);
292        }
293
294        switch (argc) {
295        case 0:
296                dev = 0;
297                break;
298
299        case 1:
300                dev = numbers[0];
301                break;
302
303        default:
304                dev = callPack(globals, pack, argc, numbers);
305                break;
306        }
307
308#if RTEMS_REMOVED
309        if (modes != NULL)
310                mode = getmode(modes, mode);
311#endif
312        umask(0);
313        rval = fifo ? mkfifo(name, mode) : mknod(name, mode, dev);
314        if (rval < 0 && errno == EEXIST && r_flag) {
315                struct stat sb;
316                if (lstat(name, &sb) != 0 || (!fifo && sb.st_rdev != dev))
317                        sb.st_mode = 0;
318
319                if ((sb.st_mode & S_IFMT) == (mode & S_IFMT)) {
320                        if (r_flag == 1)
321                                /* Ignore permissions and user/group */
322                                return 0;
323                        if (sb.st_mode != mode)
324                                rval = chmod(name, mode);
325                        else
326                                rval = 0;
327                } else {
328                        unlink(name);
329                        rval = fifo ? mkfifo(name, mode)
330                                    : mknod(name, mode, dev);
331                }
332        }
333        if (rval < 0)
334                err(exit_jump, 1, "%s", name);
335        if ((uid != (uid_t)-1 || gid != (uid_t)-1) && chown(name, uid, gid) == -1)
336                /* XXX Should we unlink the files here? */
337                warn("%s: uid/gid not changed", name);
338
339        return 0;
340}
341
342static void
343usage(rtems_shell_mknod_globals* globals)
344{
345        const char *progname = getprogname();
346
347        (void)fprintf(stderr,
348            "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
349            progname);
350        (void)fprintf(stderr,
351#ifdef KERN_DRIVERS
352            "                   [ name [b | c] [major | driver] minor\n"
353#else
354            "                   [ name [b | c] major minor\n"
355#endif
356            "                   | name [b | c] major unit subunit\n"
357            "                   | name [b | c] number\n"
358            "                   | name p ]\n");
359#ifdef KERN_DRIVERS
360        (void)fprintf(stderr, "       %s -l [driver] ...\n", progname);
361#endif
362        exit(1);
363}
364
365static int
366gid_name(const char *name, gid_t *gid)
367{
368        struct group *g;
369
370        g = getgrnam(name);
371        if (!g)
372                return -1;
373        *gid = g->gr_gid;
374        return 0;
375}
376
377static portdev_t
378callPack(rtems_shell_mknod_globals* globals, pack_t *f, int n, u_long *numbers)
379{
380        portdev_t d;
381        const char *error = NULL;
382
383        d = (*f)(n, numbers, &error);
384        if (error != NULL)
385                errx(exit_jump, 1, "%s", error);
386        return d;
387}
388
389#ifdef KERN_DRIVERS
390static void
391get_device_info(void)
392{
393        static int mib[2] = {CTL_KERN, KERN_DRIVERS};
394        size_t len;
395
396        if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
397                err(1, "kern.drivers" );
398        kern_drivers = malloc(len);
399        if (kern_drivers == NULL)
400                err(1, "malloc");
401        if (sysctl(mib, 2, kern_drivers, &len, NULL, 0) != 0)
402                err(1, "kern.drivers" );
403
404        num_drivers = len / sizeof *kern_drivers;
405}
406
407static void
408print_device_info(char **names)
409{
410        int i;
411        struct kinfo_drivers *kd;
412
413        if (kern_drivers == NULL)
414                get_device_info();
415
416        do {
417                kd = kern_drivers;
418                for (i = 0; i < num_drivers; kd++, i++) {
419                        if (*names && strcmp(*names, kd->d_name))
420                                continue;
421                        printf("%s", kd->d_name);
422                        if (kd->d_cmajor != -1)
423                                printf(" character major %d", kd->d_cmajor);
424                        if (kd->d_bmajor != -1)
425                                printf(" block major %d", kd->d_bmajor);
426                        printf("\n");
427                }
428        } while (*names && *++names);
429}
430
431static int
432major_from_name(const char *name, mode_t mode)
433{
434        int i;
435        struct kinfo_drivers *kd;
436
437        if (kern_drivers == NULL)
438                get_device_info();
439
440        kd = kern_drivers;
441        for (i = 0; i < num_drivers; kd++, i++) {
442                if (strcmp(name, kd->d_name))
443                        continue;
444                if (S_ISCHR(mode))
445                        return kd->d_cmajor;
446                return kd->d_bmajor;
447        }
448        return -1;
449}
450#endif
451
452rtems_shell_cmd_t rtems_shell_MKNOD_Command = {
453  "mknod",                                                   /* name */
454  "mknod mknod [-rR] [-F fmt] [-m mode] name [c | b] minor", /* usage */
455  "files",                                                   /* topic */
456  rtems_shell_main_mknod,                                    /* command */
457  NULL,                                                      /* alias */
458  NULL                                                       /* next */
459};
Note: See TracBrowser for help on using the repository browser.