Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / util / lndir.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: lndir.c /main/17 1998/02/06 11:23:50 kaleb $ */
24 /* Create shadow link tree (after X11R4 script of the same name)
25    Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
26
27 /* 
28 Copyright (c) 1990, 1998 The Open Group
29
30 All Rights Reserved.
31
32 The above copyright notice and this permission notice shall be included in
33 all copies or substantial portions of the Software.
34
35 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
38 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
39 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41
42 Except as contained in this notice, the name of The Open Group shall not be
43 used in advertising or otherwise to promote the sale, use or other dealings
44 in this Software without prior written authorization from The Open Group.
45
46 */
47
48 /* From the original /bin/sh script:
49
50   Used to create a copy of the a directory tree that has links for all
51   non-directories (except those named RCS, SCCS or CVS.adm).  If you are
52   building the distribution on more than one machine, you should use
53   this technique.
54
55   If your master sources are located in /usr/local/src/X and you would like
56   your link tree to be in /usr/local/src/new-X, do the following:
57
58         %  mkdir /usr/local/src/new-X
59         %  cd /usr/local/src/new-X
60         %  lndir ../X
61 */
62
63 #include <X11/Xos.h>
64 #include <X11/Xfuncproto.h>
65 #include <stdio.h>
66 #include <sys/stat.h>
67 #include <sys/param.h>
68 #include <errno.h>
69
70 #ifndef X_NOT_POSIX
71 #include <dirent.h>
72 #else
73 #ifdef SYSV
74 #include <dirent.h>
75 #else
76 #ifdef USG
77 #include <dirent.h>
78 #else
79 #include <sys/dir.h>
80 #ifndef dirent
81 #define dirent direct
82 #endif
83 #endif
84 #endif
85 #endif
86 #ifndef MAXPATHLEN
87 #define MAXPATHLEN 2048
88 #endif
89
90 #if NeedVarargsPrototypes
91 #include <stdarg.h>
92 #endif
93
94 #ifdef X_NOT_STDC_ENV
95 extern int errno;
96 #endif
97 int silent = 0;                 /* -silent */
98 int ignore_links = 0;           /* -ignorelinks */
99
100 char *rcurdir;
101 char *curdir;
102
103 void
104 quit (
105 #if NeedVarargsPrototypes
106     int code, char * fmt, ...)
107 #else
108     code, fmt, a1, a2, a3)
109     char *fmt;
110 #endif
111 {
112 #if NeedVarargsPrototypes
113     va_list args;
114     va_start(args, fmt);
115     vfprintf (stderr, fmt, args);
116     va_end(args);
117 #else
118     fprintf (stderr, fmt, a1, a2, a3);
119 #endif
120     putc ('\n', stderr);
121     exit (code);
122 }
123
124 void
125 quiterr (code, s)
126     char *s;
127 {
128     perror (s);
129     exit (code);
130 }
131
132 void
133 msg (
134 #if NeedVarargsPrototypes
135     char * fmt, ...)
136 #else
137     fmt, a1, a2, a3)
138     char *fmt;
139 #endif
140 {
141 #if NeedVarargsPrototypes
142     va_list args;
143 #endif
144     if (curdir) {
145         fprintf (stderr, "%s:\n", curdir);
146         curdir = 0;
147     }
148 #if NeedVarargsPrototypes
149     va_start(args, fmt);
150     vfprintf (stderr, fmt, args);
151     va_end(args);
152 #else
153     fprintf (stderr, fmt, a1, a2, a3);
154 #endif
155     putc ('\n', stderr);
156 }
157
158 void
159 mperror (s)
160     char *s;
161 {
162     if (curdir) {
163         fprintf (stderr, "%s:\n", curdir);
164         curdir = 0;
165     }
166     perror (s);
167 }
168
169
170 int equivalent(lname, rname)
171     char *lname;
172     char *rname;
173 {
174     char *s;
175
176     if (!strcmp(lname, rname))
177         return 1;
178     for (s = lname; *s && (s = strchr(s, '/')); s++) {
179         while (s[1] == '/')
180             strcpy(s+1, s+2);
181     }
182     return !strcmp(lname, rname);
183 }
184
185
186 /* Recursively create symbolic links from the current directory to the "from"
187    directory.  Assumes that files described by fs and ts are directories. */
188
189 dodir (fn, fs, ts, rel)
190 char *fn;                       /* name of "from" directory, either absolute or
191                                    relative to cwd */
192 struct stat *fs, *ts;           /* stats for the "from" directory and cwd */
193 int rel;                        /* if true, prepend "../" to fn before using */
194 {
195     DIR *df;
196     struct dirent *dp;
197     char buf[MAXPATHLEN + 1], *p;
198     char symbuf[MAXPATHLEN + 1];
199     char basesym[MAXPATHLEN + 1];
200     struct stat sb, sc;
201     int n_dirs;
202     int symlen;
203     int basesymlen = -1;
204     char *ocurdir;
205
206     if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
207         msg ("%s: From and to directories are identical!", fn);
208         return 1;
209     }
210
211     if (rel)
212         strcpy (buf, "../");
213     else
214         buf[0] = '\0';
215     strcat (buf, fn);
216     
217     if (!(df = opendir (buf))) {
218         msg ("%s: Cannot opendir", buf);
219         return 1;
220     }
221
222     p = buf + strlen (buf);
223     *p++ = '/';
224     n_dirs = fs->st_nlink;
225     while (dp = readdir (df)) {
226         if (dp->d_name[strlen(dp->d_name) - 1] == '~')
227             continue;
228         strcpy (p, dp->d_name);
229
230         if (n_dirs > 0) {
231             if (stat (buf, &sb) < 0) {
232                 mperror (buf);
233                 continue;
234             }
235
236 #ifdef S_ISDIR
237             if(S_ISDIR(sb.st_mode))
238 #else
239             if (sb.st_mode & S_IFDIR) 
240 #endif
241             {
242                 /* directory */
243                 n_dirs--;
244                 if (dp->d_name[0] == '.' &&
245                     (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' &&
246                                                dp->d_name[2] == '\0')))
247                     continue;
248                 if (!strcmp (dp->d_name, "RCS"))
249                     continue;
250                 if (!strcmp (dp->d_name, "SCCS"))
251                     continue;
252                 if (!strcmp (dp->d_name, "CVS"))
253                     continue;
254                 if (!strcmp (dp->d_name, "CVS.adm"))
255                     continue;
256                 ocurdir = rcurdir;
257                 rcurdir = buf;
258                 curdir = silent ? buf : (char *)0;
259                 if (!silent)
260                     printf ("%s:\n", buf);
261                 if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
262                     if (mkdir (dp->d_name, 0777) < 0 ||
263                         stat (dp->d_name, &sc) < 0) {
264                         mperror (dp->d_name);
265                         curdir = rcurdir = ocurdir;
266                         continue;
267                     }
268                 }
269                 if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
270                     msg ("%s: is a link instead of a directory", dp->d_name);
271                     curdir = rcurdir = ocurdir;
272                     continue;
273                 }
274                 if (chdir (dp->d_name) < 0) {
275                     mperror (dp->d_name);
276                     curdir = rcurdir = ocurdir;
277                     continue;
278                 }
279                 dodir (buf, &sb, &sc, (buf[0] != '/'));
280                 if (chdir ("..") < 0)
281                     quiterr (1, "..");
282                 curdir = rcurdir = ocurdir;
283                 continue;
284             }
285         }
286
287         /* non-directory */
288         symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1);
289         if (symlen >= 0)
290             symbuf[symlen] = '\0';
291
292         /* The option to ignore links exists mostly because
293            checking for them slows us down by 10-20%.
294            But it is off by default because this really is a useful check. */
295         if (!ignore_links) {
296             /* see if the file in the base tree was a symlink */
297             basesymlen = readlink(buf, basesym, sizeof(basesym) - 1);
298             if (basesymlen >= 0)
299                 basesym[basesymlen] = '\0';
300         }
301
302         if (symlen >= 0) {
303             /* Link exists in new tree.  Print message if it doesn't match. */
304             if (!equivalent (basesymlen>=0 ? basesym : buf, symbuf))
305                 msg ("%s: %s", dp->d_name, symbuf);
306         } else {
307             if (symlink (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
308                 mperror (dp->d_name);
309         }
310     }
311
312     closedir (df);
313     return 0;
314 }
315
316
317 main (ac, av)
318 int ac;
319 char **av;
320 {
321     char *prog_name = av[0];
322     char *fn, *tn;
323     struct stat fs, ts;
324
325     while (++av, --ac) {
326         if (strcmp(*av, "-silent") == 0)
327             silent = 1;
328         else if (strcmp(*av, "-ignorelinks") == 0)
329             ignore_links = 1;
330         else if (strcmp(*av, "--") == 0) {
331             ++av, --ac;
332             break;
333         }
334         else
335             break;
336     }
337
338     if (ac < 1 || ac > 2)
339         quit (1, "usage: %s [-silent] [-ignorelinks] fromdir [todir]",
340               prog_name);
341
342     fn = av[0];
343     if (ac == 2)
344         tn = av[1];
345     else
346         tn = ".";
347
348     /* to directory */
349     if (stat (tn, &ts) < 0)
350         quiterr (1, tn);
351 #ifdef S_ISDIR
352     if (!(S_ISDIR(ts.st_mode)))
353 #else
354     if (!(ts.st_mode & S_IFDIR))
355 #endif
356         quit (2, "%s: Not a directory", tn);
357     if (chdir (tn) < 0)
358         quiterr (1, tn);
359
360     /* from directory */
361     if (stat (fn, &fs) < 0)
362         quiterr (1, fn);
363 #ifdef S_ISDIR
364     if (!(S_ISDIR(fs.st_mode)))
365 #else
366     if (!(fs.st_mode & S_IFDIR))
367 #endif
368         quit (2, "%s: Not a directory", fn);
369
370     exit (dodir (fn, &fs, &ts, 0));
371 }