| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: rcsprog.c,v 1.161 2016/07/04 01:39:12 millert Exp $ */  | 
    ||
2  | 
    /*  | 
    ||
3  | 
    * Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org>  | 
    ||
4  | 
    * All rights reserved.  | 
    ||
5  | 
    *  | 
    ||
6  | 
    * Redistribution and use in source and binary forms, with or without  | 
    ||
7  | 
    * modification, are permitted provided that the following conditions  | 
    ||
8  | 
    * are met:  | 
    ||
9  | 
    *  | 
    ||
10  | 
    * 1. Redistributions of source code must retain the above copyright  | 
    ||
11  | 
    * notice, this list of conditions and the following disclaimer.  | 
    ||
12  | 
    * 2. The name of the author may not be used to endorse or promote products  | 
    ||
13  | 
    * derived from this software without specific prior written permission.  | 
    ||
14  | 
    *  | 
    ||
15  | 
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,  | 
    ||
16  | 
    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY  | 
    ||
17  | 
    * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  | 
    ||
18  | 
    * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  | 
    ||
19  | 
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  | 
    ||
20  | 
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  | 
    ||
21  | 
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  | 
    ||
22  | 
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  | 
    ||
23  | 
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  | 
    ||
24  | 
    * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
    ||
25  | 
    */  | 
    ||
26  | 
    |||
27  | 
    #include <sys/stat.h>  | 
    ||
28  | 
    |||
29  | 
    #include <err.h>  | 
    ||
30  | 
    #include <signal.h>  | 
    ||
31  | 
    #include <stdio.h>  | 
    ||
32  | 
    #include <stdlib.h>  | 
    ||
33  | 
    #include <string.h>  | 
    ||
34  | 
    #include <unistd.h>  | 
    ||
35  | 
    |||
36  | 
    #include "rcsprog.h"  | 
    ||
37  | 
    |||
38  | 
    #define RCSPROG_OPTSTRING "A:a:b::c:e::Iik:Ll::m:Mn:N:o:qt::TUu::Vx::z::"  | 
    ||
39  | 
    |||
40  | 
    const char rcs_version[] = "OpenRCS 4.5";  | 
    ||
41  | 
    |||
42  | 
    int rcsflags;  | 
    ||
43  | 
    int rcs_optind;  | 
    ||
44  | 
    char *rcs_optarg;  | 
    ||
45  | 
    char *rcs_suffixes = RCS_DEFAULT_SUFFIX;  | 
    ||
46  | 
    char *rcs_tmpdir = RCS_TMPDIR_DEFAULT;  | 
    ||
47  | 
    |||
48  | 
    struct rcs_prog { | 
    ||
49  | 
    char *prog_name;  | 
    ||
50  | 
    int (*prog_hdlr)(int, char **);  | 
    ||
51  | 
    void (*prog_usage)(void);  | 
    ||
52  | 
    } programs[] = { | 
    ||
53  | 
    	{ "rcs",	rcs_main,	rcs_usage	}, | 
    ||
54  | 
    	{ "ci",		checkin_main,	checkin_usage   }, | 
    ||
55  | 
    	{ "co",		checkout_main,	checkout_usage  }, | 
    ||
56  | 
    	{ "rcsclean",	rcsclean_main,	rcsclean_usage	}, | 
    ||
57  | 
    	{ "rcsdiff",	rcsdiff_main,	rcsdiff_usage	}, | 
    ||
58  | 
    	{ "rcsmerge",	rcsmerge_main,	rcsmerge_usage	}, | 
    ||
59  | 
    	{ "rlog",	rlog_main,	rlog_usage	}, | 
    ||
60  | 
    	{ "ident",	ident_main,	ident_usage	}, | 
    ||
61  | 
    	{ "merge",	merge_main,	merge_usage	}, | 
    ||
62  | 
    };  | 
    ||
63  | 
    |||
64  | 
    struct wklhead temp_files;  | 
    ||
65  | 
    |||
66  | 
    void sighdlr(int);  | 
    ||
67  | 
    static void rcs_attach_symbol(RCSFILE *, const char *);  | 
    ||
68  | 
    |||
69  | 
    /* ARGSUSED */  | 
    ||
70  | 
    void  | 
    ||
71  | 
    sighdlr(int sig)  | 
    ||
72  | 
    { | 
    ||
73  | 
    worklist_clean(&temp_files, worklist_unlink);  | 
    ||
74  | 
    _exit(1);  | 
    ||
75  | 
    }  | 
    ||
76  | 
    |||
77  | 
    int  | 
    ||
78  | 
    build_cmd(char ***cmd_argv, char **argv, int argc)  | 
    ||
