admin.c revision 17721
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((char *dir, char *repos, char *update_dir));
20static int admin_fileproc PROTO((struct file_info *finfo));
21
22static const char *const admin_usage[] =
23{
24    "Usage: %s %s rcs-options files...\n",
25    NULL
26};
27
28static int ac;
29static char **av;
30
31int
32admin (argc, argv)
33    int argc;
34    char **argv;
35{
36    int err;
37#ifdef CVS_ADMIN_GROUP
38    struct group *grp;
39#endif
40    if (argc <= 1)
41	usage (admin_usage);
42
43#ifdef CVS_ADMIN_GROUP
44    grp = getgrnam(CVS_ADMIN_GROUP);
45     /* skip usage right check if group CVS_ADMIN_GROUP does not exist */
46    if (grp != NULL)
47    {
48	char *me = getcaller();
49	char **grnam = grp->gr_mem;
50	int denied = 1;
51
52	while (*grnam)
53	{
54	    if (strcmp(*grnam, me) == 0)
55	    {
56		denied = 0;
57		break;
58	    }
59	    grnam++;
60	}
61
62	if (denied)
63	    error (1, 0, "usage is restricted to members of the group %s",
64		   CVS_ADMIN_GROUP);
65    }
66#endif
67
68    wrap_setup ();
69
70    /* skip all optional arguments to see if we have any file names */
71    for (ac = 1; ac < argc; ac++)
72	if (argv[ac][0] != '-')
73	    break;
74    argc -= ac;
75    av = argv + 1;
76    argv += ac;
77    ac--;
78    if (ac == 0 || argc == 0)
79	usage (admin_usage);
80
81#ifdef CLIENT_SUPPORT
82    if (client_active)
83    {
84	int i;
85
86	/* We're the client side.  Fire up the remote server.  */
87	start_server ();
88
89	ign_setup ();
90
91	for (i = 0; i <= ac; ++i)	/* XXX send -ko too with i = 0 */
92	    send_arg (av[i]);
93
94	send_file_names (argc, argv, SEND_EXPAND_WILD);
95	/* FIXME:  We shouldn't have to send current files, but I'm not sure
96	   whether it works.  So send the files --
97	   it's slower but it works.  */
98	send_files (argc, argv, 0, 0);
99	send_to_server ("admin\012", 0);
100        return get_responses_and_close ();
101    }
102#endif /* CLIENT_SUPPORT */
103
104    /* start the recursion processor */
105    err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
106			   (DIRLEAVEPROC) NULL, argc, argv, 0,
107			   W_LOCAL, 0, 1, (char *) NULL, 1, 0);
108    return (err);
109}
110
111/*
112 * Called to run "rcs" on a particular file.
113 */
114/* ARGSUSED */
115static int
116admin_fileproc (finfo)
117    struct file_info *finfo;
118{
119    Vers_TS *vers;
120    char *version;
121    char **argv;
122    int argc;
123    int retcode = 0;
124    int status = 0;
125
126    vers = Version_TS (finfo->repository, (char *) NULL, (char *) NULL, (char *) NULL,
127		       finfo->file, 0, 0, finfo->entries, finfo->rcs);
128
129    version = vers->vn_user;
130    if (version == NULL)
131	goto exitfunc;
132    else if (strcmp (version, "0") == 0)
133    {
134	error (0, 0, "cannot admin newly added file `%s'", finfo->file);
135	goto exitfunc;
136    }
137
138    run_setup ("%s%s -x,v/", Rcsbin, RCS);
139    for (argc = ac, argv = av; argc; argc--, argv++)
140	run_arg (*argv);
141    run_arg (vers->srcfile->path);
142    if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
143    {
144	if (!quiet)
145	    error (0, retcode == -1 ? errno : 0,
146		   "%s failed for `%s'", RCS, finfo->file);
147	status = 1;
148	goto exitfunc;
149    }
150  exitfunc:
151    freevers_ts (&vers);
152    return status;
153}
154
155/*
156 * Print a warm fuzzy message
157 */
158/* ARGSUSED */
159static Dtype
160admin_dirproc (dir, repos, update_dir)
161    char *dir;
162    char *repos;
163    char *update_dir;
164{
165    if (!quiet)
166	error (0, 0, "Administrating %s", update_dir);
167    return (R_PROCESS);
168}
169