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