79  | 
    { | 
    ||
80  | 
    int cmd_argc, i, cur;  | 
    ||
81  | 
    356  | 
    char *cp, *rcsinit, *linebuf, *lp;  | 
    |
82  | 
    |||
83  | 
    ✓✓ | 178  | 
    	if ((rcsinit = getenv("RCSINIT")) == NULL) { | 
    
84  | 
    177  | 
    *cmd_argv = argv;  | 
    |
85  | 
    177  | 
    return argc;  | 
    |
86  | 
    }  | 
    ||
87  | 
    |||
88  | 
    1  | 
    cur = argc + 2;  | 
    |
89  | 
    cmd_argc = 0;  | 
    ||
90  | 
    1  | 
    *cmd_argv = xcalloc(cur, sizeof(char *));  | 
    |
91  | 
    1  | 
    (*cmd_argv)[cmd_argc++] = argv[0];  | 
    |
92  | 
    |||
93  | 
    1  | 
    linebuf = xstrdup(rcsinit);  | 
    |
94  | 
    ✓✓ | 4  | 
    	for (lp = linebuf; lp != NULL;) { | 
    
95  | 
    1  | 
    cp = strsep(&lp, " \t\b\f\n\r\t\v");  | 
    |
96  | 
    ✓✗ | 1  | 
    if (cp == NULL)  | 
    
97  | 
    break;  | 
    ||
98  | 
    ✗✓ | 1  | 
    if (*cp == '\0')  | 
    
99  | 
    continue;  | 
    ||
100  | 
    |||
101  | 
    ✗✓ | 1  | 
    		if (cmd_argc == cur) { | 
    
102  | 
    cur += 8;  | 
    ||
103  | 
    *cmd_argv = xreallocarray(*cmd_argv, cur,  | 
    ||
104  | 
    sizeof(char *));  | 
    ||
105  | 
    }  | 
    ||
106  | 
    |||
107  | 
    1  | 
    (*cmd_argv)[cmd_argc++] = cp;  | 
    |
108  | 
    }  | 
    ||
109  | 
    |||
110  | 
    ✗✓ | 1  | 
    	if (cmd_argc + argc > cur) { | 
    
111  | 
    cur = cmd_argc + argc + 1;  | 
    ||
112  | 
    *cmd_argv = xreallocarray(*cmd_argv, cur,  | 
    ||
113  | 
    sizeof(char *));  | 
    ||
114  | 
    }  | 
    ||
115  | 
    |||
116  | 
    ✓✓ | 6  | 
    for (i = 1; i < argc; i++)  | 
    
117  | 
    2  | 
    (*cmd_argv)[cmd_argc++] = argv[i];  | 
    |
118  | 
    |||
119  | 
    1  | 
    (*cmd_argv)[cmd_argc] = NULL;  | 
    |
120  | 
    |||
121  | 
    1  | 
    return cmd_argc;  | 
    |
122  | 
    178  | 
    }  | 
    |
123  | 
    |||
124  | 
    int  | 
    ||
125  | 
    main(int argc, char **argv)  | 
    ||
126  | 
    { | 
    ||
127  | 
    u_int i;  | 
    ||
128  | 
    356  | 
    char **cmd_argv;  | 
    |
129  | 
    int ret, cmd_argc;  | 
    ||
130  | 
    |||
131  | 
    ✗✓ | 178  | 
    	if (pledge("stdio rpath wpath cpath fattr flock getpw", NULL) == -1) | 
    
132  | 
    err(2, "pledge");  | 
    ||
133  | 
    |||
134  | 
    ret = -1;  | 
    ||
135  | 
    178  | 
    rcs_optind = 1;  | 
    |
136  | 
    178  | 
    SLIST_INIT(&temp_files);  | 
    |
137  | 
    |||
138  | 
    178  | 
    cmd_argc = build_cmd(&cmd_argv, argv, argc);  | 
    |
139  | 
    |||
140  | 
    178  | 
    	if ((rcs_tmpdir = getenv("TMPDIR")) == NULL) | 
    |
141  | 
    178  | 
    rcs_tmpdir = RCS_TMPDIR_DEFAULT;  | 
    |
142  | 
    |||
143  | 
    178  | 
    signal(SIGHUP, sighdlr);  | 
    |
144  | 
    178  | 
    signal(SIGINT, sighdlr);  | 
    |
145  | 
    178  | 
    signal(SIGQUIT, sighdlr);  | 
    |
146  | 
    178  | 
    signal(SIGABRT, sighdlr);  | 
    |
147  | 
    178  | 
    signal(SIGALRM, sighdlr);  | 
    |
148  | 
    178  | 
    signal(SIGTERM, sighdlr);  | 
    |
149  | 
    |||
150  | 
    ✓✗ | 1102  | 
    for (i = 0; i < (sizeof(programs)/sizeof(programs[0])); i++)  | 
    
151  | 
    ✓✓ | 551  | 
    		if (strcmp(__progname, programs[i].prog_name) == 0) { | 
    
152  | 
    178  | 
    usage = programs[i].prog_usage;  | 
    |
153  | 
    178  | 
    ret = programs[i].prog_hdlr(cmd_argc, cmd_argv);  | 
    |
154  | 
    178  | 
    break;  | 
    |
155  | 
    }  | 
    ||
156  | 
    |||
157  | 
    /* clean up temporary files */  | 
    ||
158  | 
    worklist_run(&temp_files, worklist_unlink);  | 
    ||
159  | 
    |||
160  | 
    exit(ret);  | 
    ||
161  | 
    }  | 
    ||
