| /* |
| * Copyright 1991 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ |
| /* All Rights Reserved */ |
| |
| /* |
| * Copyright (c) 1980 Regents of the University of California. |
| * All rights reserved. The Berkeley software License Agreement |
| * specifies the terms and conditions for redistribution. |
| */ |
| |
| #pragma ident "%Z%%M% %I% %E% SMI" |
| |
| /* |
| * ln |
| */ |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <sys/param.h> |
| #include <sys/stat.h> |
| #include <errno.h> |
| #include <unistd.h> |
| |
| struct stat stb; |
| int fflag; /* force flag set? */ |
| int sflag; |
| |
| int linkit(char *, char *); |
| void Perror(char *); |
| |
| int |
| main(int argc, char **argv) |
| { |
| int i, r; |
| |
| argc--, argv++; |
| again: |
| if (argc && strcmp(argv[0], "-f") == 0) { |
| fflag++; |
| argv++; |
| argc--; |
| } |
| if (argc && strcmp(argv[0], "-s") == 0) { |
| sflag++; |
| argv++; |
| argc--; |
| } |
| if (argc == 0) |
| goto usage; |
| else if (argc == 1) { |
| argv[argc] = "."; |
| argc++; |
| } |
| if (argc > 2) { |
| if (stat(argv[argc-1], &stb) < 0) |
| goto usage; |
| if ((stb.st_mode&S_IFMT) != S_IFDIR) |
| goto usage; |
| } |
| r = 0; |
| for (i = 0; i < argc-1; i++) |
| r |= linkit(argv[i], argv[argc-1]); |
| exit(r); |
| usage: |
| (void) fprintf(stderr, |
| "Usage: ln [-f] [-s] f1\n\ |
| ln [-f] [-s] f1 f2\n\ |
| ln [-f] [-s] f1 ... fn d1\n"); |
| return (1); |
| } |
| |
| int |
| linkit(char *from, char *to) |
| { |
| char destname[MAXPATHLEN + 1]; |
| char *tail; |
| int (*linkf)() = sflag ? symlink : link; |
| char *strrchr(); |
| |
| /* is target a directory? */ |
| if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 && |
| (stb.st_mode&S_IFMT) == S_IFDIR) { |
| printf("%s is a directory\n", from); |
| return (1); |
| } |
| if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) { |
| tail = strrchr(from, '/'); |
| if (tail == 0) |
| tail = from; |
| else |
| tail++; |
| if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) { |
| (void) fprintf(stderr, "ln: %s/%s: Name too long\n", |
| to, tail); |
| return (1); |
| } |
| (void) sprintf(destname, "%s/%s", to, tail); |
| to = destname; |
| } |
| if ((*linkf)(from, to) < 0) { |
| if (errno == EEXIST || sflag) |
| Perror(to); |
| else if (access(from, 0) < 0) |
| Perror(from); |
| else |
| Perror(to); |
| return (1); |
| } |
| return (0); |
| } |
| |
| void |
| Perror(char *s) |
| { |
| (void) fprintf(stderr, "ln: "); |
| perror(s); |
| } |