1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)ln.c 4.15 (Berkeley) 02/24/91"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/stat.h> 20 #include <stdio.h> 21 #include <errno.h> 22 #include <string.h> 23 #include <stdlib.h> 24 #include <unistd.h> 25 26 static int dirflag, /* undocumented force flag */ 27 sflag, /* symbolic, not hard, link */ 28 (*linkf)(); /* system link call */ 29 static linkit(), usage(); 30 31 main(argc, argv) 32 int argc; 33 char **argv; 34 { 35 extern int optind; 36 struct stat buf; 37 int ch, exitval, link(), symlink(); 38 char *sourcedir; 39 40 while ((ch = getopt(argc, argv, "Fs")) != EOF) 41 switch((char)ch) { 42 case 'F': 43 dirflag = 1; 44 break; 45 case 's': 46 sflag = 1; 47 break; 48 case '?': 49 default: 50 usage(); 51 } 52 53 argv += optind; 54 argc -= optind; 55 56 linkf = sflag ? symlink : link; 57 58 switch(argc) { 59 case 0: 60 usage(); 61 case 1: /* ln target */ 62 exit(linkit(argv[0], ".", 1)); 63 case 2: /* ln target source */ 64 exit(linkit(argv[0], argv[1], 0)); 65 default: /* ln target1 target2 directory */ 66 sourcedir = argv[argc - 1]; 67 if (stat(sourcedir, &buf)) { 68 (void)fprintf(stderr, 69 "ln: %s: %s\n", sourcedir, strerror(errno)); 70 exit(1); 71 } 72 if (!S_ISDIR(buf.st_mode)) 73 usage(); 74 for (exitval = 0; *argv != sourcedir; ++argv) 75 exitval |= linkit(*argv, sourcedir, 1); 76 exit(exitval); 77 } 78 /* NOTREACHED */ 79 } 80 81 static 82 linkit(target, source, isdir) 83 char *target, *source; 84 int isdir; 85 { 86 struct stat buf; 87 char path[MAXPATHLEN], *cp; 88 89 if (!sflag) { 90 /* if target doesn't exist, quit now */ 91 if (stat(target, &buf)) { 92 (void)fprintf(stderr, 93 "ln: %s: %s\n", target, strerror(errno)); 94 return(1); 95 } 96 /* only symbolic links to directories, unless -F option used */ 97 if (!dirflag && (buf.st_mode & S_IFMT) == S_IFDIR) { 98 (void)printf("ln: %s is a directory.\n", target); 99 return(1); 100 } 101 } 102 103 /* if the source is a directory, append the target's name */ 104 if (isdir || !stat(source, &buf) && (buf.st_mode & S_IFMT) == S_IFDIR) { 105 if (!(cp = rindex(target, '/'))) 106 cp = target; 107 else 108 ++cp; 109 (void)sprintf(path, "%s/%s", source, cp); 110 source = path; 111 } 112 113 if ((*linkf)(target, source)) { 114 (void)fprintf(stderr, "ln: %s: %s\n", source, strerror(errno)); 115 return(1); 116 } 117 return(0); 118 } 119 120 static 121 usage() 122 { 123 (void)fprintf(stderr, 124 "usage:\tln [-s] file1 file2\n\tln [-s] file ... directory\n"); 125 exit(1); 126 } 127