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