1*cc6c5292Schin /* 2*cc6c5292Schin * Copyright 1991 Sun Microsystems, Inc. All rights reserved. 3*cc6c5292Schin * Use is subject to license terms. 4*cc6c5292Schin */ 5*cc6c5292Schin 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 15*cc6c5292Schin #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate /* 187c478bd9Sstevel@tonic-gate * ln 197c478bd9Sstevel@tonic-gate */ 207c478bd9Sstevel@tonic-gate #include <stdio.h> 217c478bd9Sstevel@tonic-gate #include <sys/types.h> 227c478bd9Sstevel@tonic-gate #include <sys/param.h> 237c478bd9Sstevel@tonic-gate #include <sys/stat.h> 247c478bd9Sstevel@tonic-gate #include <errno.h> 25*cc6c5292Schin #include <unistd.h> 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate struct stat stb; 287c478bd9Sstevel@tonic-gate int fflag; /* force flag set? */ 297c478bd9Sstevel@tonic-gate int sflag; 307c478bd9Sstevel@tonic-gate 31*cc6c5292Schin int linkit(char *, char *); 32*cc6c5292Schin void Perror(char *); 33*cc6c5292Schin 34*cc6c5292Schin int 35*cc6c5292Schin main(int argc, char **argv) 367c478bd9Sstevel@tonic-gate { 37*cc6c5292Schin int i, r; 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate argc--, argv++; 407c478bd9Sstevel@tonic-gate again: 417c478bd9Sstevel@tonic-gate if (argc && strcmp(argv[0], "-f") == 0) { 427c478bd9Sstevel@tonic-gate fflag++; 437c478bd9Sstevel@tonic-gate argv++; 447c478bd9Sstevel@tonic-gate argc--; 457c478bd9Sstevel@tonic-gate } 467c478bd9Sstevel@tonic-gate if (argc && strcmp(argv[0], "-s") == 0) { 477c478bd9Sstevel@tonic-gate sflag++; 487c478bd9Sstevel@tonic-gate argv++; 497c478bd9Sstevel@tonic-gate argc--; 507c478bd9Sstevel@tonic-gate } 517c478bd9Sstevel@tonic-gate if (argc == 0) 527c478bd9Sstevel@tonic-gate goto usage; 537c478bd9Sstevel@tonic-gate else if (argc == 1) { 547c478bd9Sstevel@tonic-gate argv[argc] = "."; 557c478bd9Sstevel@tonic-gate argc++; 567c478bd9Sstevel@tonic-gate } 577c478bd9Sstevel@tonic-gate if (argc > 2) { 587c478bd9Sstevel@tonic-gate if (stat(argv[argc-1], &stb) < 0) 597c478bd9Sstevel@tonic-gate goto usage; 607c478bd9Sstevel@tonic-gate if ((stb.st_mode&S_IFMT) != S_IFDIR) 617c478bd9Sstevel@tonic-gate goto usage; 627c478bd9Sstevel@tonic-gate } 637c478bd9Sstevel@tonic-gate r = 0; 647c478bd9Sstevel@tonic-gate for (i = 0; i < argc-1; i++) 657c478bd9Sstevel@tonic-gate r |= linkit(argv[i], argv[argc-1]); 667c478bd9Sstevel@tonic-gate exit(r); 677c478bd9Sstevel@tonic-gate usage: 687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 697c478bd9Sstevel@tonic-gate "Usage: ln [-f] [-s] f1\n\ 707c478bd9Sstevel@tonic-gate ln [-f] [-s] f1 f2\n\ 717c478bd9Sstevel@tonic-gate ln [-f] [-s] f1 ... fn d1\n"); 72*cc6c5292Schin return (1); 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate 75*cc6c5292Schin int 76*cc6c5292Schin linkit(char *from, char *to) 777c478bd9Sstevel@tonic-gate { 787c478bd9Sstevel@tonic-gate char destname[MAXPATHLEN + 1]; 797c478bd9Sstevel@tonic-gate char *tail; 807c478bd9Sstevel@tonic-gate int (*linkf)() = sflag ? symlink : link; 817c478bd9Sstevel@tonic-gate char *strrchr(); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* is target a directory? */ 84*cc6c5292Schin if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 && 85*cc6c5292Schin (stb.st_mode&S_IFMT) == S_IFDIR) { 867c478bd9Sstevel@tonic-gate printf("%s is a directory\n", from); 877c478bd9Sstevel@tonic-gate return (1); 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) { 907c478bd9Sstevel@tonic-gate tail = strrchr(from, '/'); 917c478bd9Sstevel@tonic-gate if (tail == 0) 927c478bd9Sstevel@tonic-gate tail = from; 937c478bd9Sstevel@tonic-gate else 947c478bd9Sstevel@tonic-gate tail++; 95*cc6c5292Schin if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) { 967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ln: %s/%s: Name too long\n", 977c478bd9Sstevel@tonic-gate to, tail); 987c478bd9Sstevel@tonic-gate return (1); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate (void) sprintf(destname, "%s/%s", to, tail); 1017c478bd9Sstevel@tonic-gate to = destname; 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate if ((*linkf)(from, to) < 0) { 1047c478bd9Sstevel@tonic-gate if (errno == EEXIST || sflag) 1057c478bd9Sstevel@tonic-gate Perror(to); 1067c478bd9Sstevel@tonic-gate else if (access(from, 0) < 0) 1077c478bd9Sstevel@tonic-gate Perror(from); 1087c478bd9Sstevel@tonic-gate else 1097c478bd9Sstevel@tonic-gate Perror(to); 1107c478bd9Sstevel@tonic-gate return (1); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate return (0); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 115*cc6c5292Schin void 116*cc6c5292Schin Perror(char *s) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ln: "); 1197c478bd9Sstevel@tonic-gate perror(s); 1207c478bd9Sstevel@tonic-gate } 121