Annotation of src/usr.bin/cvs/edit.c, Revision 1.20
1.20 ! xsa 1: /* $OpenBSD: edit.c,v 1.19 2007/01/05 08:52:37 xsa Exp $ */
1.1 jfb 2: /*
1.15 xsa 3: * Copyright (c) 2006, 2007 Xavier Santolaria <xsa@openbsd.org>
1.1 jfb 4: *
1.14 xsa 5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 jfb 16: */
17:
1.11 xsa 18: #include "includes.h"
1.1 jfb 19:
20: #include "cvs.h"
21: #include "log.h"
1.14 xsa 22: #include "remote.h"
1.1 jfb 23:
1.18 xsa 24: #define E_COMMIT 0x01
25: #define E_EDIT 0x02
26: #define E_UNEDIT 0x04
27: #define E_ALL (E_EDIT|E_COMMIT|E_UNEDIT)
28:
29: static void cvs_edit_local(struct cvs_file *);
1.14 xsa 30: static void cvs_editors_local(struct cvs_file *);
1.15 xsa 31: static void cvs_unedit_local(struct cvs_file *);
1.1 jfb 32:
1.18 xsa 33: static int edit_aflags = 0;
34:
35: struct cvs_cmd cvs_cmd_edit = {
36: CVS_OP_EDIT, 0, "edit",
37: { },
38: "Get ready to edit a watched file",
39: "[-lR] [-a action] [file ...]",
40: "a:lR",
41: NULL,
42: cvs_edit
43: };
44:
1.1 jfb 45: struct cvs_cmd cvs_cmd_editors = {
1.14 xsa 46: CVS_OP_EDITORS, 0, "editors",
1.1 jfb 47: { },
1.14 xsa 48: "See who is editing a watched file",
1.3 xsa 49: "[-lR] [file ...]",
1.1 jfb 50: "lR",
51: NULL,
1.14 xsa 52: cvs_editors
1.1 jfb 53: };
54:
1.15 xsa 55: struct cvs_cmd cvs_cmd_unedit = {
56: CVS_OP_UNEDIT, 0, "unedit",
57: { },
58: "Undo an edit command",
59: "[-lR] [file ...]",
60: "lR",
61: NULL,
62: cvs_unedit
63: };
64:
1.14 xsa 65: int
1.18 xsa 66: cvs_edit(int argc, char **argv)
67: {
68: int ch;
69: int flags;
70: struct cvs_recursion cr;
71:
72: flags = CR_RECURSE_DIRS;
73:
74: while ((ch = getopt(argc, argv, cvs_cmd_edit.cmd_opts)) != -1) {
75: switch (ch) {
76: case 'a':
77: if (strcmp(optarg, "edit") == 0)
78: edit_aflags |= E_EDIT;
79: else if (strcmp(optarg, "unedit") == 0)
80: edit_aflags |= E_UNEDIT;
81: else if (strcmp(optarg, "commit") == 0)
82: edit_aflags |= E_COMMIT;
83: else if (strcmp(optarg, "all") == 0)
84: edit_aflags |= E_ALL;
85: else if (strcmp(optarg, "none") == 0)
86: edit_aflags &= ~E_ALL;
87: else
88: fatal("%s", cvs_cmd_edit.cmd_synopsis);
89: break;
90: case 'l':
91: flags &= ~CR_RECURSE_DIRS;
92: break;
93: case 'R':
94: break;
95: default:
96: fatal("%s", cvs_cmd_edit.cmd_synopsis);
97: }
98: }
99:
100: argc -= optind;
101: argv += optind;
102:
103: if (argc == 0)
104: fatal("%s", cvs_cmd_edit.cmd_synopsis);
105:
106: if (edit_aflags == 0)
107: edit_aflags |= E_ALL;
108:
109: cr.enterdir = NULL;
110: cr.leavedir = NULL;
111:
112: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
113: cr.fileproc = cvs_client_sendfile;
114:
115: if (!(flags & CR_RECURSE_DIRS))
116: cvs_client_send_request("Argument -l");
117: } else {
118: cr.fileproc = cvs_edit_local;
119: }
120:
121: cr.flags = flags;
122:
123: cvs_file_run(argc, argv, &cr);
124:
125: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
126: cvs_client_send_files(argv, argc);
127: cvs_client_senddir(".");
128: cvs_client_send_request("edit");
129: cvs_client_get_responses();
130: }
131:
132: return (0);
133: }
134:
135: int
1.14 xsa 136: cvs_editors(int argc, char **argv)
1.1 jfb 137: {
1.12 xsa 138: int ch;
1.14 xsa 139: int flags;
140: struct cvs_recursion cr;
141:
142: flags = CR_RECURSE_DIRS;
1.1 jfb 143:
1.14 xsa 144: while ((ch = getopt(argc, argv, cvs_cmd_editors.cmd_opts)) != -1) {
1.1 jfb 145: switch (ch) {
146: case 'l':
1.14 xsa 147: flags &= ~CR_RECURSE_DIRS;
1.1 jfb 148: break;
149: case 'R':
150: break;
151: default:
1.14 xsa 152: fatal("%s", cvs_cmd_editors.cmd_synopsis);
1.1 jfb 153: }
154: }
155:
1.14 xsa 156: argc -= optind;
157: argv += optind;
1.1 jfb 158:
1.14 xsa 159: if (argc == 0)
160: fatal("%s", cvs_cmd_editors.cmd_synopsis);
1.1 jfb 161:
1.14 xsa 162: cr.enterdir = NULL;
163: cr.leavedir = NULL;
1.1 jfb 164:
1.14 xsa 165: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
166: cr.fileproc = cvs_client_sendfile;
167:
168: if (!(flags & CR_RECURSE_DIRS))
169: cvs_client_send_request("Argument -l");
170: } else {
171: cr.fileproc = cvs_editors_local;
172: }
1.1 jfb 173:
1.14 xsa 174: cr.flags = flags;
1.9 xsa 175:
1.14 xsa 176: cvs_file_run(argc, argv, &cr);
1.9 xsa 177:
1.14 xsa 178: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
179: cvs_client_send_files(argv, argc);
180: cvs_client_senddir(".");
181: cvs_client_send_request("editors");
182: cvs_client_get_responses();
1.9 xsa 183: }
184:
1.14 xsa 185: return (0);
186: }
1.9 xsa 187:
1.15 xsa 188: int
189: cvs_unedit(int argc, char **argv)
190: {
191: int ch;
192: int flags;
193: struct cvs_recursion cr;
194:
195: flags = CR_RECURSE_DIRS;
196:
197: while ((ch = getopt(argc, argv, cvs_cmd_unedit.cmd_opts)) != -1) {
198: switch (ch) {
199: case 'l':
200: flags &= ~CR_RECURSE_DIRS;
201: break;
202: case 'R':
203: break;
204: default:
205: fatal("%s", cvs_cmd_unedit.cmd_synopsis);
206: }
207: }
208:
209: argc -= optind;
210: argv += optind;
211:
212: if (argc == 0)
213: fatal("%s", cvs_cmd_unedit.cmd_synopsis);
214:
215: cr.enterdir = NULL;
216: cr.leavedir = NULL;
217:
218: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
219: cr.fileproc = cvs_client_sendfile;
220:
221: if (!(flags & CR_RECURSE_DIRS))
222: cvs_client_send_request("Argument -l");
223: } else {
224: cr.fileproc = cvs_unedit_local;
225: }
226:
227: cr.flags = flags;
228:
229: cvs_file_run(argc, argv, &cr);
230:
231: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
232: cvs_client_send_files(argv, argc);
233: cvs_client_senddir(".");
234: cvs_client_send_request("unedit");
235: cvs_client_get_responses();
236: }
237:
238: return (0);
1.18 xsa 239: }
240:
241: static void
242: cvs_edit_local(struct cvs_file *cf)
243: {
244: FILE *fp;
245: struct tm *t;
246: time_t now;
1.20 ! xsa 247: char *bfpath, timebuf[64], thishost[MAXHOSTNAMELEN];
1.18 xsa 248:
249: if (cvs_noexec == 1)
250: return;
251:
252: if ((fp = fopen(CVS_PATH_NOTIFY, "a")) == NULL)
253: fatal("cvs_edit_local: fopen: `%s': %s",
254: CVS_PATH_NOTIFY, strerror(errno));
255:
256: (void)time(&now);
257: if ((t = gmtime(&now)) == NULL)
258: fatal("gmtime failed");
259:
1.20 ! xsa 260: asctime_r(t, timebuf);
! 261: if (timebuf[strlen(timebuf) - 1] == '\n')
! 262: timebuf[strlen(timebuf) - 1] = '\0';
1.18 xsa 263:
1.19 xsa 264: if (gethostname(thishost, sizeof(thishost)) == -1)
265: fatal("gethostname failed");
266:
1.18 xsa 267: (void)fprintf(fp, "E%s\t%s GMT\t%s\t%s\t\n",
1.20 ! xsa 268: cf->file_name, timebuf, thishost, cf->file_wd);
1.18 xsa 269:
270: if (edit_aflags & E_EDIT)
271: (void)fprintf(fp, "E");
272: if (edit_aflags & E_UNEDIT)
273: (void)fprintf(fp, "U");
274: if (edit_aflags & E_COMMIT)
275: (void)fprintf(fp, "C");
276:
277: (void)fprintf(fp, "\n");
278:
279: (void)fclose(fp);
280:
281: if (fchmod(cf->fd, 0644) == -1)
282: fatal("cvs_edit_local: fchmod %s", strerror(errno));
283:
284: bfpath = xmalloc(MAXPATHLEN);
285: if (cvs_path_cat(CVS_PATH_BASEDIR, cf->file_name, bfpath,
286: MAXPATHLEN) >= MAXPATHLEN)
287: fatal("cvs_edit_local: truncation");
288:
289: /* XXX: copy cf->file_path to bfpath */
290:
291: xfree(bfpath);
292:
293: /* XXX: Update revision number in CVS/Baserev from CVS/Entries */
1.15 xsa 294: }
295:
1.14 xsa 296: static void
297: cvs_editors_local(struct cvs_file *cf)
298: {
1.15 xsa 299: }
300:
301: static void
302: cvs_unedit_local(struct cvs_file *cf)
303: {
304: FILE *fp;
305: struct stat st;
306: struct tm *t;
307: time_t now;
1.20 ! xsa 308: char *bfpath, timebuf[64], thishost[MAXHOSTNAMELEN];
1.15 xsa 309:
310: if (cvs_noexec == 1)
311: return;
312:
313: bfpath = xmalloc(MAXPATHLEN);
314: if (cvs_path_cat(CVS_PATH_BASEDIR, cf->file_name, bfpath,
315: MAXPATHLEN) >= MAXPATHLEN)
316: fatal("cvs_unedit_local: truncation");
317:
318: if (stat(bfpath, &st) == -1) {
319: xfree(bfpath);
320: return;
321: }
322:
1.17 xsa 323: if (cvs_file_cmp(cf->file_path, bfpath) != 0) {
324: cvs_printf("%s has been modified; revert changes? ",
325: cf->file_name);
326:
327: if (cvs_yesno() == -1) {
328: xfree(bfpath);
329: return;
330: }
331: }
1.15 xsa 332:
333: cvs_rename(bfpath, cf->file_path);
334: xfree(bfpath);
335:
336: if ((fp = fopen(CVS_PATH_NOTIFY, "a")) == NULL)
337: fatal("cvs_unedit_local: fopen: `%s': %s",
338: CVS_PATH_NOTIFY, strerror(errno));
339:
340: (void)time(&now);
341: if ((t = gmtime(&now)) == NULL)
342: fatal("gmtime failed");
343:
1.20 ! xsa 344: asctime_r(t, timebuf);
! 345: if (timebuf[strlen(timebuf) - 1] == '\n')
! 346: timebuf[strlen(timebuf) - 1] = '\0';
1.15 xsa 347:
1.19 xsa 348: if (gethostname(thishost, sizeof(thishost)) == -1)
349: fatal("gethostname failed");
350:
1.15 xsa 351: (void)fprintf(fp, "U%s\t%s GMT\t%s\t%s\t\n",
1.20 ! xsa 352: cf->file_name, timebuf, thishost, cf->file_wd);
1.15 xsa 353:
354: (void)fclose(fp);
355:
356: /* XXX: Update revision number in CVS/Entries from CVS/Baserev */
1.16 xsa 357:
358: if (fchmod(cf->fd, 0644) == -1)
359: fatal("cvs_unedit_local: fchmod %s", strerror(errno));
1.1 jfb 360: }