Commit | Line | Data |
---|---|---|
8fb84ebd | 1 | /* |
7a909b83 | 2 | * Copyright (c) 1987 Regents of the University of California. |
a754946e KB |
3 | * All rights reserved. |
4 | * | |
f15db449 | 5 | * %sccs.include.redist.c% |
8fb84ebd | 6 | */ |
7a909b83 | 7 | |
a754946e | 8 | #ifndef lint |
7a909b83 KB |
9 | char copyright[] = |
10 | "@(#) Copyright (c) 1987 Regents of the University of California.\n\ | |
11 | All rights reserved.\n"; | |
a754946e | 12 | #endif /* not lint */ |
7a909b83 | 13 | |
a754946e | 14 | #ifndef lint |
77011f17 | 15 | static char sccsid[] = "@(#)ln.c 5.1 (Berkeley) %G%"; |
a754946e | 16 | #endif /* not lint */ |
7a909b83 KB |
17 | |
18 | #include <sys/param.h> | |
8fb84ebd | 19 | #include <sys/stat.h> |
77011f17 KB |
20 | |
21 | #include <err.h> | |
56abc04a | 22 | #include <errno.h> |
77011f17 | 23 | #include <stdio.h> |
337f474e | 24 | #include <stdlib.h> |
77011f17 | 25 | #include <string.h> |
337f474e | 26 | #include <unistd.h> |
8fb84ebd | 27 | |
77011f17 KB |
28 | int dirflag, /* Undocumented force flag. */ |
29 | sflag, /* Symbolic, not hard, link. */ | |
30 | /* System link call. */ | |
31 | (*linkf) __P((const char *, const char *)); | |
8fb84ebd | 32 | |
77011f17 KB |
33 | static int linkit __P((char *, char *, int)); |
34 | static void usage __P((void)); | |
35 | ||
36 | int | |
8fb84ebd | 37 | main(argc, argv) |
be183d1e | 38 | int argc; |
77011f17 | 39 | char *argv[]; |
8fb84ebd | 40 | { |
fd5596d8 | 41 | extern int optind; |
77011f17 KB |
42 | struct stat sb; |
43 | int ch, exitval; | |
fd5596d8 | 44 | char *sourcedir; |
8fb84ebd | 45 | |
fd5596d8 | 46 | while ((ch = getopt(argc, argv, "Fs")) != EOF) |
7a909b83 | 47 | switch((char)ch) { |
fd5596d8 KB |
48 | case 'F': |
49 | dirflag = 1; | |
7a909b83 KB |
50 | break; |
51 | case 's': | |
52 | sflag = 1; | |
53 | break; | |
54 | case '?': | |
55 | default: | |
56 | usage(); | |
57 | } | |
58 | ||
59 | argv += optind; | |
60 | argc -= optind; | |
61 | ||
62 | linkf = sflag ? symlink : link; | |
63 | ||
64 | switch(argc) { | |
65 | case 0: | |
66 | usage(); | |
67 | case 1: /* ln target */ | |
68 | exit(linkit(argv[0], ".", 1)); | |
69 | case 2: /* ln target source */ | |
70 | exit(linkit(argv[0], argv[1], 0)); | |
8fb84ebd | 71 | } |
77011f17 KB |
72 | /* ln target1 target2 directory */ |
73 | sourcedir = argv[argc - 1]; | |
74 | if (stat(sourcedir, &sb)) | |
75 | err(1, "%s", sourcedir); | |
76 | if (!S_ISDIR(sb.st_mode)) | |
77 | usage(); | |
78 | for (exitval = 0; *argv != sourcedir; ++argv) | |
79 | exitval |= linkit(*argv, sourcedir, 1); | |
80 | exit(exitval); | |
8fb84ebd BJ |
81 | } |
82 | ||
77011f17 | 83 | static int |
7a909b83 | 84 | linkit(target, source, isdir) |
be183d1e KB |
85 | char *target, *source; |
86 | int isdir; | |
8fb84ebd | 87 | { |
77011f17 KB |
88 | struct stat sb; |
89 | char path[MAXPATHLEN], *p; | |
8fb84ebd | 90 | |
7a909b83 KB |
91 | if (!sflag) { |
92 | /* if target doesn't exist, quit now */ | |
77011f17 KB |
93 | if (stat(target, &sb)) { |
94 | warn("%s", target); | |
95 | return (1); | |
7a909b83 | 96 | } |
fd5596d8 | 97 | /* only symbolic links to directories, unless -F option used */ |
77011f17 KB |
98 | if (!dirflag && (sb.st_mode & S_IFMT) == S_IFDIR) { |
99 | warnx("%s: is a directory", target); | |
100 | return (1); | |
7a909b83 | 101 | } |
8fb84ebd | 102 | } |
7a909b83 KB |
103 | |
104 | /* if the source is a directory, append the target's name */ | |
77011f17 KB |
105 | if (isdir || !stat(source, &sb) && (sb.st_mode & S_IFMT) == S_IFDIR) { |
106 | if (!(p = strrchr(target, '/'))) | |
107 | p = target; | |
1bfeaa36 | 108 | else |
77011f17 KB |
109 | ++p; |
110 | (void)snprintf(path, sizeof(path), "%s/%s", source, p); | |
7a909b83 | 111 | source = path; |
8fb84ebd | 112 | } |
7a909b83 KB |
113 | |
114 | if ((*linkf)(target, source)) { | |
77011f17 KB |
115 | warn("%s", source); |
116 | return (1); | |
8fb84ebd | 117 | } |
77011f17 | 118 | return (0); |
7a909b83 KB |
119 | } |
120 | ||
77011f17 | 121 | static void |
7a909b83 KB |
122 | usage() |
123 | { | |
be183d1e KB |
124 | (void)fprintf(stderr, |
125 | "usage:\tln [-s] file1 file2\n\tln [-s] file ... directory\n"); | |
7a909b83 | 126 | exit(1); |
8fb84ebd | 127 | } |