Back to index

glibc  2.9
hurdmsg.c
Go to the documentation of this file.
00001 /* Copyright (C) 1992, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <hurd.h>
00020 #include <hurd/msg_server.h>
00021 #include <hurd/fd.h>
00022 #include <unistd.h>
00023 #include <limits.h>
00024 #include <string.h>
00025 #include <argz.h>
00026 
00027 
00028 #define AUTHCHECK \
00029   if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
00030     return EPERM
00031 
00032 
00033 /* Snarfing and frobbing the init ports.  */
00034 
00035 kern_return_t
00036   _S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which,
00037                      mach_port_t *result, mach_msg_type_name_t *result_type)
00038 {
00039   AUTHCHECK;
00040   *result_type = MACH_MSG_TYPE_MOVE_SEND;
00041   /* This function adds a new user reference for the *RESULT it gives back.
00042      Our reply message uses a move-send right that consumes this reference.  */
00043   return _hurd_ports_get (which, result);
00044 }
00045 
00046 kern_return_t
00047 _S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
00048                     int which, mach_port_t port)
00049 {
00050   error_t err;
00051 
00052   AUTHCHECK;
00053 
00054   err = _hurd_ports_set (which, port);
00055   if (err == 0)
00056     __mach_port_deallocate (__mach_task_self (), port);
00057 
00058   return 0;
00059 }
00060 
00061 kern_return_t
00062 _S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
00063                      mach_port_t **ports,
00064                      mach_msg_type_name_t *ports_type,
00065                      mach_msg_type_number_t *nports)
00066 {
00067   mach_msg_type_number_t i;
00068   error_t err;
00069 
00070   AUTHCHECK;
00071 
00072   if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports,
00073                         _hurd_nports * sizeof (mach_port_t), 1))
00074     return err;
00075   *nports = _hurd_nports;
00076 
00077   for (i = 0; i < _hurd_nports; ++i)
00078     /* This function adds a new user ref for the *RESULT it gives back.
00079        Our reply message uses move-send rights that consumes this ref.  */
00080     if (err = _hurd_ports_get (i, &(*ports)[i]))
00081       {
00082        /* Died part way through.  Deallocate the ports already fetched.  */
00083        while (i-- > 0)
00084          __mach_port_deallocate (__mach_task_self (), (*ports)[i]);
00085        __vm_deallocate (__mach_task_self (),
00086                       (vm_address_t) *ports,
00087                       *nports * sizeof (mach_port_t));
00088        return err;
00089       }
00090 
00091   *ports_type = MACH_MSG_TYPE_MOVE_SEND;
00092   return 0;
00093 }
00094 
00095 kern_return_t
00096 _S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
00097                      mach_port_t *ports, mach_msg_type_number_t nports)
00098 {
00099   mach_msg_type_number_t i;
00100   error_t err;
00101 
00102   AUTHCHECK;
00103 
00104   for (i = 0; i < _hurd_nports; ++i)
00105     {
00106       if (err = _hurd_ports_set (i, ports[i]))
00107        return err;
00108       else
00109        __mach_port_deallocate (__mach_task_self (), ports[i]);
00110     }
00111 
00112   return 0;
00113 }
00114 
00115 /* Snarfing and frobbing the init ints.  */
00116 
00117 static kern_return_t
00118 get_int (int which, int *value)
00119 {
00120   switch (which)
00121     {
00122     case INIT_UMASK:
00123       *value = _hurd_umask;
00124       return 0;
00125     case INIT_SIGMASK:
00126       {
00127        struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
00128        __spin_lock (&ss->lock);
00129        *value = ss->blocked;
00130        __spin_unlock (&ss->lock);
00131        return 0;
00132       }
00133     case INIT_SIGPENDING:
00134       {
00135        struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
00136        __spin_lock (&ss->lock);
00137        *value = ss->pending;
00138        __spin_unlock (&ss->lock);
00139        return 0;
00140       }
00141     case INIT_SIGIGN:
00142       {
00143        struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
00144        sigset_t ign;
00145        int sig;
00146        __spin_lock (&ss->lock);
00147        __sigemptyset (&ign);
00148        for (sig = 1; sig < NSIG; ++sig)
00149          if (ss->actions[sig].sa_handler == SIG_IGN)
00150            __sigaddset (&ign, sig);
00151        __spin_unlock (&ss->lock);
00152        *value = ign;
00153        return 0;
00154       }
00155     default:
00156       return EINVAL;
00157     }
00158 }
00159 
00160 kern_return_t
00161 _S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
00162                    int which, int *value)
00163 {
00164   AUTHCHECK;
00165 
00166   return get_int (which, value);
00167 }
00168 
00169 kern_return_t
00170 _S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
00171                     int **values, mach_msg_type_number_t *nvalues)
00172 {
00173   error_t err;
00174   mach_msg_type_number_t i;
00175 
00176   AUTHCHECK;
00177 
00178   if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
00179                         INIT_INT_MAX * sizeof (int), 1))
00180     return err;
00181   *nvalues = INIT_INT_MAX;
00182 
00183   for (i = 0; i < INIT_INT_MAX; ++i)
00184     switch (err = get_int (i, &(*values)[i]))
00185       {
00186       case 0:               /* Success.  */
00187        break;
00188       case EINVAL:          /* Unknown index.  */
00189        (*values)[i] = 0;
00190        break;
00191       default:                     /* Lossage.  */
00192        __vm_deallocate (__mach_task_self (),
00193                       (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
00194        return err;
00195       }
00196 
00197   return 0;
00198 }
00199 
00200 
00201 static kern_return_t
00202 set_int (int which, int value)
00203 {
00204   switch (which)
00205     {
00206     case INIT_UMASK:
00207       _hurd_umask = value;
00208       return 0;
00209 
00210       /* These are pretty odd things to do.  But you asked for it.  */
00211     case INIT_SIGMASK:
00212       {
00213        struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
00214        __spin_lock (&ss->lock);
00215        ss->blocked = value;
00216        __spin_unlock (&ss->lock);
00217        return 0;
00218       }
00219     case INIT_SIGPENDING:
00220       {
00221        struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
00222        __spin_lock (&ss->lock);
00223        ss->pending = value;
00224        __spin_unlock (&ss->lock);
00225        return 0;
00226       }
00227     case INIT_SIGIGN:
00228       {
00229        struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
00230        int sig;
00231        const sigset_t ign = value;
00232        __spin_lock (&ss->lock);
00233        for (sig = 1; sig < NSIG; ++sig)
00234          {
00235            if (__sigismember (&ign, sig))
00236              ss->actions[sig].sa_handler = SIG_IGN;
00237            else if (ss->actions[sig].sa_handler == SIG_IGN)
00238              ss->actions[sig].sa_handler = SIG_DFL;
00239          }
00240        __spin_unlock (&ss->lock);
00241        return 0;
00242 
00243       case INIT_TRACEMASK:
00244        _hurdsig_traced = value;
00245        return 0;
00246       }
00247     default:
00248       return EINVAL;
00249     }
00250 }
00251 
00252 kern_return_t
00253 _S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
00254                    int which, int value)
00255 {
00256   AUTHCHECK;
00257 
00258   return set_int (which, value);
00259 }
00260 
00261 kern_return_t
00262 _S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
00263                     int *values, mach_msg_type_number_t nvalues)
00264 {
00265   error_t err;
00266   mach_msg_type_number_t i;
00267 
00268   AUTHCHECK;
00269 
00270   for (i = 0; i < INIT_INT_MAX; ++i)
00271     switch (err = set_int (i, values[i]))
00272       {
00273       case 0:               /* Success.  */
00274        break;
00275       case EINVAL:          /* Unknown index.  */
00276        break;
00277       default:                     /* Lossage.  */
00278        return err;
00279       }
00280 
00281   return 0;
00282 }
00283 
00284 
00285 kern_return_t
00286 _S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which,
00287               mach_port_t *result, mach_msg_type_name_t *result_type)
00288 {
00289   AUTHCHECK;
00290 
00291   /* This creates a new user reference for the send right.
00292      Our reply message will move that reference to the caller.  */
00293   *result = __getdport (which);
00294   if (*result == MACH_PORT_NULL)
00295     return errno;
00296   *result_type = MACH_MSG_TYPE_MOVE_SEND;
00297 
00298   return 0;
00299 }
00300 
00301 kern_return_t
00302 _S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
00303               int which, mach_port_t port)
00304 {
00305   AUTHCHECK;
00306 
00307   /* We consume the reference if successful.  */
00308   return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0));
00309 }
00310 
00311 /* Snarfing and frobbing environment variables.  */
00312 
00313 kern_return_t
00314 _S_msg_get_env_variable (mach_port_t msgport,
00315                       char *variable,
00316                       char **data, mach_msg_type_number_t *datalen)
00317 {
00318   error_t err;
00319   mach_msg_type_number_t valuelen;
00320   const char *value = getenv (variable);
00321 
00322   if (value == NULL)
00323     return ENOENT;
00324 
00325   valuelen = strlen (value);
00326   if (valuelen > *datalen)
00327     {
00328       if (err = __vm_allocate (__mach_task_self (), 
00329                             (vm_address_t *) data, valuelen, 1))
00330        return err;
00331     }
00332 
00333   memcpy (*data, value, valuelen);
00334   *datalen = valuelen;
00335 
00336   return 0;
00337 }
00338 
00339 
00340 kern_return_t
00341 _S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
00342                       char *variable,
00343                       char *value,
00344                       int replace)
00345 {
00346   AUTHCHECK;
00347 
00348   if (setenv (variable, value, replace)) /* XXX name space */
00349     return errno;
00350   return 0;
00351 }
00352 
00353 kern_return_t
00354 _S_msg_get_environment (mach_port_t msgport,
00355                      char **data, mach_msg_type_number_t *datalen)
00356 {
00357   /* Pack the environment into an array with nulls separating elements.  */
00358   if (__environ != NULL)
00359     {
00360       char *ap, **p;
00361       size_t envlen = 0;
00362 
00363       for (p = __environ; *p != NULL; ++p)
00364        envlen += strlen (*p) + 1;
00365 
00366       if (envlen > *datalen)
00367        {
00368          if (__vm_allocate (__mach_task_self (),
00369                           (vm_address_t *) data, envlen, 1))
00370            return ENOMEM;
00371        }
00372 
00373       ap = *data;
00374       for (p = __environ; *p != NULL; ++p)
00375        ap = __memccpy (ap, *p, '\0', ULONG_MAX);
00376 
00377       *datalen = envlen;
00378     }
00379   else
00380     *datalen = 0;
00381 
00382   return 0;
00383 }
00384 
00385 kern_return_t
00386 _S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
00387                      char *data, mach_msg_type_number_t datalen)
00388 {
00389   int _hurd_split_args (char *, mach_msg_type_number_t, char **);
00390   int envc;
00391   char **envp;
00392 
00393   AUTHCHECK;
00394 
00395   envc = __argz_count (data, datalen);
00396   envp = malloc ((envc + 1) * sizeof (char *));
00397   if (envp == NULL)
00398     return errno;
00399   __argz_extract (data, datalen, envp);
00400   __environ = envp;         /* XXX cooperate with loadenv et al */
00401   return 0;
00402 }
00403 
00404 
00405 /* XXX */
00406 
00407 kern_return_t
00408 _S_msg_get_dtable (mach_port_t process,
00409                  mach_port_t refport,
00410                  portarray_t *dtable,
00411                  mach_msg_type_name_t *dtablePoly,
00412                  mach_msg_type_number_t *dtableCnt)
00413 { return EOPNOTSUPP; }
00414 
00415 kern_return_t
00416 _S_msg_set_dtable (mach_port_t process,
00417                  mach_port_t refport,
00418                  portarray_t dtable,
00419                  mach_msg_type_number_t dtableCnt)
00420 { return EOPNOTSUPP; }