162  | 
    |||
163  | 
    |||
164  | 
    __dead void  | 
    ||
165  | 
    rcs_usage(void)  | 
    ||
166  | 
    { | 
    ||
167  | 
    fprintf(stderr,  | 
    ||
168  | 
    "usage: rcs [-IiLqTUV] [-Aoldfile] [-ausers] [-b[rev]]\n"  | 
    ||
169  | 
    " [-cstring] [-e[users]] [-kmode] [-l[rev]] [-mrev:msg]\n"  | 
    ||
170  | 
    " [-orev] [-t[str]] [-u[rev]] [-xsuffixes] file ...\n");  | 
    ||
171  | 
    |||
172  | 
    exit(1);  | 
    ||
173  | 
    }  | 
    ||
174  | 
    |||
175  | 
    /*  | 
    ||
176  | 
    * rcs_main()  | 
    ||
177  | 
    *  | 
    ||
178  | 
    * Handler for the `rcs' program.  | 
    ||
179  | 
    * Returns 0 on success, or >0 on error.  | 
    ||
180  | 
    */  | 
    ||
181  | 
    int  | 
    ||
182  | 
    rcs_main(int argc, char **argv)  | 
    ||
183  | 
    { | 
    ||
184  | 
    int fd;  | 
    ||
185  | 
    int i, j, ch, flags, kflag, lkmode;  | 
    ||
186  | 
    const char *nflag, *oldfilename, *orange;  | 
    ||
187  | 
    58  | 
    char fpath[PATH_MAX];  | 
    |
188  | 
    char *logstr, *logmsg, *descfile;  | 
    ||
189  | 
    char *alist, *comment, *elist, *lrev, *urev;  | 
    ||
190  | 
    mode_t fmode;  | 
    ||
191  | 
    RCSFILE *file;  | 
    ||
192  | 
    RCSNUM *logrev;  | 
    ||
193  | 
    struct rcs_access *acp;  | 
    ||
194  | 
    time_t rcs_mtime = -1;  | 
    ||
195  | 
    |||
196  | 
    kflag = RCS_KWEXP_ERR;  | 
    ||
197  | 
    lkmode = RCS_LOCK_INVAL;  | 
    ||
198  | 
    fmode = S_IRUSR|S_IRGRP|S_IROTH;  | 
    ||
199  | 
    flags = RCS_RDWR|RCS_PARSE_FULLY;  | 
    ||
200  | 
    lrev = urev = descfile = NULL;  | 
    ||
201  | 
    logstr = alist = comment = elist = NULL;  | 
    ||
202  | 
    nflag = oldfilename = orange = NULL;  | 
    ||
203  | 
    |||
204  | 
    /* match GNU */  | 
    ||
205  | 
    ✓✗✗✓ | 
    58  | 
    if (1 < argc && argv[1][0] != '-')  | 
    
206  | 
    		warnx("warning: No options were given; " | 
    ||
207  | 
    "this usage is obsolescent.");  | 
    ||
208  | 
    |||
209  | 
    ✓✓ | 92  | 
    	while ((ch = rcs_getopt(argc, argv, RCSPROG_OPTSTRING)) != -1) { | 
    
210  | 
    ✗✓✓✓ ✗✓✗✓ ✗✗✓✓ ✗✗✓✓ ✓✗✗✓ ✗✗✗  | 
    126  | 
    		switch (ch) { | 
    
211  | 
    case 'A':  | 
    ||
212  | 
    1  | 
    oldfilename = rcs_optarg;  | 
    |
213  | 
    1  | 
    rcsflags |= CO_ACLAPPEND;  | 
    |
214  | 
    1  | 
    break;  | 
    |
215  | 
    case 'a':  | 
    ||
216  | 
    3  | 
    alist = rcs_optarg;  | 
    |
217  | 
    3  | 
    break;  | 
    |
218  | 
    case 'c':  | 
    ||
219  | 
    comment = rcs_optarg;  | 
    ||
220  | 
    break;  | 
    ||
221  | 
    case 'e':  | 
    ||
222  | 
    1  | 
    elist = rcs_optarg;  | 
    |
223  | 
    1  | 
    rcsflags |= RCSPROG_EFLAG;  | 
    |
224  | 
    1  | 
    break;  | 
    |
225  | 
    case 'I':  | 
    ||
226  | 
    rcsflags |= INTERACTIVE;  | 
    ||
227  | 
    break;  | 
    ||
228  | 
    case 'i':  | 
    ||
229  | 
    10  | 
    flags |= RCS_CREATE;  | 
    |
230  | 
    10  | 
    break;  | 
    |
231  | 
    case 'k':  | 
    ||
232  | 
    kflag = rcs_kflag_get(rcs_optarg);  | 
    ||
233  | 
    			if (RCS_KWEXP_INVAL(kflag)) { | 
    ||
234  | 
    				warnx("invalid RCS keyword substitution mode"); | 
    ||
235  | 
    (usage)();  | 
    ||
236  | 
    }  | 
    ||
237  | 
    break;  | 
    ||
238  | 
    case 'L':  | 
    ||
239  | 
    if (lkmode == RCS_LOCK_LOOSE)  | 
    ||
240  | 
    				warnx("-U overridden by -L"); | 
    ||
241  | 
    lkmode = RCS_LOCK_STRICT;  | 
    ||
242  | 
    break;  | 
    ||
243  | 
    case 'l':  | 
    ||
244  | 
    ✗✓ | 6  | 
    if (rcsflags & RCSPROG_UFLAG)  | 
    
245  | 
    				warnx("-u overridden by -l"); | 
    ||
246  | 
    6  | 
    lrev = rcs_optarg;  | 
    |
247  | 
    6  | 
    rcsflags &= ~RCSPROG_UFLAG;  | 
    |
248  | 
    6  | 
    rcsflags |= RCSPROG_LFLAG;  | 
    |
249  | 
    6  | 
    break;  | 
    |
250  | 
    case 'm':  | 
    ||
251  | 
    2  | 
    free(logstr);  | 
    |
252  | 
    2  | 
    logstr = xstrdup(rcs_optarg);  | 
    |
253  | 
    2  | 
    break;  | 
    |
254  | 
    case 'M':  | 
    ||
255  | 
    /* ignore for the moment */  | 
    ||
256  | 
    break;  | 
    ||
257  | 
    case 'n':  | 
    ||
258  | 
    nflag = rcs_optarg;  | 
    ||
259  | 
    break;  | 
    ||
260  | 
    case 'N':  | 
    ||
261  | 
    nflag = rcs_optarg;  | 
    ||
262  | 
    rcsflags |= RCSPROG_NFLAG;  | 
    ||
263  | 
    break;  | 
    ||
264  | 
    case 'o':  | 
    ||
265  | 
    1  | 
    orange = rcs_optarg;  | 
    |
266  | 
    1  | 
    break;  | 
    |
267  | 
    case 'q':  | 
    ||
268  | 
    29  | 
    rcsflags |= QUIET;  | 
    |
269  | 
    29  | 
    break;  | 
    |
270  | 
    case 't':  | 
    ||
271  | 
    5  | 
    descfile = rcs_optarg;  | 
    |
272  | 
    5  | 
    rcsflags |= DESCRIPTION;  | 
    |
273  | 
    5  | 
    break;  | 
    |
274  | 
    case 'T':  | 
    ||
275  | 
    rcsflags |= PRESERVETIME;  | 
    ||
276  | 
    break;  | 
    ||
277  | 
    case 'U':  | 
    ||
278  | 
    if (lkmode == RCS_LOCK_STRICT)  | 
    ||
279  | 
    				warnx("-L overridden by -U"); | 
    ||
280  | 
    lkmode = RCS_LOCK_LOOSE;  | 
    ||
281  | 
    break;  | 
    ||
282  | 
    case 'u':  | 
    ||
283  | 
    ✗✓ | 5  | 
    if (rcsflags & RCSPROG_LFLAG)  | 
    
284  | 
    				warnx("-l overridden by -u"); | 
    ||
285  | 
    5  | 
    urev = rcs_optarg;  | 
    |
286  | 
    5  | 
    rcsflags &= ~RCSPROG_LFLAG;  | 
    |
287  | 
    5  | 
    rcsflags |= RCSPROG_UFLAG;  | 
    |
288  | 
    5  | 
    break;  | 
    |
289  | 
    case 'V':  | 
    ||
290  | 
    			printf("%s\n", rcs_version); | 
    ||
291  | 
    exit(0);  | 
    ||
292  | 
    case 'x':  | 
    ||
293  | 
    /* Use blank extension if none given. */  | 
    ||
294  | 
    rcs_suffixes = rcs_optarg ? rcs_optarg : "";  | 
    ||
295  | 
    break;  | 
    ||
296  | 
    case 'z':  | 
    ||
297  | 
    /*  | 
    ||
298  | 
    * kept for compatibility  | 
    ||
299  | 
    */  | 
    ||
300  | 
    break;  | 
    ||
301  | 
    default:  | 
    ||
302  | 
    (usage)();  | 
    ||
303  | 
    }  | 
    ||
304  | 
    }  | 
    ||
305  | 
    |||
306  | 
    29  | 
    argc -= rcs_optind;  | 
    |
307  | 
    29  | 
    argv += rcs_optind;  | 
    |
308  | 
    |||
309  | 
    ✗✓ | 29  | 
    	if (argc == 0) { | 
    
310  | 
    		warnx("no input file"); | 
    ||
311  | 
    (usage)();  | 
    ||
312  | 
    }  | 
    ||
313  | 
    |||
314  | 
    ✓✓ | 112  | 
    	for (i = 0; i < argc; i++) { | 
    
315  | 
    29  | 
    fd = rcs_choosefile(argv[i], fpath, sizeof(fpath));  | 
    |
316  | 
    ✓✓✗✓ | 
    39  | 
    		if (fd < 0 && !(flags & RCS_CREATE)) { | 
    
317  | 
    			warn("%s", fpath); | 
    ||
318  | 
    continue;  | 
    ||
319  | 
    }  | 
    ||
320  | 
    |||
321  | 
    ✗✓ | 29  | 
    if (!(rcsflags & QUIET))  | 
    
322  | 
    (void)fprintf(stderr, "RCS file: %s\n", fpath);  | 
    ||
323  | 
    |||
324  | 
    ✗✓ | 29  | 
    		if ((file = rcs_open(fpath, fd, flags, fmode)) == NULL) { | 
    
325  | 
    close(fd);  | 
    ||
326  | 
    continue;  | 
    ||
327  | 
    }  | 
    ||
328  | 
    |||
329  | 
    ✓✓ | 29  | 
    		if (rcsflags & DESCRIPTION) { | 
    
330  | 
    ✗✓ | 5  | 
    			if (rcs_set_description(file, descfile, rcsflags) == -1) { | 
    
331  | 
    				warn("%s", descfile); | 
    ||
332  | 
    rcs_close(file);  | 
    ||
333  | 
    continue;  | 
    ||
334  | 
    }  | 
    ||
335  | 
    }  | 
    ||
336  | 
    ✓✓ | 24  | 
    		else if (flags & RCS_CREATE) { | 
    
337  | 
    ✗✓ | 5  | 
    			if (rcs_set_description(file, NULL, rcsflags) == -1) { | 
    
338  | 
    				warn("stdin"); | 
    ||
339  | 
    rcs_close(file);  | 
    ||
340  | 
    continue;  | 
    ||
341  | 
    }  | 
    ||
342  | 
    }  | 
    ||
343  | 
    |||
344  | 
    ✗✓ | 29  | 
    if (rcsflags & PRESERVETIME)  | 
    
345  | 
    rcs_mtime = rcs_get_mtime(file);  | 
    ||
346  | 
    |||
347  | 
    ✗✓ | 29  | 
    if (nflag != NULL)  | 
    
348  | 
    rcs_attach_symbol(file, nflag);  | 
    ||
349  | 
    |||
350  | 
    ✓✓ | 29  | 
    		if (logstr != NULL) { | 
    
351  | 
    ✗✓ | 2  | 
    			if ((logmsg = strchr(logstr, ':')) == NULL) { | 
    
352  | 
    				warnx("missing log message"); | 
    ||
353  | 
    rcs_close(file);  | 
    ||
354  | 
    continue;  | 
    ||
355  | 
    }  | 
    ||
356  | 
    |||
357  | 
    2  | 
    *logmsg++ = '\0';  | 
    |
358  | 
    ✗✓ | 2  | 
    			if ((logrev = rcsnum_parse(logstr)) == NULL) { | 
    
359  | 
    				warnx("`%s' bad revision number", logstr); | 
    ||
360  | 
    rcs_close(file);  | 
    ||
361  | 
    continue;  | 
    ||
362  | 
    }  | 
    ||
363  | 
    |||
364  | 
    ✗✓ | 2  | 
    			if (rcs_rev_setlog(file, logrev, logmsg) < 0) { | 
    
365  | 
    				warnx("failed to set logmsg for `%s' to `%s'", | 
    ||
366  | 
    logstr, logmsg);  | 
    ||
367  | 
    rcs_close(file);  | 
    ||
368  | 
    rcsnum_free(logrev);  | 
    ||
369  | 
    continue;  | 
    ||
370  | 
    }  | 
    ||
371  | 
    |||
372  | 
    2  | 
    rcsnum_free(logrev);  | 
    |
373  | 
    2  | 
    }  | 
    |
374  | 
    |||
375  | 
    /* entries to add from <oldfile> */  | 
    ||
376  | 
    ✓✓ | 29  | 
    		if (rcsflags & CO_ACLAPPEND) { | 
    
377  | 
    RCSFILE *oldfile;  | 
    ||
378  | 
    int ofd;  | 
    ||
379  | 
    1  | 
    char ofpath[PATH_MAX];  | 
    |
380  | 
    |||
381  | 
    1  | 
    ofd = rcs_choosefile(oldfilename, ofpath, sizeof(ofpath));  | 
    |
382  | 
    ✗✓ | 1  | 
    			if (ofd < 0) { | 
    
383  | 
    if (!(flags & RCS_CREATE))  | 
    ||
384  | 
    					warn("%s", ofpath); | 
    ||
385  | 
    exit(1);  | 
    ||
386  | 
    }  | 
    ||
387  | 
    ✗✓ | 1  | 
    if ((oldfile = rcs_open(ofpath, ofd, RCS_READ)) == NULL)  | 
    
388  | 
    exit(1);  | 
    ||
389  | 
    |||
390  | 
    ✓✓ | 8  | 
    TAILQ_FOREACH(acp, &(oldfile->rf_access), ra_list)  | 
    
391  | 
    3  | 
    rcs_access_add(file, acp->ra_name);  | 
    |
392  | 
    |||
393  | 
    1  | 
    rcs_close(oldfile);  | 
    |
394  | 
    1  | 
    (void)close(ofd);  | 
    |
395  | 
    1  | 
    }  | 
    |
396  | 
    |||
397  | 
    /* entries to add to the access list */  | 
    ||
398  | 
    ✓✓ | 29  | 
    		if (alist != NULL) { | 
    
399  | 
    struct rcs_argvector *aargv;  | 
    ||
400  | 
    |||
401  | 
    3  | 
    aargv = rcs_strsplit(alist, ",");  | 
    |
402  | 
    ✓✓ | 24  | 
    for (j = 0; aargv->argv[j] != NULL; j++)  | 
    
403  | 
    9  | 
    rcs_access_add(file, aargv->argv[j]);  | 
    |
404  | 
    |||
405  | 
    3  | 
    rcs_argv_destroy(aargv);  | 
    |
406  | 
    3  | 
    }  | 
    |
407  | 
    |||
408  | 
    ✗✓ | 29  | 
    if (comment != NULL)  | 
    
409  | 
    rcs_comment_set(file, comment);  | 
    ||
410  | 
    |||
411  | 
    ✓✓ | 29  | 
    		if (elist != NULL) { | 
    
412  | 
    struct rcs_argvector *eargv;  | 
    ||
413  | 
    |||
414  | 
    1  | 
    eargv = rcs_strsplit(elist, ",");  | 
    |
415  | 
    ✓✓ | 8  | 
    for (j = 0; eargv->argv[j] != NULL; j++)  | 
    
416  | 
    3  | 
    rcs_access_remove(file, eargv->argv[j]);  | 
    |
417  | 
    |||
418  | 
    1  | 
    rcs_argv_destroy(eargv);  | 
    |
419  | 
    ✗✓ | 29  | 
    		} else if (rcsflags & RCSPROG_EFLAG) { | 
    
420  | 
    struct rcs_access *rap;  | 
    ||
421  | 
    |||
422  | 
    /* XXX rcs_access_remove(file, NULL); ?? */  | 
    ||
423  | 
    			while (!TAILQ_EMPTY(&(file->rf_access))) { | 
    ||
424  | 
    rap = TAILQ_FIRST(&(file->rf_access));  | 
    ||
425  | 
    TAILQ_REMOVE(&(file->rf_access), rap, ra_list);  | 
    ||
426  | 
    free(rap->ra_name);  | 
    ||
427  | 
    free(rap);  | 
    ||
428  | 
    }  | 
    ||
429  | 
    /* not synced anymore */  | 
    ||
430  | 
    file->rf_flags &= ~RCS_SYNCED;  | 
    ||
431  | 
    }  | 
    ||
432  | 
    |||
433  | 
    29  | 
    rcs_kwexp_set(file, kflag);  | 
    |
434  | 
    |||
435  | 
    ✗✓ | 29  | 
    if (lkmode != RCS_LOCK_INVAL)  | 
    
436  | 
    (void)rcs_lock_setmode(file, lkmode);  | 
    ||
437  | 
    |||
438  | 
    ✓✓ | 29  | 
    		if (rcsflags & RCSPROG_LFLAG) { | 
    
439  | 
    RCSNUM *rev;  | 
    ||
440  | 
    const char *username;  | 
    ||
441  | 
    6  | 
    char rev_str[RCS_REV_BUFSZ];  | 
    |
442  | 
    |||
443  | 
    ✗✓ | 6  | 
    			if (file->rf_head == NULL) { | 
    
444  | 
    				warnx("%s contains no revisions", fpath); | 
    ||
445  | 
    rcs_close(file);  | 
    ||
446  | 
    continue;  | 
    ||
447  | 
    }  | 
    ||
448  | 
    |||
449  | 
    ✗✓ | 6  | 
    if ((username = getlogin()) == NULL)  | 
    
450  | 
    err(1, "getlogin");  | 
    ||
451  | 
    ✓✓ | 6  | 
    			if (lrev == NULL) { | 
    
452  | 
    3  | 
    rev = rcsnum_alloc();  | 
    |
453  | 
    3  | 
    rcsnum_cpy(file->rf_head, rev, 0);  | 
    |
454  | 
    ✗✓ | 6  | 
    			} else if ((rev = rcsnum_parse(lrev)) == NULL) { | 
    
455  | 
    				warnx("unable to unlock file"); | 
    ||
456  | 
    rcs_close(file);  | 
    ||
457  | 
    continue;  | 
    ||
458  | 
    }  | 
    ||
459  | 
    6  | 
    rcsnum_tostr(rev, rev_str, sizeof(rev_str));  | 
    |
460  | 
    /* Make sure revision exists. */  | 
    ||
461  | 
    ✓✓ | 6  | 
    if (rcs_findrev(file, rev) == NULL)  | 
    
462  | 
    errx(1, "%s: cannot lock nonexisting "  | 
    ||
463  | 
    "revision %s", fpath, rev_str);  | 
    ||
464  | 
    ✓✓✗✓ | 
    9  | 
    if (rcs_lock_add(file, username, rev) != -1 &&  | 
    
465  | 
    4  | 
    !(rcsflags & QUIET))  | 
    |
466  | 
    (void)fprintf(stderr, "%s locked\n", rev_str);  | 
    ||
467  | 
    5  | 
    rcsnum_free(rev);  | 
    |
468  | 
    ✓✗ | 10  | 
    }  | 
    
469  | 
    |||
470  | 
    ✓✓ | 28  | 
    		if (rcsflags & RCSPROG_UFLAG) { | 
    
471  | 
    RCSNUM *rev;  | 
    ||
472  | 
    const char *username;  | 
    ||
473  | 
    5  | 
    char rev_str[RCS_REV_BUFSZ];  | 
    |
474  | 
    |||
475  | 
    ✗✓ | 5  | 
    			if (file->rf_head == NULL) { | 
    
476  | 
    				warnx("%s contains no revisions", fpath); | 
    ||
477  | 
    rcs_close(file);  | 
    ||
478  | 
    continue;  | 
    ||
479  | 
    }  | 
    ||
480  | 
    |||
481  | 
    ✗✓ | 5  | 
    if ((username = getlogin()) == NULL)  | 
    
482  | 
    err(1, "getlogin");  | 
    ||
483  | 
    ✓✓ | 5  | 
    			if (urev == NULL) { | 
    
484  | 
    2  | 
    rev = rcsnum_alloc();  | 
    |
485  | 
    2  | 
    rcsnum_cpy(file->rf_head, rev, 0);  | 
    |
486  | 
    ✗✓ | 5  | 
    			} else if ((rev = rcsnum_parse(urev)) == NULL) { | 
    
487  | 
    				warnx("unable to unlock file"); | 
    ||
488  | 
    rcs_close(file);  | 
    ||
489  | 
    continue;  | 
    ||
490  | 
    }  | 
    ||
491  | 
    5  | 
    rcsnum_tostr(rev, rev_str, sizeof(rev_str));  | 
    |
492  | 
    /* Make sure revision exists. */  | 
    ||
493  | 
    ✓✓ | 5  | 
    if (rcs_findrev(file, rev) == NULL)  | 
    
494  | 
    errx(1, "%s: cannot unlock nonexisting "  | 
    ||
495  | 
    "revision %s", fpath, rev_str);  | 
    ||
496  | 
    ✓✓✗✓ | 
    5  | 
    if (rcs_lock_remove(file, username, rev) == -1 &&  | 
    
497  | 
    1  | 
    !(rcsflags & QUIET))  | 
    |
498  | 
    				warnx("%s: warning: No locks are set.", fpath); | 
    ||
499  | 
    			else { | 
    ||
500  | 
    ✗✓ | 4  | 
    if (!(rcsflags & QUIET))  | 
    
501  | 
    (void)fprintf(stderr,  | 
    ||
502  | 
    "%s unlocked\n", rev_str);  | 
    ||
503  | 
    }  | 
    ||
504  | 
    4  | 
    rcsnum_free(rev);  | 
    |
505  | 
    ✓✗ | 8  | 
    }  | 
    
506  | 
    |||
507  | 
    ✓✓ | 27  | 
    		if (orange != NULL) { | 
    
508  | 
    struct rcs_delta *rdp, *nrdp;  | 
    ||
509  | 
    1  | 
    char b[RCS_REV_BUFSZ];  | 
    |
510  | 
    |||
511  | 
    1  | 
    rcs_rev_select(file, orange);  | 
    |
512  | 
    ✓✓ | 14  | 
    for (rdp = TAILQ_FIRST(&(file->rf_delta));  | 
    
513  | 
    7  | 
    			    rdp != NULL; rdp = nrdp) { | 
    |
514  | 
    6  | 
    nrdp = TAILQ_NEXT(rdp, rd_list);  | 
    |
515  | 
    |||
516  | 
    /*  | 
    ||
517  | 
    * Delete selected revisions.  | 
    ||
518  | 
    */  | 
    ||
519  | 
    ✓✓ | 6  | 
    				if (rdp->rd_flags & RCS_RD_SELECT) { | 
    
520  | 
    3  | 
    rcsnum_tostr(rdp->rd_num, b, sizeof(b));  | 
    |
521  | 
    ✗✓ | 3  | 
    					if (!(rcsflags & QUIET)) { | 
    
522  | 
    (void)fprintf(stderr, "deleting"  | 
    ||
523  | 
    " revision %s\n", b);  | 
    ||
524  | 
    }  | 
    ||
525  | 
    3  | 
    (void)rcs_rev_remove(file, rdp->rd_num);  | 
    |
526  | 
    3  | 
    }  | 
    |
527  | 
    }  | 
    ||
528  | 
    1  | 
    }  | 
    |
529  | 
    |||
530  | 
    27  | 
    rcs_write(file);  | 
    |
531  | 
    |||
532  | 
    ✗✓ | 27  | 
    if (rcsflags & PRESERVETIME)  | 
    
533  | 
    rcs_set_mtime(file, rcs_mtime);  | 
    ||
534  | 
    |||
535  | 
    27  | 
    rcs_close(file);  | 
    |
536  | 
    |||
537  | 
    ✗✓ | 27  | 
    if (!(rcsflags & QUIET))  | 
    
538  | 
    (void)fprintf(stderr, "done\n");  | 
    ||
539  | 
    }  | 
    ||
540  | 
    |||
541  | 
    27  | 
    return (0);  | 
    |
542  | 
    27  | 
    }  | 
    |
