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