xref: /openbsd-src/usr.bin/cvs/add.c (revision 37fdff3fa60fdd1baf6bc6082eee5bd7ac3b858c)
1*37fdff3fStobias /*	$OpenBSD: add.c,v 1.90 2008/02/04 15:07:32 tobias Exp $	*/
291e2b091Sjoris /*
391e2b091Sjoris  * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
42ec286b3Sxsa  * Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
591e2b091Sjoris  *
691e2b091Sjoris  * Permission to use, copy, modify, and distribute this software for any
791e2b091Sjoris  * purpose with or without fee is hereby granted, provided that the above
891e2b091Sjoris  * copyright notice and this permission notice appear in all copies.
991e2b091Sjoris  *
1091e2b091Sjoris  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1191e2b091Sjoris  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1291e2b091Sjoris  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1391e2b091Sjoris  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1491e2b091Sjoris  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1591e2b091Sjoris  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1691e2b091Sjoris  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1791e2b091Sjoris  */
1891e2b091Sjoris 
191f8531bdSotto #include <sys/stat.h>
201f8531bdSotto 
211f8531bdSotto #include <errno.h>
221f8531bdSotto #include <string.h>
231f8531bdSotto #include <unistd.h>
2491e2b091Sjoris 
2591e2b091Sjoris #include "cvs.h"
2677a3e292Sxsa #include "remote.h"
2791e2b091Sjoris 
28932258d9Sxsa extern char *__progname;
29932258d9Sxsa 
3091e2b091Sjoris void	cvs_add_local(struct cvs_file *);
31e453c9e9Sjoris void	cvs_add_entry(struct cvs_file *);
320096e8ebStobias void	cvs_add_remote(struct cvs_file *);
3391e2b091Sjoris 
34ee416d02Sjoris static void add_directory(struct cvs_file *);
35ee416d02Sjoris static void add_file(struct cvs_file *);
362ec286b3Sxsa static void add_entry(struct cvs_file *);
37ee416d02Sjoris 
38*37fdff3fStobias int		kflag = 0;
39*37fdff3fStobias static char	kbuf[8];
4056f996a2Sxsa 
4191e2b091Sjoris char	*logmsg;
4291e2b091Sjoris 
4391e2b091Sjoris struct cvs_cmd cvs_cmd_add = {
44f331ff59Stobias 	CVS_OP_ADD, CVS_USE_WDIR, "add",
4591e2b091Sjoris 	{ "ad", "new" },
4691e2b091Sjoris 	"Add a new file or directory to the repository",
4756f996a2Sxsa 	"[-k mode] [-m message] ...",
4856f996a2Sxsa 	"k:m:",
4991e2b091Sjoris 	NULL,
5091e2b091Sjoris 	cvs_add
5191e2b091Sjoris };
5291e2b091Sjoris 
5391e2b091Sjoris int
5491e2b091Sjoris cvs_add(int argc, char **argv)
5591e2b091Sjoris {
5691e2b091Sjoris 	int ch;
5791e2b091Sjoris 	int flags;
5891e2b091Sjoris 	struct cvs_recursion cr;
5991e2b091Sjoris 
60ee416d02Sjoris 	flags = CR_REPO;
6191e2b091Sjoris 
6291e2b091Sjoris 	while ((ch = getopt(argc, argv, cvs_cmd_add.cmd_opts)) != -1) {
6391e2b091Sjoris 		switch (ch) {
6456f996a2Sxsa 		case 'k':
65*37fdff3fStobias 			kflag = rcs_kflag_get(optarg);
6656f996a2Sxsa 			if (RCS_KWEXP_INVAL(kflag)) {
6756f996a2Sxsa 				cvs_log(LP_ERR,
6856f996a2Sxsa 				    "invalid RCS keyword expension mode");
6956f996a2Sxsa 				fatal("%s", cvs_cmd_add.cmd_synopsis);
7056f996a2Sxsa 			}
71*37fdff3fStobias 			(void)xsnprintf(kbuf, sizeof(kbuf), "-k%s", optarg);
7256f996a2Sxsa 			break;
7391e2b091Sjoris 		case 'm':
744f1ce0f6Stobias 			logmsg = optarg;
7591e2b091Sjoris 			break;
7691e2b091Sjoris 		default:
7791e2b091Sjoris 			fatal("%s", cvs_cmd_add.cmd_synopsis);
7891e2b091Sjoris 		}
7991e2b091Sjoris 	}
8091e2b091Sjoris 
8191e2b091Sjoris 	argc -= optind;
8291e2b091Sjoris 	argv += optind;
8391e2b091Sjoris 
842a7e332fSjoris 	if (argc == 0)
852a7e332fSjoris 		fatal("%s", cvs_cmd_add.cmd_synopsis);
862a7e332fSjoris 
8791e2b091Sjoris 	cr.enterdir = NULL;
8891e2b091Sjoris 	cr.leavedir = NULL;
8977a3e292Sxsa 
9077a3e292Sxsa 	if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
9180f6ca9bSjoris 		cvs_client_connect_to_server();
920096e8ebStobias 		cr.fileproc = cvs_add_remote;
9377a3e292Sxsa 
94*37fdff3fStobias 		if (kflag);
9556f996a2Sxsa 			cvs_client_send_request("Argument %s", kbuf);
9656f996a2Sxsa 
9777a3e292Sxsa 		if (logmsg != NULL)
98f76ce13cSjoris 			cvs_client_send_logmsg(logmsg);
9977a3e292Sxsa 	} else {
100bc5d89feSjoris 		cr.fileproc = cvs_add_local;
10177a3e292Sxsa 	}
10277a3e292Sxsa 
10391e2b091Sjoris 	cr.flags = flags;
10491e2b091Sjoris 
10591e2b091Sjoris 	cvs_file_run(argc, argv, &cr);
10677a3e292Sxsa 
10777a3e292Sxsa 	if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
10877a3e292Sxsa 		cvs_client_senddir(".");
1090096e8ebStobias 		cvs_client_send_files(argv, argc);
11077a3e292Sxsa 		cvs_client_send_request("add");
11177a3e292Sxsa 		cvs_client_get_responses();
112e453c9e9Sjoris 
113e453c9e9Sjoris 		if (server_response == SERVER_OK) {
114e453c9e9Sjoris 			cr.fileproc = cvs_add_entry;
115e453c9e9Sjoris 			cvs_file_run(argc, argv, &cr);
116e453c9e9Sjoris 		}
11777a3e292Sxsa 	}
11877a3e292Sxsa 
11991e2b091Sjoris 	return (0);
12091e2b091Sjoris }
12191e2b091Sjoris 
12291e2b091Sjoris void
123e453c9e9Sjoris cvs_add_entry(struct cvs_file *cf)
124e453c9e9Sjoris {
125ba7b4b60Sotto 	char entry[CVS_ENT_MAXLINELEN];
126e453c9e9Sjoris 	CVSENTRIES *entlist;
127e453c9e9Sjoris 
128e453c9e9Sjoris 	if (cf->file_type == CVS_DIR) {
129c486465dSxsa 		(void)xsnprintf(entry, CVS_ENT_MAXLINELEN,
130bb3d3fd3Stobias 		    "D/%s////", cf->file_name);
131428adc2bSjoris 
132e453c9e9Sjoris 		entlist = cvs_ent_open(cf->file_wd);
133e453c9e9Sjoris 		cvs_ent_add(entlist, entry);
134e453c9e9Sjoris 		cvs_ent_close(entlist, ENT_SYNC);
135e453c9e9Sjoris 	} else {
136e453c9e9Sjoris 		add_entry(cf);
137e453c9e9Sjoris 	}
138e453c9e9Sjoris }
139e453c9e9Sjoris 
140e453c9e9Sjoris void
14191e2b091Sjoris cvs_add_local(struct cvs_file *cf)
14291e2b091Sjoris {
14391e2b091Sjoris 	cvs_log(LP_TRACE, "cvs_add_local(%s)", cf->file_path);
14491e2b091Sjoris 
14551ef6581Sjoris 	cvs_file_classify(cf, cvs_directory_tag);
14691e2b091Sjoris 
14723aa6532Sxsa 	/* dont use `cvs add *' */
14823aa6532Sxsa 	if (strcmp(cf->file_name, ".") == 0 ||
14923aa6532Sxsa 	    strcmp(cf->file_name, "..") == 0 ||
15023aa6532Sxsa 	    strcmp(cf->file_name, CVS_PATH_CVSDIR) == 0) {
15123aa6532Sxsa 		if (verbosity > 1)
15223aa6532Sxsa 			cvs_log(LP_ERR,
15323aa6532Sxsa 			    "cannot add special file `%s'; skipping",
15423aa6532Sxsa 			    cf->file_name);
15523aa6532Sxsa 		return;
15623aa6532Sxsa 	}
15723aa6532Sxsa 
158ee416d02Sjoris 	if (cf->file_type == CVS_DIR)
159ee416d02Sjoris 		add_directory(cf);
160ee416d02Sjoris 	else
161ee416d02Sjoris 		add_file(cf);
162ee416d02Sjoris }
163ee416d02Sjoris 
1640096e8ebStobias void
1650096e8ebStobias cvs_add_remote(struct cvs_file *cf)
1660096e8ebStobias {
1670096e8ebStobias 	char path[MAXPATHLEN];
1680096e8ebStobias 
1690096e8ebStobias 	cvs_log(LP_TRACE, "cvs_add_remote(%s)", cf->file_path);
1700096e8ebStobias 
1710096e8ebStobias 	cvs_file_classify(cf, cvs_directory_tag);
1720096e8ebStobias 
1730096e8ebStobias 	if (cf->file_type == CVS_DIR) {
1740096e8ebStobias 		cvs_get_repository_path(cf->file_wd, path, MAXPATHLEN);
1750096e8ebStobias 		if (strlcat(path, "/", sizeof(path)) >= sizeof(path))
1760096e8ebStobias 			fatal("cvs_add_remote: truncation");
1770096e8ebStobias 		if (strlcat(path, cf->file_path, sizeof(path)) >= sizeof(path))
1780096e8ebStobias 			fatal("cvs_add_remote: truncation");
1790096e8ebStobias 		cvs_client_send_request("Directory %s\n%s", cf->file_path,
1800096e8ebStobias 		    path);
1810096e8ebStobias 
1820096e8ebStobias 		add_directory(cf);
1830096e8ebStobias 	} else {
1840096e8ebStobias 		cvs_client_sendfile(cf);
1850096e8ebStobias 	}
1860096e8ebStobias }
1870096e8ebStobias 
188ee416d02Sjoris static void
189ee416d02Sjoris add_directory(struct cvs_file *cf)
190ee416d02Sjoris {
191c486465dSxsa 	int added, nb;
192ee416d02Sjoris 	struct stat st;
193ee416d02Sjoris 	CVSENTRIES *entlist;
194ba7b4b60Sotto 	char *date, entry[MAXPATHLEN], msg[1024], repo[MAXPATHLEN], *tag, *p;
195ee416d02Sjoris 
196ee416d02Sjoris 	cvs_log(LP_TRACE, "add_directory(%s)", cf->file_path);
197ee416d02Sjoris 
198c486465dSxsa 	(void)xsnprintf(entry, MAXPATHLEN, "%s%s",
199c486465dSxsa 	    cf->file_rpath, RCS_FILE_EXT);
200ee416d02Sjoris 
2017938e528Sjoris 	added = 1;
202ee416d02Sjoris 	if (stat(entry, &st) != -1) {
203ee416d02Sjoris 		cvs_log(LP_NOTICE, "cannot add directory %s: "
204ee416d02Sjoris 		    "a file with that name already exists",
205ee416d02Sjoris 		    cf->file_path);
2067938e528Sjoris 		added = 0;
207ee416d02Sjoris 	} else {
208890ecb5aSxsa 		/* Let's see if we have any per-directory tags first. */
209890ecb5aSxsa 		cvs_parse_tagfile(cf->file_wd, &tag, &date, &nb);
210890ecb5aSxsa 
211e40de241Sxsa 		(void)xsnprintf(entry, MAXPATHLEN, "%s/%s",
212e40de241Sxsa 		    cf->file_path, CVS_PATH_CVSDIR);
213ee416d02Sjoris 
2140096e8ebStobias 		if (cvs_server_active) {
2150096e8ebStobias 			if (mkdir(cf->file_rpath, 0755) == -1 &&
2160096e8ebStobias 			    errno != EEXIST)
2170096e8ebStobias 				fatal("add_directory: %s: %s", cf->file_rpath,
2180096e8ebStobias 				    strerror(errno));
2190096e8ebStobias 		} else if (stat(entry, &st) != -1) {
220ee416d02Sjoris 			if (!S_ISDIR(st.st_mode)) {
221ee416d02Sjoris 				cvs_log(LP_ERR, "%s exists but is not "
222ee416d02Sjoris 				    "directory", entry);
223ee416d02Sjoris 			} else {
224ee416d02Sjoris 				cvs_log(LP_NOTICE, "%s already exists",
225ee416d02Sjoris 				    entry);
226ee416d02Sjoris 			}
2277938e528Sjoris 			added = 0;
2287938e528Sjoris 		} else if (cvs_noexec != 1) {
229ee416d02Sjoris 			if (mkdir(cf->file_rpath, 0755) == -1 &&
230ee416d02Sjoris 			    errno != EEXIST)
2310096e8ebStobias 				fatal("add_directory: %s: %s", cf->file_rpath,
232ee416d02Sjoris 				    strerror(errno));
233ee416d02Sjoris 
234ee416d02Sjoris 			cvs_get_repository_name(cf->file_wd, repo,
235ee416d02Sjoris 			    MAXPATHLEN);
236ee416d02Sjoris 
237e40de241Sxsa 			(void)xsnprintf(entry, MAXPATHLEN, "%s/%s",
238e40de241Sxsa 			    repo, cf->file_name);
239ee416d02Sjoris 
240ee416d02Sjoris 			cvs_mkadmin(cf->file_path, current_cvsroot->cr_dir,
241890ecb5aSxsa 			    entry, tag, date, nb);
242ee416d02Sjoris 
243ba7b4b60Sotto 			p = xmalloc(CVS_ENT_MAXLINELEN);
244c486465dSxsa 			(void)xsnprintf(p, CVS_ENT_MAXLINELEN,
245bb3d3fd3Stobias 			    "D/%s////", cf->file_name);
246ee416d02Sjoris 			entlist = cvs_ent_open(cf->file_wd);
247ba7b4b60Sotto 			cvs_ent_add(entlist, p);
248ee416d02Sjoris 			cvs_ent_close(entlist, ENT_SYNC);
2492597d60cSjoris 			xfree(p);
2507938e528Sjoris 		}
2517938e528Sjoris 	}
252ee416d02Sjoris 
2530096e8ebStobias 	if (added == 1 && current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
254c486465dSxsa 		(void)xsnprintf(msg, sizeof(msg),
255890ecb5aSxsa 		    "Directory %s added to the repository", cf->file_rpath);
256890ecb5aSxsa 
257890ecb5aSxsa 		if (tag != NULL) {
258890ecb5aSxsa 			(void)strlcat(msg,
259890ecb5aSxsa 			    "\n--> Using per-directory sticky tag ",
260890ecb5aSxsa 			    sizeof(msg));
261890ecb5aSxsa 			(void)strlcat(msg, tag, sizeof(msg));
262890ecb5aSxsa 		}
263890ecb5aSxsa 		if (date != NULL) {
264890ecb5aSxsa 			(void)strlcat(msg,
265890ecb5aSxsa 			    "\n--> Using per-directory sticky date ",
266890ecb5aSxsa 			    sizeof(msg));
267890ecb5aSxsa 			(void)strlcat(msg, date, sizeof(msg));
268890ecb5aSxsa 		}
269890ecb5aSxsa 		cvs_printf("%s\n", msg);
270890ecb5aSxsa 
271890ecb5aSxsa 		if (tag != NULL)
272890ecb5aSxsa 			xfree(tag);
273890ecb5aSxsa 		if (date != NULL)
274890ecb5aSxsa 			xfree(date);
275ee416d02Sjoris 	}
276ee416d02Sjoris 
277ee416d02Sjoris 	cf->file_status = FILE_SKIP;
278ee416d02Sjoris }
279ee416d02Sjoris 
280ee416d02Sjoris static void
281ee416d02Sjoris add_file(struct cvs_file *cf)
282ee416d02Sjoris {
2832ec286b3Sxsa 	int added, stop;
2840a7da307Sxsa 	char revbuf[CVS_REV_BUFSZ];
28508458e59Sjoris 	RCSNUM *head;
286ee416d02Sjoris 
287570941ffSjoris 	if (cf->file_rcs != NULL) {
288570941ffSjoris 		head = rcs_head_get(cf->file_rcs);
2899af0ab72Stobias 		if (head == NULL)
2909af0ab72Stobias 			fatal("RCS head empty or missing in %s\n",
2919af0ab72Stobias 			    cf->file_rcs->rf_path);
292570941ffSjoris 		rcsnum_tostr(head, revbuf, sizeof(revbuf));
293570941ffSjoris 		rcsnum_free(head);
294570941ffSjoris 	}
29519615a73Sjoris 
296932258d9Sxsa 	added = stop = 0;
29791e2b091Sjoris 	switch (cf->file_status) {
29891e2b091Sjoris 	case FILE_ADDED:
299932258d9Sxsa 		if (verbosity > 1)
30091e2b091Sjoris 			cvs_log(LP_NOTICE, "%s has already been entered",
30191e2b091Sjoris 			    cf->file_path);
30219615a73Sjoris 		stop = 1;
30319615a73Sjoris 		break;
304932258d9Sxsa 	case FILE_REMOVED:
305932258d9Sxsa 		if (cf->file_rcs == NULL) {
306932258d9Sxsa 			cvs_log(LP_NOTICE, "cannot resurrect %s; "
307932258d9Sxsa 			    "RCS file removed by second party", cf->file_name);
3088085e067Sjoris 		} else if (cf->fd == -1) {
3092ec286b3Sxsa 			add_entry(cf);
310932258d9Sxsa 
3112ec286b3Sxsa 			/* Restore the file. */
31208458e59Sjoris 			head = rcs_head_get(cf->file_rcs);
3139af0ab72Stobias 			if (head == NULL)
3149af0ab72Stobias 				fatal("RCS head empty or missing in %s\n",
3159af0ab72Stobias 				    cf->file_rcs->rf_path);
3165d320860Sjoris 			cvs_checkout_file(cf, head, NULL, 0);
317570941ffSjoris 			rcsnum_free(head);
318570941ffSjoris 
319932258d9Sxsa 			cvs_printf("U %s\n", cf->file_path);
320932258d9Sxsa 
321932258d9Sxsa 			cvs_log(LP_NOTICE, "%s, version %s, resurrected",
322932258d9Sxsa 			    cf->file_name, revbuf);
323932258d9Sxsa 
324932258d9Sxsa 			cf->file_status = FILE_UPTODATE;
325932258d9Sxsa 		}
326932258d9Sxsa 		stop = 1;
327932258d9Sxsa 		break;
328e10eccadSxsa 	case FILE_CONFLICT:
329e10eccadSxsa 	case FILE_LOST:
330e10eccadSxsa 	case FILE_MODIFIED:
33119615a73Sjoris 	case FILE_UPTODATE:
33219615a73Sjoris 		if (cf->file_rcs != NULL && cf->file_rcs->rf_dead == 0) {
33319615a73Sjoris 			cvs_log(LP_NOTICE, "%s already exists, with version "
33419615a73Sjoris 			     "number %s", cf->file_path, revbuf);
33519615a73Sjoris 			stop = 1;
33619615a73Sjoris 		}
33791e2b091Sjoris 		break;
33891e2b091Sjoris 	case FILE_UNKNOWN:
33919615a73Sjoris 		if (cf->file_rcs != NULL && cf->file_rcs->rf_dead == 1) {
34019615a73Sjoris 			cvs_log(LP_NOTICE, "re-adding file %s "
34119615a73Sjoris 			    "(instead of dead revision %s)",
34219615a73Sjoris 			    cf->file_path, revbuf);
3438085e067Sjoris 			added++;
3448085e067Sjoris 		} else if (cf->fd != -1) {
34519615a73Sjoris 			cvs_log(LP_NOTICE, "scheduling file '%s' for addition",
34691e2b091Sjoris 			    cf->file_path);
347c67fc6ccSjoris 			added++;
3488085e067Sjoris 		} else {
3498085e067Sjoris 			stop = 1;
3508085e067Sjoris 		}
35191e2b091Sjoris 		break;
35291e2b091Sjoris 	default:
35391e2b091Sjoris 		break;
35491e2b091Sjoris 	}
35519615a73Sjoris 
35619615a73Sjoris 	if (stop == 1)
35719615a73Sjoris 		return;
35819615a73Sjoris 
3592ec286b3Sxsa 	add_entry(cf);
36019615a73Sjoris 
361932258d9Sxsa 	if (added != 0) {
362932258d9Sxsa 		cvs_log(LP_NOTICE, "use '%s commit' to add %s "
363932258d9Sxsa 		    "permanently", __progname,
364932258d9Sxsa 		    (added == 1) ? "this file" : "these files");
365932258d9Sxsa 	}
36691e2b091Sjoris }
3672ec286b3Sxsa 
3682ec286b3Sxsa static void
3692ec286b3Sxsa add_entry(struct cvs_file *cf)
3702ec286b3Sxsa {
3712ec286b3Sxsa 	FILE *fp;
3720a7da307Sxsa 	char entry[CVS_ENT_MAXLINELEN], path[MAXPATHLEN];
3730a7da307Sxsa 	char revbuf[CVS_REV_BUFSZ], tbuf[CVS_TIME_BUFSZ];
3742ec286b3Sxsa 	CVSENTRIES *entlist;
3752ec286b3Sxsa 
3762ec286b3Sxsa 	if (cvs_noexec == 1)
3772ec286b3Sxsa 		return;
3782ec286b3Sxsa 
3792ec286b3Sxsa 	if (cf->file_status == FILE_REMOVED) {
3802ec286b3Sxsa 		rcsnum_tostr(cf->file_ent->ce_rev, revbuf, sizeof(revbuf));
3812ec286b3Sxsa 
3822ec286b3Sxsa 		ctime_r(&cf->file_ent->ce_mtime, tbuf);
3832820b891Stobias 		tbuf[strcspn(tbuf, "\n")] = '\0';
3842ec286b3Sxsa 
3852ec286b3Sxsa 		/* Remove the '-' prefixing the version number. */
386c486465dSxsa 		(void)xsnprintf(entry, CVS_ENT_MAXLINELEN,
38756f996a2Sxsa 		    "/%s/%s/%s/%s/", cf->file_name, revbuf, tbuf,
38856f996a2Sxsa 		    cf->file_ent->ce_opts ? cf->file_ent->ce_opts : "");
3892ec286b3Sxsa 	} else {
3902ec286b3Sxsa 		if (logmsg != NULL) {
391c486465dSxsa 			(void)xsnprintf(path, MAXPATHLEN, "%s/%s%s",
3922ec286b3Sxsa 			    CVS_PATH_CVSDIR, cf->file_name, CVS_DESCR_FILE_EXT);
3932ec286b3Sxsa 
3942ec286b3Sxsa 			if ((fp = fopen(path, "w+")) == NULL)
3952ec286b3Sxsa 				fatal("add_entry: fopen `%s': %s",
3962ec286b3Sxsa 				    path, strerror(errno));
3972ec286b3Sxsa 
3982ec286b3Sxsa 			if (fputs(logmsg, fp) == EOF) {
3992ec286b3Sxsa 				(void)unlink(path);
4002ec286b3Sxsa 				fatal("add_entry: fputs `%s': %s",
4012ec286b3Sxsa 				    path, strerror(errno));
4022ec286b3Sxsa 			}
4032ec286b3Sxsa 			(void)fclose(fp);
4042ec286b3Sxsa 		}
4052ec286b3Sxsa 
406c486465dSxsa 		(void)xsnprintf(entry, CVS_ENT_MAXLINELEN,
40756f996a2Sxsa 		    "/%s/0/Initial %s/%s/", cf->file_name, cf->file_name,
408*37fdff3fStobias 		    kflag ? kbuf : "");
4092ec286b3Sxsa 	}
4102ec286b3Sxsa 
4117bd344d4Stobias 	if (cvs_server_active) {
4127bd344d4Stobias 		cvs_server_send_response("Checked-in %s/", cf->file_wd);
4137bd344d4Stobias 		cvs_server_send_response(cf->file_path);
4147bd344d4Stobias 		cvs_server_send_response(entry);
4157bd344d4Stobias 	} else {
4162ec286b3Sxsa 		entlist = cvs_ent_open(cf->file_wd);
4172ec286b3Sxsa 		cvs_ent_add(entlist, entry);
4182ec286b3Sxsa 		cvs_ent_close(entlist, ENT_SYNC);
4192ec286b3Sxsa 	}
4207bd344d4Stobias }
421