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 #include <sys/types.h>
28 #include <sys/termio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <pwd.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <project.h>
36 #include <locale.h>
37 #include <libintl.h>
38
39 struct projlist {
40 void *pl_next;
41 char *pl_name;
42 char *pl_comm;
43 };
44
45 static struct projlist *projects;
46 static char *progname;
47
48 static void *
safe_malloc(size_t size)49 safe_malloc(size_t size)
50 {
51 void *buf;
52
53 if ((buf = malloc(size)) == NULL) {
54 (void) fprintf(stderr, gettext("%s: not enough memory\n"),
55 progname);
56 exit(1);
57 }
58 return (buf);
59 }
60
61 static int
find_projects(char * name,int default_only)62 find_projects(char *name, int default_only)
63 {
64 struct projlist *tail, *prev;
65 char *projname, *projcomm;
66 struct project proj;
67 void *buffer, *tmp;
68 int found = 0;
69
70 tmp = safe_malloc(PROJECT_BUFSZ);
71
72 if (default_only) {
73 if (getdefaultproj(name, &proj, tmp, PROJECT_BUFSZ) != NULL) {
74 projects = safe_malloc(sizeof (struct projlist));
75 projname = safe_malloc(strlen(proj.pj_name) + 1);
76 projcomm = safe_malloc(strlen(proj.pj_comment) + 1);
77 (void) strcpy(projname, proj.pj_name);
78 (void) strcpy(projcomm, proj.pj_comment);
79 projects->pl_next = NULL;
80 projects->pl_name = projname;
81 projects->pl_comm = projcomm;
82 found = 1;
83 }
84 } else {
85 buffer = safe_malloc(PROJECT_BUFSZ);
86 setprojent();
87 while (getprojent(&proj, tmp, PROJECT_BUFSZ) != NULL) {
88 if (inproj(name, proj.pj_name, buffer, PROJECT_BUFSZ)) {
89 tail = safe_malloc(sizeof (struct projlist));
90 projname =
91 safe_malloc(strlen(proj.pj_name) + 1);
92 projcomm =
93 safe_malloc(strlen(proj.pj_comment) + 1);
94 (void) strcpy(projname, proj.pj_name);
95 (void) strcpy(projcomm, proj.pj_comment);
96 tail->pl_next = NULL;
97 tail->pl_name = projname;
98 tail->pl_comm = projcomm;
99 if (!projects) {
100 projects = tail;
101 prev = projects;
102 } else {
103 prev->pl_next = tail;
104 prev = tail;
105 }
106 found = 1;
107 }
108 }
109 endprojent();
110 free(buffer);
111 }
112 free(tmp);
113 return (found);
114 }
115
116 /*
117 * Get the maximum length of the project name string.
118 */
119 static int
max_projname()120 max_projname()
121 {
122 struct projlist *pl;
123 int max = 0;
124 int len;
125
126 for (pl = projects; pl; pl = pl->pl_next)
127 if ((len = strlen(pl->pl_name)) > max)
128 max = len;
129 return (max);
130 }
131
132 static int
print_projects(char * name,int verbose,int default_only)133 print_projects(char *name, int verbose, int default_only)
134 {
135 struct projlist *pl, *next;
136 struct winsize ws;
137 int length = 0;
138 int smart = isatty(STDOUT_FILENO);
139 int columns;
140
141 if (!find_projects(name, default_only)) {
142 if (default_only)
143 (void) fprintf(stderr,
144 gettext("%s: no default project for user %s\n"),
145 progname, name);
146 else
147 (void) fprintf(stderr,
148 gettext("%s: no projects for user %s\n"),
149 progname, name);
150 return (1);
151 }
152
153 if (verbose)
154 length = max_projname();
155
156 if (smart) {
157 /*
158 * Get the number of columns.
159 */
160 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 &&
161 ws.ws_col > 0)
162 columns = ws.ws_col;
163 else
164 columns = 80;
165 }
166
167 for (pl = projects; pl; ) {
168 /*
169 * Display information about projects.
170 */
171 if (verbose) {
172 (void) printf("%1-*3$s %s\n",
173 pl->pl_name, pl->pl_comm, length);
174 } else {
175 if (smart &&
176 length + strlen(pl->pl_name) >= columns) {
177 (void) printf("\n");
178 length = 0;
179 }
180 (void) printf("%s ", pl->pl_name);
181 length += strlen(pl->pl_name) + 1;
182 }
183 /*
184 * Free previously allocated buffers.
185 */
186 next = pl->pl_next;
187 free(pl->pl_name);
188 free(pl->pl_comm);
189 free(pl);
190 pl = next;
191 }
192 if (!verbose && length != 0)
193 (void) printf("\n");
194
195 return (0);
196 }
197
198 void
print_projent(struct project * projent)199 print_projent(struct project *projent)
200 {
201 char **next;
202 char *nextc;
203 char *nextsemi;
204
205 (void) fprintf(stdout, "%s\n", projent->pj_name);
206 (void) fprintf(stdout, "\tprojid : %d\n", projent->pj_projid);
207 (void) fprintf(stdout, "\tcomment: \"%s\"\n", projent->pj_comment);
208
209 (void) fprintf(stdout, "\tusers : ");
210 next = projent->pj_users;
211 if (*next == NULL) {
212 (void) fprintf(stdout, "(none)\n");
213 } else {
214 (void) fprintf(stdout, "%s\n", *next);
215 for (next++; *next != NULL; next++) {
216 (void) fprintf(stdout, "\t %s\n", *next);
217 }
218 }
219
220 (void) fprintf(stdout, "\tgroups : ");
221 next = projent->pj_groups;
222 if (*next == NULL) {
223 (void) fprintf(stdout, "(none)\n");
224 } else {
225 (void) fprintf(stdout, "%s\n", *next);
226 for (next++; *next != NULL; next++) {
227 (void) fprintf(stdout, "\t %s\n", *next);
228 }
229 }
230
231 (void) fprintf(stdout, "\tattribs: ");
232
233 nextc = projent->pj_attr;
234 if (nextc == NULL) {
235 (void) fprintf(stdout, "(none)\n");
236 } else {
237 /* print first attribute */
238 nextsemi = strchr(nextc, ';');
239 if (nextsemi)
240 *nextsemi = '\0';
241 (void) fprintf(stdout, "%s\n", nextc);
242
243 while (nextsemi) {
244 nextc = nextsemi + 1;
245 nextsemi = strchr(nextc, ';');
246 if (nextsemi)
247 *nextsemi = '\0';
248 (void) fprintf(stdout, "\t %s\n", nextc);
249 }
250 }
251 }
252
253 static int
print_projents(char ** projlist)254 print_projents(char **projlist)
255 {
256 struct project projent;
257 char buf[PROJECT_BUFSZ];
258
259 if (*projlist == NULL) {
260 setprojent();
261
262 while (getprojent(&projent, buf, sizeof (buf)) != NULL) {
263 print_projent(&projent);
264 }
265 endprojent();
266 return (0);
267 }
268
269 while (*projlist != NULL) {
270
271 if (getprojbyname(*projlist, &projent, buf, sizeof (buf))
272 == NULL) {
273 (void) fprintf(stderr, "%s: project \"%s\" does "
274 "not exist\n", progname, *projlist);
275 exit(1);
276 }
277 print_projent(&projent);
278 projlist++;
279 }
280
281 return (0);
282 }
283
284 int
main(int argc,char * argv[])285 main(int argc, char *argv[])
286 {
287 struct passwd *pwd;
288 char *name;
289 int c;
290 int verbose = 0;
291 int default_only = 0;
292 int listmode = 0;
293 uid_t uid;
294
295 (void) setlocale(LC_ALL, "");
296 (void) textdomain(TEXT_DOMAIN);
297 progname = argv[0];
298 while ((c = getopt(argc, argv, "dvl")) != EOF) {
299 switch (c) {
300 case 'd':
301 default_only = 1;
302 break;
303 case 'v':
304 verbose = 1;
305 break;
306 case 'l':
307 listmode = 1;
308 break;
309 default:
310 (void) fprintf(stderr, gettext(
311 "Usage: %s [-dv] [user]\n"
312 " %s -l [project [project...]]\n"),
313 progname, progname);
314 return (2);
315 }
316 }
317
318 /* just list projects if -l is specified */
319 if (listmode) {
320 if (default_only || verbose) {
321 (void) fprintf(stderr, gettext(
322 "%s: -l incompatible with -d and -v\n"),
323 progname);
324 (void) fprintf(stderr, gettext(
325 "Usage: %s [-dv] [user]\n"
326 " %s -l [project [project...]]\n"),
327 progname, progname);
328 }
329 exit(print_projents(argv + optind));
330 }
331 if (optind == argc) {
332 uid = getuid();
333 if ((pwd = getpwuid(uid)) == NULL) {
334 (void) fprintf(stderr,
335 gettext("%s: getpwuid failed (%s)\n"),
336 progname, strerror(errno));
337 return (1);
338 }
339 name = pwd->pw_name;
340 } else {
341 name = argv[optind];
342 if (getpwnam(name) == NULL) {
343 (void) fprintf(stderr,
344 gettext("%s: user %s does not exist\n"),
345 progname, name);
346 return (1);
347 }
348 }
349 return (print_projects(name, verbose, default_only));
350 }
351