543  | 
    |||
544  | 
    static void  | 
    ||
545  | 
    rcs_attach_symbol(RCSFILE *file, const char *symname)  | 
    ||
546  | 
    { | 
    ||
547  | 
    char *rnum;  | 
    ||
548  | 
    RCSNUM *rev;  | 
    ||
549  | 
    char rbuf[RCS_REV_BUFSZ];  | 
    ||
550  | 
    int rm;  | 
    ||
551  | 
    |||
552  | 
    rm = 0;  | 
    ||
553  | 
    rev = NULL;  | 
    ||
554  | 
    	if ((rnum = strrchr(symname, ':')) != NULL) { | 
    ||
555  | 
    if (rnum[1] == '\0')  | 
    ||
556  | 
    rev = file->rf_head;  | 
    ||
557  | 
    *(rnum++) = '\0';  | 
    ||
558  | 
    	} else { | 
    ||
559  | 
    rm = 1;  | 
    ||
560  | 
    }  | 
    ||
561  | 
    |||
562  | 
    	if (rev == NULL && rm != 1) { | 
    ||
563  | 
    if ((rev = rcsnum_parse(rnum)) == NULL)  | 
    ||
564  | 
    errx(1, "bad revision %s", rnum);  | 
    ||
565  | 
    }  | 
    ||
566  | 
    |||
567  | 
    if (rcsflags & RCSPROG_NFLAG)  | 
    ||
568  | 
    rm = 1;  | 
    ||
569  | 
    |||
570  | 
    	if (rm == 1) { | 
    ||
571  | 
    		if (rcs_sym_remove(file, symname) < 0) { | 
    ||
572  | 
    if (rcs_errno == RCS_ERR_NOENT &&  | 
    ||
573  | 
    !(rcsflags & RCSPROG_NFLAG))  | 
    ||
574  | 
    				warnx("cannot delete nonexisting symbol %s", | 
    ||
575  | 
    symname);  | 
    ||
576  | 
    		} else { | 
    ||
577  | 
    if (rcsflags & RCSPROG_NFLAG)  | 
    ||
578  | 
    rm = 0;  | 
    ||
579  | 
    }  | 
    ||
580  | 
    }  | 
    ||
581  | 
    |||
582  | 
    	if (rm == 0) { | 
    ||
583  | 
    if (rcs_sym_add(file, symname, rev) < 0 &&  | 
    ||
584  | 
    		    rcs_errno == RCS_ERR_DUPENT) { | 
    ||
585  | 
    rcsnum_tostr(rcs_sym_getrev(file, symname),  | 
    ||
586  | 
    rbuf, sizeof(rbuf));  | 
    ||
587  | 
    errx(1, "symbolic name %s already bound to %s",  | 
    ||
588  | 
    symname, rbuf);  | 
    ||
589  | 
    }  | 
    ||
590  | 
    }  | 
    ||
591  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |