3 * Command line oriented SMS List tool.
5 * by Mark Rosenstein, September 1988.
7 * Copyright 1989 by the Massachusetts Institute of Technology.
10 #include <mit-copyright.h>
17 static char smslist_rcsid[] = "$Header$";
32 /* flags from command line */
33 int infoflg, verbose, syncflg, memberflg, debugflg;
35 /* various member lists */
36 struct save_queue *addlist, *dellist, *memberlist, *synclist;
38 char *listname, *whoami;
43 int show_list_info(), show_list_count(), get_list_members(), scream();
44 struct member *parse_member();
55 struct member *memberstruct;
57 /* clear all flags & lists */
58 infoflg = verbose = syncflg = memberflg = debugflg = 0;
60 addlist = sq_create();
61 dellist = sq_create();
62 memberlist = sq_create();
63 synclist = sq_create();
66 /* parse args, building addlist, dellist, & synclist */
67 while (++arg - argv < argc) {
83 if (arg - argv < argc - 1) {
85 if (memberstruct = parse_member(*arg))
86 sq_save_data(addlist, memberstruct);
91 if (arg - argv < argc - 1) {
93 if (memberstruct = parse_member(*arg))
94 sq_save_data(dellist, memberstruct);
99 if (arg - argv < argc - 1) {
105 if (!strcmp(*arg, "-"))
108 in = fopen(*arg, "r");
110 com_err(whoami, errno, " while opening %s for input",
115 while (fgets(buf, BUFSIZ, in))
116 if (memberstruct = parse_member(buf))
117 sq_save_data(synclist, memberstruct);
119 com_err(whoami, errno, " while reading from %s", *arg);
126 else if (listname == NULL)
131 if (listname == NULL)
134 /* if no other options specified, turn on list members flag */
135 if (!(infoflg || syncflg ||
136 addlist->q_next != addlist || dellist->q_next != dellist))
140 if (status = sms_connect()) {
141 com_err(whoami, status, " unable to connect to SMS");
144 if (status = sms_auth("blanche")) {
145 com_err(whoami, status, " unable to authenticate to SMS");
149 /* display list info if requested to */
151 status = sms_query("get_list_info", 1, &listname, show_list_info,NULL);
153 com_err(whoami, status, " while getting list information");
154 if (verbose && !memberflg) {
155 status = sms_query("count_members_of_list", 1, &listname,
156 show_list_count, NULL);
158 com_err(whoami, status, " while getting list count");
162 /* if we're synchronizing to a file, we need to:
163 * get the current members of the list
164 * for each member of the sync file
165 * if they are on the list, remove them from the in-memory copy
166 * if they're not on the list, add them to add-list
167 * if anyone is left on the in-memory copy, put them on the delete-list
168 * lastly, reset memberlist so we can use it again later
171 status = sms_query("get_members_of_list", 1, &listname,
172 get_list_members, memberlist);
174 com_err(whoami, status, " while getting members of list");
175 while (sq_get_data(synclist, &memberstruct)) {
176 struct save_queue *q;
179 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
180 if (membermatch(q->q_data, memberstruct)) {
181 q->q_prev->q_next = q->q_next;
182 q->q_next->q_prev = q->q_prev;
188 sq_save_data(addlist, memberstruct);
190 while (sq_get_data(memberlist, &memberstruct))
191 sq_save_data(dellist, memberstruct);
192 sq_destroy(memberlist);
193 memberlist = sq_create();
196 /* Process the add list */
197 while (sq_get_data(addlist, &memberstruct)) {
198 membervec[0] = listname;
199 membervec[2] = memberstruct->name;
200 switch (memberstruct->type) {
203 membervec[1] = "USER";
204 status = sms_query("add_member_to_list", 3, membervec, scream, NULL);
205 if (status == SMS_SUCCESS)
207 else if (status != SMS_USER || memberstruct->type != M_ANY) {
208 com_err(whoami, status, " while adding member %s to %s",
209 memberstruct->name, listname);
213 membervec[1] = "LIST";
214 status = sms_query("add_member_to_list", 3, membervec,
216 if (status == SMS_SUCCESS)
218 else if (status != SMS_LIST || memberstruct->type != M_ANY) {
219 com_err(whoami, status, " while adding member %s to %s",
220 memberstruct->name, listname);
224 membervec[1] = "STRING";
225 status = sms_query("add_member_to_list", 3, membervec,
227 if (status != SMS_SUCCESS)
228 com_err(whoami, status, " while adding member %s to %s",
229 memberstruct->name, listname);
233 /* Process the delete list */
234 while (sq_get_data(dellist, &memberstruct)) {
235 membervec[0] = listname;
236 membervec[2] = memberstruct->name;
237 switch (memberstruct->type) {
240 membervec[1] = "USER";
241 status = sms_query("delete_member_from_list", 3, membervec,
243 if (status == SMS_SUCCESS)
245 else if ((status != SMS_USER && status != SMS_NO_MATCH) ||
246 memberstruct->type != M_ANY) {
247 com_err(whoami, status, " while deleteing member %s from %s",
248 memberstruct->name, listname);
252 membervec[1] = "LIST";
253 status = sms_query("delete_member_from_list", 3, membervec,
255 if (status == SMS_SUCCESS)
257 else if ((status != SMS_LIST && status != SMS_NO_MATCH) ||
258 memberstruct->type != M_ANY) {
259 com_err(whoami, status, " while deleteing member %s from %s",
260 memberstruct->name, listname);
264 membervec[1] = "STRING";
265 status = sms_query("delete_member_from_list", 3, membervec,
267 if (status == SMS_STRING && memberstruct->type == M_ANY)
268 com_err(whoami, 0, "Unable to find member %s to delete from %s",
269 memberstruct->name, listname);
270 else if (status != SMS_SUCCESS)
271 com_err(whoami, status, " while deleteing member %s from %s",
272 memberstruct->name, listname);
276 /* Display the members of the list now, if requested */
278 status = sms_query("get_members_of_list", 1, &listname,
279 get_list_members, memberlist);
281 com_err(whoami, status, " while getting members of list");
282 while (sq_get_data(memberlist, &memberstruct)) {
285 switch (memberstruct->type) {
296 printf("%s: %s\n", s, memberstruct->name);
298 if (memberstruct->type == M_LIST)
299 printf("LIST:%s\n", memberstruct->name);
300 else if (memberstruct->type == M_STRING &&
301 !index(memberstruct->name, '@'))
302 printf("STRING:%s\n", memberstruct->name);
304 printf("%s\n", memberstruct->name);
317 printf("Usage: %s [-i] [-v] [-m] listname [-a member] [-d member] [-f file]\n",
323 show_list_info(argc, argv, hint)
328 printf("List: %s\n", argv[0]);
329 printf("Description: %s\n", argv[9]);
330 printf("Flags: %s, %s, and %s\n",
331 atoi(argv[1]) ? "active" : "inactive",
332 atoi(argv[2]) ? "public" : "private",
333 atoi(argv[3]) ? "hidden" : "visible");
334 printf("%s is %sa maillist, and is %sa group", argv[0],
335 atoi(argv[4]) ? "" : "not ",
336 atoi(argv[5]) ? "" : "not ");
338 printf(" with GID %d\n", atoi(argv[6]));
341 printf("Owner: %s %s\n", argv[7], argv[8]);
342 printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
347 show_list_count(argc, argv, hint)
352 printf("Members: %s\n", argv[0]);
356 get_list_members(argc, argv, q)
359 struct save_queue *q;
363 m = (struct member *) malloc(sizeof(struct member));
364 switch (argv[0][0]) {
375 m->name = strsave(argv[1]);
383 fprintf(stderr, "Programmer botch\n");
388 struct member *parse_member(s)
391 register struct member *m;
394 while (*s && isspace(*s))
397 while (*p && isprint(*p) && !isspace(*p) && *p != ';')
400 if (p == s || strlen(s) == 0)
403 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
406 if (p = index(s, ':')) {
409 if (!strcasecmp("user", s))
411 else if (!strcasecmp("list", s))
413 else if (!strcasecmp("string", s))
420 m->name = strsave(m->name);
423 m->name = strsave(s);
424 if (index(s, '@') || index(s, '!') || index(s, '%'))
432 int membermatch(m1, m2)
433 struct member *m1, *m2;
435 if (strcmp(m1->name, m2->name))
437 if (m1->type == M_ANY || m2->type == M_ANY)
439 if (m1->type == m2->type)