1*cc6c5292Schin /*
2*cc6c5292Schin * Copyright 1991 Sun Microsystems, Inc. All rights reserved.
3*cc6c5292Schin * Use is subject to license terms.
4*cc6c5292Schin */
5*cc6c5292Schin
67c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
77c478bd9Sstevel@tonic-gate /* All Rights Reserved */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement
127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
15*cc6c5292Schin #pragma ident "%Z%%M% %I% %E% SMI"
167c478bd9Sstevel@tonic-gate
177c478bd9Sstevel@tonic-gate /*
187c478bd9Sstevel@tonic-gate * ln
197c478bd9Sstevel@tonic-gate */
207c478bd9Sstevel@tonic-gate #include <stdio.h>
217c478bd9Sstevel@tonic-gate #include <sys/types.h>
227c478bd9Sstevel@tonic-gate #include <sys/param.h>
237c478bd9Sstevel@tonic-gate #include <sys/stat.h>
247c478bd9Sstevel@tonic-gate #include <errno.h>
25*cc6c5292Schin #include <unistd.h>
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate struct stat stb;
287c478bd9Sstevel@tonic-gate int fflag; /* force flag set? */
297c478bd9Sstevel@tonic-gate int sflag;
307c478bd9Sstevel@tonic-gate
31*cc6c5292Schin int linkit(char *, char *);
32*cc6c5292Schin void Perror(char *);
33*cc6c5292Schin
34*cc6c5292Schin int
main(int argc,char ** argv)35*cc6c5292Schin main(int argc, char **argv)
367c478bd9Sstevel@tonic-gate {
37*cc6c5292Schin int i, r;
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate argc--, argv++;
407c478bd9Sstevel@tonic-gate again:
417c478bd9Sstevel@tonic-gate if (argc && strcmp(argv[0], "-f") == 0) {
427c478bd9Sstevel@tonic-gate fflag++;
437c478bd9Sstevel@tonic-gate argv++;
447c478bd9Sstevel@tonic-gate argc--;
457c478bd9Sstevel@tonic-gate }
467c478bd9Sstevel@tonic-gate if (argc && strcmp(argv[0], "-s") == 0) {
477c478bd9Sstevel@tonic-gate sflag++;
487c478bd9Sstevel@tonic-gate argv++;
497c478bd9Sstevel@tonic-gate argc--;
507c478bd9Sstevel@tonic-gate }
517c478bd9Sstevel@tonic-gate if (argc == 0)
527c478bd9Sstevel@tonic-gate goto usage;
537c478bd9Sstevel@tonic-gate else if (argc == 1) {
547c478bd9Sstevel@tonic-gate argv[argc] = ".";
557c478bd9Sstevel@tonic-gate argc++;
567c478bd9Sstevel@tonic-gate }
577c478bd9Sstevel@tonic-gate if (argc > 2) {
587c478bd9Sstevel@tonic-gate if (stat(argv[argc-1], &stb) < 0)
597c478bd9Sstevel@tonic-gate goto usage;
607c478bd9Sstevel@tonic-gate if ((stb.st_mode&S_IFMT) != S_IFDIR)
617c478bd9Sstevel@tonic-gate goto usage;
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate r = 0;
647c478bd9Sstevel@tonic-gate for (i = 0; i < argc-1; i++)
657c478bd9Sstevel@tonic-gate r |= linkit(argv[i], argv[argc-1]);
667c478bd9Sstevel@tonic-gate exit(r);
677c478bd9Sstevel@tonic-gate usage:
687c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
697c478bd9Sstevel@tonic-gate "Usage: ln [-f] [-s] f1\n\
707c478bd9Sstevel@tonic-gate ln [-f] [-s] f1 f2\n\
717c478bd9Sstevel@tonic-gate ln [-f] [-s] f1 ... fn d1\n");
72*cc6c5292Schin return (1);
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate
75*cc6c5292Schin int
linkit(char * from,char * to)76*cc6c5292Schin linkit(char *from, char *to)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate char destname[MAXPATHLEN + 1];
797c478bd9Sstevel@tonic-gate char *tail;
807c478bd9Sstevel@tonic-gate int (*linkf)() = sflag ? symlink : link;
817c478bd9Sstevel@tonic-gate char *strrchr();
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /* is target a directory? */
84*cc6c5292Schin if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 &&
85*cc6c5292Schin (stb.st_mode&S_IFMT) == S_IFDIR) {
867c478bd9Sstevel@tonic-gate printf("%s is a directory\n", from);
877c478bd9Sstevel@tonic-gate return (1);
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) {
907c478bd9Sstevel@tonic-gate tail = strrchr(from, '/');
917c478bd9Sstevel@tonic-gate if (tail == 0)
927c478bd9Sstevel@tonic-gate tail = from;
937c478bd9Sstevel@tonic-gate else
947c478bd9Sstevel@tonic-gate tail++;
95*cc6c5292Schin if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) {
967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ln: %s/%s: Name too long\n",
977c478bd9Sstevel@tonic-gate to, tail);
987c478bd9Sstevel@tonic-gate return (1);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate (void) sprintf(destname, "%s/%s", to, tail);
1017c478bd9Sstevel@tonic-gate to = destname;
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate if ((*linkf)(from, to) < 0) {
1047c478bd9Sstevel@tonic-gate if (errno == EEXIST || sflag)
1057c478bd9Sstevel@tonic-gate Perror(to);
1067c478bd9Sstevel@tonic-gate else if (access(from, 0) < 0)
1077c478bd9Sstevel@tonic-gate Perror(from);
1087c478bd9Sstevel@tonic-gate else
1097c478bd9Sstevel@tonic-gate Perror(to);
1107c478bd9Sstevel@tonic-gate return (1);
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate return (0);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
115*cc6c5292Schin void
Perror(char * s)116*cc6c5292Schin Perror(char *s)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ln: ");
1197c478bd9Sstevel@tonic-gate perror(s);
1207c478bd9Sstevel@tonic-gate }
121