admin.c revision 25839
1/*
2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
4 *
5 * You may distribute under the terms of the GNU General Public License as
6 * specified in the README file that comes with the CVS 1.4 kit.
7 *
8 * Administration
9 *
10 * For now, this is basically a front end for rcs.  All options are passed
11 * directly on.
12 */
13
14#include "cvs.h"
15#ifdef CVS_ADMIN_GROUP
16#include <grp.h>
17#endif
18
19static Dtype admin_dirproc PROTO ((void *callerdat, char *dir,
20				   char *repos, char *update_dir,
21				   List *entries));
22static int admin_fileproc PROTO ((void *callerdat, struct file_info *finfo));
23
24static const char *const admin_usage[] =
25{
26    "Usage: %s %s rcs-options files...\n",
27    NULL
28};
29
30static int ac;
31static char **av;
32
33int
34admin (argc, argv)
35    int argc;
36    char **argv;
37{
38    int err;
39#ifdef CVS_ADMIN_GROUP
40    struct group *grp;
41    struct group *getgrnam();
42#endif
43    if (argc <= 1)
44	usage (admin_usage);
45
46#ifdef CVS_ADMIN_GROUP
47    grp = getgrnam(CVS_ADMIN_GROUP);
48     /* skip usage right check if group CVS_ADMIN_GROUP does not exist */
49    if (grp != NULL)
50    {
51	char *me = getcaller();
52	char **grnam = grp->gr_mem;
53	int denied = 1;
54
55	while (*grnam)
56	{
57	    if (strcmp(*grnam, me) == 0)
58	    {
59		denied = 0;
60		break;
61	    }
62	    grnam++;
63	}
64
65	if (denied)
66	    error (1, 0, "usage is restricted to members of the group %s",
67		   CVS_ADMIN_GROUP);
68    }
69#endif
70
71    wrap_setup ();
72
73    /* skip all optional arguments to see if we have any file names */
74    for (ac = 1; ac < argc; ac++)
75	if (argv[ac][0] != '-')
76	    break;
77    argc -= ac;
78    av = argv + 1;
79    argv += ac;
80    ac--;
81
82#ifdef CLIENT_SUPPORT
83    if (client_active)
84    {
85	int i;
86
87	/* We're the client side.  Fire up the remote server.  */
88	start_server ();
89
90	ign_setup ();
91
92	for (i = 0; i < ac; ++i)	/* XXX send -ko too with i = 0 */
93	    send_arg (av[i]);
94
95	send_file_names (argc, argv, SEND_EXPAND_WILD);
96	send_files (argc, argv, 0, 0, SEND_NO_CONTENTS);
97	send_to_server ("admin\012", 0);
98        return get_responses_and_close ();
99    }
100#endif /* CLIENT_SUPPORT */
101
102    /* start the recursion processor */
103    err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
104			   (DIRLEAVEPROC) NULL, NULL, argc, argv, 0,
105			   W_LOCAL, 0, 1, (char *) NULL, 1);
106    return (err);
107}
108
109/*
110 * Called to run "rcs" on a particular file.
111 */
112/* ARGSUSED */
113static int
114admin_fileproc (callerdat, finfo)
115    void *callerdat;
116    struct file_info *finfo;
117{
118    Vers_TS *vers;
119    char *version;
120    char **argv;
121    int argc;
122    int retcode = 0;
123    int status = 0;
124
125    vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
126
127    version = vers->vn_user;
128    if (version == NULL)
129	goto exitfunc;
130    else if (strcmp (version, "0") == 0)
131    {
132	error (0, 0, "cannot admin newly added file `%s'", finfo->file);
133	goto exitfunc;
134    }
135
136    run_setup ("%s%s -x,v/", Rcsbin, RCS);
137    for (argc = ac, argv = av; argc; argc--, argv++)
138	run_arg (*argv);
139    run_arg (vers->srcfile->path);
140    if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
141    {
142	if (!quiet)
143	    error (0, retcode == -1 ? errno : 0,
144		   "%s failed for `%s'", RCS, finfo->file);
145	status = 1;
146	goto exitfunc;
147    }
148  exitfunc:
149    freevers_ts (&vers);
150    return status;
151}
152
153/*
154 * Print a warm fuzzy message
155 */
156/* ARGSUSED */
157static Dtype
158admin_dirproc (callerdat, dir, repos, update_dir, entries)
159    void *callerdat;
160    char *dir;
161    char *repos;
162    char *update_dir;
163    List *entries;
164{
165    if (!quiet)
166	error (0, 0, "Administrating %s", update_dir);
167    return (R_PROCESS);
168}
169