source: rtems/cpukit/libmisc/shell/main_ln.c @ 9a77af8

4.104.115
Last change on this file since 9a77af8 was 9a77af8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/26/10 at 17:18:43

Add HAVE_CONFIG_H support to let files receive configure defines.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/* $NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $ */
2
3/*
4 * Copyright (c) 1987, 1993, 1994
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#if 0
37#ifndef lint
38__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
39 The Regents of the University of California.  All rights reserved.");
40#endif /* not lint */
41
42#ifndef lint
43#if 0
44static char sccsid[] = "@(#)ln.c        8.2 (Berkeley) 3/31/94";
45#else
46__RCSID("$NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $");
47#endif
48#endif /* not lint */
49#endif
50
51#include <rtems.h>
52#include <rtems/shell.h>
53#include <rtems/shellconfig.h>
54#define __need_getopt_newlib
55#include <getopt.h>
56
57#include <sys/cdefs.h>
58#include <sys/param.h>
59#include <sys/stat.h>
60
61#include <err.h>
62#include <errno.h>
63#include <locale.h>
64#include <stdio.h>
65#include <stdlib.h>
66#include <string.h>
67#include <unistd.h>
68
69#include <setjmp.h>
70
71typedef struct {
72  int   fflag;                          /* Unlink existing files. */
73  int   hflag;                          /* Check new name for symlink first. */
74  int   iflag;                          /* Interactive mode. */
75  int   sflag;                          /* Symbolic, not hard, link. */
76  int   vflag;                          /* Verbose output */
77  char   linkch;
78
79  int exit_code;
80  jmp_buf exit_jmp;
81} rtems_shell_ln_globals;
82
83#define fflag  globals->fflag
84#define hflag  globals->hflag
85#define iflag  globals->iflag
86#define sflag  globals->sflag
87#define vflag  globals->vflag
88#define linkch globals->linkch
89
90#define exit_jump &(globals->exit_jmp)
91
92#define exit(ec) rtems_shell_ln_exit(globals, ec)
93
94static int      main_ln(rtems_shell_ln_globals* , int, char *[]);
95
96static void
97rtems_shell_ln_exit (rtems_shell_ln_globals* globals, int code)
98{
99  globals->exit_code = code;
100  longjmp (globals->exit_jmp, 1);
101}
102
103static int main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[]);
104
105int
106rtems_shell_main_ln(int argc, char *argv[])
107{
108  rtems_shell_ln_globals  ln_globals;
109  rtems_shell_ln_globals* globals = &ln_globals;
110  memset (globals, 0, sizeof (ln_globals));
111  ln_globals.exit_code = 1;
112  if (setjmp (ln_globals.exit_jmp) == 0)
113    return main_ln (globals, argc, argv);
114  return ln_globals.exit_code;
115}
116
117#if RTEMS_REMOVED
118int     fflag;                          /* Unlink existing files. */
119int     hflag;                          /* Check new name for symlink first. */
120int     iflag;                          /* Interactive mode. */
121int     sflag;                          /* Symbolic, not hard, link. */
122int     vflag;                          /* Verbose output */
123
124                                        /* System link call. */
125int (*linkf)(const char *, const char *);
126char   linkch;
127#endif
128
129int (*linkf)(const char *, const char *);
130
131static int      linkit(rtems_shell_ln_globals* , const char *, const char *, int);
132static void     usage(rtems_shell_ln_globals* );
133
134static int
135main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[])
136{
137        struct stat sb;
138        int ch, exitval;
139        char *sourcedir;
140
141        struct getopt_data getopt_reent;
142        memset(&getopt_reent, 0, sizeof(getopt_data));
143
144#if RTEMS_REMOVED
145        setprogname(argv[0]);
146        (void)setlocale(LC_ALL, "");
147#endif
148
149        while ((ch = getopt_r(argc, argv, "fhinsv", &getopt_reent)) != -1)
150                switch (ch) {
151                case 'f':
152                        fflag = 1;
153                        iflag = 0;
154                        break;
155                case 'h':
156                case 'n':
157                        hflag = 1;
158                        break;
159                case 'i':
160                        iflag = 1;
161                        fflag = 0;
162                        break;
163                case 's':
164                        sflag = 1;
165                        break;
166                case 'v':
167                        vflag = 1;
168                        break;
169                case '?':
170                default:
171                        usage(globals);
172                        /* NOTREACHED */
173                }
174
175        argv += getopt_reent.optind;
176        argc -= getopt_reent.optind;
177
178        if (sflag) {
179                linkf  = symlink;
180                linkch = '-';
181        } else {
182                linkf  = link;
183                linkch = '=';
184        }
185
186        switch(argc) {
187        case 0:
188                usage(globals);
189                /* NOTREACHED */
190        case 1:                         /* ln target */
191                exit(linkit(globals, argv[0], ".", 1));
192                /* NOTREACHED */
193        case 2:                         /* ln target source */
194                exit(linkit(globals, argv[0], argv[1], 0));
195                /* NOTREACHED */
196        }
197
198                                        /* ln target1 target2 directory */
199        sourcedir = argv[argc - 1];
200        if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
201                /* we were asked not to follow symlinks, but found one at
202                   the target--simulate "not a directory" error */
203                errno = ENOTDIR;
204                err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
205                /* NOTREACHED */
206        }
207        if (stat(sourcedir, &sb)) {
208                err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
209                /* NOTREACHED */
210        }
211        if (!S_ISDIR(sb.st_mode)) {
212                usage(globals);
213                /* NOTREACHED */
214        }
215        for (exitval = 0; *argv != sourcedir; ++argv)
216                exitval |= linkit(globals, *argv, sourcedir, 1);
217        exit(exitval);
218        /* NOTREACHED */
219  return 0;
220}
221
222int
223linkit(rtems_shell_ln_globals* globals, const char *source, const char *target, int isdir)
224{
225        struct stat sb;
226        const char *p;
227        char path[MAXPATHLEN];
228        int ch, exists, first;
229
230        if (!sflag) {
231                /* If target doesn't exist, quit now. */
232                if (stat(target, &sb)) {
233                        warn("%s", target);
234                        return (1);
235                }
236        }
237
238        /* If the source is a directory (and not a symlink if hflag),
239           append the target's name. */
240        if (isdir ||
241            (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
242            (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
243                if ((p = strrchr(target, '/')) == NULL)
244                        p = target;
245                else
246                        ++p;
247                (void)snprintf(path, sizeof(path), "%s/%s", source, p);
248                source = path;
249        }
250
251        exists = !lstat(source, &sb);
252
253        /*
254         * If the file exists, then unlink it forcibly if -f was specified
255         * and interactively if -i was specified.
256         */
257        if (fflag && exists) {
258                if (unlink(source)) {
259                        warn("%s", source);
260                        return (1);
261                }
262        } else if (iflag && exists) {
263                fflush(stdout);
264                (void)fprintf(stderr, "replace %s? ", source);
265
266                first = ch = getchar();
267                while (ch != '\n' && ch != EOF)
268                        ch = getchar();
269                if (first != 'y' && first != 'Y') {
270                        (void)fprintf(stderr, "not replaced\n");
271                        return (1);
272                }
273
274                if (unlink(source)) {
275                        warn("%s", source);
276                        return (1);
277                }
278        }
279
280        /* Attempt the link. */
281        if ((*linkf)(target, source)) {
282                warn("%s", source);
283                return (1);
284        }
285        if (vflag)
286                (void)printf("%s %c> %s\n", source, linkch, target);
287
288        return (0);
289}
290
291void
292usage(rtems_shell_ln_globals* globals)
293{
294#define getprogname() "ln"
295        (void)fprintf(stderr,
296            "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n",
297            getprogname(), getprogname());
298        exit(1);
299        /* NOTREACHED */
300}
301
302rtems_shell_cmd_t rtems_shell_LN_Command = {
303  "ln",                                         /* name */
304  "ln ln [-fhinsv] source_file [target_file]",  /* usage */
305  "files",                                      /* topic */
306  rtems_shell_main_ln,                          /* command */
307  NULL,                                         /* alias */
308  NULL                                          /* next */
309};
Note: See TracBrowser for help on using the repository browser.