Back to index

glibc  2.9
pt_chown.c
Go to the documentation of this file.
00001 /* pt_chmod - helper program for `grantpt'.
00002    Copyright (C) 1998, 1999 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <argp.h>
00022 #include <errno.h>
00023 #include <error.h>
00024 #include <grp.h>
00025 #include <libintl.h>
00026 #include <locale.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <sys/stat.h>
00031 #include <unistd.h>
00032 
00033 #include "pty-private.h"
00034 
00035 /* Get libc version number.  */
00036 #include "../version.h"
00037 
00038 #define PACKAGE _libc_intl_domainname
00039 
00040 /* Name and version of program.  */
00041 static void print_version (FILE *stream, struct argp_state *state);
00042 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
00043 
00044 /* Function to print some extra text in the help message.  */
00045 static char *more_help (int key, const char *text, void *input);
00046 
00047 /* Data structure to communicate with argp functions.  */
00048 static struct argp argp =
00049 {
00050   NULL, NULL, NULL, NULL, NULL, more_help
00051 };
00052 
00053 
00054 /* Print the version information.  */
00055 static void
00056 print_version (FILE *stream, struct argp_state *state)
00057 {
00058   fprintf (stream, "pt_chown (GNU %s) %s\n", PACKAGE, VERSION);
00059   fprintf (stream, gettext ("\
00060 Copyright (C) %s Free Software Foundation, Inc.\n\
00061 This is free software; see the source for copying conditions.  There is NO\n\
00062 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
00063 "), "1999");
00064 }
00065 
00066 static char *
00067 more_help (int key, const char *text, void *input)
00068 {
00069   char *cp;
00070 
00071   switch (key)
00072     {
00073     case ARGP_KEY_HELP_PRE_DOC:
00074       asprintf (&cp, gettext ("\
00075 Set the owner, group and access permission of the slave pseudo\
00076  terminal corresponding to the master pseudo terminal passed on\
00077  file descriptor `%d'.  This is the helper program for the\
00078  `grantpt' function.  It is not intended to be run directly from\
00079  the command line.\n"),
00080               PTY_FILENO);
00081       return cp;
00082     case ARGP_KEY_HELP_EXTRA:
00083       /* We print some extra information.  */
00084       asprintf (&cp, gettext ("\
00085 The owner is set to the current user, the group is set to `%s',\
00086  and the access permission is set to `%o'.\n\n\
00087 %s"),
00088               TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, gettext ("\
00089 For bug reporting instructions, please see:\n\
00090 <http://www.gnu.org/software/libc/bugs.html>.\n"));
00091       return cp;
00092     default:
00093       break;
00094     }
00095   return (char *) text;
00096 }
00097 
00098 static int
00099 do_pt_chown (void)
00100 {
00101   char *pty;
00102   struct stat st;
00103   struct group *p;
00104   gid_t gid;
00105 
00106   /* Check that PTY_FILENO is a valid master pseudo terminal.  */
00107   pty = ptsname (PTY_FILENO);
00108   if (pty == NULL)
00109     return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL;
00110 
00111   /* Check that the returned slave pseudo terminal is a
00112      character device.  */
00113   if (stat (pty, &st) < 0 || !S_ISCHR(st.st_mode))
00114     return FAIL_EINVAL;
00115 
00116   /* Get the group ID of the special `tty' group.  */
00117   p = getgrnam (TTY_GROUP);
00118   gid = p ? p->gr_gid : getgid ();
00119 
00120   /* Set the owner to the real user ID, and the group to that special
00121      group ID.  */
00122   if (chown (pty, getuid (), gid) < 0)
00123     return FAIL_EACCES;
00124 
00125   /* Set the permission mode to readable and writable by the owner,
00126      and writable by the group.  */
00127   if (chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
00128     return FAIL_EACCES;
00129 
00130   return 0;
00131 }
00132 
00133 
00134 int
00135 main (int argc, char *argv[])
00136 {
00137   uid_t euid = geteuid ();
00138   int remaining;
00139 
00140   /* Normal invocation of this program is with no arguments and
00141      with privileges.
00142      FIXME: Should use capable (CAP_CHOWN|CAP_FOWNER).  */
00143   if (argc == 1 && euid == 0)
00144     return do_pt_chown ();
00145 
00146   /* We aren't going to be using privileges, so drop them right now. */
00147   setuid (getuid ());
00148 
00149   /* Set locale via LC_ALL.  */
00150   setlocale (LC_ALL, "");
00151 
00152   /* Set the text message domain.  */
00153   textdomain (PACKAGE);
00154 
00155   /* parse and process arguments.  */
00156   argp_parse (&argp, argc, argv, 0, &remaining, NULL);
00157 
00158   if (remaining < argc)
00159     {
00160       /* We should not be called with any non-option parameters.  */
00161       error (0, 0, gettext ("too many arguments"));
00162       argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
00163                program_invocation_short_name);
00164       return EXIT_FAILURE;
00165     }
00166 
00167   /* Check if we are properly installed.  */
00168   if (euid != 0)
00169     error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));
00170 
00171   return EXIT_SUCCESS;
00172 }