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