1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1992-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * * 20 ***********************************************************************/ 21 #pragma prototyped 22 /* 23 * David Korn 24 * AT&T Bell Laboratories 25 * 26 * dirname path [suffix] 27 * 28 * print the dirname of a pathname 29 */ 30 31 static const char usage[] = 32 "[-?\n@(#)$Id: dirname (AT&T Research) 2000-03-07 $\n]" 33 USAGE_LICENSE 34 "[+NAME?dirname - return directory portion of file name]" 35 "[+DESCRIPTION?\bdirname\b treats \astring\a as a file name and returns " 36 "the name of the directory containing the file name by deleting " 37 "the last component from \astring\a.]" 38 "[+?If \astring\a consists solely of \b/\b characters the output will " 39 "be a single \b/\b unless \bPATH_LEADING_SLASHES\b returned by " 40 "\bgetconf\b(1) is \b1\b and \astring\a consists of multiple " 41 "\b/\b characters in which case \b//\b will be output. " 42 "Otherwise, trailing \b/\b characters are removed, and if " 43 "there are no remaining \b/\b characters in \astring\a, " 44 "the string \b.\b will be written to standard output. " 45 "Otherwise, all characters following the last \b/\b are removed. " 46 "If the remaining string consists solely of \b/\b characters, " 47 "the output will be as if the original string had consisted solely " 48 "as \b/\b characters as described above. Otherwise, all " 49 "trailing slashes are removed and the output will be this string " 50 "unless this string is empty. If empty the output will be \b.\b.]" 51 "\n" 52 "\n string\n" 53 "\n" 54 "[+EXIT STATUS?]{" 55 "[+0?Successful Completion.]" 56 "[+>0?An error occurred.]" 57 "}" 58 "[+SEE ALSO?\bbasename\b(1), \bgetconf\b(1), \bdirname\b(3)]" 59 ; 60 61 #include <cmd.h> 62 63 static void l_dirname(register Sfio_t *outfile, register const char *pathname) 64 { 65 register const char *last; 66 /* go to end of path */ 67 for(last=pathname; *last; last++); 68 /* back over trailing '/' */ 69 while(last>pathname && *--last=='/'); 70 /* back over non-slash chars */ 71 for(;last>pathname && *last!='/';last--); 72 if(last==pathname) 73 { 74 /* all '/' or "" */ 75 if(*pathname!='/') 76 last = pathname = "."; 77 } 78 else 79 { 80 /* back over trailing '/' */ 81 for(;*last=='/' && last > pathname; last--); 82 } 83 /* preserve // */ 84 if(last!=pathname && pathname[0]=='/' && pathname[1]=='/') 85 { 86 while(pathname[2]=='/' && pathname<last) 87 pathname++; 88 if(last!=pathname && pathname[0]=='/' && pathname[1]=='/' && *astconf("PATH_LEADING_SLASHES",NiL,NiL)!='1') 89 pathname++; 90 } 91 sfwrite(outfile,pathname,last+1-pathname); 92 sfputc(outfile,'\n'); 93 } 94 95 int 96 b_dirname(int argc,register char *argv[], void* context) 97 { 98 register int n; 99 100 cmdinit(argc, argv, context, ERROR_CATALOG, 0); 101 while (n = optget(argv, usage)) switch (n) 102 { 103 case ':': 104 error(2, "%s", opt_info.arg); 105 break; 106 case '?': 107 error(ERROR_usage(2), "%s", opt_info.arg); 108 break; 109 } 110 argv += opt_info.index; 111 argc -= opt_info.index; 112 if(error_info.errors || argc != 1) 113 error(ERROR_usage(2),"%s", optusage(NiL)); 114 l_dirname(sfstdout,argv[0]); 115 return(0); 116 } 117