diff options
Diffstat (limited to 'contrib/cvs/src/admin.c')
-rw-r--r-- | contrib/cvs/src/admin.c | 92 |
1 files changed, 55 insertions, 37 deletions
diff --git a/contrib/cvs/src/admin.c b/contrib/cvs/src/admin.c index 637663a..359bedf 100644 --- a/contrib/cvs/src/admin.c +++ b/contrib/cvs/src/admin.c @@ -46,13 +46,13 @@ static const char *const admin_usage[] = "\t revision on the default branch.\n", "\t-N tag[:[rev]] Same as -n except override existing tag.\n", "\t-o range Delete (outdate) specified range of revisions:\n", + "\t rev1:rev2 Between rev1 and rev2, including rev1 and rev2.\n", "\t rev1::rev2 Between rev1 and rev2, excluding rev1 and rev2.\n", + "\t rev: rev and following revisions on the same branch.\n", "\t rev:: After rev on the same branch.\n", + "\t :rev rev and previous revisions on the same branch.\n", "\t ::rev Before rev on the same branch.\n", "\t rev Just rev.\n", - "\t rev1:rev2 Between rev1 and rev2, including rev1 and rev2.\n", - "\t rev: rev and following revisions on the same branch.\n", - "\t :rev rev and previous revisions on the same branch.\n", "\t-q Run quietly.\n", "\t-s state[:rev] Set revision state (latest revision on branch,\n", "\t latest revision on trunk if omitted).\n", @@ -97,10 +97,6 @@ struct admin_data /* Interactive (-I). Problematic with client/server. */ int interactive; - /* Quiet (-q). Not the same as the global -q option, which is a bit - on the confusing side, perhaps. */ - int quiet; - /* This is the cheesy part. It is a vector with the options which we don't deal with above (e.g. "-afoo" "-abar,baz"). In the future this presumably will be replaced by other variables which break @@ -337,7 +333,15 @@ admin (argc, argv) break; case 'q': - admin_data.quiet = 1; + /* Silently set the global really_quiet flag. This keeps admin in + * sync with the RCS man page and allows us to silently support + * older servers when necessary. + * + * Some logic says we might want to output a deprecation warning + * here, but I'm opting not to in order to stay quietly in sync + * with the RCS man page. + */ + really_quiet = 1; break; case 'x': @@ -372,29 +376,40 @@ admin (argc, argv) argv += optind; #ifdef CVS_ADMIN_GROUP - grp = getgrnam(CVS_ADMIN_GROUP); - /* skip usage right check if group CVS_ADMIN_GROUP does not exist */ - if (grp != NULL) + /* The use of `cvs admin -k' is unrestricted. However, any other + option is restricted if the group CVS_ADMIN_GROUP exists. */ + if (!only_k_option && + (grp = getgrnam(CVS_ADMIN_GROUP)) != NULL) { +#ifdef HAVE_GETGROUPS + gid_t *grps; + int n; + + /* get number of auxiliary groups */ + n = getgroups (0, NULL); + if (n < 0) + error (1, errno, "unable to get number of auxiliary groups"); + grps = (gid_t *) xmalloc((n + 1) * sizeof *grps); + n = getgroups (n, grps); + if (n < 0) + error (1, errno, "unable to get list of auxiliary groups"); + grps[n] = getgid(); + for (i = 0; i <= n; i++) + if (grps[i] == grp->gr_gid) break; + free (grps); + if (i > n) + error (1, 0, "usage is restricted to members of the group %s", + CVS_ADMIN_GROUP); +#else char *me = getcaller(); - char **grnam = grp->gr_mem; - /* The use of `cvs admin -k' is unrestricted. However, any - other option is restricted. */ - int denied = ! only_k_option; + char **grnam; - while (*grnam) - { - if (strcmp(*grnam, me) == 0) - { - denied = 0; - break; - } - grnam++; - } - - if (denied) + for (grnam = grp->gr_mem; *grnam; grnam++) + if (strcmp (*grnam, me) == 0) break; + if (!*grnam && getgid() != grp->gr_gid) error (1, 0, "usage is restricted to members of the group %s", CVS_ADMIN_GROUP); +#endif } #endif @@ -427,7 +442,7 @@ admin (argc, argv) } #ifdef CLIENT_SUPPORT - if (client_active) + if (current_parsed_root->isremote) { /* We're the client side. Fire up the remote server. */ start_server (); @@ -470,7 +485,10 @@ admin (argc, argv) } send_to_server ("\012", 1); } - if (admin_data.quiet) + /* Send this for all really_quiets since we know that it will be silently + * ignored when unneeded. This supports old servers. + */ + if (really_quiet) send_arg ("-q"); if (admin_data.kflag != NULL) send_arg (admin_data.kflag); @@ -486,7 +504,7 @@ admin (argc, argv) } #endif /* CLIENT_SUPPORT */ - lock_tree_for_write (argc, argv, 0, 0); + lock_tree_for_write (argc, argv, 0, W_LOCAL, 0); err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc, (DIRLEAVEPROC) NULL, (void *)&admin_data, @@ -546,7 +564,7 @@ admin_fileproc (callerdat, finfo) status = 0; - if (!admin_data->quiet) + if (!really_quiet) { cvs_output ("RCS file: ", 0); cvs_output (rcs->path, 0); @@ -767,9 +785,10 @@ admin_fileproc (callerdat, finfo) } else { - error (0, 0, - "%s: Symbolic name or revision %s is undefined", - rcs->path, p); + if (!really_quiet) + error (0, 0, + "%s: Symbolic name or revision %s is undefined.", + rcs->path, p); status = 1; } free (tag); @@ -854,12 +873,10 @@ admin_fileproc (callerdat, finfo) } } - /* TODO: reconcile the weird discrepancies between - admin_data->quiet and quiet. */ if (status == 0) { RCS_rewrite (rcs, NULL, NULL); - if (!admin_data->quiet) + if (!really_quiet) cvs_output ("done\n", 5); } else @@ -868,7 +885,8 @@ admin_fileproc (callerdat, finfo) message has given a more specific error. The point of this additional message is to make it clear that the previous problems caused CVS to forget about the idea of modifying the RCS file. */ - error (0, 0, "cannot modify RCS file for `%s'", finfo->file); + if (!really_quiet) + error (0, 0, "RCS file for `%s' not modified.", finfo->file); RCS_abandon (rcs); } |