~ubuntu-branches/ubuntu/precise/util-linux/precise

« back to all changes in this revision

Viewing changes to term-utils/ttymsg.c

  • Committer: Package Import Robot
  • Author(s): Steve Langasek
  • Date: 2011-12-16 22:53:42 UTC
  • mfrom: (1.6.4) (4.5.5 sid)
  • Revision ID: package-import@ubuntu.com-20111216225342-206wz4bhvutyvx0d
Tags: 2.20.1-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Build for multiarch.
  - Add pre-depends on multiarch-support.
  - configure.ac: don't try to be clever about extracting a path name from
    $libdir to append to /usr in a way that's not overridable; instead,
    reuse the built-in configurable libexecdir.
  - Fix up the .pc.in files to know about libexecdir, so our substitutions
    don't leave us with unusable pkg-config files.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.
  - Since upstart is required in Ubuntu, the hwclock.sh init script is not
    called on startup and the hwclockfirst.sh init script is removed.
  - Drop depends on initscripts for the above.
  - Replace hwclock udev rule with an Upstart job.
  - For the case where mount is called with a directory to mount, look
    that directory up in mountall's /lib/init/fstab if we couldn't find
    it mentioned anywhere else.  This means "mount /proc", "mount /sys",
    etc. work.
  - mount.8 points to the cifs-utils package, not the obsolete smbfs one. 
  - Use canonicalize_spec in getmntdevbackward. proc should not be
    interpreted as a non-canonical-path.
* Dropped changes, superseded upstream:
  - shlibs/mount/src/tab_update.c: don't refuse to update mtab when source
    is 'none'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1989, 1993
 
3
 *      The Regents of the University of California.  All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 * 3. All advertising materials mentioning features or use of this software
 
14
 *    must display the following acknowledgement:
 
15
 *      This product includes software developed by the University of
 
16
 *      California, Berkeley and its contributors.
 
17
 * 4. Neither the name of the University nor the names of its contributors
 
18
 *    may be used to endorse or promote products derived from this software
 
19
 *    without specific prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
31
 * SUCH DAMAGE.
 
32
 *
 
33
 * Modified Sun Mar 12 10:39:22 1995, faith@cs.unc.edu for Linux
 
34
 *
 
35
 */
 
36
 
 
37
 /* 1999-02-22 Arkadiusz Mi�kiewicz <misiek@pld.ORG.PL>
 
38
  * - added Native Language Support
 
39
  * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 
40
  * - fixed strerr(errno) in gettext calls
 
41
  */
 
42
 
 
43
#include <sys/types.h>
 
44
#include <sys/uio.h>
 
45
#include <signal.h>
 
46
#include <fcntl.h>
 
47
#include <dirent.h>
 
48
#include <errno.h>
 
49
#include <paths.h>
 
50
#include <unistd.h>
 
51
#include <stdio.h>
 
52
#include <string.h>
 
53
#include <stdlib.h>
 
54
#include "nls.h"
 
55
 
 
56
#include "pathnames.h"
 
57
#include "ttymsg.h"
 
58
 
 
59
/*
 
60
 * Display the contents of a uio structure on a terminal.  Used by wall(1),
 
61
 * syslogd(8), and talkd(8).  Forks and finishes in child if write would block,
 
62
 * waiting up to tmout seconds.  Returns pointer to error string on unexpected
 
63
 * error; string is not newline-terminated.  Various "normal" errors are
 
64
 * ignored (exclusive-use, lack of permission, etc.).
 
65
 */
 
66
char *
 
67
ttymsg(struct iovec *iov, size_t iovcnt, char *line, int tmout) {
 
68
        static char device[MAXNAMLEN];
 
69
        static char errbuf[MAXNAMLEN+1024];
 
70
        size_t cnt, left;
 
71
        ssize_t wret;
 
72
        struct iovec localiov[6];
 
73
        int fd, forked = 0, errsv;
 
74
 
 
75
        if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
 
76
                return (_("too many iov's (change code in wall/ttymsg.c)"));
 
77
 
 
78
        /* The old code here rejected the line argument when it contained a '/',
 
79
           saying: "A slash may be an attempt to break security...".
 
80
           However, if a user can control the line argument here
 
81
           then he can make this routine write to /dev/hda or /dev/sda
 
82
           already. So, this test was worthless, and these days it is
 
83
           also wrong since people use /dev/pts/xxx. */
 
84
 
 
85
        if (strlen(line) + sizeof(_PATH_DEV) + 1 > sizeof(device)) {
 
86
                (void) sprintf(errbuf, _("excessively long line arg"));
 
87
                return (errbuf);
 
88
        }
 
89
        (void) sprintf(device, "%s%s", _PATH_DEV, line);
 
90
 
 
91
        /*
 
92
         * open will fail on slip lines or exclusive-use lines
 
93
         * if not running as root; not an error.
 
94
         */
 
95
        if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
 
96
                if (errno == EBUSY || errno == EACCES)
 
97
                        return (NULL);
 
98
                if (strlen(strerror(errno)) > 1000)
 
99
                        return (NULL);
 
100
                (void) sprintf(errbuf, "%s: %s", device, strerror(errno));
 
101
                errbuf[1024] = 0;
 
102
                return (errbuf);
 
103
        }
 
