summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/admin.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/admin.c')
-rw-r--r--contrib/cvs/src/admin.c92
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);
}
OpenPOWER on IntegriCloud