PageRenderTime 50ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/procfs/main.c

https://github.com/jeremie-koenig/hurd
C | 190 lines | 145 code | 24 blank | 21 comment | 23 complexity | 20e5d96cf19e78c4ac013dbe1ed03d02 MD5 | raw file
  1. /* Hurd /proc filesystem, main program.
  2. Copyright (C) 2010 Free Software Foundation, Inc.
  3. This file is part of the GNU Hurd.
  4. The GNU Hurd is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License as
  6. published by the Free Software Foundation; either version 2, or (at
  7. your option) any later version.
  8. The GNU Hurd is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  15. #include <mach.h>
  16. #include <hurd.h>
  17. #include <unistd.h>
  18. #include <error.h>
  19. #include <argp.h>
  20. #include <hurd/netfs.h>
  21. #include <ps.h>
  22. #include "procfs.h"
  23. #include "proclist.h"
  24. #include "rootdir.h"
  25. #include "dircat.h"
  26. #include "main.h"
  27. /* Command-line options */
  28. int opt_clk_tck;
  29. mode_t opt_stat_mode;
  30. pid_t opt_fake_self;
  31. pid_t opt_kernel_pid;
  32. uid_t opt_anon_owner;
  33. static error_t
  34. argp_parser (int key, char *arg, struct argp_state *state)
  35. {
  36. struct passwd *pw;
  37. char *endp;
  38. switch (key)
  39. {
  40. case 'h':
  41. opt_clk_tck = strtol (arg, &endp, 0);
  42. if (*endp || ! *arg || opt_clk_tck <= 0)
  43. error (1, 0, "--clk-tck: HZ should be a positive integer");
  44. break;
  45. case 's':
  46. opt_stat_mode = strtol (arg, &endp, 8);
  47. if (*endp || ! *arg || opt_stat_mode & ~07777)
  48. error (1, 0, "--stat-mode: MODE should be an octal mode");
  49. break;
  50. case 'S':
  51. if (arg)
  52. {
  53. opt_fake_self = strtol (arg, &endp, 0);
  54. if (*endp || ! *arg)
  55. error (1, 0, "--fake-self: PID must be an integer");
  56. }
  57. else
  58. opt_fake_self = 1;
  59. break;
  60. case 'k':
  61. opt_kernel_pid = strtol (arg, &endp, 0);
  62. if (*endp || ! *arg || (signed) opt_kernel_pid < 0)
  63. error (1, 0, "--kernel-process: PID must be a positive integer");
  64. break;
  65. case 'c':
  66. opt_clk_tck = 100;
  67. opt_stat_mode = 0444;
  68. opt_fake_self = 1;
  69. break;
  70. case 'a':
  71. pw = getpwnam (arg);
  72. if (pw)
  73. {
  74. opt_anon_owner = pw->pw_uid;
  75. break;
  76. }
  77. opt_anon_owner = strtol (arg, &endp, 0);
  78. if (*endp || ! *arg || (signed) opt_anon_owner < 0)
  79. error(1, 0, "--anonymous-owner: USER should be the a user name "
  80. "or a numeric UID.");
  81. break;
  82. }
  83. return 0;
  84. }
  85. struct argp argp = {
  86. .options = (struct argp_option []) {
  87. { "clk-tck", 'h', "HZ", 0,
  88. "Unit used for the values expressed in system clock ticks "
  89. "(default: sysconf(_SC_CLK_TCK))" },
  90. { "stat-mode", 's', "MODE", 0,
  91. "The [pid]/stat file publishes information which on Hurd is only "
  92. "available to the process owner. "
  93. "You can use this option to override its mode to be more permissive "
  94. "for compatibility purposes. "
  95. "(default: 0400)" },
  96. { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL,
  97. "Provide a fake \"self\" symlink to the given PID, for compatibility "
  98. "purposes. If PID is omitted, \"self\" will point to init. "
  99. "(default: no self link)" },
  100. { "kernel-process", 'k', "PID", 0,
  101. "Process identifier for the kernel, used to retreive its command "
  102. "line, as well as the global up and idle times. "
  103. "(default: 2)" },
  104. { "compatible", 'c', NULL, 0,
  105. "Try to be compatible with the Linux procps utilities. "
  106. "Currently equivalent to -h 100 -s 0444 -S 1." },
  107. { "anonymous-owner", 'a', "USER", 0,
  108. "Make USER the owner of files related to processes without one. "
  109. "Be aware that USER will be granted access to the environment and "
  110. "other sensitive information about the processes in question. "
  111. "(default: use uid 0)" },
  112. {}
  113. },
  114. .parser = argp_parser,
  115. .doc = "A virtual filesystem emulating the Linux procfs.",
  116. .children = (struct argp_child []) {
  117. { &netfs_std_startup_argp, },
  118. {}
  119. },
  120. };
  121. error_t
  122. root_make_node (struct ps_context *pc, struct node **np)
  123. {
  124. struct node *root_dirs[] = {
  125. proclist_make_node (pc),
  126. rootdir_make_node (pc),
  127. };
  128. *np = dircat_make_node (root_dirs, sizeof root_dirs / sizeof root_dirs[0]);
  129. if (! *np)
  130. return ENOMEM;
  131. /* Since this one is not created through proc_lookup(), we have to affect an
  132. inode number to it. */
  133. (*np)->nn_stat.st_ino = * (uint32_t *) "PROC";
  134. return 0;
  135. }
  136. int main (int argc, char **argv)
  137. {
  138. struct ps_context *pc;
  139. mach_port_t bootstrap;
  140. error_t err;
  141. opt_clk_tck = sysconf(_SC_CLK_TCK);
  142. opt_stat_mode = 0400;
  143. opt_fake_self = -1;
  144. opt_kernel_pid = 2;
  145. opt_anon_owner = 0;
  146. err = argp_parse (&argp, argc, argv, 0, 0, 0);
  147. if (err)
  148. error (1, err, "Could not parse command line");
  149. err = ps_context_create (getproc (), &pc);
  150. if (err)
  151. error (1, err, "Could not create libps context");
  152. task_get_bootstrap_port (mach_task_self (), &bootstrap);
  153. if (bootstrap == MACH_PORT_NULL)
  154. error (1, 0, "Must be started as a translator");
  155. netfs_init ();
  156. err = root_make_node (pc, &netfs_root_node);
  157. if (err)
  158. error (1, err, "Could not create the root node");
  159. netfs_startup (bootstrap, 0);
  160. netfs_server_loop ();
  161. assert (0 /* netfs_server_loop returned after all */);
  162. }