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