1/*
2 * Copyright 1991 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
7/*	  All Rights Reserved  	*/
8
9/*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15#pragma ident	"%Z%%M%	%I%	%E% SMI"
16
17/*
18 * ln
19 */
20#include <stdio.h>
21#include <sys/types.h>
22#include <sys/param.h>
23#include <sys/stat.h>
24#include <errno.h>
25#include <unistd.h>
26
27struct	stat stb;
28int	fflag;		/* force flag set? */
29int	sflag;
30
31int linkit(char *, char *);
32void Perror(char *);
33
34int
35main(int argc, char **argv)
36{
37	int i, r;
38
39	argc--, argv++;
40again:
41	if (argc && strcmp(argv[0], "-f") == 0) {
42		fflag++;
43		argv++;
44		argc--;
45	}
46	if (argc && strcmp(argv[0], "-s") == 0) {
47		sflag++;
48		argv++;
49		argc--;
50	}
51	if (argc == 0)
52		goto usage;
53	else if (argc == 1) {
54		argv[argc] = ".";
55		argc++;
56	}
57	if (argc > 2) {
58		if (stat(argv[argc-1], &stb) < 0)
59			goto usage;
60		if ((stb.st_mode&S_IFMT) != S_IFDIR)
61			goto usage;
62	}
63	r = 0;
64	for (i = 0; i < argc-1; i++)
65		r |= linkit(argv[i], argv[argc-1]);
66	exit(r);
67usage:
68	(void) fprintf(stderr,
69	    "Usage: ln [-f] [-s] f1\n\
70       ln [-f] [-s] f1 f2\n\
71       ln [-f] [-s] f1 ... fn d1\n");
72	return (1);
73}
74
75int
76linkit(char *from, char *to)
77{
78	char destname[MAXPATHLEN + 1];
79	char *tail;
80	int (*linkf)() = sflag ? symlink : link;
81	char *strrchr();
82
83	/* is target a directory? */
84	if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 &&
85	    (stb.st_mode&S_IFMT) == S_IFDIR) {
86		printf("%s is a directory\n", from);
87		return (1);
88	}
89	if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) {
90		tail = strrchr(from, '/');
91		if (tail == 0)
92			tail = from;
93		else
94			tail++;
95		if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) {
96			(void) fprintf(stderr, "ln: %s/%s: Name too long\n",
97			    to, tail);
98			return (1);
99		}
100		(void) sprintf(destname, "%s/%s", to, tail);
101		to = destname;
102	}
103	if ((*linkf)(from, to) < 0) {
104		if (errno == EEXIST || sflag)
105			Perror(to);
106		else if (access(from, 0) < 0)
107			Perror(from);
108		else
109			Perror(to);
110		return (1);
111	}
112	return (0);
113}
114
115void
116Perror(char *s)
117{
118	(void) fprintf(stderr, "ln: ");
119	perror(s);
120}
121