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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <libintl.h> 25 #include <locale.h> 26 #include <errno.h> 27 #include <string.h> 28 #include <stddef.h> 29 #include <sys/types.h> 30 31 #include "projent.h" 32 #include "util.h" 33 34 35 #define CHECK_ERRORS_FREE_PLST(errlst, plst, attrs, ecode) { \ 36 if (!lst_is_empty(errlst)) { \ 37 util_print_errmsgs(errlst); \ 38 if (plst != NULL) { \ 39 projent_free_lst(plst); \ 40 free(plst); \ 41 } \ 42 free(attrs); \ 43 usage(); \ 44 exit(ecode); \ 45 } \ 46 } 47 48 /* 49 * Print usage 50 */ 51 static void 52 usage(void) 53 { 54 (void) fprintf(stderr, gettext( 55 "Usage:\n" 56 "projadd [-n] [-f filename] [-p projid [-o]] [-c comment]\n" 57 " [-U user[,user...]] [-G group[,group...]]\n" 58 " [-K name[=value[,value...]]] project\n")); 59 } 60 61 /* 62 * main() 63 */ 64 int 65 main(int argc, char **argv) 66 { 67 int e, c; 68 69 extern char *optarg; 70 extern int optind, optopt; 71 projid_t maxpjid = 99; 72 lst_t *plst = NULL; 73 int flags = 0; 74 char *projfile = PROJF_PATH; 75 76 projent_t *ent; 77 boolean_t nflag, pflag, oflag; /* Command line flags. */ 78 char *pname, *projidstr, *comment; /* projent fields. */ 79 char *users, *groups, *attrs; 80 projid_t projid; 81 82 lst_t errlst; 83 84 /* Project file defaults to system project file "/etc/project" */ 85 users = groups = comment = projidstr = ""; 86 87 nflag = pflag = oflag = B_FALSE; 88 attrs = util_safe_zmalloc(1); 89 lst_create(&errlst); 90 91 92 (void) setlocale(LC_ALL, ""); 93 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 94 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 95 #endif 96 (void) textdomain(TEXT_DOMAIN); 97 98 /* Parse the command line argument list */ 99 while ((c = getopt(argc, argv, ":hnf:p:oc:U:G:K:")) != EOF) 100 switch (c) { 101 case 'h': 102 usage(); 103 exit(0); 104 break; 105 case 'n': 106 nflag = B_TRUE; 107 break; 108 case 'f': 109 projfile = optarg; 110 break; 111 case 'p': 112 pflag = B_TRUE; 113 projidstr = optarg; 114 break; 115 case 'o': 116 oflag = B_TRUE; 117 break; 118 case 'c': 119 comment = optarg; 120 break; 121 case 'U': 122 users = optarg; 123 break; 124 case 'G': 125 groups = optarg; 126 break; 127 case 'K': 128 attrs = UTIL_STR_APPEND2(attrs, ";", optarg); 129 break; 130 default: 131 util_add_errmsg(&errlst, gettext( 132 "Invalid option: -%c"), optopt); 133 break; 134 } 135 136 137 138 if (oflag && !pflag) { 139 util_add_errmsg(&errlst, gettext( 140 "-o requires -p projid to be specified")); 141 } 142 143 if (optind != argc -1) { 144 util_add_errmsg(&errlst, gettext("No project name specified")); 145 } 146 147 CHECK_ERRORS_FREE_PLST(&errlst, plst, attrs, 2); 148 149 if (!nflag) 150 flags |= F_PAR_VLD; 151 flags |= F_PAR_RES | F_PAR_DUP; 152 153 /* Parse the project file to get the list of the projects */ 154 plst = projent_get_lst(projfile, flags, &errlst); 155 CHECK_ERRORS_FREE_PLST(&errlst, plst, attrs, 2); 156 157 158 /* Parse and validate new project id */ 159 if (pflag && projent_parse_projid(projidstr, &projid, &errlst) == 0) { 160 if (!nflag) { 161 projent_validate_projid(projid, 0, &errlst); 162 if (!oflag) { 163 projent_validate_unique_id(plst, projid, 164 &errlst); 165 } 166 } 167 } 168 CHECK_ERRORS_FREE_PLST(&errlst, plst, attrs, 2); 169 170 /* Find the maxprojid */ 171 for (e = 0; e < lst_size(plst); e++) { 172 ent = lst_at(plst, e); 173 maxpjid = (ent->projid > maxpjid) ? ent->projid : maxpjid; 174 } 175 176 177 if (!pflag && asprintf(&projidstr, "%ld", maxpjid + 1) == -1) { 178 util_add_errmsg(&errlst, gettext("Failed to allocate memory")); 179 CHECK_ERRORS_FREE_PLST(&errlst, plst, attrs, 2); 180 } 181 182 pname = argv[optind]; 183 ent = projent_parse_components(pname, projidstr, comment, users, 184 groups, attrs, F_PAR_SPC | F_PAR_UNT, &errlst); 185 if (!pflag) 186 free(projidstr); 187 188 if (!nflag) 189 projent_validate_unique_name(plst, pname, &errlst); 190 191 CHECK_ERRORS_FREE_PLST(&errlst, plst, attrs, 2); 192 193 /* Sort attributes list */ 194 projent_sort_attributes(ent->attrs); 195 196 197 /* Add the new project entry to the list */ 198 lst_insert_tail(plst, ent); 199 200 /* Validate the projent before writing the list to the project file */ 201 (void) projent_validate(ent, flags, &errlst); 202 CHECK_ERRORS_FREE_PLST(&errlst, plst, attrs, 2); 203 204 /* Write out the project file */ 205 projent_put_lst(projfile, plst, &errlst); 206 CHECK_ERRORS_FREE_PLST(&errlst, plst, attrs, 2); 207 208 return (0); 209 }