104
 
 
105
        for (cnt = left = 0; cnt < iovcnt; ++cnt)
 
106
                left += iov[cnt].iov_len;
 
107
 
 
108
        for (;;) {
 
109
                wret = writev(fd, iov, iovcnt);
 
110
                if (wret >= (ssize_t) left)
 
111
                        break;
 
112
                if (wret >= 0) {
 
113
                        left -= wret;
 
114
                        if (iov != localiov) {
 
115
                                memmove(localiov, iov,
 
116
                                    iovcnt * sizeof(struct iovec));
 
117
                                iov = localiov;
 
118
                        }
 
119
                        for (cnt = 0; wret >= (ssize_t) iov->iov_len; ++cnt) {
 
120
                                wret -= iov->iov_len;
 
121
                                ++iov;
 
122
                                --iovcnt;
 
123
                        }
 
124
                        if (wret) {
 
125
                                iov->iov_base = (char *) iov->iov_base + wret;
 
126
                                iov->iov_len -= wret;
 
127
                        }
 
128
                        continue;
 
129
                }
 
130
                if (errno == EWOULDBLOCK) {
 
131
                        int cpid, flags;
 
132
                        sigset_t sigmask;
 
133
 
 
134
                        if (forked) {
 
135
                                (void) close(fd);
 
136
                                _exit(EXIT_FAILURE);
 
137
                        }
 
138
                        cpid = fork();
 
139
                        if (cpid < 0) {
 
140
                                if (strlen(strerror(errno)) > 1000)
 
141
                                        (void) sprintf(errbuf, _("cannot fork"));
 
142
                                else {
 
143
                                        errsv = errno;
 
144
                                        (void) sprintf(errbuf,
 
145
                                                 _("fork: %s"), strerror(errsv));
 
146
                                }
 
147
                                (void) close(fd);
 
148
                                return (errbuf);
 
149
                        }
 
150
                        if (cpid) {     /* parent */
 
151
                                (void) close(fd);
 
152
                                return (NULL);
 
153
                        }
 
154
                        forked++;
 
155
                        /* wait at most tmout seconds */
 
156
                        (void) signal(SIGALRM, SIG_DFL);
 
157
                        (void) signal(SIGTERM, SIG_DFL); /* XXX */
 
158
                        sigemptyset(&sigmask);
 
159
                        sigprocmask (SIG_SETMASK, &sigmask, NULL);
 
160
                        (void) alarm((u_int)tmout);
 
161
                        flags = fcntl(fd, F_GETFL);
 
162
                        fcntl(flags, F_SETFL, (long) (flags & ~O_NONBLOCK));
 
163
                        continue;
 
164
                }
 
165
                /*
 
166
                 * We get ENODEV on a slip line if we're running as root,
 
167
                 * and EIO if the line just went away.
 
168
                 */
 
169
                if (errno == ENODEV || errno == EIO)
 
170
                        break;
 
171
                (void) close(fd);
 
172
                if (forked)
 
173
                        _exit(EXIT_FAILURE);
 
174
                if (strlen(strerror(errno)) > 1000)
 
175
                        (void) sprintf(errbuf, _("%s: BAD ERROR, message is "
 
176
                                                 "far too long"), device);
 
177
                else {
 
178
                        errsv = errno;
 
179
                        (void) sprintf(errbuf, "%s: %s", device,
 
180
                                       strerror(errsv));
 
181
                }
 
182
                errbuf[1024] = 0;
 
183
                return (errbuf);
 
184
        }
 
185
 
 
186
        (void) close(fd);
 
187
        if (forked)
 
188
                _exit(EXIT_SUCCESS);
 
189
        return (NULL);
 
190
}