mkfs: symlink support
[minix.git] / commands / co / co.c
blob4269c8b44fceab6ee20076327282d29e41e63336
1 /* co - check out Author: Peter S. Housel 12/24/87 */
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>
11 #define SUFFIX ",S" /* svc indicator */
12 #define SVCDIR "SVC" /* svc postfix indicator */
14 #define LINELEN 256 /* maximum line length */
16 #ifdef MAXPATHLEN
17 #define PATHLEN MAXPATHLEN
18 #else
19 #define PATHLEN 128 /* buffer length for filenames */
20 #endif
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 */
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 */
36 char difftemp[PATHLEN]; /* extract() fix/patch input */
38 int main(int argc, char **argv);
39 void fname(char *src, char *dst);
40 void svcname(char *src, char *dst);
41 void extract(char *script, char *out, int rev);
42 char *basename(char *name);
43 char *whoami(void);
44 int getyn(void);
46 int main(argc, argv)
47 int argc;
48 char **argv;
50 #ifdef perprintf
51 char errbuf[BUFSIZ];
52 setbuf(stderr, errbuf);
53 perprintf(stderr);
54 #endif
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);
65 } else if ('l' == (*argv)[1])
66 ++svclock;
67 else {
68 fprintf(stderr, "co: illegal option -%c\n", (*argv)[1]);
69 exit(1);
71 } else
72 break;
75 if (1 != argc) {
76 fprintf(stderr, "co: bad number of files arguments\n");
77 exit(1);
79 fname(*argv, file);
80 svcname(file, svc);
82 fprintf(stderr, "%s -> %s\n", svc, base = basename(file));
84 if (NULL == (svcfp = fopen(svc, "r"))) {
85 perror("co: can't read SVC file");
86 exit(1);
88 if (1 != fscanf(svcfp, "# %d", &lastrev) || lastrev < 1) {
89 fprintf(stderr, "co: illegal SVC file format\n");
90 exit(1);
92 fclose(svcfp);
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);
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);
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");
112 if (stat(base, &stb) < 0 || chmod(base, stb.st_mode | 0200) < 0)
113 perror("co: can't chmod source file");
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);
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");
128 return(0);
132 void fname(src, dst)
133 char *src, *dst;
135 char *p;
136 strcpy(dst, src);
137 p = &dst[strlen(src) - strlen(SUFFIX)];
138 if (!strcmp(p, SUFFIX)) *p = '\0';
141 void svcname(src, dst)
142 char *src, *dst;
144 char *p;
146 strcpy(dst, src);
147 strcat(dst, SUFFIX);
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);
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);
169 void extract(script, out, rev)
170 char *script, *out;
171 int rev;
173 FILE *outfp;
174 int testrev;
175 char buf[80];
177 sprintf(difftemp, "Fix.%s", out);
179 svcfp = fopen(script, "r");
180 fgets(line, LINELEN, svcfp); /* skip '# rev' line */
181 fgets(line, LINELEN, svcfp); /* skip 'cat <***MAIN-eof***' line */
183 if (NULL == (outfp = fopen(out, "w"))) {
184 perror("co: can't create output file");
185 return;
187 while (NULL != fgets(line, LINELEN, svcfp) &&
188 strcmp(line, "***MAIN-eof***\n"))
189 fputs(line, outfp);
191 fclose(outfp);
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;
200 if (NULL == (outfp = fopen(difftemp, "w"))) {
201 perror("co: can't create output file");
202 return;
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 */
222 unlink(difftemp);
223 return;
226 char *basename(name)
227 char *name;
229 char *p;
231 if (NULL == (p = strrchr(name, '/')))
232 return name;
233 else
234 return p + 1;
237 char *whoami()
239 struct passwd *pw;
241 if (NULL != (pw = getpwuid(getuid())))
242 return pw->pw_name;
243 else
244 return "nobody";
247 int getyn()
249 char ans[10];
251 return(NULL != fgets(ans, 10, stdin)) && ('y' == ans[0] || 'Y' == ans[0]);