File indexing completed on 2025-05-11 08:24:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #ifdef HAVE_CONFIG_H
0033 #include "config.h"
0034 #endif
0035
0036 #if 0
0037 #ifndef lint
0038 __COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
0039 The Regents of the University of California. All rights reserved.");
0040 #endif
0041
0042 #ifndef lint
0043 #if 0
0044 static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94";
0045 #else
0046 __RCSID("$NetBSD: ln.c,v 1.34 2008/07/20 00:52:40 lukem Exp $");
0047 #endif
0048 #endif
0049 #endif
0050
0051 #include <rtems.h>
0052 #include <rtems/shell.h>
0053 #include <rtems/shellconfig.h>
0054 #define __need_getopt_newlib
0055 #include <getopt.h>
0056
0057 #include <sys/cdefs.h>
0058 #include <sys/param.h>
0059 #include <sys/stat.h>
0060
0061 #include "err.h"
0062 #include <errno.h>
0063 #include <locale.h>
0064 #include <stdio.h>
0065 #include <stdlib.h>
0066 #include <string.h>
0067 #include <unistd.h>
0068
0069 #include <setjmp.h>
0070
0071 typedef struct {
0072 int fflag;
0073 int hflag;
0074 int iflag;
0075 int sflag;
0076 int vflag;
0077 char linkch;
0078
0079 int exit_code;
0080 jmp_buf exit_jmp;
0081 } rtems_shell_ln_globals;
0082
0083 #define fflag globals->fflag
0084 #define hflag globals->hflag
0085 #define iflag globals->iflag
0086 #define sflag globals->sflag
0087 #define vflag globals->vflag
0088 #define linkch globals->linkch
0089
0090 #define exit_jump &(globals->exit_jmp)
0091
0092 #define exit(ec) rtems_shell_ln_exit(globals, ec)
0093
0094 static int main_ln(rtems_shell_ln_globals* , int, char *[]);
0095
0096 static void
0097 rtems_shell_ln_exit (rtems_shell_ln_globals* globals, int code)
0098 {
0099 globals->exit_code = code;
0100 longjmp (globals->exit_jmp, 1);
0101 }
0102
0103 static int main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[]);
0104
0105 static int rtems_shell_main_ln(int argc, char *argv[])
0106 {
0107 rtems_shell_ln_globals ln_globals;
0108 rtems_shell_ln_globals* globals = &ln_globals;
0109 memset (globals, 0, sizeof (ln_globals));
0110 ln_globals.exit_code = 1;
0111 if (setjmp (ln_globals.exit_jmp) == 0)
0112 return main_ln (globals, argc, argv);
0113 return ln_globals.exit_code;
0114 }
0115
0116 #if RTEMS_REMOVED
0117 int fflag;
0118 int hflag;
0119 int iflag;
0120 int sflag;
0121 int vflag;
0122
0123
0124 int (*linkf)(const char *, const char *);
0125 char linkch;
0126 #endif
0127
0128 int (*linkf)(const char *, const char *);
0129
0130 static int linkit(rtems_shell_ln_globals* , const char *, const char *, int);
0131 static void usage(rtems_shell_ln_globals* );
0132
0133 static int
0134 main_ln(rtems_shell_ln_globals* globals, int argc, char *argv[])
0135 {
0136 struct stat sb;
0137 int ch, exitval;
0138 char *sourcedir;
0139
0140 struct getopt_data getopt_reent;
0141 memset(&getopt_reent, 0, sizeof(getopt_data));
0142
0143 #if RTEMS_REMOVED
0144 setprogname(argv[0]);
0145 (void)setlocale(LC_ALL, "");
0146 #endif
0147
0148 while ((ch = getopt_r(argc, argv, "fhinsv", &getopt_reent)) != -1)
0149 switch (ch) {
0150 case 'f':
0151 fflag = 1;
0152 iflag = 0;
0153 break;
0154 case 'h':
0155 case 'n':
0156 hflag = 1;
0157 break;
0158 case 'i':
0159 iflag = 1;
0160 fflag = 0;
0161 break;
0162 case 's':
0163 sflag = 1;
0164 break;
0165 case 'v':
0166 vflag = 1;
0167 break;
0168 case '?':
0169 default:
0170 usage(globals);
0171
0172 }
0173
0174 argv += getopt_reent.optind;
0175 argc -= getopt_reent.optind;
0176
0177 if (sflag) {
0178 linkf = symlink;
0179 linkch = '-';
0180 } else {
0181 linkf = link;
0182 linkch = '=';
0183 }
0184
0185 switch(argc) {
0186 case 0:
0187 usage(globals);
0188
0189 case 1:
0190 exit(linkit(globals, argv[0], ".", 1));
0191
0192 case 2:
0193 exit(linkit(globals, argv[0], argv[1], 0));
0194
0195 }
0196
0197
0198 sourcedir = argv[argc - 1];
0199 if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
0200
0201
0202 errno = ENOTDIR;
0203 err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
0204
0205 }
0206 if (stat(sourcedir, &sb)) {
0207 err(exit_jump, EXIT_FAILURE, "%s", sourcedir);
0208
0209 }
0210 if (!S_ISDIR(sb.st_mode)) {
0211 usage(globals);
0212
0213 }
0214 for (exitval = 0; *argv != sourcedir; ++argv)
0215 exitval |= linkit(globals, *argv, sourcedir, 1);
0216 exit(exitval);
0217
0218 return 0;
0219 }
0220
0221 int
0222 linkit(rtems_shell_ln_globals* globals, const char *source, const char *target, int isdir)
0223 {
0224 struct stat sb;
0225 const char *p;
0226 char path[MAXPATHLEN];
0227 int ch, exists, first;
0228
0229 if (!sflag) {
0230
0231 if (stat(target, &sb)) {
0232 warn("%s", target);
0233 return (1);
0234 }
0235 }
0236
0237
0238
0239 if (isdir ||
0240 (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
0241 (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
0242 if ((p = strrchr(target, '/')) == NULL)
0243 p = target;
0244 else
0245 ++p;
0246 (void)snprintf(path, sizeof(path), "%s/%s", source, p);
0247 source = path;
0248 }
0249
0250 exists = !lstat(source, &sb);
0251
0252
0253
0254
0255
0256 if (fflag && exists) {
0257 if (unlink(source)) {
0258 warn("%s", source);
0259 return (1);
0260 }
0261 } else if (iflag && exists) {
0262 fflush(stdout);
0263 (void)fprintf(stderr, "replace %s? ", source);
0264
0265 first = ch = getchar();
0266 while (ch != '\n' && ch != EOF)
0267 ch = getchar();
0268 if (first != 'y' && first != 'Y') {
0269 (void)fprintf(stderr, "not replaced\n");
0270 return (1);
0271 }
0272
0273 if (unlink(source)) {
0274 warn("%s", source);
0275 return (1);
0276 }
0277 }
0278
0279
0280 if ((*linkf)(target, source)) {
0281 warn("%s", source);
0282 return (1);
0283 }
0284 if (vflag)
0285 (void)printf("%s %c> %s\n", source, linkch, target);
0286
0287 return (0);
0288 }
0289
0290 void
0291 usage(rtems_shell_ln_globals* globals)
0292 {
0293 #define getprogname() "ln"
0294 (void)fprintf(stderr,
0295 "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n",
0296 getprogname(), getprogname());
0297 exit(1);
0298
0299 }
0300
0301 rtems_shell_cmd_t rtems_shell_LN_Command = {
0302 "ln",
0303 "ln ln [-fhinsv] source_file [target_file]",
0304 "files",
0305 rtems_shell_main_ln,
0306 NULL,
0307 NULL
0308 };