source: rtems/cpukit/libmisc/shell/main_ln.c @ 0893220

4.104.115
Last change on this file since 0893220 was 0893220, checked in by Ralf Corsepius <ralf.corsepius@…>, on Nov 29, 2009 at 12:12:39 PM

Whitespace removal.

  • 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#if 0
33#ifndef lint
34__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
35 The Regents of the University of California.  All rights reserved.");
36#endif /* not lint */
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)ln.c        8.2 (Berkeley) 3/31/94";
41#else
42__RCSID("$NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $");
43#endif
44#endif /* not lint */
45#endif
46
47#include <rtems.h>
48#include <rtems/shell.h>
49#include <rtems/shellconfig.h>
50#define __need_getopt_newlib
51#include <getopt.h>
52
53#include <sys/cdefs.h>
54#include <sys/param.h>
55#include <sys/stat.h>
56
57#include <err.h>
58#include <errno.h>
59#include <locale.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <string.h>
63#include <unistd.h>
64
65#include <setjmp.h>
66
67typedef struct {
68  int   fflag;                          /* Unlink existing files. */
69  int   hflag;                          /* Check new name for symlink first. */
70  int   iflag;                          /* Interactive mode. */
71  int   sflag;                          /* Symbolic, not hard, link. */
72  int   vflag;                          /* Verbose output */
73  char   linkch;
74
75  int exit_code;
76  jmp_buf exit_jmp;
77} rtems_shell_ln_globals;
78
79#define fflag  globals->fflag
80#define hflag  globals->hflag
81#define iflag  globals->iflag
82#define sflag  globals->sflag
83#define vflag  globals->vflag
84#define linkch globals->linkch
85
86#define exit_jump &(globals->exit_jmp)
87
88#define exit(ec) rtems_shell_ln_exit(globals, ec)
89
90static int      main_ln(rtems_shell_ln_globals* , int, char *[]);
91
92static void
93rtems_shell_ln_exit (rtems_shell_ln_globals* globals, int code)
94{
95  globals->exit_code = code;
96  longjmp (globals->exit_jmp, 1);
97}
98
99static int main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[]);
100
101int
102rtems_shell_main_ln(int argc, char *argv[])
103{
104  rtems_shell_ln_globals  ln_globals;
105  rtems_shell_ln_globals* globals = &ln_globals;
106  memset (globals, 0, sizeof (ln_globals));
107  ln_globals.exit_code = 1;
108  if (setjmp (ln_globals.exit_jmp) == 0)
109    return main_ln (globals, argc, argv);
110  return ln_globals.exit_code;
111}
112
113#if RTEMS_REMOVED
114int     fflag;                          /* Unlink existing files. */
115int     hflag;                          /* Check new name for symlink first. */
116int     iflag;                          /* Interactive mode. */
117int     sflag;                          /* Symbolic, not hard, link. */
118int     vflag;                          /* Verbose output */
119
120                                        /* System link call. */
121int (*linkf)(const char *, const char *);
122char   linkch;
123#endif
124
125int (*linkf)(const char *, const char *);
126
127static int      linkit(rtems_shell_ln_globals* , const char *, const char *, int);
128static void     usage(rtems_shell_ln_globals* );
129
130static int
131main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[])
132{
133        struct stat sb;
134        int ch, exitval;
135        char *sourcedir;
136
137        struct getopt_data getopt_reent;
138        memset(&getopt_reent, 0, sizeof(getopt_data));
139
140#if RTEMS_REMOVED
141        setprogname(argv[0]);
142        (void)setlocale(LC_ALL, "");
143#endif
144
145        while ((ch = getopt_r(argc, argv, "fhinsv", &getopt_reent)) != -1)
146                switch (ch) {
147                case 'f':
148                        fflag = 1;
149                        iflag = 0;
150                        break;
151                case 'h':
152                case 'n':
153                        hflag = 1;
154                        break;
155                case 'i':
156                        iflag = 1;
157                        fflag = 0;
158                        break;
159                case 's':
160                        sflag = 1;
161                        break;
162                case 'v':
163                        vflag = 1;
164                        break;
165                case '?':
166                default:
167                        usage(globals);
168                        /* NOTREACHED */
169                }
170
171        argv += getopt_reent.optind;
172        argc -= getopt_reent.optind;
173
174        if (sflag) {
175                linkf  = symlink;
176                linkch = '-';
177        } else {
178                linkf  = link;
179                linkch = '=';
180        }
181
182        switch(argc) {
183        case 0:
184                usage(globals);
185                /* NOTREACHED */
186        case 1:                         /* ln target */
187                exit(linkit(globals, argv[0], ".", 1));
188                /* NOTREACHED */
189        case 2:                         /* ln target source */
190                exit(linkit(globals, argv[0], argv[1], 0));
191                /* NOTREACHED */
192        }
193
194                                        /* ln target1 target2 directory */
195        sourcedir = argv[argc - 1];
196        if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
197                /* we were asked not to follow symlinks, but found one at
198                   the target--simulate "not a directory" error */
199                errno = ENOTDIR;
200                err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
201                /* NOTREACHED */
202        }
203        if (stat(sourcedir, &sb)) {
204                err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
205                /* NOTREACHED */
206        }
207        if (!S_ISDIR(sb.st_mode)) {
208                usage(globals);
209                /* NOTREACHED */
210        }
211        for (exitval = 0; *argv != sourcedir; ++argv)
212                exitval |= linkit(globals, *argv, sourcedir, 1);
213        exit(exitval);
214        /* NOTREACHED */
215  return 0;
216}
217
218int
219linkit(rtems_shell_ln_globals* globals, const char *source, const char *target, int isdir)
220{
221        struct stat sb;
222        const char *p;
223        char path[MAXPATHLEN];
224        int ch, exists, first;
225
226        if (!sflag) {
227                /* If target doesn't exist, quit now. */
228                if (stat(target, &sb)) {
229                        warn("%s", target);
230                        return (1);
231                }
232        }
233
234        /* If the source is a directory (and not a symlink if hflag),
235           append the target's name. */
236        if (isdir ||
237            (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
238            (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
239                if ((p = strrchr(target, '/')) == NULL)
240                        p = target;
241                else
242                        ++p;
243                (void)snprintf(path, sizeof(path), "%s/%s", source, p);
244                source = path;
245        }
246
247        exists = !lstat(source, &sb);
248
249        /*
250         * If the file exists, then unlink it forcibly if -f was specified
251         * and interactively if -i was specified.
252         */
253        if (fflag && exists) {
254                if (unlink(source)) {
255                        warn("%s", source);
256                        return (1);
257                }
258        } else if (iflag && exists) {
259                fflush(stdout);
260                (void)fprintf(stderr, "replace %s? ", source);
261
262                first = ch = getchar();
263                while (ch != '\n' && ch != EOF)
264                        ch = getchar();
265                if (first != 'y' && first != 'Y') {
266                        (void)fprintf(stderr, "not replaced\n");
267                        return (1);
268                }
269
270                if (unlink(source)) {
271                        warn("%s", source);
272                        return (1);
273                }
274        }
275
276        /* Attempt the link. */
277        if ((*linkf)(target, source)) {
278                warn("%s", source);
279                return (1);
280        }
281        if (vflag)
282                (void)printf("%s %c> %s\n", source, linkch, target);
283
284        return (0);
285}
286
287void
288usage(rtems_shell_ln_globals* globals)
289{
290#define getprogname() "ln"
291        (void)fprintf(stderr,
292            "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n",
293            getprogname(), getprogname());
294        exit(1);
295        /* NOTREACHED */
296}
297
298rtems_shell_cmd_t rtems_shell_LN_Command = {
299  "ln",                                         /* name */
300  "ln ln [-fhinsv] source_file [target_file]",  /* usage */
301  "files",                                      /* topic */
302  rtems_shell_main_ln,                          /* command */
303  NULL,                                         /* alias */
304  NULL                                          /* next */
305};
Note: See TracBrowser for help on using the repository browser.