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
157c478bd9Sstevel@tonic-gate /*
167c478bd9Sstevel@tonic-gate * ln
177c478bd9Sstevel@tonic-gate */
187c478bd9Sstevel@tonic-gate #include <stdio.h>
197c478bd9Sstevel@tonic-gate #include <sys/types.h>
207c478bd9Sstevel@tonic-gate #include <sys/param.h>
217c478bd9Sstevel@tonic-gate #include <sys/stat.h>
227c478bd9Sstevel@tonic-gate #include <errno.h>
23*cc6c5292Schin #include <unistd.h>
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate struct stat stb;
267c478bd9Sstevel@tonic-gate int fflag; /* force flag set? */
277c478bd9Sstevel@tonic-gate int sflag;
287c478bd9Sstevel@tonic-gate
29*cc6c5292Schin int linkit(char *, char *);
30*cc6c5292Schin void Perror(char *);
31*cc6c5292Schin
32*cc6c5292Schin int
main(int argc,char ** argv)33*cc6c5292Schin main(int argc, char **argv)
347c478bd9Sstevel@tonic-gate {
35*cc6c5292Schin int i, r;
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate argc--, argv++;
387c478bd9Sstevel@tonic-gate again:
397c478bd9Sstevel@tonic-gate if (argc && strcmp(argv[0], "-f") == 0) {
407c478bd9Sstevel@tonic-gate fflag++;
417c478bd9Sstevel@tonic-gate argv++;
427c478bd9Sstevel@tonic-gate argc--;
437c478bd9Sstevel@tonic-gate }
447c478bd9Sstevel@tonic-gate if (argc && strcmp(argv[0], "-s") == 0) {
457c478bd9Sstevel@tonic-gate sflag++;
467c478bd9Sstevel@tonic-gate argv++;
477c478bd9Sstevel@tonic-gate argc--;
487c478bd9Sstevel@tonic-gate }
497c478bd9Sstevel@tonic-gate if (argc == 0)
507c478bd9Sstevel@tonic-gate goto usage;
517c478bd9Sstevel@tonic-gate else if (argc == 1) {
527c478bd9Sstevel@tonic-gate argv[argc] = ".";
537c478bd9Sstevel@tonic-gate argc++;
547c478bd9Sstevel@tonic-gate }
557c478bd9Sstevel@tonic-gate if (argc > 2) {
567c478bd9Sstevel@tonic-gate if (stat(argv[argc-1], &stb) < 0)
577c478bd9Sstevel@tonic-gate goto usage;
587c478bd9Sstevel@tonic-gate if ((stb.st_mode&S_IFMT) != S_IFDIR)
597c478bd9Sstevel@tonic-gate goto usage;
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate r = 0;
627c478bd9Sstevel@tonic-gate for (i = 0; i < argc-1; i++)
637c478bd9Sstevel@tonic-gate r |= linkit(argv[i], argv[argc-1]);
647c478bd9Sstevel@tonic-gate exit(r);
657c478bd9Sstevel@tonic-gate usage:
667c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
677c478bd9Sstevel@tonic-gate "Usage: ln [-f] [-s] f1\n\
687c478bd9Sstevel@tonic-gate ln [-f] [-s] f1 f2\n\
697c478bd9Sstevel@tonic-gate ln [-f] [-s] f1 ... fn d1\n");
70*cc6c5292Schin return (1);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate
73*cc6c5292Schin int
linkit(char * from,char * to)74*cc6c5292Schin linkit(char *from, char *to)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate char destname[MAXPATHLEN + 1];
777c478bd9Sstevel@tonic-gate char *tail;
787c478bd9Sstevel@tonic-gate int (*linkf)() = sflag ? symlink : link;
797c478bd9Sstevel@tonic-gate char *strrchr();
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate /* is target a directory? */
82*cc6c5292Schin if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 &&
83*cc6c5292Schin (stb.st_mode&S_IFMT) == S_IFDIR) {
847c478bd9Sstevel@tonic-gate printf("%s is a directory\n", from);
857c478bd9Sstevel@tonic-gate return (1);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) {
887c478bd9Sstevel@tonic-gate tail = strrchr(from, '/');
897c478bd9Sstevel@tonic-gate if (tail == 0)
907c478bd9Sstevel@tonic-gate tail = from;
917c478bd9Sstevel@tonic-gate else
927c478bd9Sstevel@tonic-gate tail++;
93*cc6c5292Schin if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) {
947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ln: %s/%s: Name too long\n",
957c478bd9Sstevel@tonic-gate to, tail);
967c478bd9Sstevel@tonic-gate return (1);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate (void) sprintf(destname, "%s/%s", to, tail);
997c478bd9Sstevel@tonic-gate to = destname;
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate if ((*linkf)(from, to) < 0) {
1027c478bd9Sstevel@tonic-gate if (errno == EEXIST || sflag)
1037c478bd9Sstevel@tonic-gate Perror(to);
1047c478bd9Sstevel@tonic-gate else if (access(from, 0) < 0)
1057c478bd9Sstevel@tonic-gate Perror(from);
1067c478bd9Sstevel@tonic-gate else
1077c478bd9Sstevel@tonic-gate Perror(to);
1087c478bd9Sstevel@tonic-gate return (1);
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate return (0);
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate
113*cc6c5292Schin void
Perror(char * s)114*cc6c5292Schin Perror(char *s)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ln: ");
1177c478bd9Sstevel@tonic-gate perror(s);
1187c478bd9Sstevel@tonic-gate }
119