BSD style makefile
[unix-history] / usr / src / bin / ln / ln.c
CommitLineData
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
9char 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
fd5596d8 15static char sccsid[] = "@(#)ln.c 4.13 (Berkeley) %G%";
a754946e 16#endif /* not lint */
7a909b83
KB
17
18#include <sys/param.h>
8fb84ebd 19#include <sys/stat.h>
7a909b83 20#include <stdio.h>
56abc04a 21#include <errno.h>
8fb84ebd 22
fd5596d8 23static int dirflag, /* undocumented force flag */
7a909b83
KB
24 sflag, /* symbolic, not hard, link */
25 (*linkf)(); /* system link call */
8fb84ebd
BJ
26
27main(argc, argv)
7a909b83
KB
28 int argc;
29 char **argv;
8fb84ebd 30{
fd5596d8
KB
31 extern int optind;
32 struct stat buf;
33 int ch, exitval, link(), symlink();
34 char *sourcedir;
8fb84ebd 35
fd5596d8 36 while ((ch = getopt(argc, argv, "Fs")) != EOF)
7a909b83 37 switch((char)ch) {
fd5596d8
KB
38 case 'F':
39 dirflag = 1;
7a909b83
KB
40 break;
41 case 's':
42 sflag = 1;
43 break;
44 case '?':
45 default:
46 usage();
47 }
48
49 argv += optind;
50 argc -= optind;
51
52 linkf = sflag ? symlink : link;
53
54 switch(argc) {
55 case 0:
56 usage();
57 case 1: /* ln target */
58 exit(linkit(argv[0], ".", 1));
59 case 2: /* ln target source */
60 exit(linkit(argv[0], argv[1], 0));
61 default: /* ln target1 target2 directory */
62 sourcedir = argv[argc - 1];
63 if (stat(sourcedir, &buf)) {
64 perror(sourcedir);
65 exit(1);
66 }
67 if ((buf.st_mode & S_IFMT) != S_IFDIR)
68 usage();
69 for (exitval = 0; *argv != sourcedir; ++argv)
70 exitval |= linkit(*argv, sourcedir, 1);
71 exit(exitval);
8fb84ebd 72 }
7a909b83 73 /*NOTREACHED*/
8fb84ebd
BJ
74}
75
7a909b83
KB
76static
77linkit(target, source, isdir)
78 char *target, *source;
79 int isdir;
8fb84ebd 80{
7a909b83
KB
81 extern int errno;
82 struct stat buf;
83 char path[MAXPATHLEN],
84 *cp, *rindex(), *strcpy();
8fb84ebd 85
7a909b83
KB
86 if (!sflag) {
87 /* if target doesn't exist, quit now */
88 if (stat(target, &buf)) {
89 perror(target);
90 return(1);
91 }
fd5596d8
KB
92 /* only symbolic links to directories, unless -F option used */
93 if (!dirflag && (buf.st_mode & S_IFMT) == S_IFDIR) {
7a909b83
KB
94 printf("%s is a directory.\n", target);
95 return(1);
96 }
8fb84ebd 97 }
7a909b83
KB
98
99 /* if the source is a directory, append the target's name */
100 if (isdir || !stat(source, &buf) && (buf.st_mode & S_IFMT) == S_IFDIR) {
101 if (!(cp = rindex(target, '/')))
102 cp = target;
1bfeaa36 103 else
7a909b83
KB
104 ++cp;
105 (void)sprintf(path, "%s/%s", source, cp);
106 source = path;
8fb84ebd 107 }
7a909b83
KB
108
109 if ((*linkf)(target, source)) {
110 perror(source);
111 return(1);
8fb84ebd 112 }
7a909b83
KB
113 return(0);
114}
115
116static
117usage()
118{
119 fputs("usage:\tln [-s] targetname [sourcename]\n\tln [-s] targetname1 targetname2 [... targetnameN] sourcedirectory\n", stderr);
120 exit(1);
8fb84ebd 121}