~ubuntu-branches/ubuntu/precise/parted/precise

« back to all changes in this revision

Viewing changes to gnulib/lib/closein.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2010-02-06 16:39:19 UTC
  • mfrom: (1.1.5 upstream)
  • mto: (7.3.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 48.
  • Revision ID: james.westby@ubuntu.com-20100206163919-nsxr2vtchk0ecabf
Tags: upstream-2.1
ImportĀ upstreamĀ versionĀ 2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Close standard input, rewinding seekable stdin if necessary.
2
 
 
3
 
   Copyright (C) 2007 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 2, or (at your option)
8
 
   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, write to the Free Software Foundation,
17
 
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18
 
 
19
 
#include <config.h>
20
 
 
21
 
#include "closein.h"
22
 
 
23
 
#include <errno.h>
24
 
#include <stdbool.h>
25
 
#include <stdio.h>
26
 
#include <unistd.h>
27
 
 
28
 
#include "gettext.h"
29
 
#define _(msgid) gettext (msgid)
30
 
 
31
 
#include "close-stream.h"
32
 
#include "closeout.h"
33
 
#include "error.h"
34
 
#include "exitfail.h"
35
 
#include "quotearg.h"
36
 
 
37
 
static const char *file_name;
38
 
 
39
 
/* Set the file name to be reported in the event an error is detected
40
 
   on stdin by close_stdin.  See also close_stdout_set_file_name, if
41
 
   an error is detected when closing stdout.  */
42
 
void
43
 
close_stdin_set_file_name (const char *file)
44
 
{
45
 
  file_name = file;
46
 
}
47
 
 
48
 
/* Close standard input, rewinding any unused input if stdin is
49
 
   seekable.  On error, issue a diagnostic and _exit with status
50
 
   'exit_failure'.  Then call close_stdout.
51
 
 
52
 
   Most programs can get by with close_stdout.  close_stdin is only
53
 
   needed when a program wants to guarantee that partially read input
54
 
   from seekable stdin is not consumed, for any subsequent clients.
55
 
   For example, POSIX requires that these two commands behave alike:
56
 
 
57
 
     (sed -ne 1q; cat) < file
58
 
     tail -n 1 file
59
 
 
60
 
   Since close_stdin is commonly registered via 'atexit', POSIX
61
 
   and the C standard both say that it should not call 'exit',
62
 
   because the behavior is undefined if 'exit' is called more than
63
 
   once.  So it calls '_exit' instead of 'exit'.  If close_stdin
64
 
   is registered via atexit before other functions are registered,
65
 
   the other functions can act before this _exit is invoked.
66
 
 
67
 
   Applications that use close_stdout should flush any streams other
68
 
   than stdin, stdout, and stderr before exiting, since the call to
69
 
   _exit will bypass other buffer flushing.  Applications should be
70
 
   flushing and closing other streams anyway, to check for I/O errors.
71
 
   Also, applications should not use tmpfile, since _exit can bypass
72
 
   the removal of these files.
73
 
 
74
 
   It's important to detect such failures and exit nonzero because many
75
 
   tools (most notably `make' and other build-management systems) depend
76
 
   on being able to detect failure in other tools via their exit status.  */
77
 
 
78
 
void
79
 
close_stdin (void)
80
 
{
81
 
  bool fail = false;
82
 
 
83
 
  /* Only attempt flush if stdin is seekable, as fflush is entitled to
84
 
     fail on non-seekable streams.  */
85
 
  if (fseeko (stdin, 0, SEEK_CUR) == 0 && fflush (stdin) != 0)
86
 
    fail = true;
87
 
  if (close_stream (stdin) != 0)
88
 
    fail = true;
89
 
  if (fail)
90
 
    {
91
 
      /* Report failure, but defer exit until after closing stdout,
92
 
         since the failure report should still be flushed.  */
93
 
      char const *close_error = _("error closing file");
94
 
      if (file_name)
95
 
        error (0, errno, "%s: %s", quotearg_colon (file_name),
96
 
               close_error);
97
 
      else
98
 
        error (0, errno, "%s", close_error);
99
 
    }
100
 
 
101
 
  close_stdout ();
102
 
 
103
 
  if (fail)
104
 
    _exit (exit_failure);
105
 
}