usage.c: remove reference to busybox.h
[oweals/busybox.git] / coreutils / id.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini id implementation for busybox
4  *
5  * Copyright (C) 2000 by Randolph Chung <tausq@debian.org>
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8  */
9
10 /* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
11 /* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
12  * be more similar to GNU id.
13  * -Z option support: by Yuichi Nakamura <ynakam@hitachisoft.jp>
14  */
15
16 #include "libbb.h"
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20
21 #define PRINT_REAL        1
22 #define NAME_NOT_NUMBER   2
23 #define JUST_USER         4
24 #define JUST_GROUP        8
25 #if ENABLE_SELINUX
26 #define JUST_CONTEXT    16
27 #endif
28
29 static short printf_full(unsigned int id, const char *arg, const char prefix)
30 {
31         const char *fmt = "%cid=%u";
32         short status = EXIT_FAILURE;
33
34         if (arg) {
35                 fmt = "%cid=%u(%s)";
36                 status = EXIT_SUCCESS;
37         }
38         printf(fmt, prefix, id, arg);
39         return status;
40 }
41
42 int id_main(int argc, char **argv);
43 int id_main(int argc, char **argv)
44 {
45         struct passwd *p;
46         uid_t uid;
47         gid_t gid;
48         unsigned long flags;
49         short status;
50 #if ENABLE_SELINUX
51         security_context_t scontext;
52 #endif
53         /* Don't allow -n -r -nr -ug -rug -nug -rnug */
54         /* Don't allow more than one username */
55         opt_complementary = "?1:?:u--g:g--u:r?ug:n?ug" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
56         flags = getopt32(argc, argv, "rnug" USE_SELINUX("Z"));
57
58         /* This values could be overwritten later */
59         uid = geteuid();
60         gid = getegid();
61         if (flags & PRINT_REAL) {
62                 uid = getuid();
63                 gid = getgid();
64         }
65
66         if (argv[optind]) {
67                 p = getpwnam(argv[optind]);
68                 /* xuname2uid is needed because it exits on failure */
69                 uid = xuname2uid(argv[optind]);
70                 gid = p->pw_gid;
71                 /* in this case PRINT_REAL is the same */
72         }
73
74         if (flags & (JUST_GROUP | JUST_USER USE_SELINUX(| JUST_CONTEXT))) {
75                 /* JUST_GROUP and JUST_USER are mutually exclusive */
76                 if (flags & NAME_NOT_NUMBER) {
77                         /* bb_getpwuid and bb_getgrgid exit on failure so puts cannot segfault */
78                         puts((flags & JUST_USER) ? bb_getpwuid(NULL, uid, -1 ) : bb_getgrgid(NULL, gid, -1 ));
79                 } else {
80                         if (flags & JUST_USER) {
81                                 printf("%u\n", uid);
82                         }
83                         if (flags & JUST_GROUP) {
84                                 printf("%u\n", gid);
85                         }
86                 }
87
88 #if ENABLE_SELINUX
89                 if (flags & JUST_CONTEXT) {
90                         selinux_or_die();
91                         if (argc - optind == 1) {
92                                 bb_error_msg_and_die("user name can't be passed with -Z");
93                         }
94
95                         if (getcon(&scontext)) {
96                                 bb_error_msg_and_die("can't get process context");
97                         }
98                         printf("%s\n", scontext);
99                 }
100 #endif
101                 /* exit */
102                 fflush_stdout_and_exit(EXIT_SUCCESS);
103         }
104
105         /* Print full info like GNU id */
106         /* bb_getpwuid doesn't exit on failure here */
107         status = printf_full(uid, bb_getpwuid(NULL, uid, 0), 'u');
108         putchar(' ');
109         /* bb_getgrgid doesn't exit on failure here */
110         status |= printf_full(gid, bb_getgrgid(NULL, gid, 0), 'g');
111
112 #if ENABLE_SELINUX
113         if (is_selinux_enabled()) {
114                 security_context_t mysid;
115                 const char *context;
116
117                 context = "unknown";
118                 getcon(&mysid);
119                 if (mysid) {
120                         context = alloca(strlen(mysid) + 1);
121                         strcpy((char*)context, mysid);
122                         freecon(mysid);
123                 }
124                 printf(" context=%s", context);
125         }
126 #endif
127
128         putchar('\n');
129         fflush_stdout_and_exit(status);
130 }