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 }