xref: /illumos-gate/usr/src/cmd/projects/projects.c (revision b0bb0d63258be430b0e22afcb1581974bd7b568e)
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 *
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
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
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
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
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
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
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