1 | /* co - check out Author: Peter S. Housel 12/24/87 */
|
---|
2 |
|
---|
3 | #include <sys/types.h>
|
---|
4 | #include <sys/stat.h>
|
---|
5 | #include <string.h>
|
---|
6 | #include <pwd.h>
|
---|
7 | #include <stdlib.h>
|
---|
8 | #include <unistd.h>
|
---|
9 | #include <stdio.h>
|
---|
10 |
|
---|
11 | #define SUFFIX ",S" /* svc indicator */
|
---|
12 | #define SVCDIR "SVC" /* svc postfix indicator */
|
---|
13 |
|
---|
14 | #define LINELEN 256 /* maximum line length */
|
---|
15 |
|
---|
16 | #ifdef MAXPATHLEN
|
---|
17 | #define PATHLEN MAXPATHLEN
|
---|
18 | #else
|
---|
19 | #define PATHLEN 128 /* buffer length for filenames */
|
---|
20 | #endif
|
---|
21 |
|
---|
22 | char file[PATHLEN]; /* file to be checked in */
|
---|
23 | char svc[PATHLEN]; /* filename for svc file */
|
---|
24 | char newsvc[PATHLEN]; /* new copy of SVC file */
|
---|
25 | char line[LINELEN]; /* temporary line buffer */
|
---|
26 | char *p; /* scratch character pointer */
|
---|
27 |
|
---|
28 | FILE *svcfp; /* svc file */
|
---|
29 | int rev; /* old revision number */
|
---|
30 | int lastrev, lockrev; /* latest file revision, lock into */
|
---|
31 | int status; /* wait() buffer */
|
---|
32 | int svclock; /* lock the SVC file */
|
---|
33 | struct stat stb; /* stat() buffer */
|
---|
34 | char *base; /* basename of file */
|
---|
35 |
|
---|
36 | char difftemp[PATHLEN]; /* extract() fix/patch input */
|
---|
37 |
|
---|
38 | _PROTOTYPE(int main, (int argc, char **argv));
|
---|
39 | _PROTOTYPE(void fname, (char *src, char *dst));
|
---|
40 | _PROTOTYPE(void svcname, (char *src, char *dst));
|
---|
41 | _PROTOTYPE(void extract, (char *script, char *out, int rev));
|
---|
42 | _PROTOTYPE(char *basename, (char *name));
|
---|
43 | _PROTOTYPE(char *whoami, (void));
|
---|
44 | _PROTOTYPE(int getyn, (void));
|
---|
45 |
|
---|
46 | int main(argc, argv)
|
---|
47 | int argc;
|
---|
48 | char **argv;
|
---|
49 | {
|
---|
50 | #ifdef perprintf
|
---|
51 | char errbuf[BUFSIZ];
|
---|
52 | setbuf(stderr, errbuf);
|
---|
53 | perprintf(stderr);
|
---|
54 | #endif
|
---|
55 |
|
---|
56 | while (++argv, --argc) {
|
---|
57 | if ('-' == (*argv)[0]) {
|
---|
58 | if ('r' == (*argv)[1]) {
|
---|
59 | --argc;
|
---|
60 | rev = atoi(*++argv);
|
---|
61 | if (rev < 1) {
|
---|
62 | fprintf(stderr, "Illegal revision number\n");
|
---|
63 | exit(1);
|
---|
64 | }
|
---|
65 | } else if ('l' == (*argv)[1])
|
---|
66 | ++svclock;
|
---|
67 | else {
|
---|
68 | fprintf(stderr, "co: illegal option -%c\n", (*argv)[1]);
|
---|
69 | exit(1);
|
---|
70 | }
|
---|
71 | } else
|
---|
72 | break;
|
---|
73 | }
|
---|
74 |
|
---|
75 | if (1 != argc) {
|
---|
76 | fprintf(stderr, "co: bad number of files arguments\n");
|
---|
77 | exit(1);
|
---|
78 | }
|
---|
79 | fname(*argv, file);
|
---|
80 | svcname(file, svc);
|
---|
81 |
|
---|
82 | fprintf(stderr, "%s -> %s\n", svc, base = basename(file));
|
---|
83 |
|
---|
84 | if (NULL == (svcfp = fopen(svc, "r"))) {
|
---|
85 | perror("co: can't read SVC file");
|
---|
86 | exit(1);
|
---|
87 | }
|
---|
88 | if (1 != fscanf(svcfp, "# %d", &lastrev) || lastrev < 1) {
|
---|
89 | fprintf(stderr, "co: illegal SVC file format\n");
|
---|
90 | exit(1);
|
---|
91 | }
|
---|
92 | fclose(svcfp);
|
---|
93 |
|
---|
94 | if (stat(base, &stb) >= 0 && (stb.st_mode & 0222)) {
|
---|
95 | fprintf(stderr, "Writable %s exists - overwrite (n/y)? ", base);
|
---|
96 | if (!getyn()) {
|
---|
97 | fprintf(stderr, "Checkout aborted\n");
|
---|
98 | exit(1);
|
---|
99 | }
|
---|
100 | }
|
---|
101 | if (strlen(base)) unlink(base);
|
---|
102 | if (0 == rev) rev = lastrev;
|
---|
103 | fprintf(stderr, "Checking out revision %d", rev);
|
---|
104 | extract(svc, base, rev);
|
---|
105 |
|
---|
106 | if (svclock) {
|
---|
107 | lockrev = lastrev + 1;
|
---|
108 | fprintf(stderr, "; Locking into revision %d\n", lockrev);
|
---|
109 | if (stat(svc, &stb) < 0 || chmod(svc, stb.st_mode | 0200) < 0)
|
---|
110 | perror("co: can't chmod SVC file");
|
---|
111 |
|
---|
112 | if (stat(base, &stb) < 0 || chmod(base, stb.st_mode | 0200) < 0)
|
---|
113 | perror("co: can't chmod source file");
|
---|
114 |
|
---|
115 | if (NULL == (svcfp = fopen(svc, "a"))
|
---|
116 | || (fprintf(svcfp, "#***SVCLOCK*** %s %d\n", whoami(), lockrev), ferror(svcfp))) {
|
---|
117 | fprintf(stderr, "co: can't lock %s\n", svc);
|
---|
118 | exit(1);
|
---|
119 | }
|
---|
120 | if (stat(svc, &stb) < 0 || chmod(svc, stb.st_mode & 0555))
|
---|
121 | perror("co: can't chmod SVC file");
|
---|
122 | } else {
|
---|
123 | putchar('\n');
|
---|
124 | if (stat(base, &stb) < 0 || chmod(base, stb.st_mode & 0555))
|
---|
125 | perror("co: can't chmod source file");
|
---|
126 | }
|
---|
127 |
|
---|
128 | return(0);
|
---|
129 | }
|
---|
130 |
|
---|
131 |
|
---|
132 | void fname(src, dst)
|
---|
133 | char *src, *dst;
|
---|
134 | {
|
---|
135 | char *p;
|
---|
136 | strcpy(dst, src);
|
---|
137 | p = &dst[strlen(src) - strlen(SUFFIX)];
|
---|
138 | if (!strcmp(p, SUFFIX)) *p = '\0';
|
---|
139 | }
|
---|
140 |
|
---|
141 | void svcname(src, dst)
|
---|
142 | char *src, *dst;
|
---|
143 | {
|
---|
144 | char *p;
|
---|
145 |
|
---|
146 | strcpy(dst, src);
|
---|
147 | strcat(dst, SUFFIX);
|
---|
148 |
|
---|
149 | if (0 != access(dst, 4)) {
|
---|
150 | char dirname[PATHLEN];
|
---|
151 | if (NULL != (p = strrchr(src, '/')))
|
---|
152 | strncpy(dirname, src, (size_t)(p - src) + 1);
|
---|
153 | else
|
---|
154 | dirname[0] = '\0';
|
---|
155 | strcat(dirname, SVCDIR);
|
---|
156 |
|
---|
157 | if (0 == access(dirname, 1)) {
|
---|
158 | strcpy(dst, dirname);
|
---|
159 | if (NULL == p) {
|
---|
160 | strcat(dst, "/");
|
---|
161 | strcat(dst, src);
|
---|
162 | } else
|
---|
163 | strcat(dst, p);
|
---|
164 | strcat(dst, SUFFIX);
|
---|
165 | }
|
---|
166 | }
|
---|
167 | }
|
---|
168 |
|
---|
169 | void extract(script, out, rev)
|
---|
170 | char *script, *out;
|
---|
171 | int rev;
|
---|
172 | {
|
---|
173 | FILE *outfp;
|
---|
174 | int testrev;
|
---|
175 | char buf[80];
|
---|
176 |
|
---|
177 | sprintf(difftemp, "Fix.%s", out);
|
---|
178 |
|
---|
179 | svcfp = fopen(script, "r");
|
---|
180 | fgets(line, LINELEN, svcfp); /* skip '# rev' line */
|
---|
181 | fgets(line, LINELEN, svcfp); /* skip 'cat <***MAIN-eof***' line */
|
---|
182 |
|
---|
183 | if (NULL == (outfp = fopen(out, "w"))) {
|
---|
184 | perror("co: can't create output file");
|
---|
185 | return;
|
---|
186 | }
|
---|
187 | while (NULL != fgets(line, LINELEN, svcfp) &&
|
---|
188 | strcmp(line, "***MAIN-eof***\n"))
|
---|
189 | fputs(line, outfp);
|
---|
190 |
|
---|
191 | fclose(outfp);
|
---|
192 |
|
---|
193 | while (NULL != fgets(line, LINELEN, svcfp)) {
|
---|
194 | if (!strncmp(line, "if ", (size_t)3)) {
|
---|
195 | sscanf(line, "if test $2 -ge %d", &testrev);
|
---|
196 | if (rev >= testrev) {
|
---|
197 | unlink(difftemp);
|
---|
198 | return;
|
---|
199 | }
|
---|
200 | if (NULL == (outfp = fopen(difftemp, "w"))) {
|
---|
201 | perror("co: can't create output file");
|
---|
202 | return;
|
---|
203 | }
|
---|
204 | sprintf(buf, "***%d-eof***\n", testrev);
|
---|
205 | while (NULL != fgets(line, LINELEN, svcfp) &&
|
---|
206 | strcmp(line, buf))
|
---|
207 | fputs(line, outfp);
|
---|
208 | fclose(outfp);
|
---|
209 | } else if (!strncmp(line, "mv ", (size_t)3)) {
|
---|
210 | sprintf(buf, "mv Fix.%s %s", out, out);
|
---|
211 | system(buf);
|
---|
212 | } else if (!strncmp(line, "fix ", (size_t)4)) {
|
---|
213 | sprintf(buf, "fix %s Fix.%s > New.%s; mv New.%s %s", out, out, out, out, out);
|
---|
214 | system(buf);
|
---|
215 | } else if (!strncmp(line, "patch ", (size_t)6)) {
|
---|
216 | sprintf(buf, "patch -n -s %s < Fix.%s; rm -f %s.orig", out, out, out);
|
---|
217 | system(buf);
|
---|
218 | } else { /* ignore */
|
---|
219 | }
|
---|
220 | }
|
---|
221 |
|
---|
222 | unlink(difftemp);
|
---|
223 | return;
|
---|
224 | }
|
---|
225 |
|
---|
226 | char *basename(name)
|
---|
227 | char *name;
|
---|
228 | {
|
---|
229 | char *p;
|
---|
230 |
|
---|
231 | if (NULL == (p = strrchr(name, '/')))
|
---|
232 | return name;
|
---|
233 | else
|
---|
234 | return p + 1;
|
---|
235 | }
|
---|
236 |
|
---|
237 | char *whoami()
|
---|
238 | {
|
---|
239 | struct passwd *pw;
|
---|
240 |
|
---|
241 | if (NULL != (pw = getpwuid(getuid())))
|
---|
242 | return pw->pw_name;
|
---|
243 | else
|
---|
244 | return "nobody";
|
---|
245 | }
|
---|
246 |
|
---|
247 | int getyn()
|
---|
248 | {
|
---|
249 | char ans[10];
|
---|
250 |
|
---|
251 | return(NULL != fgets(ans, 10, stdin)) && ('y' == ans[0] || 'Y' == ans[0]);
|
---|
252 | }
|
---|