]> andersk Git - moira.git/blame - clients/moira/attach.c
Redo argument parsing to be more consistant with other applications.
[moira.git] / clients / moira / attach.c
CommitLineData
c441a31a 1/* $Id$
7ac48069 2 *
3 * This is the file attach.c for the Moira Client, which allows users
59ec8dae 4 * to quickly and easily maintain most parts of the Moira database.
5eaef520 5 * It Contains: Functions for maintaining data used by Hesiod
6 * to map courses/projects/users to their file systems,
7 * and maintain filesys info.
8 *
08345b74 9 * Created: 5/4/88
10 * By: Chris D. Peterson
08345b74 11 *
7ac48069 12 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
13 * For copying and distribution information, please see the file
14 * <mit-copyright.h>.
08345b74 15 */
16
7ac48069 17#include <mit-copyright.h>
8defc06b 18#include <moira.h>
19#include <moira_site.h>
08345b74 20
0a2c64cb 21#include "defs.h"
22#include "f_defs.h"
461c03b6 23#include "globals.h"
461c03b6 24
7ac48069 25#include <sys/stat.h>
26
27#include <ctype.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
533bacb3 31#ifdef HAVE_UNISTD_H
7ac48069 32#include <unistd.h>
533bacb3 33#endif /* HAVE_UNISTD_H */
7ac48069 34
35RCSID("$Header$");
36
37char *canonicalize_cell(char *c);
38int GetAliasValue(int argc, char **argv, void *retval);
39void RealDeleteFS(char **info, Bool one_item);
600b459e 40char *SortAfter(struct mqelem *elem, int count);
7ac48069 41void RealDeleteFSAlias(char **info, Bool one_item);
42
08345b74 43#define FS_ALIAS_TYPE "FILESYS"
44
461c03b6 45#define LABEL 0
46#define MACHINE 1
47#define GROUP 2
48#define ALIAS 3
1d4e1e0f 49#define ALIAS_CHECK 4
50#define FS_ALIASES 5
08345b74 51
6966e6fe 52#define NO_MACHINE ("[NONE]")
9e2516d6 53
1104552d 54#define DEFAULT_TYPE ("AFS")
85ca828a 55#define DEFAULT_MACHINE DEFAULT_NONE
56#define DEFAULT_PACK DEFAULT_NONE
7f6743f7 57#define DEFAULT_ACCESS ("w")
85ca828a 58#define DEFAULT_COMMENTS DEFAULT_COMMENT
59#define DEFAULT_OWNER (user)
60#define DEFAULT_OWNERS (user)
61#define DEFAULT_CREATE DEFAULT_YES
7f6743f7 62#define DEFAULT_L_TYPE ("PROJECT")
7cb7d352 63#define DEFAULT_CELL ("athena.mit.edu")
85ca828a 64
65/* Function Name: SetDefaults
66 * Description: sets the default values for filesystem additions.
5eaef520 67 * Arguments: info - an array of char pointers to recieve defaults.
85ca828a 68 * Returns: char ** (this array, now filled).
69 */
70
5eaef520 71static char **SetDefaults(char **info, char *name)
85ca828a 72{
5eaef520 73 char buf[BUFSIZ];
74
7ac48069 75 info[FS_NAME] = strdup(name);
76 info[FS_TYPE] = strdup(DEFAULT_TYPE);
77 info[FS_MACHINE] = strdup(DEFAULT_MACHINE);
78 info[FS_PACK] = strdup(DEFAULT_PACK);
5eaef520 79 sprintf(buf, "/mit/%s", name);
7ac48069 80 info[FS_M_POINT] = strdup(buf);
81 info[FS_ACCESS] = strdup(DEFAULT_ACCESS);
82 info[FS_COMMENTS] = strdup(DEFAULT_COMMENTS);
83 info[FS_OWNER] = strdup(DEFAULT_OWNER);
84 info[FS_OWNERS] = strdup(DEFAULT_OWNERS);
85 info[FS_CREATE] = strdup(DEFAULT_CREATE);
86 info[FS_L_TYPE] = strdup(DEFAULT_L_TYPE);
5eaef520 87 info[FS_MODTIME] = info[FS_MODBY] = info[FS_MODWITH] = info[FS_END] = NULL;
88 return info;
85ca828a 89}
90
08345b74 91/* Function Name: GetFSInfo
92 * Description: Stores the info in a queue.
93 * Arguments: type - type of information to get.
94 * name - name of the item to get information on.
95 * Returns: a pointer to the first element in the queue.
96 */
97
600b459e 98static struct mqelem *GetFSInfo(int type, char *name)
08345b74 99{
5eaef520 100 int stat;
600b459e 101 struct mqelem *elem = NULL;
5eaef520 102 char *args[5];
08345b74 103
5eaef520 104 switch (type)
105 {
461c03b6 106 case LABEL:
5eaef520 107 if ((stat = do_mr_query("get_filesys_by_label", 1, &name,
7ac48069 108 StoreInfo, &elem)))
5eaef520 109 {
110 com_err(program_name, stat, " in GetFSInfo");
111 return NULL;
08345b74 112 }
5eaef520 113 break;
461c03b6 114 case MACHINE:
5eaef520 115 if ((stat = do_mr_query("get_filesys_by_machine", 1, &name,
7ac48069 116 StoreInfo, &elem)))
5eaef520 117 {
118 com_err(program_name, stat, " in GetFSInfo");
119 return NULL;
08345b74 120 }
5eaef520 121 break;
461c03b6 122 case GROUP:
5eaef520 123 if ((stat = do_mr_query("get_filesys_by_group", 1, &name,
7ac48069 124 StoreInfo, &elem)))
5eaef520 125 {
126 com_err(program_name, stat, " in GetFSInfo");
127 return NULL;
08345b74 128 }
5eaef520 129 break;
461c03b6 130 case ALIAS:
1d4e1e0f 131 case ALIAS_CHECK:
5eaef520 132 args[ALIAS_NAME] = name;
133 args[ALIAS_TYPE] = FS_ALIAS_TYPE;
134 args[ALIAS_TRANS] = "*";
7ac48069 135 if ((stat = do_mr_query("get_alias", 3, args, StoreInfo, &elem)))
5eaef520 136 {
1d4e1e0f 137 if (type != ALIAS_CHECK || stat != MR_NO_MATCH)
138 com_err(program_name, stat, " in get_alias.");
5eaef520 139 return NULL;
08345b74 140 }
1d4e1e0f 141 break;
142 case FS_ALIASES:
143 args[ALIAS_NAME] = "*";
144 args[ALIAS_TYPE] = FS_ALIAS_TYPE;
145 args[ALIAS_TRANS] = name;
146 if ((stat = do_mr_query("get_alias", 3, args, StoreInfo, &elem)))
147 {
148 if (stat != MR_NO_MATCH)
149 com_err(program_name, stat, " in get_alias.");
150 return NULL;
151 }
152 break;
08345b74 153 }
154
5eaef520 155 return QueueTop(elem);
08345b74 156}
157
85ca828a 158/* Function Name: PrintFSAlias
159 * Description: Prints a filesystem alias
160 * Arguments: info - an array contains the strings of info.
402461ad 161 * Returns: the name of the filesys - used be QueryLoop().
85ca828a 162 */
163
5eaef520 164static char *PrintFSAlias(char **info)
85ca828a 165{
5eaef520 166 char buf[BUFSIZ];
85ca828a 167
5eaef520 168 sprintf(buf, "Alias: %-25s Filesystem: %s", info[ALIAS_NAME],
169 info[ALIAS_TRANS]);
170 Put_message(buf);
171 return info[ALIAS_NAME];
85ca828a 172}
173
1d4e1e0f 174static char aliasbuf[256];
175
176static char *PrintFSAliasList(char **info)
177{
178 if (strlen(aliasbuf) == 0)
179 snprintf(aliasbuf, sizeof(aliasbuf), "Aliases: %s", info[ALIAS_NAME]);
180 else
181 {
182 strncat(aliasbuf, ", ", sizeof(aliasbuf));
183 strncat(aliasbuf, info[ALIAS_NAME], sizeof(aliasbuf));
184 }
185}
186
187static char labelbuf[256];
188
189static char *GetFSLabel(char **info)
190{
191 snprintf(labelbuf, sizeof(labelbuf), info[ALIAS_TRANS]);
192}
193
9e2516d6 194static int fsgCount = 1;
195
7ac48069 196static void PrintFSGMembers(char **info)
9e2516d6 197{
5eaef520 198 char print_buf[BUFSIZ];
9e2516d6 199
5eaef520 200 sprintf(print_buf, " %d. Filesystem: %-32s (sort key: %s)",
201 fsgCount++, info[0], info[1]);
202 Put_message(print_buf);
9e2516d6 203}
204
205
08345b74 206/* Function Name: PrintFSInfo
207 * Description: Prints the filesystem information.
208 * Arguments: info - a pointer to the filesystem information.
209 * Returns: none.
210 */
211
5eaef520 212static char *PrintFSInfo(char **info)
08345b74 213{
5eaef520 214 char print_buf[BUFSIZ];
1d4e1e0f 215 struct mqelem *top;
5eaef520 216
217 FORMFEED;
218
219 if (!strcmp(info[FS_TYPE], "FSGROUP") || !strcmp(info[FS_TYPE], "MUL"))
220 {
221 int stat;
600b459e 222 struct mqelem *elem = NULL;
5eaef520 223
224 if (!strcmp(info[FS_TYPE], "MUL"))
225 sprintf(print_buf, "%20s Multiple Filesystem: %s", " ", info[FS_NAME]);
226 else
227 sprintf(print_buf, "%20s Filesystem Group: %s", " ", info[FS_NAME]);
228 Put_message(print_buf);
229
1d4e1e0f 230 top = GetFSInfo(FS_ALIASES, info[FS_NAME]);
231 if (top != NULL) {
232 *aliasbuf = 0;
233 Loop(top, (void (*)(char **))PrintFSAliasList);
234 Put_message(aliasbuf);
235 FreeQueue(top); /* clean the queue. */
236 }
237
5eaef520 238 sprintf(print_buf, "Comments: %s", info[FS_COMMENTS]);
239 Put_message(print_buf);
240 sprintf(print_buf, MOD_FORMAT, info[FS_MODBY], info[FS_MODTIME],
241 info[FS_MODWITH]);
242 Put_message(print_buf);
243 Put_message("Containing the filesystems (in order):");
244 if ((stat = do_mr_query("get_fsgroup_members", 1, &info[FS_NAME],
7ac48069 245 StoreInfo, &elem)))
5eaef520 246 {
247 if (stat == MR_NO_MATCH)
248 Put_message(" [no members]");
249 else
250 com_err(program_name, stat, " in PrintFSInfo");
251 }
252 else
253 {
254 fsgCount = 1;
255 Loop(QueueTop(elem), PrintFSGMembers);
256 FreeQueue(elem);
9e2516d6 257 }
9e2516d6 258 }
5eaef520 259 else
260 {
261 sprintf(print_buf, "%20s Filesystem: %s", " ", info[FS_NAME]);
262 Put_message(print_buf);
1d4e1e0f 263
264 top = GetFSInfo(FS_ALIASES, info[FS_NAME]);
265 if (top != NULL) {
266 *aliasbuf = 0;
267 Loop(top, (void (*)(char **))PrintFSAliasList);
268 Put_message(aliasbuf);
269 FreeQueue(top); /* clean the queue. */
270 }
271
5eaef520 272 sprintf(print_buf, "Type: %-40s Machine: %-15s",
273 info[FS_TYPE], info[FS_MACHINE]);
274 Put_message(print_buf);
275 sprintf(print_buf, "Default Access: %-2s Packname: %-17s Mountpoint %s ",
276 info[FS_ACCESS], info[FS_PACK], info[FS_M_POINT]);
277 Put_message(print_buf);
278 sprintf(print_buf, "Comments: %s", info[FS_COMMENTS]);
279 Put_message(print_buf);
280 sprintf(print_buf, "User Ownership: %-30s Group Ownership: %s",
281 info[FS_OWNER], info[FS_OWNERS]);
282 Put_message(print_buf);
283 sprintf(print_buf, "Update Fileserver: %-27s Locker Type: %s",
284 atoi(info[FS_CREATE]) ? "ON" : "OFF", info[FS_L_TYPE]);
285 Put_message(print_buf);
286 sprintf(print_buf, MOD_FORMAT, info[FS_MODBY], info[FS_MODTIME],
287 info[FS_MODWITH]);
288 Put_message(print_buf);
289 }
290 return info[FS_NAME];
08345b74 291}
292
5eaef520 293char *canonicalize_cell(char *c)
7cb7d352 294{
533bacb3 295#ifdef _WIN32
296 return c;
297#else /* !_WIN32 */
5eaef520 298 struct stat stbuf;
299 char path[512];
300 int count;
301
302 sprintf(path, "/afs/%s", c);
303 if (lstat(path, &stbuf) || !stbuf.st_mode & S_IFLNK)
304 return c;
305 count = readlink(path, path, sizeof(path));
306 if (count < 1)
307 return c;
308 path[count] = 0;
309 free(c);
7ac48069 310 return strdup(path);
533bacb3 311#endif /* _WIN32 */
7cb7d352 312}
313
314
7ac48069 315int GetAliasValue(int argc, char **argv, void *retval)
7cb7d352 316{
7ac48069 317 *(char **)retval = strdup(argv[2]);
5eaef520 318 return MR_CONT;
7cb7d352 319}
320
08345b74 321/* Function Name: AskFSInfo.
5eaef520 322 * Description: This function askes the user for information about a
08345b74 323 * machine and saves it into a structure.
324 * Arguments: info - a pointer the the structure to put the
325 * info into.
326 * name - add a newname field? (T/F)
327 * Returns: none.
328 */
329
5eaef520 330static char **AskFSInfo(char **info, Bool name)
08345b74 331{
5eaef520 332 char temp_buf[BUFSIZ], *newname, access_type[32];
333 int fsgroup = 0, newdefaults = 0;
334
335 Put_message("");
336 sprintf(temp_buf, "Changing Attributes of filesystem %s.", info[FS_NAME]);
337 Put_message(temp_buf);
338 Put_message("");
339
340 if (name)
341 {
7ac48069 342 newname = strdup(info[FS_NAME]);
5eaef520 343 if (GetValueFromUser("The new name for this filesystem",
344 &newname) == SUB_ERROR)
345 return NULL;
08345b74 346 }
347
5eaef520 348 strcpy(temp_buf, info[FS_TYPE]);
349 if (GetTypeFromUser("Filesystem's Type", "filesys", &info[FS_TYPE]) ==
350 SUB_ERROR)
351 return NULL;
352 if (!strcasecmp(info[FS_TYPE], "FSGROUP") ||
353 !strcasecmp(info[FS_TYPE], "MUL"))
354 fsgroup++;
355 if (strcasecmp(info[FS_TYPE], temp_buf))
356 newdefaults++;
357 if (fsgroup)
358 {
359 free(info[FS_MACHINE]);
7ac48069 360 info[FS_MACHINE] = strdup(NO_MACHINE);
5eaef520 361 }
362 else
363 {
364 if (!strcasecmp(info[FS_TYPE], "AFS"))
365 {
366 if (!name || newdefaults)
367 {
368 free(info[FS_MACHINE]);
7ac48069 369 info[FS_MACHINE] = strdup(DEFAULT_CELL);
7cb7d352 370 }
5eaef520 371 if (GetValueFromUser("Filesystem's Cell", &info[FS_MACHINE]) ==
7cb7d352 372 SUB_ERROR)
5eaef520 373 return NULL;
374 info[FS_MACHINE] = canonicalize_cell(info[FS_MACHINE]);
375 }
376 else
377 {
378 if (GetValueFromUser("Filesystem's Machine", &info[FS_MACHINE]) ==
379 SUB_ERROR)
380 return NULL;
381 info[FS_MACHINE] = canonicalize_hostname(info[FS_MACHINE]);
7cb7d352 382 }
9e2516d6 383 }
5eaef520 384 if (!fsgroup)
385 {
386 if (!strcasecmp(info[FS_TYPE], "AFS"))
387 {
388 char *path, *args[3], *p;
389 int status, depth;
390 if (GetTypeFromUser("Filesystem's lockertype", "lockertype",
391 &info[FS_L_TYPE]) == SUB_ERROR)
392 return NULL;
393 if (!name || newdefaults)
394 {
395 free(info[FS_PACK]);
396 lowercase(info[FS_MACHINE]);
397 sprintf(temp_buf, "%s:%s", info[FS_MACHINE], info[FS_L_TYPE]);
398 args[0] = temp_buf;
399 args[1] = "AFSPATH";
400 args[2] = "*";
401 path = "???";
402 status = do_mr_query("get_alias", 3, args, GetAliasValue, &path);
403 if (status == MR_SUCCESS)
404 {
405 p = strchr(path, ':');
406 if (p)
407 {
408 *p = '\0';
409 depth = atoi(++p);
410 }
411 else
412 depth = 0;
413 sprintf(temp_buf, "/afs/%s/%s", info[FS_MACHINE], path);
414 if (depth >= 0)
415 {
416 for (p = info[FS_NAME];
417 *p && (p - info[FS_NAME]) < depth; p++)
418 {
419 if (islower(*p))
420 {
421 strcat(temp_buf, "/x");
422 temp_buf[strlen(temp_buf) - 1] = *p;
423 }
424 else
425 {
426 sprintf(temp_buf, "/afs/%s/%s/other",
427 info[FS_MACHINE], path);
428 break;
d678d80c 429 }
b7e66e09 430 }
5eaef520 431 }
432 else if (depth == -1)
433 {
434 if (isdigit(info[FS_NAME][0]))
435 {
436 strcat(temp_buf, "/");
437 depth = strlen(temp_buf);
438 for (p = info[FS_NAME]; *p && isdigit(*p); p++)
439 {
440 temp_buf[depth++] = *p;
441 temp_buf[depth] = 0;
b7e66e09 442 }
5eaef520 443 }
444 else
445 strcat(temp_buf, "/other");
446 }
447 else
448 {
b7e66e09 449 /* no default */
7cb7d352 450 }
5eaef520 451 strcat(temp_buf, "/");
452 strcat(temp_buf, info[FS_NAME]);
453 free(path);
7cb7d352 454 }
5eaef520 455 else
456 {
457 sprintf(temp_buf, "/afs/%s/%s/%s", info[FS_MACHINE],
458 lowercase(info[FS_L_TYPE]), info[FS_NAME]);
459 }
7ac48069 460 info[FS_PACK] = strdup(temp_buf);
7cb7d352 461 }
462 }
5eaef520 463 if (GetValueFromUser("Filesystem's Pack Name", &info[FS_PACK]) ==
464 SUB_ERROR)
465 return NULL;
466 if (GetValueFromUser("Filesystem's Mount Point", &info[FS_M_POINT]) ==
467 SUB_ERROR)
468 return NULL;
469 sprintf(access_type, "fs_access_%s", info[FS_TYPE]);
470 if (GetTypeFromUser("Filesystem's Default Access", access_type,
471 &info[FS_ACCESS]) == SUB_ERROR)
472 return NULL;
9e2516d6 473 }
5eaef520 474 if (GetValueFromUser("Comments about this Filesystem", &info[FS_COMMENTS])
475 == SUB_ERROR)
476 return NULL;
477 if (GetValueFromUser("Filesystem's owner (user)", &info[FS_OWNER]) ==
478 SUB_ERROR)
479 return NULL;
480 if (GetValueFromUser("Filesystem's owners (group)", &info[FS_OWNERS]) ==
481 SUB_ERROR)
482 return NULL;
483 if (!fsgroup)
484 if (GetYesNoValueFromUser("Propagate changes to fileserver",
485 &info[FS_CREATE]) == SUB_ERROR)
486 return NULL;
487 if (strcasecmp(info[FS_TYPE], "AFS"))
488 {
489 if (GetTypeFromUser("Filesystem's lockertype", "lockertype",
490 &info[FS_L_TYPE]) == SUB_ERROR)
491 return NULL;
7cb7d352 492 }
08345b74 493
5eaef520 494 FreeAndClear(&info[FS_MODTIME], TRUE);
495 FreeAndClear(&info[FS_MODBY], TRUE);
496 FreeAndClear(&info[FS_MODWITH], TRUE);
08345b74 497
5eaef520 498 if (name) /* slide the newname into the #2 slot. */
499 SlipInNewName(info, newname);
08345b74 500
5eaef520 501 return info;
08345b74 502}
503
7cb7d352 504
08345b74 505/* --------------- Filesystem Menu ------------- */
506
507/* Function Name: GetFS
508 * Description: Get Filesystem information by name.
509 * Arguments: argc, argv - name of filsys in argv[1].
510 * Returns: DM_NORMAL.
511 */
512
5eaef520 513int GetFS(int argc, char **argv)
08345b74 514{
600b459e 515 struct mqelem *top;
1d4e1e0f 516 char *fs_label;
517
518 fs_label = argv[1];
519
520 top = GetFSInfo(ALIAS_CHECK, argv[1]);
521 if (top != NULL) {
522 Loop(top, (void (*)(char **))GetFSLabel);
523 fs_label = labelbuf;
524 }
08345b74 525
1d4e1e0f 526 top = GetFSInfo(LABEL, fs_label); /* get info. */
7ac48069 527 Loop(top, (void (*)(char **))PrintFSInfo);
5eaef520 528 FreeQueue(top); /* clean the queue. */
529 return DM_NORMAL;
ef1e47d8 530}
531
532/* Function Name: GetFSM
533 * Description: Get Filesystem information by machine.
534 * Arguments: argc, argv - name of server in argv[1].
535 * Returns: DM_NORMAL.
536 */
537
5eaef520 538int GetFSM(int argc, char **argv)
ef1e47d8 539{
600b459e 540 struct mqelem *top;
ef1e47d8 541
7ac48069 542 argv[1] = canonicalize_hostname(strdup(argv[1]));
5eaef520 543 top = GetFSInfo(MACHINE, argv[1]); /* get info. */
7ac48069 544 Loop(top, (void (*)(char **))PrintFSInfo);
5eaef520 545 FreeQueue(top); /* clean the queue. */
546 return DM_NORMAL;
08345b74 547}
548
402461ad 549/* Function Name: RealDeleteFS
550 * Description: Does the real deletion work.
551 * Arguments: info - array of char *'s containing all useful info.
5eaef520 552 * one_item - a Boolean that is true if only one item
402461ad 553 * in queue that dumped us here.
554 * Returns: none.
555 */
556
5eaef520 557void RealDeleteFS(char **info, Bool one_item)
402461ad 558{
5eaef520 559 int stat;
560 char temp_buf[BUFSIZ];
561
562 /*
563 * Deletions are performed if the user hits 'y' on a list of multiple
564 * filesystem, or if the user confirms on a unique alias.
565 */
566 sprintf(temp_buf, "Are you sure that you want to delete filesystem %s",
567 info[FS_NAME]);
568 if (!one_item || Confirm(temp_buf))
569 {
570 if ((stat = do_mr_query("delete_filesys", 1,
7ac48069 571 &info[FS_NAME], NULL, NULL)))
5eaef520 572 com_err(program_name, stat, " filesystem not deleted.");
573 else
574 Put_message("Filesystem deleted.");
402461ad 575 }
5eaef520 576 else
577 Put_message("Filesystem not deleted.");
402461ad 578}
579
08345b74 580/* Function Name: DeleteFS
581 * Description: Delete a filesystem give its name.
582 * Arguments: argc, argv - argv[1] is the name of the filesystem.
583 * Returns: none.
584 */
585
5eaef520 586int DeleteFS(int argc, char **argv)
08345b74 587{
600b459e 588 struct mqelem *elem = GetFSInfo(LABEL, argv[1]);
5eaef520 589 QueryLoop(elem, PrintFSInfo, RealDeleteFS, "Delete the Filesystem");
08345b74 590
5eaef520 591 FreeQueue(elem);
592 return DM_NORMAL;
08345b74 593}
594
402461ad 595/* Function Name: RealChangeFS
596 * Description: performs the actual change to the filesys.
5eaef520 597 * Arguments: info - the information
402461ad 598 * junk - an unused boolean.
599 * Returns: none.
600 */
601
5eaef520 602static void RealChangeFS(char **info, Bool junk)
402461ad 603{
5eaef520 604 int stat;
605 char **args;
606 extern Menu nfsphys_menu;
607
608 args = AskFSInfo(info, TRUE);
609 if (!args)
610 {
611 Put_message("Aborted.");
612 return;
9777ade9 613 }
7ac48069 614 stat = do_mr_query("update_filesys", CountArgs(args), args, NULL, NULL);
5eaef520 615 switch (stat)
616 {
8defc06b 617 case MR_NFS:
5eaef520 618 Put_message("That NFS filesystem is not exported.");
619 if (YesNoQuestion("Fix this now (Y/N)", TRUE) == TRUE)
620 {
621 Do_menu(&nfsphys_menu, 0, NULL);
622 if (YesNoQuestion("Retry filesystem update now (Y/N)", TRUE) == TRUE)
623 {
624 if ((stat = do_mr_query("update_filesys", CountArgs(args), args,
7ac48069 625 NULL, NULL)))
5eaef520 626 com_err(program_name, stat, " filesystem not updated");
627 else
628 Put_message("filesystem sucessfully updated.");
bff71786 629 }
630 }
5eaef520 631 break;
8defc06b 632 case MR_SUCCESS:
5eaef520 633 break;
bff71786 634 default:
5eaef520 635 com_err(program_name, stat, " in UpdateFS");
bff71786 636 }
402461ad 637}
638
08345b74 639/* Function Name: ChangeFS
640 * Description: change the information in a filesys record.
641 * Arguments: arc, argv - value of filsys in argv[1].
642 * Returns: DM_NORMAL.
643 */
644
5eaef520 645int ChangeFS(int argc, char **argv)
08345b74 646{
600b459e 647 struct mqelem *elem = GetFSInfo(LABEL, argv[1]);
5eaef520 648 QueryLoop(elem, NullPrint, RealChangeFS, "Update the Filesystem");
08345b74 649
5eaef520 650 FreeQueue(elem);
651 return DM_NORMAL;
08345b74 652}
653
654/* Function Name: AddFS
655 * Description: change the information in a filesys record.
656 * Arguments: arc, argv - name of filsys in argv[1].
657 * Returns: DM_NORMAL.
658 */
659
5eaef520 660int AddFS(int argc, char **argv)
08345b74 661{
5eaef520 662 char *info[MAX_ARGS_SIZE], **args, buf[BUFSIZ];
663 int stat;
664 extern Menu nfsphys_menu;
665
666 if (!ValidName(argv[1]))
667 return DM_NORMAL;
668
669 if (!(stat = do_mr_query("get_filesys_by_label", 1, argv + 1,
7ac48069 670 NULL, NULL)))
5eaef520 671 {
672 Put_message ("A Filesystem by that name already exists.");
673 return DM_NORMAL;
674 }
675 else if (stat != MR_NO_MATCH)
676 {
677 com_err(program_name, stat, " in AddFS");
678 return DM_NORMAL;
679 }
680
681 if (!(args = AskFSInfo(SetDefaults(info, argv[1]), FALSE)))
682 {
683 Put_message("Aborted.");
684 return DM_NORMAL;
44b10c87 685 }
461c03b6 686
7ac48069 687 stat = do_mr_query("add_filesys", CountArgs(args), args, NULL, NULL);
5eaef520 688 switch (stat)
689 {
8defc06b 690 case MR_NFS:
5eaef520 691 Put_message("That NFS filesystem is not exported.");
692 if (YesNoQuestion("Fix this now (Y/N)", TRUE) == TRUE)
693 {
694 Do_menu(&nfsphys_menu, 0, NULL);
695 if (YesNoQuestion("Retry filesystem creation now (Y/N)", TRUE)
696 == TRUE) {
697 if ((stat = do_mr_query("add_filesys", CountArgs(args), args,
7ac48069 698 NULL, NULL)))
5eaef520 699 com_err(program_name, stat, " in AddFS");
700 else
701 Put_message("Created.");
702 }
bff71786 703 }
5eaef520 704 break;
8defc06b 705 case MR_SUCCESS:
5eaef520 706 break;
bff71786 707 default:
5eaef520 708 com_err(program_name, stat, " in AddFS");
bff71786 709 }
08345b74 710
5eaef520 711 if (stat == MR_SUCCESS && !strcasecmp(info[FS_L_TYPE], "HOMEDIR"))
712 {
713 static char *val[] = {"def_quota", NULL};
714 static char *def_quota = NULL;
715 char *argv[Q_QUOTA + 1];
600b459e 716 struct mqelem *top = NULL;
5eaef520 717
718 if (!def_quota)
719 {
720 stat = do_mr_query("get_value", CountArgs(val), val,
7ac48069 721 StoreInfo, &top);
5eaef520 722 if (stat != MR_SUCCESS)
723 com_err(program_name, stat, " getting default quota");
724 else
725 {
726 top = QueueTop(top);
7ac48069 727 def_quota = strdup(((char **)top->q_data)[0]);
5eaef520 728 FreeQueue(top);
7cce48da 729 }
730 }
5eaef520 731 if (def_quota)
732 {
733 sprintf(buf, "Give user %s a quota of %s on filesys %s (Y/N)",
734 info[FS_NAME], def_quota, info[FS_NAME]);
735 if (YesNoQuestion(buf, 1) == TRUE)
736 {
737 argv[Q_NAME] = argv[Q_FILESYS] = info[FS_NAME];
738 if (!strcmp(info[FS_TYPE], "NFS"))
739 argv[Q_TYPE] = "USER";
740 else
741 argv[Q_TYPE] = "ANY";
742 argv[Q_QUOTA] = def_quota;
7ac48069 743 if ((stat = do_mr_query("add_quota", Q_QUOTA + 1, argv, NULL,
5eaef520 744 NULL)))
745 com_err(program_name, stat, " while adding quota");
7cce48da 746 }
747 }
5eaef520 748 }
749 else if (stat == MR_SUCCESS)
750 {
751 if (YesNoQuestion("Assign a quota on this filesystem (Y/N)", 1) == TRUE)
752 {
753 parsed_argc = 1;
754 parsed_argv[0] = info[FS_NAME];
7ac48069 755 AddQuota(parsed_argc, parsed_argv);
d25fad50 756 }
7cce48da 757 }
758
5eaef520 759 FreeInfo(info);
760 return DM_NORMAL;
08345b74 761}
762
9e2516d6 763/* Function Name: SortAfter
5eaef520 764 * Description: choose a sortkey to cause an item to be added after
9e2516d6 765 * the count element in the queue
766 * Arguments: queue of filesys names & sortkeys, queue count pointer
767 * Returns: sort key to use.
768 */
769
600b459e 770char *SortAfter(struct mqelem *elem, int count)
9e2516d6 771{
5eaef520 772 char *prev, *next, prevnext, *key, keybuf[9];
773
774 /* first find the two keys we need to insert between */
775 prev = "A";
776 for (; count > 0; count--)
777 {
778 prev = ((char **)elem->q_data)[1];
779 if (elem->q_forw)
780 elem = elem->q_forw;
781 else
782 break;
9e2516d6 783 }
5eaef520 784 if (count > 0)
785 next = "Z";
786 else
787 next = ((char **)elem->q_data)[1];
788
789 /* now copy the matching characters */
790 for (key = keybuf; *prev && *prev == *next; next++)
791 *key++ = *prev++;
792
793 /* and set the last character */
794 if (*prev == 0)
795 *prev = prevnext = 'A';
796 else
797 prevnext = prev[1];
798 if (prevnext == 0)
799 prevnext = 'A';
800 if (*next == 0)
801 *next = 'Z';
802 if (*next - *prev > 1)
803 *key++ = (*next + *prev) / 2;
804 else
805 {
806 *key++ = *prev;
807 *key++ = (prevnext + 'Z') / 2;
9e2516d6 808 }
5eaef520 809 *key = 0;
7ac48069 810 return strdup(keybuf);
9e2516d6 811}
812
813/* Function Name: AddFSToGroup
814 * Description: add a filesystem to an FS group
815 * Arguments: arc, argv - name of group in argv[1], filesys in argv[2].
816 * Returns: DM_NORMAL.
817 */
818
5eaef520 819int AddFSToGroup(int argc, char **argv)
9e2516d6 820{
5eaef520 821 int stat, count;
600b459e 822 struct mqelem *elem = NULL;
5eaef520 823 char buf[BUFSIZ], *args[5], *bufp;
824
825 if ((stat = do_mr_query("get_fsgroup_members", 1, argv + 1, StoreInfo,
7ac48069 826 &elem)))
5eaef520 827 {
828 if (stat != MR_NO_MATCH)
829 com_err(program_name, stat, " in AddFSToGroup");
9e2516d6 830 }
5eaef520 831 if (elem == NULL)
832 {
833 args[0] = argv[1];
834 args[1] = argv[2];
835 args[2] = "M";
7ac48069 836 stat = do_mr_query("add_filesys_to_fsgroup", 3, args, NULL, NULL);
5eaef520 837 if (stat)
838 com_err(program_name, stat, " in AddFSToGroup");
839 return DM_NORMAL;
9e2516d6 840 }
5eaef520 841 elem = QueueTop(elem);
842 fsgCount = 1;
843 Loop(elem, PrintFSGMembers);
844 sprintf(buf, "%d", QueueCount(elem));
7ac48069 845 bufp = strdup(buf);
5eaef520 846 if (GetValueFromUser("Enter number of filesystem it should follow "
847 "(0 to make it first):", &bufp) == SUB_ERROR)
848 return DM_NORMAL;
849 count = atoi(bufp);
850 free(bufp);
851 args[2] = SortAfter(elem, count);
852
853 FreeQueue(QueueTop(elem));
854 args[0] = argv[1];
855 args[1] = argv[2];
7ac48069 856 stat = do_mr_query("add_filesys_to_fsgroup", 3, args, NULL, NULL);
5eaef520 857 if (stat == MR_EXISTS)
858 {
859 Put_message("That filesystem is already a member of the group.");
860 Put_message("Use the order command if you want to change the "
861 "sorting order.");
862 }
863 else if (stat)
864 com_err(program_name, stat, " in AddFSToGroup");
865 return DM_NORMAL;
9e2516d6 866}
867
868
869/* Function Name: RemoveFSFromGroup
870 * Description: delete a filesystem from an FS group
871 * Arguments: arc, argv - name of group in argv[1].
872 * Returns: DM_NORMAL.
873 */
874
5eaef520 875int RemoveFSFromGroup(int argc, char **argv)
9e2516d6 876{
5eaef520 877 int stat;
878 char buf[BUFSIZ];
879
880 sprintf(buf, "Delete filesystem %s from FS group %s", argv[2], argv[1]);
881 if (!Confirm(buf))
882 return DM_NORMAL;
883 if ((stat = do_mr_query("remove_filesys_from_fsgroup", 2, argv + 1,
7ac48069 884 NULL, NULL)))
5eaef520 885 com_err(program_name, stat, ", not removed.");
886 return DM_NORMAL;
9e2516d6 887}
888
889/* Function Name: ChangeFSGroupOrder
890 * Description: change the sortkey on a filesys in an FSgroup
891 * Arguments: arc, argv - name of group in argv[1].
892 * Returns: DM_NORMAL.
893 */
894
5eaef520 895int ChangeFSGroupOrder(int argc, char **argv)
9e2516d6 896{
5eaef520 897 int stat, src, dst, i;
600b459e 898 struct mqelem *elem = NULL, *top, *tmpelem;
5eaef520 899 char buf[BUFSIZ], *bufp, *args[3];
900
901 if ((stat = do_mr_query("get_fsgroup_members", 1, argv + 1, StoreInfo,
7ac48069 902 &elem)))
5eaef520 903 {
904 if (stat == MR_NO_MATCH)
905 {
906 sprintf(buf,
907 "Ether %s is not a filesystem group or it has no members",
908 argv[1]);
909 Put_message(buf);
910 }
911 else
912 com_err(program_name, stat, " in ChangeFSGroupOrder");
913 return DM_NORMAL;
9e2516d6 914 }
5eaef520 915 top = QueueTop(elem);
916 fsgCount = 1;
917 Loop(top, PrintFSGMembers);
918 while (1)
919 {
7ac48069 920 bufp = strdup("1");
5eaef520 921 if (GetValueFromUser("Enter number of the filesystem to move:",
922 &bufp) == SUB_ERROR)
923 return DM_NORMAL;
924 src = atoi(bufp);
925 free(bufp);
926 if (src < 0)
927 {
928 Put_message("You must enter a positive number (or 0 to abort).");
929 continue;
9e2516d6 930 }
5eaef520 931 else if (src == 0)
932 {
933 Put_message("Aborted.");
934 return DM_NORMAL;
9e2516d6 935 }
5eaef520 936 for (elem = top, i = src; i-- > 1 && elem->q_forw; elem = elem->q_forw)
937 ;
938 if (i > 0)
939 {
940 Put_message("You entered a number that is too high");
941 continue;
942 }
943 break;
9e2516d6 944 }
5eaef520 945 while (1)
946 {
7ac48069 947 bufp = strdup("0");
5eaef520 948 if (GetValueFromUser("Enter number of filesystem it should follow "
949 "(0 to make it first):", &bufp) == SUB_ERROR)
950 return DM_NORMAL;
951 dst = atoi(bufp);
952 free(bufp);
953 if (src == dst || src == dst + 1)
954 {
955 Put_message("That has no effect on the sorting order!");
956 return DM_NORMAL;
860a8dbe 957 }
5eaef520 958 if (dst < 0)
959 {
960 Put_message("You must enter a non-negative number.");
961 continue;
860a8dbe 962 }
5eaef520 963 for (tmpelem = top, i = dst; i-- > 1 && tmpelem->q_forw;
964 tmpelem = tmpelem->q_forw)
965 ;
966 if (i > 0)
967 {
968 Put_message("You entered a number that is too high");
969 continue;
860a8dbe 970 }
5eaef520 971 break;
9e2516d6 972 }
5eaef520 973 args[2] = SortAfter(top, dst);
974 args[0] = argv[1];
975 args[1] = ((char **)elem->q_data)[0];
976 if ((stat = do_mr_query("remove_filesys_from_fsgroup", 2, args,
7ac48069 977 NULL, NULL)))
5eaef520 978 {
979 com_err(program_name, stat, " in ChangeFSGroupOrder");
980 return DM_NORMAL;
9e2516d6 981 }
5eaef520 982 if ((stat = do_mr_query("add_filesys_to_fsgroup", 3, args,
7ac48069 983 NULL, NULL)))
5eaef520 984 com_err(program_name, stat, " in ChangeFSGroupOrder");
985 return DM_NORMAL;
9e2516d6 986}
987
988
08345b74 989/* -------------- Top Level Menu ---------------- */
990
991/* Function Name: GetFSAlias
992 * Description: Gets the value for a Filesystem Alias.
993 * Arguments: argc, argv - name of alias in argv[1].
994 * Returns: DM_NORMAL.
995 * NOTES: There should only be one filesystem per alias, thus
996 * this will work correctly.
997 */
998
5eaef520 999int GetFSAlias(int argc, char **argv)
08345b74 1000{
600b459e 1001 struct mqelem *top;
08345b74 1002
5eaef520 1003 top = GetFSInfo(ALIAS, argv[1]);
1004 Put_message(" "); /* blank line. */
a6da9354 1005 Loop(top, (void (*)(char **))PrintFSAlias);
5eaef520 1006 FreeQueue(top);
1007 return DM_NORMAL;
08345b74 1008}
1009
1010/* Function Name: CreateFSAlias
6c7a2fcf 1011 * Description: Create an alias name for a filesystem
08345b74 1012 * Arguments: argc, argv - name of alias in argv[1].
1013 * Returns: DM_NORMAL.
1014 * NOTES: This requires (name, type, transl) I get {name, translation}
5eaef520 1015 * from the user. I provide type, which is well-known.
08345b74 1016 */
1017
5eaef520 1018int CreateFSAlias(int argc, char **argv)
08345b74 1019{
44d12d58 1020 int stat;
600b459e 1021 struct mqelem *elem, *top;
5eaef520 1022 char *args[MAX_ARGS_SIZE], buf[BUFSIZ], **info;
1023
1024 elem = NULL;
1025
1026 if (!ValidName(argv[1]))
1027 return DM_NORMAL;
1028
7ac48069 1029 args[ALIAS_NAME] = strdup(argv[1]);
1030 args[ALIAS_TYPE] = strdup(FS_ALIAS_TYPE);
1031 args[ALIAS_TRANS] = strdup("*");
5eaef520 1032
1033 /*
1034 * Check to see if this alias already exists in the database, if so then
1035 * print out values, free memory used and then exit.
1036 */
1037
7ac48069 1038 if (!(stat = do_mr_query("get_alias", 3, args, StoreInfo, &elem)))
5eaef520 1039 {
1040 top = elem = QueueTop(elem);
1041 while (elem)
1042 {
7ac48069 1043 info = elem->q_data;
5eaef520 1044 sprintf(buf, "The alias: %s currently describes the filesystem %s",
1045 info[ALIAS_NAME], info[ALIAS_TRANS]);
1046 Put_message(buf);
1047 elem = elem->q_forw;
08345b74 1048 }
5eaef520 1049 FreeQueue(top);
1050 return DM_NORMAL;
08345b74 1051 }
5eaef520 1052 else if (stat != MR_NO_MATCH)
1053 {
1054 com_err(program_name, stat, " in CreateFSAlias.");
1055 return DM_NORMAL;
08345b74 1056 }
1057
7ac48069 1058 args[ALIAS_TRANS] = strdup("");
5eaef520 1059 args[ALIAS_END] = NULL;
1060 if (GetValueFromUser("Which filesystem will this alias point to?",
1061 &args[ALIAS_TRANS]) == SUB_ERROR)
1062 return DM_NORMAL;
08345b74 1063
7ac48069 1064 if ((stat = do_mr_query("add_alias", 3, args, NULL, NULL)))
5eaef520 1065 com_err(program_name, stat, " in CreateFSAlias.");
08345b74 1066
5eaef520 1067 FreeInfo(args);
1068 return DM_NORMAL;
08345b74 1069}
5eaef520 1070
402461ad 1071/* Function Name: RealDeleteFSAlias
1072 * Description: Does the real deletion work.
1073 * Arguments: info - array of char *'s containing all useful info.
5eaef520 1074 * one_item - a Boolean that is true if only one item
402461ad 1075 * in queue that dumped us here.
1076 * Returns: none.
1077 */
1078
5eaef520 1079void RealDeleteFSAlias(char **info, Bool one_item)
402461ad 1080{
5eaef520 1081 int stat;
1082 char temp_buf[BUFSIZ];
1083
1084 /*
1085 * Deletions are performed if the user hits 'y' on a list of multiple
1086 * filesystem, or if the user confirms on a unique alias.
1087 */
1088 sprintf(temp_buf,
1089 "Are you sure that you want to delete the filesystem alias %s",
1090 info[ALIAS_NAME]);
1091 if (!one_item || Confirm(temp_buf))
1092 {
1093 if ((stat = do_mr_query("delete_alias", CountArgs(info),
7ac48069 1094 info, NULL, NULL)))
5eaef520 1095 com_err(program_name, stat, " filesystem alias not deleted.");
1096 else
1097 Put_message("Filesystem alias deleted.");
402461ad 1098 }
5eaef520 1099 else
1100 Put_message("Filesystem alias not deleted.");
402461ad 1101}
08345b74 1102
1103/* Function Name: DeleteFSAlias
6c7a2fcf 1104 * Description: Delete an alias name for a filesystem
08345b74 1105 * Arguments: argc, argv - name of alias in argv[1].
1106 * Returns: DM_NORMAL.
1107 * NOTES: This requires (name, type, transl) I get {name, translation}
5eaef520 1108 * from the user. I provide type, which is well-known.
08345b74 1109 */
1110
5eaef520 1111int DeleteFSAlias(int argc, char **argv)
08345b74 1112{
600b459e 1113 struct mqelem *elem = GetFSInfo(ALIAS, argv[1]);
5eaef520 1114 QueryLoop(elem, PrintFSAlias, RealDeleteFSAlias,
1115 "Delete the Filesystem Alias");
1116 FreeQueue(elem);
1117 return DM_NORMAL;
08345b74 1118}
1119
1120/* Function Name: AttachHelp
1121 * Description: Print help info on attachmaint.
1122 * Arguments: none
1123 * Returns: DM_NORMAL.
1124 */
1125
5eaef520 1126int AttachHelp(void)
08345b74 1127{
5eaef520 1128 static char *message[] = {
1129 "These are the options:",
1130 "",
1131 "get - get information about a filesystem.",
1132 "add - add a new filesystem to the data base.",
1133 "update - update the information in the database on a filesystem.",
1134 "delete - delete a filesystem from the database.",
1135 "check - check information about association of a name and a filesys.",
1136 "alias - associate a name with a filesystem.",
1137 "unalias - disassociate a name with a filesystem.",
1138 "verbose - toggle the request for delete confirmation.",
1139 NULL,
1140 };
1141
1142 return PrintHelp(message);
08345b74 1143}
9e2516d6 1144
1145/* Function Name: FSGroupHelp
1146 * Description: Print help info on fsgroups.
1147 * Arguments: none
1148 * Returns: DM_NORMAL.
1149 */
1150
7ac48069 1151int FSGroupHelp(int argc, char **argv)
9e2516d6 1152{
5eaef520 1153 static char *message[] = {
1154 "A filesystem group is a named sorted list of filesystems.",
1155 "",
1156 "To create, modify, or delete a group itself, use the menu above",
1157 " this one, and manipulate a filesystem of type FSGROUP.",
1158 "Options here are:",
1159 " get - get info about a group and show its members",
1160 " add - add a new member to a group.",
1161 " remove - remove a member from a group.",
1162 " order - change the sorting order of a group.",
1163 NULL
1164 };
1165
1166 return PrintHelp(message);
9e2516d6 1167}
This page took 0.351446 seconds and 5 git commands to generate.