[project @ 1996-07-19 18:36:04 by partain]
[ghc-hetmet.git] / glafp-utils / scripts / lndir.c-X11R5
1 /* $XConsortium: lndir.c,v 1.5 91/07/21 15:52:11 rws Exp $ */
2 /* Create shadow link tree (after X11R4 script of the same name)
3    Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
4
5 /* Copyright 1990, Massachusetts Institute of Technology
6
7    Permission to use, copy, modify, and distribute this program for any purpose
8    and without fee is hereby granted, provided that this copyright and
9    permission notice appear on all copies and supporting documentation, that
10    the name of MIT not be used in advertising or publicity pertaining to
11    distribution of this program without specific prior permission, and that
12    notice be given in supporting documentation that copying and distribution is
13    by permission of MIT.  MIT makes no representations about the suitability of
14    this software for any purpose.  It is provided "as is" without expressed or
15    implied warranty.
16 */
17
18 /* From the original /bin/sh script:
19
20    Used to create a copy of the a directory tree that has links for all
21    non-directories (except those named RCS or SCCS).  If you are
22    building the distribution on more than one machine, you should use
23    this script.
24
25    If your master sources are located in /usr/local/src/X and you would like
26    your link tree to be in /usr/local/src/new-X, do the following:
27
28         %  mkdir /usr/local/src/new-X
29         %  cd /usr/local/src/new-X
30         %  lndir ../X
31 */
32
33 #include <X11/Xos.h>
34 #include <stdio.h>
35 #include <sys/stat.h>
36 #include <sys/param.h>
37 #include <errno.h>
38
39 #ifndef X_NOT_POSIX
40 #include <dirent.h>
41 #else
42 #ifdef SYSV
43 #include <dirent.h>
44 #else
45 #ifdef USG
46 #include <dirent.h>
47 #else
48 #include <sys/dir.h>
49 #ifndef dirent
50 #define dirent direct
51 #endif
52 #endif
53 #endif
54 #endif
55
56 extern int errno;
57 int silent;
58
59 void
60 quit (code, fmt, a1, a2, a3)
61 char *fmt;
62 {
63     fprintf (stderr, fmt, a1, a2, a3);
64     putc ('\n', stderr);
65     exit (code);
66 }
67
68 void
69 quiterr (code, s)
70 char *s;
71 {
72     perror (s);
73     exit (code);
74 }
75
76 void
77 msg (fmt, a1, a2, a3)
78 char *fmt;
79 {
80     fprintf (stderr, fmt, a1, a2, a3);
81     putc ('\n', stderr);
82 }
83
84
85 /* Recursively create symbolic links from the current directory to the "from"
86    directory.  Assumes that files described by fs and ts are directories. */
87
88 dodir (fn, fs, ts, rel)
89 char *fn;                       /* name of "from" directory, either absolute or
90                                    relative to cwd */
91 struct stat *fs, *ts;           /* stats for the "from" directory and cwd */
92 int rel;                        /* if true, prepend "../" to fn before using */
93 {
94     DIR *df;
95     struct dirent *dp;
96     char buf[MAXPATHLEN + 1], *p;
97     char symbuf[MAXPATHLEN + 1];
98     struct stat sb, sc;
99     int n_dirs;
100
101     if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
102         msg ("%s: From and to directories are identical!", fn);
103         return 1;
104     }
105
106     if (rel)
107         strcpy (buf, "../");
108     else
109         buf[0] = '\0';
110     strcat (buf, fn);
111     
112     if (!(df = opendir (buf))) {
113         msg ("%s: Cannot opendir", buf);
114         return 1;
115     }
116
117     p = buf + strlen (buf);
118     *p++ = '/';
119     n_dirs = fs->st_nlink;
120     while (dp = readdir (df)) {
121         strcpy (p, dp->d_name);
122
123         if (n_dirs > 0) {
124             if (stat (buf, &sb) < 0) {
125                 perror (buf);
126                 continue;
127             }
128
129             if (sb.st_mode & S_IFDIR) {
130                 /* directory */
131                 n_dirs--;
132                 if (dp->d_name[0] == '.' &&
133                     (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' &&
134                                                dp->d_name[2] == '\0')))
135                     continue;
136                 if (!strcmp (dp->d_name, "RCS"))
137                     continue;
138                 if (!strcmp (dp->d_name, "SCCS"))
139                     continue;
140                 if (!silent)
141                     printf ("%s:\n", buf);
142                 if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
143                     if (mkdir (dp->d_name, 0777) < 0 ||
144                         stat (dp->d_name, &sc) < 0) {
145                         perror (dp->d_name);
146                         continue;
147                     }
148                 }
149                 if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
150                     msg ("%s: is a link instead of a directory\n", dp->d_name);
151                     continue;
152                 }
153                 if (chdir (dp->d_name) < 0) {
154                     perror (dp->d_name);
155                     continue;
156                 }
157                 dodir (buf, &sb, &sc, (buf[0] != '/'));
158                 if (chdir ("..") < 0)
159                     quiterr (1, "..");
160                 continue;
161             }
162         }
163
164         /* non-directory */
165         if (symlink (buf, dp->d_name) < 0) {
166             int saverrno = errno;
167             int symlen;
168             symlen = readlink(dp->d_name, symbuf, sizeof(symbuf) - 1);
169             errno = saverrno;
170             if (symlen > 0)
171                 symbuf[symlen] = '\0';
172             if (symlen < 0 || strcmp(symbuf, buf))
173                 perror (dp->d_name);
174         }
175     }
176
177     closedir (df);
178     return 0;
179 }
180
181
182 main (ac, av)
183 int ac;
184 char **av;
185 {
186     char *fn, *tn;
187     struct stat fs, ts;
188
189     silent = 0;
190     if (ac > 1 && !strcmp(av[1], "-silent")) {
191         silent = 1;
192     }
193     if (ac < silent + 2 || ac > silent + 3)
194         quit (1, "usage: %s [-silent] fromdir [todir]", av[0]);
195
196     fn = av[silent + 1];
197     if (ac == silent + 3)
198         tn = av[silent + 2];
199     else
200         tn = ".";
201
202     /* to directory */
203     if (stat (tn, &ts) < 0)
204         quiterr (1, tn);
205     if (!(ts.st_mode & S_IFDIR))
206         quit (2, "%s: Not a directory", tn);
207     if (chdir (tn) < 0)
208         quiterr (1, tn);
209
210     /* from directory */
211     if (stat (fn, &fs) < 0)
212         quiterr (1, fn);
213     if (!(fs.st_mode & S_IFDIR))
214         quit (2, "%s: Not a directory", fn);
215
216     exit (dodir (fn, &fs, &ts, 0));
217 }