(root)/
coreutils-9.4/
src/
dirname.c
       1  /* dirname -- strip suffix from file name
       2  
       3     Copyright (C) 1990-2023 Free Software Foundation, Inc.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation, either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Written by David MacKenzie and Jim Meyering. */
      19  
      20  #include <config.h>
      21  #include <getopt.h>
      22  #include <stdio.h>
      23  #include <sys/types.h>
      24  
      25  #include "system.h"
      26  
      27  /* The official name of this program (e.g., no 'g' prefix).  */
      28  #define PROGRAM_NAME "dirname"
      29  
      30  #define AUTHORS \
      31    proper_name ("David MacKenzie"), \
      32    proper_name ("Jim Meyering")
      33  
      34  static struct option const longopts[] =
      35  {
      36    {"zero", no_argument, nullptr, 'z'},
      37    {GETOPT_HELP_OPTION_DECL},
      38    {GETOPT_VERSION_OPTION_DECL},
      39    {nullptr, 0, nullptr, 0}
      40  };
      41  
      42  void
      43  usage (int status)
      44  {
      45    if (status != EXIT_SUCCESS)
      46      emit_try_help ();
      47    else
      48      {
      49        printf (_("\
      50  Usage: %s [OPTION] NAME...\n\
      51  "),
      52                program_name);
      53        fputs (_("\
      54  Output each NAME with its last non-slash component and trailing slashes\n\
      55  removed; if NAME contains no /'s, output '.' (meaning the current directory).\n\
      56  \n\
      57  "), stdout);
      58        fputs (_("\
      59    -z, --zero     end each output line with NUL, not newline\n\
      60  "), stdout);
      61        fputs (HELP_OPTION_DESCRIPTION, stdout);
      62        fputs (VERSION_OPTION_DESCRIPTION, stdout);
      63        printf (_("\
      64  \n\
      65  Examples:\n\
      66    %s /usr/bin/          -> \"/usr\"\n\
      67    %s dir1/str dir2/str  -> \"dir1\" followed by \"dir2\"\n\
      68    %s stdio.h            -> \".\"\n\
      69  "),
      70                program_name, program_name, program_name);
      71        emit_ancillary_info (PROGRAM_NAME);
      72      }
      73    exit (status);
      74  }
      75  
      76  int
      77  main (int argc, char **argv)
      78  {
      79    static char const dot = '.';
      80    bool use_nuls = false;
      81    char const *result;
      82    size_t len;
      83  
      84    initialize_main (&argc, &argv);
      85    set_program_name (argv[0]);
      86    setlocale (LC_ALL, "");
      87    bindtextdomain (PACKAGE, LOCALEDIR);
      88    textdomain (PACKAGE);
      89  
      90    atexit (close_stdout);
      91  
      92    while (true)
      93      {
      94        int c = getopt_long (argc, argv, "z", longopts, nullptr);
      95  
      96        if (c == -1)
      97          break;
      98  
      99        switch (c)
     100          {
     101          case 'z':
     102            use_nuls = true;
     103            break;
     104  
     105          case_GETOPT_HELP_CHAR;
     106          case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
     107  
     108          default:
     109            usage (EXIT_FAILURE);
     110          }
     111      }
     112  
     113    if (argc < optind + 1)
     114      {
     115        error (0, 0, _("missing operand"));
     116        usage (EXIT_FAILURE);
     117      }
     118  
     119    for (; optind < argc; optind++)
     120      {
     121        result = argv[optind];
     122        len = dir_len (result);
     123  
     124        if (! len)
     125          {
     126            result = &dot;
     127            len = 1;
     128          }
     129  
     130        fwrite (result, 1, len, stdout);
     131        putchar (use_nuls ? '\0' :'\n');
     132      }
     133  
     134    return EXIT_SUCCESS;
     135  }