1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific written prior permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 char copyright[] = 15 "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 16 All rights reserved.\n"; 17 #endif /* not lint */ 18 19 #ifndef lint 20 static char sccsid[] = "@(#)ln.c 4.10 (Berkeley) 11/30/87"; 21 #endif /* not lint */ 22 23 #include <sys/param.h> 24 #include <sys/stat.h> 25 #include <stdio.h> 26 #include <errno.h> 27 28 static int fflag, /* undocumented force flag */ 29 sflag, /* symbolic, not hard, link */ 30 (*linkf)(); /* system link call */ 31 32 main(argc, argv) 33 int argc; 34 char **argv; 35 { 36 extern int optind; 37 struct stat buf; 38 int ch, exitval, link(), symlink(); 39 char *sourcedir; 40 41 while ((ch = getopt(argc, argv, "fs")) != EOF) 42 switch((char)ch) { 43 case 'f': 44 fflag = 1; 45 break; 46 case 's': 47 sflag = 1; 48 break; 49 case '?': 50 default: 51 usage(); 52 } 53 54 argv += optind; 55 argc -= optind; 56 57 linkf = sflag ? symlink : link; 58 59 switch(argc) { 60 case 0: 61 usage(); 62 case 1: /* ln target */ 63 exit(linkit(argv[0], ".", 1)); 64 case 2: /* ln target source */ 65 exit(linkit(argv[0], argv[1], 0)); 66 default: /* ln target1 target2 directory */ 67 sourcedir = argv[argc - 1]; 68 if (stat(sourcedir, &buf)) { 69 perror(sourcedir); 70 exit(1); 71 } 72 if ((buf.st_mode & S_IFMT) != S_IFDIR) 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 extern int errno; 87 struct stat buf; 88 char path[MAXPATHLEN], 89 *cp, *rindex(), *strcpy(); 90 91 if (!sflag) { 92 /* if target doesn't exist, quit now */ 93 if (stat(target, &buf)) { 94 perror(target); 95 return(1); 96 } 97 /* only symbolic links to directories, unless -f option used */ 98 if (!fflag && (buf.st_mode & S_IFMT) == S_IFDIR) { 99 printf("%s is a directory.\n", target); 100 return(1); 101 } 102 } 103 104 /* if the source is a directory, append the target's name */ 105 if (isdir || !stat(source, &buf) && (buf.st_mode & S_IFMT) == S_IFDIR) { 106 if (!(cp = rindex(target, '/'))) 107 cp = target; 108 else 109 ++cp; 110 (void)sprintf(path, "%s/%s", source, cp); 111 source = path; 112 } 113 114 if ((*linkf)(target, source)) { 115 perror(source); 116 return(1); 117 } 118 return(0); 119 } 120 121 static 122 usage() 123 { 124 fputs("usage:\tln [-s] targetname [sourcename]\n\tln [-s] targetname1 targetname2 [... targetnameN] sourcedirectory\n", stderr); 125 exit(1); 126 } 127