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