BOOK.TXT
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:1020k
源码类别:

操作系统开发

开发平台:

WINDOWS

  1. 13919                 cons->c_org = cons->c_start;
  2. 13920         } else {
  3. 13921                 cons->c_org = (cons->c_org + scr_width) & vid_mask;
  4. 13922         }
  5. 13923         new_line = (cons->c_org + chars) & vid_mask;
  6. 13924   } else {
  7. 13925         /* Scroll one line down in 3 ways: soft, avoid wrap, use origin. */
  8. 13926         if (softscroll) {
  9. 13927                 vid_vid_copy(cons->c_start, cons->c_start + scr_width, chars);
  10. 13928         } else
  11. 13929         if (!wrap && cons->c_org < cons->c_start + scr_width) {
  12. 13930                 new_org = cons->c_limit - scr_size;
  13. 13931                 vid_vid_copy(cons->c_org, new_org + scr_width, chars);
  14. 13932                 cons->c_org = new_org;
  15. 13933         } else {
  16. 13934                 cons->c_org = (cons->c_org - scr_width) & vid_mask;
  17. 13935         }
  18. 13936         new_line = cons->c_org;
  19. 13937   }
  20. 13938   /* Blank the new line at top or bottom. */
  21. 13939   blank_color = cons->c_blank;
  22. 13940   mem_vid_copy(BLANK_MEM, new_line, scr_width);
  23. 13941
  24. 13942   /* Set the new video origin. */
  25. 13943   if (cons == curcons) set_6845(VID_ORG, cons->c_org);
  26. 13944   flush(cons);
  27. 13945 }
  28. 13948 /*===========================================================================*
  29. 13949  *                              flush                                        *
  30. 13950  *===========================================================================*/
  31. 13951 PRIVATE void flush(cons)
  32. 13952 register console_t *cons;       /* pointer to console struct */
  33. 13953 {
  34. 13954 /* Send characters buffered in 'ramqueue' to screen memory, check the new
  35. 13955  * cursor position, compute the new hardware cursor position and set it.
  36. 13956  */
  37. 13957   unsigned cur;
  38. 13958   tty_t *tp = cons->c_tty;
  39. 13959
  40. 13960   /* Have the characters in 'ramqueue' transferred to the screen. */
  41. 13961   if (cons->c_rwords > 0) {
  42. 13962         mem_vid_copy(cons->c_ramqueue, cons->c_cur, cons->c_rwords);
  43. 13963         cons->c_rwords = 0;
  44. 13964
  45. 13965         /* TTY likes to know the current column and if echoing messed up. */
  46. 13966         tp->tty_position = cons->c_column;
  47. 13967         tp->tty_reprint = TRUE;
  48. 13968   }
  49. 13969
  50. 13970   /* Check and update the cursor position. */
  51. 13971   if (cons->c_column < 0) cons->c_column = 0;
  52. 13972   if (cons->c_column > scr_width) cons->c_column = scr_width;
  53. 13973   if (cons->c_row < 0) cons->c_row = 0;
  54. 13974   if (cons->c_row >= scr_lines) cons->c_row = scr_lines - 1;
  55. 13975   cur = cons->c_org + cons->c_row * scr_width + cons->c_column;
  56. 13976   if (cur != cons->c_cur) {
  57. 13977         if (cons == curcons) set_6845(CURSOR, cur);
  58. 13978         cons->c_cur = cur;
  59. 13979   }
  60. 13980 }
  61. 13983 /*===========================================================================*
  62. 13984  *                              parse_escape                                 *
  63. 13985  *===========================================================================*/
  64. 13986 PRIVATE void parse_escape(cons, c)
  65. 13987 register console_t *cons;       /* pointer to console struct */
  66. 13988 char c;                         /* next character in escape sequence */
  67. 13989 {
  68. 13990 /* The following ANSI escape sequences are currently supported.
  69. 13991  * If n and/or m are omitted, they default to 1. Omitted s defaults to 0.
  70. 13992  *   ESC [nA moves up n lines
  71. 13993  *   ESC [nB moves down n lines
  72. 13994  *   ESC [nC moves right n spaces
  73. 13995  *   ESC [nD moves left n spaces
  74. 13996  *   ESC [m;nH moves cursor to (m,n)
  75. 13997  *   ESC [sJ clears screen relative to cursor (0 to end, 1 from start, 2 all)
  76. 13998  *   ESC [sK clears line relative to cursor (0 to end, 1 from start, 2 all)
  77. 13999  *   ESC [nL inserts n lines at cursor
  78. 14000  *   ESC [nM deletes n lines at cursor
  79. 14001  *   ESC [nP deletes n chars at cursor
  80. 14002  *   ESC [n@ inserts n chars at cursor
  81. 14003  *   ESC [nm enables rendition n (0= normal, 1=bold, 4=underline, 5=blinking,
  82. 14004  *       7=reverse, 30..37 set foreground color, 40..47 set background color)
  83. 14005  *   ESC M scrolls the screen backwards if the cursor is on the top line
  84. 14006  */
  85. 14007
  86. 14008   switch (cons->c_esc_state) {
  87. 14009     case 1:                     /* ESC seen */
  88. 14010         cons->c_esc_intro = '';
  89. 14011         cons->c_esc_parmp = cons->c_esc_parmv;
  90. 14012         cons->c_esc_parmv[0] = cons->c_esc_parmv[1] = 0;
  91. 14013         switch (c) {
  92. 14014             case '[':   /* Control Sequence Introducer */
  93. 14015                 cons->c_esc_intro = c;
  94. 14016                 cons->c_esc_state = 2;
  95. 14017                 break;
  96. 14018             case 'M':   /* Reverse Index */
  97. 14019                 do_escape(cons, c);
  98. 14020                 break;
  99. 14021             default:
  100. 14022                 cons->c_esc_state = 0;
  101. 14023         }
  102. 14024         break;
  103. 14025
  104. 14026     case 2:                     /* ESC [ seen */
  105. 14027         if (c >= '0' && c <= '9') {
  106. 14028                 if (cons->c_esc_parmp < bufend(cons->c_esc_parmv))
  107. 14029                         *cons->c_esc_parmp = *cons->c_esc_parmp * 10 + (c-'0');
  108. 14030         } else
  109. 14031         if (c == ';') {
  110. 14032                 if (++cons->c_esc_parmp < bufend(cons->c_esc_parmv))
  111. 14033                         *cons->c_esc_parmp = 0;
  112. 14034         } else {
  113. 14035                 do_escape(cons, c);
  114. 14036         }
  115. 14037         break;
  116. 14038   }
  117. 14039 }
  118. 14042 /*===========================================================================*
  119. 14043  *                              do_escape                                    *
  120. 14044  *===========================================================================*/
  121. 14045 PRIVATE void do_escape(cons, c)
  122. 14046 register console_t *cons;       /* pointer to console struct */
  123. 14047 char c;                         /* next character in escape sequence */
  124. 14048 {
  125. 14049   int value, n;
  126. 14050   unsigned src, dst, count;
  127. 14051
  128. 14052   /* Some of these things hack on screen RAM, so it had better be up to date */
  129. 14053   flush(cons);
  130. 14054
  131. 14055   if (cons->c_esc_intro == '') {
  132. 14056         /* Handle a sequence beginning with just ESC */
  133. 14057         switch (c) {
  134. 14058             case 'M':           /* Reverse Index */
  135. 14059                 if (cons->c_row == 0) {
  136. 14060                         scroll_screen(cons, SCROLL_DOWN);
  137. 14061                 } else {
  138. 14062                         cons->c_row--;
  139. 14063                 }
  140. 14064                 flush(cons);
  141. 14065                 break;
  142. 14066
  143. 14067             default: break;
  144. 14068         }
  145. 14069   } else
  146. 14070   if (cons->c_esc_intro == '[') {
  147. 14071         /* Handle a sequence beginning with ESC [ and parameters */
  148. 14072         value = cons->c_esc_parmv[0];
  149. 14073         switch (c) {
  150. 14074             case 'A':           /* ESC [nA moves up n lines */
  151. 14075                 n = (value == 0 ? 1 : value);
  152. 14076                 cons->c_row -= n;
  153. 14077                 flush(cons);
  154. 14078                 break;
  155. 14079
  156. 14080             case 'B':           /* ESC [nB moves down n lines */
  157. 14081                 n = (value == 0 ? 1 : value);
  158. 14082                 cons->c_row += n;
  159. 14083                 flush(cons);
  160. 14084                 break;
  161. 14085
  162. 14086             case 'C':           /* ESC [nC moves right n spaces */
  163. 14087                 n = (value == 0 ? 1 : value);
  164. 14088                 cons->c_column += n;
  165. 14089                 flush(cons);
  166. 14090                 break;
  167. 14091
  168. 14092             case 'D':           /* ESC [nD moves left n spaces */
  169. 14093                 n = (value == 0 ? 1 : value);
  170. 14094                 cons->c_column -= n;
  171. 14095                 flush(cons);
  172. 14096                 break;
  173. 14097
  174. 14098             case 'H':           /* ESC [m;nH" moves cursor to (m,n) */
  175. 14099                 cons->c_row = cons->c_esc_parmv[0] - 1;
  176. 14100                 cons->c_column = cons->c_esc_parmv[1] - 1;
  177. 14101                 flush(cons);
  178. 14102                 break;
  179. 14103
  180. 14104             case 'J':           /* ESC [sJ clears in display */
  181. 14105                 switch (value) {
  182. 14106                     case 0:     /* Clear from cursor to end of screen */
  183. 14107                         count = scr_size - (cons->c_cur - cons->c_org);
  184. 14108                         dst = cons->c_cur;
  185. 14109                         break;
  186. 14110                     case 1:     /* Clear from start of screen to cursor */
  187. 14111                         count = cons->c_cur - cons->c_org;
  188. 14112                         dst = cons->c_org;
  189. 14113                         break;
  190. 14114                     case 2:     /* Clear entire screen */
  191. 14115                         count = scr_size;
  192. 14116                         dst = cons->c_org;
  193. 14117                         break;
  194. 14118                     default:    /* Do nothing */
  195. 14119                         count = 0;
  196. 14120                         dst = cons->c_org;
  197. 14121                 }
  198. 14122                 blank_color = cons->c_blank;
  199. 14123                 mem_vid_copy(BLANK_MEM, dst, count);
  200. 14124                 break;
  201. 14125
  202. 14126             case 'K':           /* ESC [sK clears line from cursor */
  203. 14127                 switch (value) {
  204. 14128                     case 0:     /* Clear from cursor to end of line */
  205. 14129                         count = scr_width - cons->c_column;
  206. 14130                         dst = cons->c_cur;
  207. 14131                         break;
  208. 14132                     case 1:     /* Clear from beginning of line to cursor */
  209. 14133                         count = cons->c_column;
  210. 14134                         dst = cons->c_cur - cons->c_column;
  211. 14135                         break;
  212. 14136                     case 2:     /* Clear entire line */
  213. 14137                         count = scr_width;
  214. 14138                         dst = cons->c_cur - cons->c_column;
  215. 14139                         break;
  216. 14140                     default:    /* Do nothing */
  217. 14141                         count = 0;
  218. 14142                         dst = cons->c_cur;
  219. 14143                 }
  220. 14144                 blank_color = cons->c_blank;
  221. 14145                 mem_vid_copy(BLANK_MEM, dst, count);
  222. 14146                 break;
  223. 14147
  224. 14148             case 'L':           /* ESC [nL inserts n lines at cursor */
  225. 14149                 n = value;
  226. 14150                 if (n < 1) n = 1;
  227. 14151                 if (n > (scr_lines - cons->c_row))
  228. 14152                         n = scr_lines - cons->c_row;
  229. 14153
  230. 14154                 src = cons->c_org + cons->c_row * scr_width;
  231. 14155                 dst = src + n * scr_width;
  232. 14156                 count = (scr_lines - cons->c_row - n) * scr_width;
  233. 14157                 vid_vid_copy(src, dst, count);
  234. 14158                 blank_color = cons->c_blank;
  235. 14159                 mem_vid_copy(BLANK_MEM, src, n * scr_width);
  236. 14160                 break;
  237. 14161
  238. 14162             case 'M':           /* ESC [nM deletes n lines at cursor */
  239. 14163                 n = value;
  240. 14164                 if (n < 1) n = 1;
  241. 14165                 if (n > (scr_lines - cons->c_row))
  242. 14166                         n = scr_lines - cons->c_row;
  243. 14167
  244. 14168                 dst = cons->c_org + cons->c_row * scr_width;
  245. 14169                 src = dst + n * scr_width;
  246. 14170                 count = (scr_lines - cons->c_row - n) * scr_width;
  247. 14171                 vid_vid_copy(src, dst, count);
  248. 14172                 blank_color = cons->c_blank;
  249. 14173                 mem_vid_copy(BLANK_MEM, dst + count, n * scr_width);
  250. 14174                 break;
  251. 14175
  252. 14176             case '@':           /* ESC [n@ inserts n chars at cursor */
  253. 14177                 n = value;
  254. 14178                 if (n < 1) n = 1;
  255. 14179                 if (n > (scr_width - cons->c_column))
  256. 14180                         n = scr_width - cons->c_column;
  257. 14181
  258. 14182                 src = cons->c_cur;
  259. 14183                 dst = src + n;
  260. 14184                 count = scr_width - cons->c_column - n;
  261. 14185                 vid_vid_copy(src, dst, count);
  262. 14186                 blank_color = cons->c_blank;
  263. 14187                 mem_vid_copy(BLANK_MEM, src, n);
  264. 14188                 break;
  265. 14189
  266. 14190             case 'P':           /* ESC [nP deletes n chars at cursor */
  267. 14191                 n = value;
  268. 14192                 if (n < 1) n = 1;
  269. 14193                 if (n > (scr_width - cons->c_column))
  270. 14194                         n = scr_width - cons->c_column;
  271. 14195
  272. 14196                 dst = cons->c_cur;
  273. 14197                 src = dst + n;
  274. 14198                 count = scr_width - cons->c_column - n;
  275. 14199                 vid_vid_copy(src, dst, count);
  276. 14200                 blank_color = cons->c_blank;
  277. 14201                 mem_vid_copy(BLANK_MEM, dst + count, n);
  278. 14202                 break;
  279. 14203
  280. 14204             case 'm':           /* ESC [nm enables rendition n */
  281. 14205                 switch (value) {
  282. 14206                     case 1:     /* BOLD  */
  283. 14207                         if (color) {
  284. 14208                                 /* Can't do bold, so use yellow */
  285. 14209                                 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0E00;
  286. 14210                         } else {
  287. 14211                                 /* Set intensity bit */
  288. 14212                                 cons->c_attr |= 0x0800;
  289. 14213                         }
  290. 14214                         break;
  291. 14215
  292. 14216                     case 4:     /* UNDERLINE */
  293. 14217                         if (color) {
  294. 14218                                 /* Use light green */
  295. 14219                                 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0A00;
  296. 14220                         } else {
  297. 14221                                 cons->c_attr = (cons->c_attr & 0x8900);
  298. 14222                         }
  299. 14223                         break;
  300. 14224
  301. 14225                     case 5:     /* BLINKING */
  302. 14226                         if (color) {
  303. 14227                                 /* Use magenta */
  304. 14228                                 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0500;
  305. 14229                         } else {
  306. 14230                                 /* Set the blink bit */
  307. 14231                                 cons->c_attr |= 0x8000;
  308. 14232                         }
  309. 14233                         break;
  310. 14234
  311. 14235                     case 7:     /* REVERSE */
  312. 14236                         if (color) {
  313. 14237                                 /* Swap fg and bg colors */
  314. 14238                                 cons->c_attr =
  315. 14239                                         ((cons->c_attr & 0xf000) >> 4) |
  316. 14240                                         ((cons->c_attr & 0x0f00) << 4);
  317. 14241                         } else
  318. 14242                         if ((cons->c_attr & 0x7000) == 0) {
  319. 14243                                 cons->c_attr = (cons->c_attr & 0x8800) | 0x7000;
  320. 14244                         } else {
  321. 14245                                 cons->c_attr = (cons->c_attr & 0x8800) | 0x0700;
  322. 14246                         }
  323. 14247                         break;
  324. 14248
  325. 14249                     default:    /* COLOR */
  326. 14250                         if (30 <= value && value <= 37) {
  327. 14251                                 cons->c_attr =
  328. 14252                                         (cons->c_attr & 0xf0ff) |
  329. 14253                                         (ansi_colors[(value - 30)] << 8);
  330. 14254                                 cons->c_blank =
  331. 14255                                         (cons->c_blank & 0xf0ff) |
  332. 14256                                         (ansi_colors[(value - 30)] << 8);
  333. 14257                         } else
  334. 14258                         if (40 <= value && value <= 47) {
  335. 14259                                 cons->c_attr =
  336. 14260                                         (cons->c_attr & 0x0fff) |
  337. 14261                                         (ansi_colors[(value - 40)] << 12);
  338. 14262                                 cons->c_blank =
  339. 14263                                         (cons->c_blank & 0x0fff) |
  340. 14264                                         (ansi_colors[(value - 40)] << 12);
  341. 14265                         } else {
  342. 14266                                 cons->c_attr = cons->c_blank;
  343. 14267                         }
  344. 14268                         break;
  345. 14269                 }
  346. 14270                 break;
  347. 14271         }
  348. 14272   }
  349. 14273   cons->c_esc_state = 0;
  350. 14274 }
  351. 14277 /*===========================================================================*
  352. 14278  *                              set_6845                                     *
  353. 14279  *===========================================================================*/
  354. 14280 PRIVATE void set_6845(reg, val)
  355. 14281 int reg;                        /* which register pair to set */
  356. 14282 unsigned val;                   /* 16-bit value to set it to */
  357. 14283 {
  358. 14284 /* Set a register pair inside the 6845.
  359. 14285  * Registers 12-13 tell the 6845 where in video ram to start
  360. 14286  * Registers 14-15 tell the 6845 where to put the cursor
  361. 14287  */
  362. 14288   lock();                       /* try to stop h/w loading in-between value */
  363. 14289   out_byte(vid_port + INDEX, reg);              /* set the index register */
  364. 14290   out_byte(vid_port + DATA, (val>>8) & BYTE);   /* output high byte */
  365. 14291   out_byte(vid_port + INDEX, reg + 1);          /* again */
  366. 14292   out_byte(vid_port + DATA, val&BYTE);          /* output low byte */
  367. 14293   unlock();
  368. 14294 }
  369. 14297 /*===========================================================================*
  370. 14298  *                              beep                                         *
  371. 14299  *===========================================================================*/
  372. 14300 PRIVATE void beep()
  373. 14301 {
  374. 14302 /* Making a beeping sound on the speaker (output for CRTL-G).
  375. 14303  * This routine works by turning on the bits 0 and 1 in port B of the 8255
  376. 14304  * chip that drives the speaker.
  377. 14305  */
  378. 14306
  379. 14307   message mess;
  380. 14308
  381. 14309   if (beeping) return;
  382. 14310   out_byte(TIMER_MODE, 0xB6);   /* set up timer channel 2 (square wave) */
  383. 14311   out_byte(TIMER2, BEEP_FREQ & BYTE);   /* load low-order bits of frequency */
  384. 14312   out_byte(TIMER2, (BEEP_FREQ >> 8) & BYTE);    /* now high-order bits */
  385. 14313   lock();                       /* guard PORT_B from keyboard intr handler */
  386. 14314   out_byte(PORT_B, in_byte(PORT_B) | 3);        /* turn on beep bits */
  387. 14315   unlock();
  388. 14316   beeping = TRUE;
  389. 14317
  390. 14318   mess.m_type = SET_ALARM;
  391. 14319   mess.CLOCK_PROC_NR = TTY;
  392. 14320   mess.DELTA_TICKS = B_TIME;
  393. 14321   mess.FUNC_TO_CALL = (sighandler_t) stop_beep;
  394. 14322   sendrec(CLOCK, &mess);
  395. 14323 }
  396. 14326 /*===========================================================================*
  397. 14327  *                              stop_beep                                    *
  398. 14328  *===========================================================================*/
  399. 14329 PRIVATE void stop_beep()
  400. 14330 {
  401. 14331 /* Turn off the beeper by turning off bits 0 and 1 in PORT_B. */
  402. 14332
  403. 14333   lock();                       /* guard PORT_B from keyboard intr handler */
  404. 14334   out_byte(PORT_B, in_byte(PORT_B) & ~3);
  405. 14335   beeping = FALSE;
  406. 14336   unlock();
  407. 14337 }
  408. 14340 /*===========================================================================*
  409. 14341  *                              scr_init                                     *
  410. 14342  *===========================================================================*/
  411. 14343 PUBLIC void scr_init(tp)
  412. 14344 tty_t *tp;
  413. 14345 {
  414. 14346 /* Initialize the screen driver. */
  415. 14347   console_t *cons;
  416. 14348   phys_bytes vid_base;
  417. 14349   u16_t bios_crtbase;
  418. 14350   int line;
  419. 14351   unsigned page_size;
  420. 14352
  421. 14353   /* Associate console and TTY. */
  422. 14354   line = tp - &tty_table[0];
  423. 14355   if (line >= nr_cons) return;
  424. 14356   cons = &cons_table[line];
  425. 14357   cons->c_tty = tp;
  426. 14358   tp->tty_priv = cons;
  427. 14359
  428. 14360   /* Initialize the keyboard driver. */
  429. 14361   kb_init(tp);
  430. 14362
  431. 14363   /* Output functions. */
  432. 14364   tp->tty_devwrite = cons_write;
  433. 14365   tp->tty_echo = cons_echo;
  434. 14366
  435. 14367   /* Get the BIOS parameters that tells the VDU I/O base register. */
  436. 14368   phys_copy(0x463L, vir2phys(&bios_crtbase), 2L);
  437. 14369
  438. 14370   vid_port = bios_crtbase;
  439. 14371
  440. 14372   if (color) {
  441. 14373         vid_base = COLOR_BASE;
  442. 14374         vid_size = COLOR_SIZE;
  443. 14375   } else {
  444. 14376         vid_base = MONO_BASE;
  445. 14377         vid_size = MONO_SIZE;
  446. 14378   }
  447. 14379   if (ega) vid_size = EGA_SIZE; /* for both EGA and VGA */
  448. 14380   wrap = !ega;
  449. 14381
  450. 14382   vid_seg = protected_mode ? VIDEO_SELECTOR : physb_to_hclick(vid_base);
  451. 14383   init_dataseg(&gdt[VIDEO_INDEX], vid_base, (phys_bytes) vid_size,
  452. 14384                                                         TASK_PRIVILEGE);
  453. 14385   vid_size >>= 1;               /* word count */
  454. 14386   vid_mask = vid_size - 1;
  455. 14387
  456. 14388   /* There can be as many consoles as video memory allows. */
  457. 14389   nr_cons = vid_size / scr_size;
  458. 14390   if (nr_cons > NR_CONS) nr_cons = NR_CONS;
  459. 14391   if (nr_cons > 1) wrap = 0;
  460. 14392   page_size = vid_size / nr_cons;
  461. 14393   cons->c_start = line * page_size;
  462. 14394   cons->c_limit = cons->c_start + page_size;
  463. 14395   cons->c_org = cons->c_start;
  464. 14396   cons->c_attr = cons->c_blank = BLANK_COLOR;
  465. 14397
  466. 14398   /* Clear the screen. */
  467. 14399   blank_color = BLANK_COLOR;
  468. 14400   mem_vid_copy(BLANK_MEM, cons->c_start, scr_size);
  469. 14401   select_console(0);
  470. 14402 }
  471. 14405 /*===========================================================================*
  472. 14406  *                              putk                                         *
  473. 14407  *===========================================================================*/
  474. 14408 PUBLIC void putk(c)
  475. 14409 int c;                          /* character to print */
  476. 14410 {
  477. 14411 /* This procedure is used by the version of printf() that is linked with
  478. 14412  * the kernel itself.  The one in the library sends a message to FS, which is
  479. 14413  * not what is needed for printing within the kernel.  This version just queues
  480. 14414  * the character and starts the output.
  481. 14415  */
  482. 14416
  483. 14417   if (c != 0) {
  484. 14418         if (c == 'n') putk('r');
  485. 14419         out_char(&cons_table[0], (int) c);
  486. 14420   } else {
  487. 14421         flush(&cons_table[0]);
  488. 14422   }
  489. 14423 }
  490. 14426 /*===========================================================================*
  491. 14427  *                              toggle_scroll                                *
  492. 14428  *===========================================================================*/
  493. 14429 PUBLIC void toggle_scroll()
  494. 14430 {
  495. 14431 /* Toggle between hardware and software scroll. */
  496. 14432
  497. 14433   cons_org0();
  498. 14434   softscroll = !softscroll;
  499. 14435   printf("%sware scrolling enabled.n", softscroll ? "Soft" : "Hard");
  500. 14436 }
  501. 14439 /*===========================================================================*
  502. 14440  *                              cons_stop                                    *
  503. 14441  *===========================================================================*/
  504. 14442 PUBLIC void cons_stop()
  505. 14443 {
  506. 14444 /* Prepare for halt or reboot. */
  507. 14445
  508. 14446   cons_org0();
  509. 14447   softscroll = 1;
  510. 14448   select_console(0);
  511. 14449   cons_table[0].c_attr = cons_table[0].c_blank = BLANK_COLOR;
  512. 14450 }
  513. 14453 /*===========================================================================*
  514. 14454  *                              cons_org0                                    *
  515. 14455  *===========================================================================*/
  516. 14456 PRIVATE void cons_org0()
  517. 14457 {
  518. 14458 /* Scroll video memory back to put the origin at 0. */
  519. 14459
  520. 14460   int cons_line;
  521. 14461   console_t *cons;
  522. 14462   unsigned n;
  523. 14463
  524. 14464   for (cons_line = 0; cons_line < nr_cons; cons_line++) {
  525. 14465         cons = &cons_table[cons_line];
  526. 14466         while (cons->c_org > cons->c_start) {
  527. 14467                 n = vid_size - scr_size;        /* amount of unused memory */
  528. 14468                 if (n > cons->c_org - cons->c_start)
  529. 14469                         n = cons->c_org - cons->c_start;
  530. 14470                 vid_vid_copy(cons->c_org, cons->c_org - n, scr_size);
  531. 14471                 cons->c_org -= n;
  532. 14472         }
  533. 14473         flush(cons);
  534. 14474   }
  535. 14475   select_console(current);
  536. 14476 }
  537. 14479 /*===========================================================================*
  538. 14480  *                              select_console                               *
  539. 14481  *===========================================================================*/
  540. 14482 PUBLIC void select_console(int cons_line)
  541. 14483 {
  542. 14484 /* Set the current console to console number 'cons_line'. */
  543. 14485
  544. 14486   if (cons_line < 0 || cons_line >= nr_cons) return;
  545. 14487   current = cons_line;
  546. 14488   curcons = &cons_table[cons_line];
  547. 14489   set_6845(VID_ORG, curcons->c_org);
  548. 14490   set_6845(CURSOR, curcons->c_cur);
  549. 14491 }
  550. 14494 /*===========================================================================*
  551. 14495  *                              con_loadfont                                 *
  552. 14496  *===========================================================================*/
  553. 14497 PUBLIC int con_loadfont(user_phys)
  554. 14498 phys_bytes user_phys;
  555. 14499 {
  556. 14500 /* Load a font into the EGA or VGA adapter. */
  557. 14501
  558. 14502   static struct sequence seq1[7] = {
  559. 14503         { GA_SEQUENCER_INDEX, 0x00, 0x01 },
  560. 14504         { GA_SEQUENCER_INDEX, 0x02, 0x04 },
  561. 14505         { GA_SEQUENCER_INDEX, 0x04, 0x07 },
  562. 14506         { GA_SEQUENCER_INDEX, 0x00, 0x03 },
  563. 14507         { GA_GRAPHICS_INDEX, 0x04, 0x02 },
  564. 14508         { GA_GRAPHICS_INDEX, 0x05, 0x00 },
  565. 14509         { GA_GRAPHICS_INDEX, 0x06, 0x00 },
  566. 14510   };
  567. 14511   static struct sequence seq2[7] = {
  568. 14512         { GA_SEQUENCER_INDEX, 0x00, 0x01 },
  569. 14513         { GA_SEQUENCER_INDEX, 0x02, 0x03 },
  570. 14514         { GA_SEQUENCER_INDEX, 0x04, 0x03 },
  571. 14515         { GA_SEQUENCER_INDEX, 0x00, 0x03 },
  572. 14516         { GA_GRAPHICS_INDEX, 0x04, 0x00 },
  573. 14517         { GA_GRAPHICS_INDEX, 0x05, 0x10 },
  574. 14518         { GA_GRAPHICS_INDEX, 0x06,    0 },
  575. 14519   };
  576. 14520
  577. 14521   seq2[6].value= color ? 0x0E : 0x0A;
  578. 14522
  579. 14523   if (!ega) return(ENOTTY);
  580. 14524
  581. 14525   lock();
  582. 14526   ga_program(seq1);     /* bring font memory into view */
  583. 14527
  584. 14528   phys_copy(user_phys, (phys_bytes)GA_VIDEO_ADDRESS, (phys_bytes)GA_FONT_SIZE);
  585. 14529
  586. 14530   ga_program(seq2);     /* restore */
  587. 14531   unlock();
  588. 14532
  589. 14533   return(OK);
  590. 14534 }
  591. 14537 /*===========================================================================*
  592. 14538  *                              ga_program                                   *
  593. 14539  *===========================================================================*/
  594. 14540 PRIVATE void ga_program(seq)
  595. 14541 struct sequence *seq;
  596. 14542 {
  597. 14543 /* support function for con_loadfont */
  598. 14544
  599. 14545   int len= 7;
  600. 14546   do {
  601. 14547         out_byte(seq->index, seq->port);
  602. 14548         out_byte(seq->index+1, seq->value);
  603. 14549         seq++;
  604. 14550   } while (--len > 0);
  605. 14551 }
  606. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  607. src/kernel/dmp.c    
  608. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  609. 14600 /* This file contains some dumping routines for debugging. */
  610. 14601
  611. 14602 #include "kernel.h"
  612. 14603 #include <minix/com.h>
  613. 14604 #include "proc.h"
  614. 14605
  615. 14606 char *vargv;
  616. 14607
  617. 14608 FORWARD _PROTOTYPE(char *proc_name, (int proc_nr));
  618. 14609
  619. 14610 /*===========================================================================*
  620. 14611  *                              p_dmp                                        *
  621. 14612  *===========================================================================*/
  622. 14613 PUBLIC void p_dmp()
  623. 14614 {
  624. 14615 /* Proc table dump */
  625. 14616
  626. 14617   register struct proc *rp;
  627. 14618   static struct proc *oldrp = BEG_PROC_ADDR;
  628. 14619   int n = 0;
  629. 14620   phys_clicks text, data, size;
  630. 14621   int proc_nr;
  631. 14622
  632. 14623   printf("n--pid --pc- ---sp- flag -user --sys-- -text- -data- -size- -recv- commandn");
  633. 14624
  634. 14625   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
  635. 14626         proc_nr = proc_number(rp);
  636. 14627         if (rp->p_flags & P_SLOT_FREE) continue;
  637. 14628         if (++n > 20) break;
  638. 14629         text = rp->p_map[T].mem_phys;
  639. 14630         data = rp->p_map[D].mem_phys;
  640. 14631         size = rp->p_map[T].mem_len
  641. 14632                 + ((rp->p_map[S].mem_phys + rp->p_map[S].mem_len) - data);
  642. 14633         printf("%5d %5lx %6lx %2x %7U %7U %5uK %5uK %5uK ",
  643. 14634                proc_nr < 0 ? proc_nr : rp->p_pid,
  644. 14635                (unsigned long) rp->p_reg.pc,
  645. 14636                (unsigned long) rp->p_reg.sp,
  646. 14637                rp->p_flags,
  647. 14638                rp->user_time, rp->sys_time,
  648. 14639                click_to_round_k(text), click_to_round_k(data),
  649. 14640                click_to_round_k(size));
  650. 14641         if (rp->p_flags & RECEIVING) {
  651. 14642                 printf("%-7.7s", proc_name(rp->p_getfrom));
  652. 14643         } else
  653. 14644         if (rp->p_flags & SENDING) {
  654. 14645                 printf("S:%-5.5s", proc_name(rp->p_sendto));
  655. 14646         } else
  656. 14647         if (rp->p_flags == 0) {
  657. 14648                 printf("       ");
  658. 14649         }
  659. 14650         printf("%sn", rp->p_name);
  660. 14651   }
  661. 14652   if (rp == END_PROC_ADDR) rp = BEG_PROC_ADDR; else printf("--more--r");
  662. 14653   oldrp = rp;
  663. 14654 }
  664. 14657 /*===========================================================================*
  665. 14658  *                              map_dmp                                      *
  666. 14659  *===========================================================================*/
  667. 14660 PUBLIC void map_dmp()
  668. 14661 {
  669. 14662   register struct proc *rp;
  670. 14663   static struct proc *oldrp = cproc_addr(HARDWARE);
  671. 14664   int n = 0;
  672. 14665   phys_clicks size;
  673. 14666
  674. 14667   printf("nPROC NAME-  -----TEXT-----  -----DATA-----  ----STACK-----  -SIZE-n");
  675. 14668   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
  676. 14669         if (rp->p_flags & P_SLOT_FREE) continue;
  677. 14670         if (++n > 20) break;
  678. 14671         size = rp->p_map[T].mem_len
  679. 14672                 + ((rp->p_map[S].mem_phys + rp->p_map[S].mem_len)
  680. 14673                                                 - rp->p_map[D].mem_phys);
  681. 14674         printf("%3d %-6.6s  %4x %4x %4x  %4x %4x %4x  %4x %4x %4x  %5uKn",
  682. 14675                proc_number(rp),
  683. 14676                rp->p_name,
  684. 14677                rp->p_map[T].mem_vir, rp->p_map[T].mem_phys, rp->p_map[T].mem_len,
  685. 14678                rp->p_map[D].mem_vir, rp->p_map[D].mem_phys, rp->p_map[D].mem_len,
  686. 14679                rp->p_map[S].mem_vir, rp->p_map[S].mem_phys, rp->p_map[S].mem_len,
  687. 14680                click_to_round_k(size));
  688. 14681   }
  689. 14682   if (rp == END_PROC_ADDR) rp = cproc_addr(HARDWARE); else printf("--more--r");
  690. 14683   oldrp = rp;
  691. 14684 }
  692. 14687 /*===========================================================================*
  693. 14688  *                              proc_name                                    *
  694. 14689  *===========================================================================*/
  695. 14690 PRIVATE char *proc_name(proc_nr)
  696. 14691 int proc_nr;
  697. 14692 {
  698. 14693   if (proc_nr == ANY) return "ANY";
  699. 14694   return proc_addr(proc_nr)->p_name;
  700. 14695 }
  701. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  702. src/kernel/system.c    
  703. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  704. 14700 /* This task handles the interface between file system and kernel as well as
  705. 14701  * between memory manager and kernel.  System services are obtained by sending
  706. 14702  * sys_task() a message specifying what is needed.  To make life easier for
  707. 14703  * MM and FS, a library is provided with routines whose names are of the
  708. 14704  * form sys_xxx, e.g. sys_xit sends the SYS_XIT message to sys_task.  The
  709. 14705  * message types and parameters are:
  710. 14706  *
  711. 14707  *   SYS_FORK    informs kernel that a process has forked
  712. 14708  *   SYS_NEWMAP  allows MM to set up a process memory map
  713. 14709  *   SYS_GETMAP  allows MM to get a process' memory map
  714. 14710  *   SYS_EXEC    sets program counter and stack pointer after EXEC
  715. 14711  *   SYS_XIT     informs kernel that a process has exited
  716. 14712  *   SYS_GETSP   caller wants to read out some process' stack pointer
  717. 14713  *   SYS_TIMES   caller wants to get accounting times for a process
  718. 14714  *   SYS_ABORT   MM or FS cannot go on; abort MINIX
  719. 14715  *   SYS_FRESH   start with a fresh process image during EXEC (68000 only)
  720. 14716  *   SYS_SENDSIG send a signal to a process (POSIX style)
  721. 14717  *   SYS_SIGRETURN complete POSIX-style signalling
  722. 14718  *   SYS_KILL    cause a signal to be sent via MM
  723. 14719  *   SYS_ENDSIG  finish up after SYS_KILL-type signal
  724. 14720  *   SYS_COPY    request a block of data to be copied between processes
  725. 14721  *   SYS_VCOPY   request a series of data blocks to be copied between procs
  726. 14722  *   SYS_GBOOT   copies the boot parameters to a process
  727. 14723  *   SYS_MEM     returns the next free chunk of physical memory
  728. 14724  *   SYS_UMAP    compute the physical address for a given virtual address
  729. 14725  *   SYS_TRACE   request a trace operation
  730. 14726  *
  731. 14727  * Message types and parameters:
  732. 14728  *
  733. 14729  *    m_type       PROC1     PROC2      PID     MEM_PTR
  734. 14730  * ------------------------------------------------------
  735. 14731  * | SYS_FORK   | parent  |  child  |   pid   |         |
  736. 14732  * |------------+---------+---------+---------+---------|
  737. 14733  * | SYS_NEWMAP | proc nr |         |         | map ptr |
  738. 14734  * |------------+---------+---------+---------+---------|
  739. 14735  * | SYS_EXEC   | proc nr | traced  | new sp  |         |
  740. 14736  * |------------+---------+---------+---------+---------|
  741. 14737  * | SYS_XIT    | parent  | exitee  |         |         |
  742. 14738  * |------------+---------+---------+---------+---------|
  743. 14739  * | SYS_GETSP  | proc nr |         |         |         |
  744. 14740  * |------------+---------+---------+---------+---------|
  745. 14741  * | SYS_TIMES  | proc nr |         | buf ptr |         |
  746. 14742  * |------------+---------+---------+---------+---------|
  747. 14743  * | SYS_ABORT  |         |         |         |         |
  748. 14744  * |------------+---------+---------+---------+---------|
  749. 14745  * | SYS_FRESH  | proc nr | data_cl |         |         |
  750. 14746  * |------------+---------+---------+---------+---------|
  751. 14747  * | SYS_GBOOT  | proc nr |         |         | bootptr |
  752. 14748  * |------------+---------+---------+---------+---------|
  753. 14749  * | SYS_GETMAP | proc nr |         |         | map ptr |
  754. 14750  * ------------------------------------------------------
  755. 14751  *
  756. 14752  *    m_type          m1_i1     m1_i2     m1_i3       m1_p1
  757. 14753  * ----------------+---------+---------+---------+--------------
  758. 14754  * | SYS_VCOPY     |  src p  |  dst p  | vec siz | vc addr     |
  759. 14755  * |---------------+---------+---------+---------+-------------|
  760. 14756  * | SYS_SENDSIG   | proc nr |         |         | smp         |
  761. 14757  * |---------------+---------+---------+---------+-------------|
  762. 14758  * | SYS_SIGRETURN | proc nr |         |         | scp         |
  763. 14759  * |---------------+---------+---------+---------+-------------|
  764. 14760  * | SYS_ENDSIG    | proc nr |         |         |             |
  765. 14761  * -------------------------------------------------------------
  766. 14762  *
  767. 14763  *    m_type       m2_i1     m2_i2     m2_l1     m2_l2
  768. 14764  * ------------------------------------------------------
  769. 14765  * | SYS_TRACE  | proc_nr | request |  addr   |  data   |
  770. 14766  * ------------------------------------------------------
  771. 14767  *
  772. 14768  *
  773. 14769  *    m_type       m6_i1     m6_i2     m6_i3     m6_f1
  774. 14770  * ------------------------------------------------------
  775. 14771  * | SYS_KILL   | proc_nr  |  sig    |         |         |
  776. 14772  * ------------------------------------------------------
  777. 14773  *
  778. 14774  *
  779. 14775  *    m_type      m5_c1   m5_i1    m5_l1   m5_c2   m5_i2    m5_l2   m5_l3
  780. 14776  * --------------------------------------------------------------------------
  781. 14777  * | SYS_COPY   |src seg|src proc|src vir|dst seg|dst proc|dst vir| byte ct |
  782. 14778  * --------------------------------------------------------------------------
  783. 14779  * | SYS_UMAP   |  seg  |proc nr |vir adr|       |        |       | byte ct |
  784. 14780  * --------------------------------------------------------------------------
  785. 14781  *
  786. 14782  *
  787. 14783  *    m_type      m1_i1      m1_i2      m1_i3
  788. 14784  * |------------+----------+----------+----------
  789. 14785  * | SYS_MEM    | mem base | mem size | tot mem |
  790. 14786  * ----------------------------------------------
  791. 14787  *
  792. 14788  * In addition to the main sys_task() entry point, there are 5 other minor
  793. 14789  * entry points:
  794. 14790  *   cause_sig: take action to cause a signal to occur, sooner or later
  795. 14791  *   inform:    tell MM about pending signals
  796. 14792  *   numap:     umap D segment starting from process number instead of pointer
  797. 14793  *   umap:      compute the physical address for a given virtual address
  798. 14794  *   alloc_segments: allocate segments for 8088 or higher processor
  799. 14795  */
  800. 14796
  801. 14797 #include "kernel.h"
  802. 14798 #include <signal.h>
  803. 14799 #include <unistd.h>
  804. 14800 #include <sys/sigcontext.h>
  805. 14801 #include <sys/ptrace.h>
  806. 14802 #include <minix/boot.h>
  807. 14803 #include <minix/callnr.h>
  808. 14804 #include <minix/com.h>
  809. 14805 #include "proc.h"
  810. 14806 #include "protect.h"
  811. 14807
  812. 14808 /* PSW masks. */
  813. 14809 #define IF_MASK 0x00000200
  814. 14810 #define IOPL_MASK 0x003000
  815. 14811
  816. 14812 PRIVATE message m;
  817. 14813
  818. 14814 FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
  819. 14815 FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
  820. 14816 FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
  821. 14817 FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
  822. 14818 FORWARD _PROTOTYPE( int do_gboot, (message *m_ptr) );
  823. 14819 FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
  824. 14820 FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
  825. 14821 FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
  826. 14822 FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
  827. 14823 FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
  828. 14824 FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
  829. 14825 FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
  830. 14826 FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
  831. 14827 FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
  832. 14828 FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
  833. 14829 FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
  834. 14830 FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
  835. 14831 FORWARD _PROTOTYPE( int do_getmap, (message *m_ptr) );
  836. 14832
  837. 14833
  838. 14834 /*===========================================================================*
  839. 14835  *                              sys_task                                     *
  840. 14836  *===========================================================================*/
  841. 14837 PUBLIC void sys_task()
  842. 14838 {
  843. 14839 /* Main entry point of sys_task.  Get the message and dispatch on type. */
  844. 14840
  845. 14841   register int r;
  846. 14842
  847. 14843   while (TRUE) {
  848. 14844         receive(ANY, &m);
  849. 14845
  850. 14846         switch (m.m_type) {     /* which system call */
  851. 14847             case SYS_FORK:      r = do_fork(&m);        break;
  852. 14848             case SYS_NEWMAP:    r = do_newmap(&m);      break;
  853. 14849             case SYS_GETMAP:    r = do_getmap(&m);      break;
  854. 14850             case SYS_EXEC:      r = do_exec(&m);        break;
  855. 14851             case SYS_XIT:       r = do_xit(&m);         break;
  856. 14852             case SYS_GETSP:     r = do_getsp(&m);       break;
  857. 14853             case SYS_TIMES:     r = do_times(&m);       break;
  858. 14854             case SYS_ABORT:     r = do_abort(&m);       break;
  859. 14855             case SYS_SENDSIG:   r = do_sendsig(&m);     break;
  860. 14856             case SYS_SIGRETURN: r = do_sigreturn(&m);   break;
  861. 14857             case SYS_KILL:      r = do_kill(&m);        break;
  862. 14858             case SYS_ENDSIG:    r = do_endsig(&m);      break;
  863. 14859             case SYS_COPY:      r = do_copy(&m);        break;
  864. 14860             case SYS_VCOPY:     r = do_vcopy(&m);       break;
  865. 14861             case SYS_GBOOT:     r = do_gboot(&m);       break;
  866. 14862             case SYS_MEM:       r = do_mem(&m);         break;
  867. 14863             case SYS_UMAP:      r = do_umap(&m);        break;
  868. 14864             case SYS_TRACE:     r = do_trace(&m);       break;
  869. 14865             default:            r = E_BAD_FCN;
  870. 14866         }
  871. 14867
  872. 14868         m.m_type = r;           /* 'r' reports status of call */
  873. 14869         send(m.m_source, &m);   /* send reply to caller */
  874. 14870   }
  875. 14871 }
  876. 14874 /*===========================================================================*
  877. 14875  *                              do_fork                                      *
  878. 14876  *===========================================================================*/
  879. 14877 PRIVATE int do_fork(m_ptr)
  880. 14878 register message *m_ptr;        /* pointer to request message */
  881. 14879 {
  882. 14880 /* Handle sys_fork().  m_ptr->PROC1 has forked.  The child is m_ptr->PROC2. */
  883. 14881
  884. 14882   reg_t old_ldt_sel;
  885. 14883   register struct proc *rpc;
  886. 14884   struct proc *rpp;
  887. 14885
  888. 14886   if (!isoksusern(m_ptr->PROC1) || !isoksusern(m_ptr->PROC2))
  889. 14887         return(E_BAD_PROC);
  890. 14888   rpp = proc_addr(m_ptr->PROC1);
  891. 14889   rpc = proc_addr(m_ptr->PROC2);
  892. 14890
  893. 14891   /* Copy parent 'proc' struct to child. */
  894. 14892   old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
  895. 14893
  896. 14894   *rpc = *rpp;                  /* copy 'proc' struct */
  897. 14895
  898. 14896   rpc->p_ldt_sel = old_ldt_sel;
  899. 14897   rpc->p_nr = m_ptr->PROC2;     /* this was obliterated by copy */
  900. 14898
  901. 14899   rpc->p_flags |= NO_MAP;       /* inhibit the process from running */
  902. 14900
  903. 14901   rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
  904. 14902
  905. 14903   /* Only 1 in group should have PENDING, child does not inherit trace status*/
  906. 14904   sigemptyset(&rpc->p_pending);
  907. 14905   rpc->p_pendcount = 0;
  908. 14906   rpc->p_pid = m_ptr->PID;      /* install child's pid */
  909. 14907   rpc->p_reg.retreg = 0;        /* child sees pid = 0 to know it is child */
  910. 14908
  911. 14909   rpc->user_time = 0;           /* set all the accounting times to 0 */
  912. 14910   rpc->sys_time = 0;
  913. 14911   rpc->child_utime = 0;
  914. 14912   rpc->child_stime = 0;
  915. 14913
  916. 14914   return(OK);
  917. 14915 }
  918. 14918 /*===========================================================================*
  919. 14919  *                              do_newmap                                    *
  920. 14920  *===========================================================================*/
  921. 14921 PRIVATE int do_newmap(m_ptr)
  922. 14922 message *m_ptr;                 /* pointer to request message */
  923. 14923 {
  924. 14924 /* Handle sys_newmap().  Fetch the memory map from MM. */
  925. 14925
  926. 14926   register struct proc *rp;
  927. 14927   phys_bytes src_phys;
  928. 14928   int caller;                   /* whose space has the new map (usually MM) */
  929. 14929   int k;                        /* process whose map is to be loaded */
  930. 14930   int old_flags;                /* value of flags before modification */
  931. 14931   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
  932. 14932
  933. 14933   /* Extract message parameters and copy new memory map from MM. */
  934. 14934   caller = m_ptr->m_source;
  935. 14935   k = m_ptr->PROC1;
  936. 14936   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
  937. 14937   if (!isokprocn(k)) return(E_BAD_PROC);
  938. 14938   rp = proc_addr(k);            /* ptr to entry of user getting new map */
  939. 14939
  940. 14940   /* Copy the map from MM. */
  941. 14941   src_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
  942. 14942   if (src_phys == 0) panic("bad call to sys_newmap", NO_NUM);
  943. 14943   phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
  944. 14944
  945. 14945   alloc_segments(rp);
  946. 14946   old_flags = rp->p_flags;      /* save the previous value of the flags */
  947. 14947   rp->p_flags &= ~NO_MAP;
  948. 14948   if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
  949. 14949
  950. 14950   return(OK);
  951. 14951 }
  952. 14954 /*===========================================================================*
  953. 14955  *                              do_getmap                                    *
  954. 14956  *===========================================================================*/
  955. 14957 PRIVATE int do_getmap(m_ptr)
  956. 14958 message *m_ptr;                 /* pointer to request message */
  957. 14959 {
  958. 14960 /* Handle sys_getmap().  Report the memory map to MM. */
  959. 14961
  960. 14962   register struct proc *rp;
  961. 14963   phys_bytes dst_phys;
  962. 14964   int caller;                   /* where the map has to be stored */
  963. 14965   int k;                        /* process whose map is to be loaded */
  964. 14966   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
  965. 14967
  966. 14968   /* Extract message parameters and copy new memory map to MM. */
  967. 14969   caller = m_ptr->m_source;
  968. 14970   k = m_ptr->PROC1;
  969. 14971   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
  970. 14972
  971. 14973   if (!isokprocn(k))
  972. 14974         panic("do_getmap got bad proc: ", m_ptr->PROC1);
  973. 14975
  974. 14976   rp = proc_addr(k);            /* ptr to entry of the map */
  975. 14977
  976. 14978   /* Copy the map to MM. */
  977. 14979   dst_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
  978. 14980   if (dst_phys == 0) panic("bad call to sys_getmap", NO_NUM);
  979. 14981   phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
  980. 14982
  981. 14983   return(OK);
  982. 14984 }
  983. 14987 /*===========================================================================*
  984. 14988  *                              do_exec                                      *
  985. 14989  *===========================================================================*/
  986. 14990 PRIVATE int do_exec(m_ptr)
  987. 14991 register message *m_ptr;        /* pointer to request message */
  988. 14992 {
  989. 14993 /* Handle sys_exec().  A process has done a successful EXEC. Patch it up. */
  990. 14994
  991. 14995   register struct proc *rp;
  992. 14996   reg_t sp;                     /* new sp */
  993. 14997   phys_bytes phys_name;
  994. 14998   char *np;
  995. 14999 #define NLEN (sizeof(rp->p_name)-1)
  996. 15000
  997. 15001   if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
  998. 15002   /* PROC2 field is used as flag to indicate process is being traced */
  999. 15003   if (m_ptr->PROC2) cause_sig(m_ptr->PROC1, SIGTRAP);
  1000. 15004   sp = (reg_t) m_ptr->STACK_PTR;
  1001. 15005   rp = proc_addr(m_ptr->PROC1);
  1002. 15006   rp->p_reg.sp = sp;            /* set the stack pointer */
  1003. 15007   rp->p_reg.pc = (reg_t) m_ptr->IP_PTR; /* set pc */
  1004. 15008   rp->p_alarm = 0;              /* reset alarm timer */
  1005. 15009   rp->p_flags &= ~RECEIVING;    /* MM does not reply to EXEC call */
  1006. 15010   if (rp->p_flags == 0) lock_ready(rp);
  1007. 15011
  1008. 15012   /* Save command name for debugging, ps(1) output, etc. */
  1009. 15013   phys_name = numap(m_ptr->m_source, (vir_bytes) m_ptr->NAME_PTR,
  1010. 15014                                                         (vir_bytes) NLEN);
  1011. 15015   if (phys_name != 0) {
  1012. 15016         phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
  1013. 15017         for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
  1014. 15018         *np = 0;
  1015. 15019   }
  1016. 15020   return(OK);
  1017. 15021 }
  1018. 15024 /*===========================================================================*
  1019. 15025  *                              do_xit                                       *
  1020. 15026  *===========================================================================*/
  1021. 15027 PRIVATE int do_xit(m_ptr)
  1022. 15028 message *m_ptr;                 /* pointer to request message */
  1023. 15029 {
  1024. 15030 /* Handle sys_xit().  A process has exited. */
  1025. 15031
  1026. 15032   register struct proc *rp, *rc;
  1027. 15033   struct proc *np, *xp;
  1028. 15034   int parent;                   /* number of exiting proc's parent */
  1029. 15035   int proc_nr;                  /* number of process doing the exit */
  1030. 15036   phys_clicks base, size;
  1031. 15037
  1032. 15038   parent = m_ptr->PROC1;        /* slot number of parent process */
  1033. 15039   proc_nr = m_ptr->PROC2;       /* slot number of exiting process */
  1034. 15040   if (!isoksusern(parent) || !isoksusern(proc_nr)) return(E_BAD_PROC);
  1035. 15041   rp = proc_addr(parent);
  1036. 15042   rc = proc_addr(proc_nr);
  1037. 15043   lock();
  1038. 15044   rp->child_utime += rc->user_time + rc->child_utime;   /* accum child times */
  1039. 15045   rp->child_stime += rc->sys_time + rc->child_stime;
  1040. 15046   unlock();
  1041. 15047   rc->p_alarm = 0;              /* turn off alarm timer */
  1042. 15048   if (rc->p_flags == 0) lock_unready(rc);
  1043. 15049
  1044. 15050   strcpy(rc->p_name, "<noname>");       /* process no longer has a name */
  1045. 15051
  1046. 15052   /* If the process being terminated happens to be queued trying to send a
  1047. 15053    * message (i.e., the process was killed by a signal, rather than it doing an
  1048. 15054    * EXIT), then it must be removed from the message queues.
  1049. 15055    */
  1050. 15056   if (rc->p_flags & SENDING) {
  1051. 15057         /* Check all proc slots to see if the exiting process is queued. */
  1052. 15058         for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
  1053. 15059                 if (rp->p_callerq == NIL_PROC) continue;
  1054. 15060                 if (rp->p_callerq == rc) {
  1055. 15061                         /* Exiting process is on front of this queue. */
  1056. 15062                         rp->p_callerq = rc->p_sendlink;
  1057. 15063                         break;
  1058. 15064                 } else {
  1059. 15065                         /* See if exiting process is in middle of queue. */
  1060. 15066                         np = rp->p_callerq;
  1061. 15067                         while ( ( xp = np->p_sendlink) != NIL_PROC)
  1062. 15068                                 if (xp == rc) {
  1063. 15069                                         np->p_sendlink = xp->p_sendlink;
  1064. 15070                                         break;
  1065. 15071                                 } else {
  1066. 15072                                         np = xp;
  1067. 15073                                 }
  1068. 15074                 }
  1069. 15075         }
  1070. 15076   }
  1071. 15077
  1072. 15078   if (rc->p_flags & PENDING) --sig_procs;
  1073. 15079   sigemptyset(&rc->p_pending);
  1074. 15080   rc->p_pendcount = 0;
  1075. 15081   rc->p_flags = P_SLOT_FREE;
  1076. 15082   return(OK);
  1077. 15083 }
  1078. 15086 /*===========================================================================*
  1079. 15087  *                              do_getsp                                     *
  1080. 15088  *===========================================================================*/
  1081. 15089 PRIVATE int do_getsp(m_ptr)
  1082. 15090 register message *m_ptr;        /* pointer to request message */
  1083. 15091 {
  1084. 15092 /* Handle sys_getsp().  MM wants to know what sp is. */
  1085. 15093
  1086. 15094   register struct proc *rp;
  1087. 15095
  1088. 15096   if (!isoksusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1089. 15097   rp = proc_addr(m_ptr->PROC1);
  1090. 15098   m_ptr->STACK_PTR = (char *) rp->p_reg.sp;     /* return sp here (bad type) */
  1091. 15099   return(OK);
  1092. 15100 }
  1093. 15103 /*===========================================================================*
  1094. 15104  *                              do_times                                     *
  1095. 15105  *===========================================================================*/
  1096. 15106 PRIVATE int do_times(m_ptr)
  1097. 15107 register message *m_ptr;        /* pointer to request message */
  1098. 15108 {
  1099. 15109 /* Handle sys_times().  Retrieve the accounting information. */
  1100. 15110
  1101. 15111   register struct proc *rp;
  1102. 15112
  1103. 15113   if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
  1104. 15114   rp = proc_addr(m_ptr->PROC1);
  1105. 15115
  1106. 15116   /* Insert the times needed by the TIMES system call in the message. */
  1107. 15117   lock();                       /* halt the volatile time counters in rp */
  1108. 15118   m_ptr->USER_TIME   = rp->user_time;
  1109. 15119   m_ptr->SYSTEM_TIME = rp->sys_time;
  1110. 15120   unlock();
  1111. 15121   m_ptr->CHILD_UTIME = rp->child_utime;
  1112. 15122   m_ptr->CHILD_STIME = rp->child_stime;
  1113. 15123   m_ptr->BOOT_TICKS  = get_uptime();
  1114. 15124   return(OK);
  1115. 15125 }
  1116. 15128 /*===========================================================================*
  1117. 15129  *                              do_abort                                     *
  1118. 15130  *===========================================================================*/
  1119. 15131 PRIVATE int do_abort(m_ptr)
  1120. 15132 message *m_ptr;                 /* pointer to request message */
  1121. 15133 {
  1122. 15134 /* Handle sys_abort.  MINIX is unable to continue.  Terminate operation. */
  1123. 15135   char monitor_code[64];
  1124. 15136   phys_bytes src_phys;
  1125. 15137
  1126. 15138   if (m_ptr->m1_i1 == RBT_MONITOR) {
  1127. 15139         /* The monitor is to run user specified instructions. */
  1128. 15140         src_phys = numap(m_ptr->m_source, (vir_bytes) m_ptr->m1_p1,
  1129. 15141                                         (vir_bytes) sizeof(monitor_code));
  1130. 15142         if (src_phys == 0) panic("bad monitor code from", m_ptr->m_source);
  1131. 15143         phys_copy(src_phys, vir2phys(monitor_code),
  1132. 15144                                         (phys_bytes) sizeof(monitor_code));
  1133. 15145         reboot_code = vir2phys(monitor_code);
  1134. 15146   }
  1135. 15147   wreboot(m_ptr->m1_i1);
  1136. 15148   return(OK);                   /* pro-forma (really EDISASTER) */
  1137. 15149 }
  1138. 15154 /*===========================================================================*
  1139. 15155  *                            do_sendsig                                     *
  1140. 15156  *===========================================================================*/
  1141. 15157 PRIVATE int do_sendsig(m_ptr)
  1142. 15158 message *m_ptr;                 /* pointer to request message */
  1143. 15159 {
  1144. 15160 /* Handle sys_sendsig, POSIX-style signal */
  1145. 15161
  1146. 15162   struct sigmsg smsg;
  1147. 15163   register struct proc *rp;
  1148. 15164   phys_bytes src_phys, dst_phys;
  1149. 15165   struct sigcontext sc, *scp;
  1150. 15166   struct sigframe fr, *frp;
  1151. 15167
  1152. 15168   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1153. 15169   rp = proc_addr(m_ptr->PROC1);
  1154. 15170
  1155. 15171   /* Get the sigmsg structure into our address space.  */
  1156. 15172   src_phys = umap(proc_addr(MM_PROC_NR), D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
  1157. 15173                   (vir_bytes) sizeof(struct sigmsg));
  1158. 15174   if (src_phys == 0)
  1159. 15175         panic("do_sendsig can't signal: bad sigmsg address from MM", NO_NUM);
  1160. 15176   phys_copy(src_phys, vir2phys(&smsg), (phys_bytes) sizeof(struct sigmsg));
  1161. 15177
  1162. 15178   /* Compute the usr stack pointer value where sigcontext will be stored. */
  1163. 15179   scp = (struct sigcontext *) smsg.sm_stkptr - 1;
  1164. 15180
  1165. 15181   /* Copy the registers to the sigcontext structure. */
  1166. 15182   memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
  1167. 15183
  1168. 15184   /* Finish the sigcontext initialization. */
  1169. 15185   sc.sc_flags = SC_SIGCONTEXT;
  1170. 15186
  1171. 15187   sc.sc_mask = smsg.sm_mask;
  1172. 15188
  1173. 15189   /* Copy the sigcontext structure to the user's stack. */
  1174. 15190   dst_phys = umap(rp, D, (vir_bytes) scp,
  1175. 15191                   (vir_bytes) sizeof(struct sigcontext));
  1176. 15192   if (dst_phys == 0) return(EFAULT);
  1177. 15193   phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
  1178. 15194
  1179. 15195   /* Initialize the sigframe structure. */
  1180. 15196   frp = (struct sigframe *) scp - 1;
  1181. 15197   fr.sf_scpcopy = scp;
  1182. 15198   fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
  1183. 15199   fr.sf_fp = rp->p_reg.fp;
  1184. 15200   rp->p_reg.fp = (reg_t) &frp->sf_fp;
  1185. 15201   fr.sf_scp = scp;
  1186. 15202   fr.sf_code = 0;       /* XXX - should be used for type of FP exception */
  1187. 15203   fr.sf_signo = smsg.sm_signo;
  1188. 15204   fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
  1189. 15205
  1190. 15206   /* Copy the sigframe structure to the user's stack. */
  1191. 15207   dst_phys = umap(rp, D, (vir_bytes) frp, (vir_bytes) sizeof(struct sigframe));
  1192. 15208   if (dst_phys == 0) return(EFAULT);
  1193. 15209   phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
  1194. 15210
  1195. 15211   /* Reset user registers to execute the signal handler. */
  1196. 15212   rp->p_reg.sp = (reg_t) frp;
  1197. 15213   rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
  1198. 15214
  1199. 15215   return(OK);
  1200. 15216 }
  1201. 15218 /*===========================================================================*
  1202. 15219  *                            do_sigreturn                                   *
  1203. 15220  *===========================================================================*/
  1204. 15221 PRIVATE int do_sigreturn(m_ptr)
  1205. 15222 register message *m_ptr;
  1206. 15223 {
  1207. 15224 /* POSIX style signals require sys_sigreturn to put things in order before the
  1208. 15225  * signalled process can resume execution
  1209. 15226  */
  1210. 15227
  1211. 15228   struct sigcontext sc;
  1212. 15229   register struct proc *rp;
  1213. 15230   phys_bytes src_phys;
  1214. 15231
  1215. 15232   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1216. 15233   rp = proc_addr(m_ptr->PROC1);
  1217. 15234
  1218. 15235   /* Copy in the sigcontext structure. */
  1219. 15236   src_phys = umap(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
  1220. 15237                   (vir_bytes) sizeof(struct sigcontext));
  1221. 15238   if (src_phys == 0) return(EFAULT);
  1222. 15239   phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
  1223. 15240
  1224. 15241   /* Make sure that this is not just a jmp_buf. */
  1225. 15242   if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
  1226. 15243
  1227. 15244   /* Fix up only certain key registers if the compiler doesn't use
  1228. 15245    * register variables within functions containing setjmp.
  1229. 15246    */
  1230. 15247   if (sc.sc_flags & SC_NOREGLOCALS) {
  1231. 15248         rp->p_reg.retreg = sc.sc_retreg;
  1232. 15249         rp->p_reg.fp = sc.sc_fp;
  1233. 15250         rp->p_reg.pc = sc.sc_pc;
  1234. 15251         rp->p_reg.sp = sc.sc_sp;
  1235. 15252         return (OK);
  1236. 15253   }
  1237. 15254   sc.sc_psw  = rp->p_reg.psw;
  1238. 15255
  1239. 15256 #if (CHIP == INTEL)
  1240. 15257   /* Don't panic kernel if user gave bad selectors. */
  1241. 15258   sc.sc_cs = rp->p_reg.cs;
  1242. 15259   sc.sc_ds = rp->p_reg.ds;
  1243. 15260   sc.sc_es = rp->p_reg.es;
  1244. 15261 #if _WORD_SIZE == 4
  1245. 15262   sc.sc_fs = rp->p_reg.fs;
  1246. 15263   sc.sc_gs = rp->p_reg.gs;
  1247. 15264 #endif
  1248. 15265 #endif
  1249. 15266
  1250. 15267   /* Restore the registers. */
  1251. 15268   memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
  1252. 15269
  1253. 15270   return(OK);
  1254. 15271 }
  1255. 15273 /*===========================================================================*
  1256. 15274  *                              do_kill                                      *
  1257. 15275  *===========================================================================*/
  1258. 15276 PRIVATE int do_kill(m_ptr)
  1259. 15277 register message *m_ptr;        /* pointer to request message */
  1260. 15278 {
  1261. 15279 /* Handle sys_kill(). Cause a signal to be sent to a process via MM.
  1262. 15280  * Note that this has nothing to do with the kill (2) system call, this
  1263. 15281  * is how the FS (and possibly other servers) get access to cause_sig to
  1264. 15282  * send a KSIG message to MM
  1265. 15283  */
  1266. 15284
  1267. 15285   if (!isokusern(m_ptr->PR)) return(E_BAD_PROC);
  1268. 15286   cause_sig(m_ptr->PR, m_ptr->SIGNUM);
  1269. 15287   return(OK);
  1270. 15288 }
  1271. 15291 /*===========================================================================*
  1272. 15292  *                            do_endsig                                      *
  1273. 15293  *===========================================================================*/
  1274. 15294 PRIVATE int do_endsig(m_ptr)
  1275. 15295 register message *m_ptr;        /* pointer to request message */
  1276. 15296 {
  1277. 15297 /* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a call
  1278. 15298  * to cause_sig by a task
  1279. 15299  */
  1280. 15300
  1281. 15301   register struct proc *rp;
  1282. 15302
  1283. 15303   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  1284. 15304   rp = proc_addr(m_ptr->PROC1);
  1285. 15305
  1286. 15306   /* MM has finished one KSIG. */
  1287. 15307   if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
  1288. 15308       && (rp->p_flags &= ~SIG_PENDING) == 0)
  1289. 15309         lock_ready(rp);
  1290. 15310   return(OK);
  1291. 15311 }
  1292. 15313 /*===========================================================================*
  1293. 15314  *                              do_copy                                      *
  1294. 15315  *===========================================================================*/
  1295. 15316 PRIVATE int do_copy(m_ptr)
  1296. 15317 register message *m_ptr;        /* pointer to request message */
  1297. 15318 {
  1298. 15319 /* Handle sys_copy().  Copy data for MM or FS. */
  1299. 15320
  1300. 15321   int src_proc, dst_proc, src_space, dst_space;
  1301. 15322   vir_bytes src_vir, dst_vir;
  1302. 15323   phys_bytes src_phys, dst_phys, bytes;
  1303. 15324
  1304. 15325   /* Dismember the command message. */
  1305. 15326   src_proc = m_ptr->SRC_PROC_NR;
  1306. 15327   dst_proc = m_ptr->DST_PROC_NR;
  1307. 15328   src_space = m_ptr->SRC_SPACE;
  1308. 15329   dst_space = m_ptr->DST_SPACE;
  1309. 15330   src_vir = (vir_bytes) m_ptr->SRC_BUFFER;
  1310. 15331   dst_vir = (vir_bytes) m_ptr->DST_BUFFER;
  1311. 15332   bytes = (phys_bytes) m_ptr->COPY_BYTES;
  1312. 15333
  1313. 15334   /* Compute the source and destination addresses and do the copy. */
  1314. 15335   if (src_proc == ABS)
  1315. 15336         src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
  1316. 15337   else {
  1317. 15338         if (bytes != (vir_bytes) bytes)
  1318. 15339                 /* This would happen for 64K segments and 16-bit vir_bytes.
  1319. 15340                  * It would happen a lot for do_fork except MM uses ABS
  1320. 15341                  * copies for that case.
  1321. 15342                  */
  1322. 15343                 panic("overflow in count in do_copy", NO_NUM);
  1323. 15344
  1324. 15345         src_phys = umap(proc_addr(src_proc), src_space, src_vir,
  1325. 15346                         (vir_bytes) bytes);
  1326. 15347         }
  1327. 15348
  1328. 15349   if (dst_proc == ABS)
  1329. 15350         dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
  1330. 15351   else
  1331. 15352         dst_phys = umap(proc_addr(dst_proc), dst_space, dst_vir,
  1332. 15353                         (vir_bytes) bytes);
  1333. 15354
  1334. 15355   if (src_phys == 0 || dst_phys == 0) return(EFAULT);
  1335. 15356   phys_copy(src_phys, dst_phys, bytes);
  1336. 15357   return(OK);
  1337. 15358 }
  1338. 15361 /*===========================================================================*
  1339. 15362  *                              do_vcopy                                     *
  1340. 15363  *===========================================================================*/
  1341. 15364 PRIVATE int do_vcopy(m_ptr)
  1342. 15365 register message *m_ptr;        /* pointer to request message */
  1343. 15366 {
  1344. 15367 /* Handle sys_vcopy(). Copy multiple blocks of memory */
  1345. 15368
  1346. 15369   int src_proc, dst_proc, vect_s, i;
  1347. 15370   vir_bytes src_vir, dst_vir, vect_addr;
  1348. 15371   phys_bytes src_phys, dst_phys, bytes;
  1349. 15372   cpvec_t cpvec_table[CPVEC_NR];
  1350. 15373
  1351. 15374   /* Dismember the command message. */
  1352. 15375   src_proc = m_ptr->m1_i1;
  1353. 15376   dst_proc = m_ptr->m1_i2;
  1354. 15377   vect_s = m_ptr->m1_i3;
  1355. 15378   vect_addr = (vir_bytes)m_ptr->m1_p1;
  1356. 15379
  1357. 15380   if (vect_s > CPVEC_NR) return EDOM;
  1358. 15381
  1359. 15382   src_phys= numap (m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
  1360. 15383   if (!src_phys) return EFAULT;
  1361. 15384   phys_copy(src_phys, vir2phys(cpvec_table),
  1362. 15385                                 (phys_bytes) (vect_s * sizeof(cpvec_t)));
  1363. 15386
  1364. 15387   for (i = 0; i < vect_s; i++) {
  1365. 15388         src_vir= cpvec_table[i].cpv_src;
  1366. 15389         dst_vir= cpvec_table[i].cpv_dst;
  1367. 15390         bytes= cpvec_table[i].cpv_size;
  1368. 15391         src_phys = numap(src_proc,src_vir,(vir_bytes)bytes);
  1369. 15392         dst_phys = numap(dst_proc,dst_vir,(vir_bytes)bytes);
  1370. 15393         if (src_phys == 0 || dst_phys == 0) return(EFAULT);
  1371. 15394         phys_copy(src_phys, dst_phys, bytes);
  1372. 15395   }
  1373. 15396   return(OK);
  1374. 15397 }
  1375. 15400 /*==========================================================================*
  1376. 15401  *                              do_gboot                                    *
  1377. 15402  *==========================================================================*/
  1378. 15403 PUBLIC struct bparam_s boot_parameters;
  1379. 15404
  1380. 15405 PRIVATE int do_gboot(m_ptr)
  1381. 15406 message *m_ptr;                 /* pointer to request message */
  1382. 15407 {
  1383. 15408 /* Copy the boot parameters.  Normally only called during fs init. */
  1384. 15409
  1385. 15410   phys_bytes dst_phys;
  1386. 15411
  1387. 15412   dst_phys = umap(proc_addr(m_ptr->PROC1), D, (vir_bytes) m_ptr->MEM_PTR,
  1388. 15413                                 (vir_bytes) sizeof(boot_parameters));
  1389. 15414   if (dst_phys == 0) panic("bad call to SYS_GBOOT", NO_NUM);
  1390. 15415   phys_copy(vir2phys(&boot_parameters), dst_phys,
  1391. 15416                                 (phys_bytes) sizeof(boot_parameters));
  1392. 15417   return(OK);
  1393. 15418 }
  1394. 15421 /*===========================================================================*
  1395. 15422  *                              do_mem                                       *
  1396. 15423  *===========================================================================*/
  1397. 15424 PRIVATE int do_mem(m_ptr)
  1398. 15425 register message *m_ptr;        /* pointer to request message */
  1399. 15426 {
  1400. 15427 /* Return the base and size of the next chunk of memory. */
  1401. 15428
  1402. 15429   struct memory *memp;
  1403. 15430
  1404. 15431   for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
  1405. 15432         m_ptr->m1_i1 = memp->base;
  1406. 15433         m_ptr->m1_i2 = memp->size;
  1407. 15434         m_ptr->m1_i3 = tot_mem_size;
  1408. 15435         memp->size = 0;
  1409. 15436         if (m_ptr->m1_i2 != 0) break;           /* found a chunk */
  1410. 15437   }
  1411. 15438   return(OK);
  1412. 15439 }
  1413. 15442 /*==========================================================================*
  1414. 15443  *                              do_umap                                     *
  1415. 15444  *==========================================================================*/
  1416. 15445 PRIVATE int do_umap(m_ptr)
  1417. 15446 register message *m_ptr;        /* pointer to request message */
  1418. 15447 {
  1419. 15448 /* Same as umap(), for non-kernel processes. */
  1420. 15449
  1421. 15450   m_ptr->SRC_BUFFER = umap(proc_addr((int) m_ptr->SRC_PROC_NR),
  1422. 15451                            (int) m_ptr->SRC_SPACE,
  1423. 15452                            (vir_bytes) m_ptr->SRC_BUFFER,
  1424. 15453                            (vir_bytes) m_ptr->COPY_BYTES);
  1425. 15454   return(OK);
  1426. 15455 }
  1427. 15458 /*==========================================================================*
  1428. 15459  *                              do_trace                                    *
  1429. 15460  *==========================================================================*/
  1430. 15461 #define TR_PROCNR       (m_ptr->m2_i1)
  1431. 15462 #define TR_REQUEST      (m_ptr->m2_i2)
  1432. 15463 #define TR_ADDR         ((vir_bytes) m_ptr->m2_l1)
  1433. 15464 #define TR_DATA         (m_ptr->m2_l2)
  1434. 15465 #define TR_VLSIZE       ((vir_bytes) sizeof(long))
  1435. 15466
  1436. 15467 PRIVATE int do_trace(m_ptr)
  1437. 15468 register message *m_ptr;
  1438. 15469 {
  1439. 15470 /* Handle the debugging commands supported by the ptrace system call
  1440. 15471  * The commands are:
  1441. 15472  * T_STOP       stop the process
  1442. 15473  * T_OK         enable tracing by parent for this process
  1443. 15474  * T_GETINS     return value from instruction space
  1444. 15475  * T_GETDATA    return value from data space
  1445. 15476  * T_GETUSER    return value from user process table
  1446. 15477  * T_SETINS     set value from instruction space
  1447. 15478  * T_SETDATA    set value from data space
  1448. 15479  * T_SETUSER    set value in user process table
  1449. 15480  * T_RESUME     resume execution
  1450. 15481  * T_EXIT       exit
  1451. 15482  * T_STEP       set trace bit
  1452. 15483  *
  1453. 15484  * The T_OK and T_EXIT commands are handled completely by the memory manager,
  1454. 15485  * all others come here.
  1455. 15486  */
  1456. 15487
  1457. 15488   register struct proc *rp;
  1458. 15489   phys_bytes src, dst;
  1459. 15490   int i;
  1460. 15491
  1461. 15492   rp = proc_addr(TR_PROCNR);
  1462. 15493   if (rp->p_flags & P_SLOT_FREE) return(EIO);
  1463. 15494   switch (TR_REQUEST) {
  1464. 15495   case T_STOP:                  /* stop process */
  1465. 15496         if (rp->p_flags == 0) lock_unready(rp);
  1466. 15497         rp->p_flags |= P_STOP;
  1467. 15498         rp->p_reg.psw &= ~TRACEBIT;     /* clear trace bit */
  1468. 15499         return(OK);
  1469. 15500
  1470. 15501   case T_GETINS:                /* return value from instruction space */
  1471. 15502         if (rp->p_map[T].mem_len != 0) {
  1472. 15503                 if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1473. 15504                 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
  1474. 15505                 break;
  1475. 15506         }
  1476. 15507         /* Text space is actually data space - fall through. */
  1477. 15508
  1478. 15509   case T_GETDATA:               /* return value from data space */
  1479. 15510         if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1480. 15511         phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
  1481. 15512         break;
  1482. 15513
  1483. 15514   case T_GETUSER:               /* return value from process table */
  1484. 15515         if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
  1485. 15516             TR_ADDR > sizeof(struct proc) - sizeof(long))
  1486. 15517                 return(EIO);
  1487. 15518         TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
  1488. 15519         break;
  1489. 15520
  1490. 15521   case T_SETINS:                /* set value in instruction space */
  1491. 15522         if (rp->p_map[T].mem_len != 0) {
  1492. 15523                 if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1493. 15524                 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
  1494. 15525                 TR_DATA = 0;
  1495. 15526                 break;
  1496. 15527         }
  1497. 15528         /* Text space is actually data space - fall through. */
  1498. 15529
  1499. 15530   case T_SETDATA:                       /* set value in data space */
  1500. 15531         if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1501. 15532         phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
  1502. 15533         TR_DATA = 0;
  1503. 15534         break;
  1504. 15535
  1505. 15536   case T_SETUSER:                       /* set value in process table */
  1506. 15537         if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
  1507. 15538              TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
  1508. 15539                 return(EIO);
  1509. 15540         i = (int) TR_ADDR;
  1510. 15541 #if (CHIP == INTEL)
  1511. 15542         /* Altering segment registers might crash the kernel when it
  1512. 15543          * tries to load them prior to restarting a process, so do
  1513. 15544          * not allow it.
  1514. 15545          */
  1515. 15546         if (i == (int) &((struct proc *) 0)->p_reg.cs ||
  1516. 15547             i == (int) &((struct proc *) 0)->p_reg.ds ||
  1517. 15548             i == (int) &((struct proc *) 0)->p_reg.es ||
  1518. 15549 #if _WORD_SIZE == 4
  1519. 15550             i == (int) &((struct proc *) 0)->p_reg.gs ||
  1520. 15551             i == (int) &((struct proc *) 0)->p_reg.fs ||
  1521. 15552 #endif
  1522. 15553             i == (int) &((struct proc *) 0)->p_reg.ss)
  1523. 15554                 return(EIO);
  1524. 15555 #endif
  1525. 15556         if (i == (int) &((struct proc *) 0)->p_reg.psw)
  1526. 15557                 /* only selected bits are changeable */
  1527. 15558                 SETPSW(rp, TR_DATA);
  1528. 15559         else
  1529. 15560                 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
  1530. 15561         TR_DATA = 0;
  1531. 15562         break;
  1532. 15563
  1533. 15564   case T_RESUME:                /* resume execution */
  1534. 15565         rp->p_flags &= ~P_STOP;
  1535. 15566         if (rp->p_flags == 0) lock_ready(rp);
  1536. 15567         TR_DATA = 0;
  1537. 15568         break;
  1538. 15569
  1539. 15570   case T_STEP:                  /* set trace bit */
  1540. 15571         rp->p_reg.psw |= TRACEBIT;
  1541. 15572         rp->p_flags &= ~P_STOP;
  1542. 15573         if (rp->p_flags == 0) lock_ready(rp);
  1543. 15574         TR_DATA = 0;
  1544. 15575         break;
  1545. 15576
  1546. 15577   default:
  1547. 15578         return(EIO);
  1548. 15579   }
  1549. 15580   return(OK);
  1550. 15581 }
  1551. 15583 /*===========================================================================*
  1552. 15584  *                              cause_sig                                    *
  1553. 15585  *===========================================================================*/
  1554. 15586 PUBLIC void cause_sig(proc_nr, sig_nr)
  1555. 15587 int proc_nr;                    /* process to be signalled */
  1556. 15588 int sig_nr;                     /* signal to be sent, 1 to _NSIG */
  1557. 15589 {
  1558. 15590 /* A task wants to send a signal to a process.   Examples of such tasks are:
  1559. 15591  *   TTY wanting to cause SIGINT upon getting a DEL
  1560. 15592  *   CLOCK wanting to cause SIGALRM when timer expires
  1561. 15593  * FS also uses this to send a signal, via the SYS_KILL message.
  1562. 15594  * Signals are handled by sending a message to MM.  The tasks don't dare do
  1563. 15595  * that directly, for fear of what would happen if MM were busy.  Instead they
  1564. 15596  * call cause_sig, which sets bits in p_pending, and then carefully checks to
  1565. 15597  * see if MM is free.  If so, a message is sent to it.  If not, when it becomes
  1566. 15598  * free, a message is sent.  The process being signaled is blocked while MM
  1567. 15599  * has not seen or finished with all signals for it.  These signals are
  1568. 15600  * counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
  1569. 15601  * there are some.  It is not sufficient to ready the process when MM is
  1570. 15602  * informed, because MM can block waiting for FS to do a core dump.
  1571. 15603  */
  1572. 15604
  1573. 15605   register struct proc *rp, *mmp;
  1574. 15606
  1575. 15607   rp = proc_addr(proc_nr);
  1576. 15608   if (sigismember(&rp->p_pending, sig_nr))
  1577. 15609         return;                 /* this signal already pending */
  1578. 15610   sigaddset(&rp->p_pending, sig_nr);
  1579. 15611   ++rp->p_pendcount;            /* count new signal pending */
  1580. 15612   if (rp->p_flags & PENDING)
  1581. 15613         return;                 /* another signal already pending */
  1582. 15614   if (rp->p_flags == 0) lock_unready(rp);
  1583. 15615   rp->p_flags |= PENDING | SIG_PENDING;
  1584. 15616   ++sig_procs;                  /* count new process pending */
  1585. 15617
  1586. 15618   mmp = proc_addr(MM_PROC_NR);
  1587. 15619   if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
  1588. 15620   inform();
  1589. 15621 }
  1590. 15624 /*===========================================================================*
  1591. 15625  *                              inform                                       *
  1592. 15626  *===========================================================================*/
  1593. 15627 PUBLIC void inform()
  1594. 15628 {
  1595. 15629 /* When a signal is detected by the kernel (e.g., DEL), or generated by a task
  1596. 15630  * (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
  1597. 15631  * p_pending field of the process to signal.  Then inform() is called to see
  1598. 15632  * if MM is idle and can be told about it.  Whenever MM blocks, a check is
  1599. 15633  * made to see if 'sig_procs' is nonzero; if so, inform() is called.
  1600. 15634  */
  1601. 15635
  1602. 15636   register struct proc *rp;
  1603. 15637
  1604. 15638   /* MM is waiting for new input.  Find a process with pending signals. */
  1605. 15639   for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
  1606. 15640         if (rp->p_flags & PENDING) {
  1607. 15641                 m.m_type = KSIG;
  1608. 15642                 m.SIG_PROC = proc_number(rp);
  1609. 15643                 m.SIG_MAP = rp->p_pending;
  1610. 15644                 sig_procs--;
  1611. 15645                 if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
  1612. 15646                         panic("can't inform MM", NO_NUM);
  1613. 15647                 sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
  1614. 15648                 rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
  1615. 15649                 lock_pick_proc();       /* avoid delay in scheduling MM */
  1616. 15650                 return;
  1617. 15651         }
  1618. 15652 }
  1619. 15655 /*===========================================================================*
  1620. 15656  *                              umap                                         *
  1621. 15657  *===========================================================================*/
  1622. 15658 PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
  1623. 15659 register struct proc *rp;       /* pointer to proc table entry for process */
  1624. 15660 int seg;                        /* T, D, or S segment */
  1625. 15661 vir_bytes vir_addr;             /* virtual address in bytes within the seg */
  1626. 15662 vir_bytes bytes;                /* # of bytes to be copied */
  1627. 15663 {
  1628. 15664 /* Calculate the physical memory address for a given virtual address. */
  1629. 15665
  1630. 15666   vir_clicks vc;                /* the virtual address in clicks */
  1631. 15667   phys_bytes pa;                /* intermediate variables as phys_bytes */
  1632. 15668   phys_bytes seg_base;
  1633. 15669
  1634. 15670   /* If 'seg' is D it could really be S and vice versa.  T really means T.
  1635. 15671    * If the virtual address falls in the gap,  it causes a problem. On the
  1636. 15672    * 8088 it is probably a legal stack reference, since "stackfaults" are
  1637. 15673    * not detected by the hardware.  On 8088s, the gap is called S and
  1638. 15674    * accepted, but on other machines it is called D and rejected.
  1639. 15675    * The Atari ST behaves like the 8088 in this respect.
  1640. 15676    */
  1641. 15677
  1642. 15678   if (bytes <= 0) return( (phys_bytes) 0);
  1643. 15679   vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;   /* last click of data */
  1644. 15680
  1645. 15681   if (seg != T)
  1646. 15682         seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
  1647. 15683
  1648. 15684   if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
  1649. 15685         return( (phys_bytes) 0 );
  1650. 15686   seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
  1651. 15687   seg_base = seg_base << CLICK_SHIFT;   /* segment origin in bytes */
  1652. 15688   pa = (phys_bytes) vir_addr;
  1653. 15689   pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
  1654. 15690   return(seg_base + pa);
  1655. 15691 }
  1656. 15694 /*==========================================================================*
  1657. 15695  *                              numap                                       *
  1658. 15696  *==========================================================================*/
  1659. 15697 PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
  1660. 15698 int proc_nr;                    /* process number to be mapped */
  1661. 15699 vir_bytes vir_addr;             /* virtual address in bytes within D seg */
  1662. 15700 vir_bytes bytes;                /* # of bytes required in segment  */
  1663. 15701 {
  1664. 15702 /* Do umap() starting from a process number instead of a pointer.  This
  1665. 15703  * function is used by device drivers, so they need not know about the
  1666. 15704  * process table.  To save time, there is no 'seg' parameter. The segment
  1667. 15705  * is always D.
  1668. 15706  */
  1669. 15707
  1670. 15708   return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
  1671. 15709 }
  1672. 15711 #if (CHIP == INTEL)
  1673. 15712 /*==========================================================================*
  1674. 15713  *                              alloc_segments                              *
  1675. 15714  *==========================================================================*/
  1676. 15715 PUBLIC void alloc_segments(rp)
  1677. 15716 register struct proc *rp;
  1678. 15717 {
  1679. 15718 /* This is called only by do_newmap, but is broken out as a separate function
  1680. 15719  * because so much is hardware-dependent.
  1681. 15720  */
  1682. 15721
  1683. 15722   phys_bytes code_bytes;
  1684. 15723   phys_bytes data_bytes;
  1685. 15724   int privilege;
  1686. 15725
  1687. 15726   if (protected_mode) {
  1688. 15727         data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
  1689. 15728                      << CLICK_SHIFT;
  1690. 15729         if (rp->p_map[T].mem_len == 0)
  1691. 15730                 code_bytes = data_bytes;        /* common I&D, poor protect */
  1692. 15731         else
  1693. 15732                 code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
  1694. 15733         privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
  1695. 15734         init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
  1696. 15735                      (phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
  1697. 15736                      code_bytes, privilege);
  1698. 15737         init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
  1699. 15738                      (phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
  1700. 15739                      data_bytes, privilege);
  1701. 15740         rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
  1702. 15741 #if _WORD_SIZE == 4
  1703. 15742         rp->p_reg.gs =
  1704. 15743         rp->p_reg.fs =
  1705. 15744 #endif
  1706. 15745         rp->p_reg.ss =
  1707. 15746         rp->p_reg.es =
  1708. 15747         rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
  1709. 15748   } else {
  1710. 15749         rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
  1711. 15750         rp->p_reg.ss =
  1712. 15751         rp->p_reg.es =
  1713. 15752         rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
  1714. 15753   }
  1715. 15754 }
  1716. 15755 #endif /* (CHIP == INTEL) */
  1717. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1718. src/mm/mm.h    
  1719. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1720. 15800 /* This is the master header for mm.  It includes some other files
  1721. 15801  * and defines the principal constants.
  1722. 15802  */
  1723. 15803 #define _POSIX_SOURCE      1    /* tell headers to include POSIX stuff */
  1724. 15804 #define _MINIX             1    /* tell headers to include MINIX stuff */
  1725. 15805 #define _SYSTEM            1    /* tell headers that this is the kernel */
  1726. 15806
  1727. 15807 /* The following are so basic, all the *.c files get them automatically. */
  1728. 15808 #include <minix/config.h>       /* MUST be first */
  1729. 15809 #include <ansi.h>               /* MUST be second */
  1730. 15810 #include <sys/types.h>
  1731. 15811 #include <minix/const.h>
  1732. 15812 #include <minix/type.h>
  1733. 15813
  1734. 15814 #include <fcntl.h>
  1735. 15815 #include <unistd.h>
  1736. 15816 #include <minix/syslib.h>
  1737. 15817
  1738. 15818 #include <limits.h>
  1739. 15819 #include <errno.h>
  1740. 15820
  1741. 15821 #include "const.h"
  1742. 15822 #include "type.h"
  1743. 15823 #include "proto.h"
  1744. 15824 #include "glo.h"
  1745. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1746. src/mm/const.h    
  1747. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1748. 15900 /* Constants used by the Memory Manager. */
  1749. 15901
  1750. 15902 #define NO_MEM ((phys_clicks) 0)  /* returned by alloc_mem() with mem is up */
  1751. 15903
  1752. 15904 #if (CHIP == INTEL && _WORD_SIZE == 2)
  1753. 15905 /* These definitions are used in size_ok and are not needed for 386.
  1754. 15906  * The 386 segment granularity is 1 for segments smaller than 1M and 4096
  1755. 15907  * above that.  
  1756. 15908  */
  1757. 15909 #define PAGE_SIZE         16    /* how many bytes in a page (s.b.HCLICK_SIZE)*/
  1758. 15910 #define MAX_PAGES       4096    /* how many pages in the virtual addr space */
  1759. 15911 #endif
  1760. 15912
  1761. 15913 #define printf        printk
  1762. 15914
  1763. 15915 #define INIT_PID           1    /* init's process id number */
  1764. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1765. src/mm/type.h    
  1766. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1767. 16000 /* If there were any type definitions local to the Memory Manager, they would
  1768. 16001  * be here.  This file is included only for symmetry with the kernel and File
  1769. 16002  * System, which do have some local type definitions.
  1770. 16003  */
  1771. 16004
  1772. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1773. src/mm/proto.h    
  1774. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1775. 16100 /* Function prototypes. */
  1776. 16101
  1777. 16102 struct mproc;           /* need types outside of parameter list --kub */
  1778. 16103 struct stat;
  1779. 16104
  1780. 16105 /* alloc.c */
  1781. 16106 _PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks)                 );
  1782. 16107 _PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks)       );
  1783. 16108 _PROTOTYPE( phys_clicks max_hole, (void)                                );
  1784. 16109 _PROTOTYPE( void mem_init, (phys_clicks *total, phys_clicks *free)      );
  1785. 16110 _PROTOTYPE( phys_clicks mem_left, (void)                                );
  1786. 16111 _PROTOTYPE( int do_brk3, (void)                                         );
  1787. 16112
  1788. 16113 /* break.c */
  1789. 16114 _PROTOTYPE( int adjust, (struct mproc *rmp,
  1790. 16115                         vir_clicks data_clicks, vir_bytes sp)           );
  1791. 16116 _PROTOTYPE( int do_brk, (void)                                          );
  1792. 16117 _PROTOTYPE( int size_ok, (int file_type, vir_clicks tc, vir_clicks dc,
  1793. 16118                         vir_clicks sc, vir_clicks dvir, vir_clicks s_vir) );
  1794. 16119
  1795. 16120 /* exec.c */
  1796. 16121 _PROTOTYPE( int do_exec, (void)                                         );
  1797. 16122 _PROTOTYPE( struct mproc *find_share, (struct mproc *mp_ign, Ino_t ino,
  1798. 16123                         Dev_t dev, time_t ctime)                        );
  1799. 16124
  1800. 16125 /* forkexit.c */
  1801. 16126 _PROTOTYPE( int do_fork, (void)                                         );
  1802. 16127 _PROTOTYPE( int do_mm_exit, (void)                                      );
  1803. 16128 _PROTOTYPE( int do_waitpid, (void)                                      );
  1804. 16129 _PROTOTYPE( void mm_exit, (struct mproc *rmp, int exit_status)          );
  1805. 16130
  1806. 16131 /* getset.c */
  1807. 16132 _PROTOTYPE( int do_getset, (void)                                       );
  1808. 16133
  1809. 16134 /* main.c */
  1810. 16135 _PROTOTYPE( void main, (void)                                           );
  1811. 16136
  1812. 16137 #if (MACHINE == MACINTOSH)
  1813. 16138 _PROTOTYPE( phys_clicks start_click, (void)                             );
  1814. 16139 #endif
  1815. 16140
  1816. 16141 _PROTOTYPE( void reply, (int proc_nr, int result, int res2, char *respt));
  1817. 16142
  1818. 16143 /* putk.c */
  1819. 16144 _PROTOTYPE( void putk, (int c)                                          );
  1820. 16145
  1821. 16146 /* signal.c */
  1822. 16147 _PROTOTYPE( int do_alarm, (void)                                        );
  1823. 16148 _PROTOTYPE( int do_kill, (void)                                         );
  1824. 16149 _PROTOTYPE( int do_ksig, (void)                                         );
  1825. 16150 _PROTOTYPE( int do_pause, (void)                                        );
  1826. 16151 _PROTOTYPE( int set_alarm, (int proc_nr, int sec)                       );
  1827. 16152 _PROTOTYPE( int check_sig, (pid_t proc_id, int signo)                   );
  1828. 16153 _PROTOTYPE( void sig_proc, (struct mproc *rmp, int sig_nr)              );
  1829. 16154 _PROTOTYPE( int do_sigaction, (void)                                    );
  1830. 16155 _PROTOTYPE( int do_sigpending, (void)                                   );
  1831. 16156 _PROTOTYPE( int do_sigprocmask, (void)                                  );
  1832. 16157 _PROTOTYPE( int do_sigreturn, (void)                                    );
  1833. 16158 _PROTOTYPE( int do_sigsuspend, (void)                                   );
  1834. 16159 _PROTOTYPE( int do_reboot, (void)                                       );
  1835. 16160
  1836. 16161 /* trace.c */
  1837. 16162 _PROTOTYPE( int do_trace, (void)                                        );
  1838. 16163 _PROTOTYPE( void stop_proc, (struct mproc *rmp, int sig_nr)             );
  1839. 16164
  1840. 16165 /* utility.c */
  1841. 16166 _PROTOTYPE( int allowed, (char *name_buf, struct stat *s_buf, int mask) );
  1842. 16167 _PROTOTYPE( int no_sys, (void)                                          );
  1843. 16168 _PROTOTYPE( void panic, (char *format, int num)                         );
  1844. 16169 _PROTOTYPE( void tell_fs, (int what, int p1, int p2, int p3)            );
  1845. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1846. src/mm/glo.h    
  1847. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1848. 16200 /* EXTERN should be extern except in table.c */
  1849. 16201 #ifdef _TABLE
  1850. 16202 #undef EXTERN
  1851. 16203 #define EXTERN
  1852. 16204 #endif
  1853. 16205
  1854. 16206 /* Global variables. */
  1855. 16207 EXTERN struct mproc *mp;        /* ptr to 'mproc' slot of current process */
  1856. 16208 EXTERN int dont_reply;          /* normally 0; set to 1 to inhibit reply */
  1857. 16209 EXTERN int procs_in_use;        /* how many processes are marked as IN_USE */
  1858. 16210
  1859. 16211 /* The parameters of the call are kept here. */
  1860. 16212 EXTERN message mm_in;           /* the incoming message itself is kept here. */
  1861. 16213 EXTERN message mm_out;          /* the reply message is built up here. */
  1862. 16214 EXTERN int who;                 /* caller's proc number */
  1863. 16215 EXTERN int mm_call;             /* system call number */
  1864. 16216
  1865. 16217 /* The following variables are used for returning results to the caller. */
  1866. 16218 EXTERN int err_code;            /* temporary storage for error number */
  1867. 16219 EXTERN int result2;             /* secondary result */
  1868. 16220 EXTERN char *res_ptr;           /* result, if pointer */
  1869. 16221
  1870. 16222 extern _PROTOTYPE (int (*call_vec[]), (void) ); /* system call handlers */
  1871. 16223 extern char core_name[];        /* file name where core images are produced */
  1872. 16224 EXTERN sigset_t core_sset;      /* which signals cause core images */
  1873. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1874. src/mm/mproc.h    
  1875. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1876. 16300 /* This table has one slot per process.  It contains all the memory management
  1877. 16301  * information for each process.  Among other things, it defines the text, data
  1878. 16302  * and stack segments, uids and gids, and various flags.  The kernel and file
  1879. 16303  * systems have tables that are also indexed by process, with the contents
  1880. 16304  * of corresponding slots referring to the same process in all three.
  1881. 16305  */
  1882. 16306
  1883. 16307 EXTERN struct mproc {
  1884. 16308   struct mem_map mp_seg[NR_SEGS];/* points to text, data, stack */
  1885. 16309   char mp_exitstatus;           /* storage for status when process exits */
  1886. 16310   char mp_sigstatus;            /* storage for signal # for killed procs */
  1887. 16311   pid_t mp_pid;                 /* process id */
  1888. 16312   pid_t mp_procgrp;             /* pid of process group (used for signals) */
  1889. 16313   pid_t mp_wpid;                /* pid this process is waiting for */
  1890. 16314   int mp_parent;                /* index of parent process */
  1891. 16315
  1892. 16316   /* Real and effective uids and gids. */
  1893. 16317   uid_t mp_realuid;             /* process' real uid */
  1894. 16318   uid_t mp_effuid;              /* process' effective uid */
  1895. 16319   gid_t mp_realgid;             /* process' real gid */
  1896. 16320   gid_t mp_effgid;              /* process' effective gid */
  1897. 16321
  1898. 16322   /* File identification for sharing. */
  1899. 16323   ino_t mp_ino;                 /* inode number of file */
  1900. 16324   dev_t mp_dev;                 /* device number of file system */
  1901. 16325   time_t mp_ctime;              /* inode changed time */
  1902. 16326
  1903. 16327   /* Signal handling information. */
  1904. 16328   sigset_t mp_ignore;           /* 1 means ignore the signal, 0 means don't */
  1905. 16329   sigset_t mp_catch;            /* 1 means catch the signal, 0 means don't */
  1906. 16330   sigset_t mp_sigmask;          /* signals to be blocked */
  1907. 16331   sigset_t mp_sigmask2;         /* saved copy of mp_sigmask */
  1908. 16332   sigset_t mp_sigpending;       /* signals being blocked */
  1909. 16333   struct sigaction mp_sigact[_NSIG + 1]; /* as in sigaction(2) */
  1910. 16334   vir_bytes mp_sigreturn;       /* address of C library __sigreturn function */
  1911. 16335
  1912. 16336   /* Backwards compatibility for signals. */
  1913. 16337   sighandler_t mp_func;         /* all sigs vectored to a single user fcn */
  1914. 16338
  1915. 16339   unsigned mp_flags;            /* flag bits */
  1916. 16340   vir_bytes mp_procargs;        /* ptr to proc's initial stack arguments */
  1917. 16341 } mproc[NR_PROCS];
  1918. 16342
  1919. 16343 /* Flag values */
  1920. 16344 #define IN_USE           001    /* set when 'mproc' slot in use */
  1921. 16345 #define WAITING          002    /* set by WAIT system call */
  1922. 16346 #define HANGING          004    /* set by EXIT system call */
  1923. 16347 #define PAUSED           010    /* set by PAUSE system call */
  1924. 16348 #define ALARM_ON         020    /* set when SIGALRM timer started */
  1925. 16349 #define SEPARATE         040    /* set if file is separate I & D space */
  1926. 16350 #define TRACED          0100    /* set if process is to be traced */
  1927. 16351 #define STOPPED         0200    /* set if process stopped for tracing */
  1928. 16352 #define SIGSUSPENDED    0400    /* set by SIGSUSPEND system call */
  1929. 16353
  1930. 16354 #define NIL_MPROC ((struct mproc *) 0)
  1931. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1932. src/mm/param.h    
  1933. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1934. 16400 /* The following names are synonyms for the variables in the input message. */
  1935. 16401 #define addr            mm_in.m1_p1
  1936. 16402 #define exec_name       mm_in.m1_p1
  1937. 16403 #define exec_len        mm_in.m1_i1
  1938. 16404 #define func            mm_in.m6_f1
  1939. 16405 #define grpid           (gid_t) mm_in.m1_i1
  1940. 16406 #define namelen         mm_in.m1_i1
  1941. 16407 #define pid             mm_in.m1_i1
  1942. 16408 #define seconds         mm_in.m1_i1
  1943. 16409 #define sig             mm_in.m6_i1
  1944. 16410 #define stack_bytes     mm_in.m1_i2
  1945. 16411 #define stack_ptr       mm_in.m1_p2
  1946. 16412 #define status          mm_in.m1_i1
  1947. 16413 #define usr_id          (uid_t) mm_in.m1_i1
  1948. 16414 #define request         mm_in.m2_i2
  1949. 16415 #define taddr           mm_in.m2_l1
  1950. 16416 #define data            mm_in.m2_l2
  1951. 16417 #define sig_nr          mm_in.m1_i2
  1952. 16418 #define sig_nsa         mm_in.m1_p1
  1953. 16419 #define sig_osa         mm_in.m1_p2
  1954. 16420 #define sig_ret         mm_in.m1_p3
  1955. 16421 #define sig_set         mm_in.m2_l1
  1956. 16422 #define sig_how         mm_in.m2_i1
  1957. 16423 #define sig_flags       mm_in.m2_i2
  1958. 16424 #define sig_context     mm_in.m2_p1
  1959. 16425 #ifdef _SIGMESSAGE
  1960. 16426 #define sig_msg         mm_in.m1_i1
  1961. 16427 #endif
  1962. 16428 #define reboot_flag     mm_in.m1_i1
  1963. 16429 #define reboot_code     mm_in.m1_p1
  1964. 16430 #define reboot_size     mm_in.m1_i2
  1965. 16431
  1966. 16432 /* The following names are synonyms for the variables in the output message. */
  1967. 16433 #define reply_type      mm_out.m_type
  1968. 16434 #define reply_i1        mm_out.m2_i1
  1969. 16435 #define reply_p1        mm_out.m2_p1
  1970. 16436 #define ret_mask        mm_out.m2_l1    
  1971. 16437
  1972. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1973. src/mm/table.c    
  1974. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1975. 16500 /* This file contains the table used to map system call numbers onto the
  1976. 16501  * routines that perform them.
  1977. 16502  */
  1978. 16503
  1979. 16504 #define _TABLE
  1980. 16505
  1981. 16506 #include "mm.h"
  1982. 16507 #include <minix/callnr.h>
  1983. 16508 #include <signal.h>
  1984. 16509 #include "mproc.h"
  1985. 16510 #include "param.h"
  1986. 16511
  1987. 16512 /* Miscellaneous */
  1988. 16513 char core_name[] = "core";      /* file name where core images are produced */
  1989. 16514
  1990. 16515 _PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
  1991. 16516         no_sys,         /*  0 = unused  */
  1992. 16517         do_mm_exit,     /*  1 = exit    */
  1993. 16518         do_fork,        /*  2 = fork    */
  1994. 16519         no_sys,         /*  3 = read    */
  1995. 16520         no_sys,         /*  4 = write   */
  1996. 16521         no_sys,         /*  5 = open    */
  1997. 16522         no_sys,         /*  6 = close   */
  1998. 16523         do_waitpid,     /*  7 = wait    */
  1999. 16524         no_sys,         /*  8 = creat   */
  2000. 16525         no_sys,         /*  9 = link    */
  2001. 16526         no_sys,         /* 10 = unlink  */
  2002. 16527         do_waitpid,     /* 11 = waitpid */
  2003. 16528         no_sys,         /* 12 = chdir   */
  2004. 16529         no_sys,         /* 13 = time    */
  2005. 16530         no_sys,         /* 14 = mknod   */
  2006. 16531         no_sys,         /* 15 = chmod   */
  2007. 16532         no_sys,         /* 16 = chown   */
  2008. 16533         do_brk,         /* 17 = break   */
  2009. 16534         no_sys,         /* 18 = stat    */
  2010. 16535         no_sys,         /* 19 = lseek   */
  2011. 16536         do_getset,      /* 20 = getpid  */
  2012. 16537         no_sys,         /* 21 = mount   */
  2013. 16538         no_sys,         /* 22 = umount  */
  2014. 16539         do_getset,      /* 23 = setuid  */
  2015. 16540         do_getset,      /* 24 = getuid  */
  2016. 16541         no_sys,         /* 25 = stime   */
  2017. 16542         do_trace,       /* 26 = ptrace  */
  2018. 16543         do_alarm,       /* 27 = alarm   */
  2019. 16544         no_sys,         /* 28 = fstat   */
  2020. 16545         do_pause,       /* 29 = pause   */
  2021. 16546         no_sys,         /* 30 = utime   */
  2022. 16547         no_sys,         /* 31 = (stty)  */
  2023. 16548         no_sys,         /* 32 = (gtty)  */
  2024. 16549         no_sys,         /* 33 = access  */
  2025. 16550         no_sys,         /* 34 = (nice)  */
  2026. 16551         no_sys,         /* 35 = (ftime) */
  2027. 16552         no_sys,         /* 36 = sync    */
  2028. 16553         do_kill,        /* 37 = kill    */
  2029. 16554         no_sys,         /* 38 = rename  */
  2030. 16555         no_sys,         /* 39 = mkdir   */
  2031. 16556         no_sys,         /* 40 = rmdir   */
  2032. 16557         no_sys,         /* 41 = dup     */
  2033. 16558         no_sys,         /* 42 = pipe    */
  2034. 16559         no_sys,         /* 43 = times   */
  2035. 16560         no_sys,         /* 44 = (prof)  */
  2036. 16561         no_sys,         /* 45 = unused  */
  2037. 16562         do_getset,      /* 46 = setgid  */
  2038. 16563         do_getset,      /* 47 = getgid  */
  2039. 16564         no_sys,         /* 48 = (signal)*/
  2040. 16565         no_sys,         /* 49 = unused  */
  2041. 16566         no_sys,         /* 50 = unused  */
  2042. 16567         no_sys,         /* 51 = (acct)  */
  2043. 16568         no_sys,         /* 52 = (phys)  */
  2044. 16569         no_sys,         /* 53 = (lock)  */
  2045. 16570         no_sys,         /* 54 = ioctl   */
  2046. 16571         no_sys,         /* 55 = fcntl   */
  2047. 16572         no_sys,         /* 56 = (mpx)   */
  2048. 16573         no_sys,         /* 57 = unused  */
  2049. 16574         no_sys,         /* 58 = unused  */
  2050. 16575         do_exec,        /* 59 = execve  */
  2051. 16576         no_sys,         /* 60 = umask   */
  2052. 16577         no_sys,         /* 61 = chroot  */
  2053. 16578         do_getset,      /* 62 = setsid  */
  2054. 16579         do_getset,      /* 63 = getpgrp */
  2055. 16580
  2056. 16581         do_ksig,        /* 64 = KSIG: signals originating in the kernel */
  2057. 16582         no_sys,         /* 65 = UNPAUSE */
  2058. 16583         no_sys,         /* 66 = unused  */
  2059. 16584         no_sys,         /* 67 = REVIVE  */
  2060. 16585         no_sys,         /* 68 = TASK_REPLY  */
  2061. 16586         no_sys,         /* 69 = unused  */
  2062. 16587         no_sys,         /* 70 = unused  */
  2063. 16588         do_sigaction,   /* 71 = sigaction   */
  2064. 16589         do_sigsuspend,  /* 72 = sigsuspend  */
  2065. 16590         do_sigpending,  /* 73 = sigpending  */
  2066. 16591         do_sigprocmask, /* 74 = sigprocmask */
  2067. 16592         do_sigreturn,   /* 75 = sigreturn   */
  2068. 16593         do_reboot,      /* 76 = reboot  */
  2069. 16594 };
  2070. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2071. src/mm/main.c    
  2072. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2073. 16600 /* This file contains the main program of the memory manager and some related
  2074. 16601  * procedures.  When MINIX starts up, the kernel runs for a little while,
  2075. 16602  * initializing itself and its tasks, and then it runs MM and FS.  Both MM
  2076. 16603  * and FS initialize themselves as far as they can.  FS then makes a call to
  2077. 16604  * MM, because MM has to wait for FS to acquire a RAM disk.  MM asks the
  2078. 16605  * kernel for all free memory and starts serving requests.
  2079. 16606  *
  2080. 16607  * The entry points into this file are:
  2081. 16608  *   main:      starts MM running
  2082. 16609  *   reply:     reply to a process making an MM system call
  2083. 16610  */
  2084. 16611
  2085. 16612 #include "mm.h"
  2086. 16613 #include <minix/callnr.h>
  2087. 16614 #include <minix/com.h>
  2088. 16615 #include <signal.h>
  2089. 16616 #include <fcntl.h>
  2090. 16617 #include <sys/ioctl.h>
  2091. 16618 #include "mproc.h"
  2092. 16619 #include "param.h"
  2093. 16620
  2094. 16621 FORWARD _PROTOTYPE( void get_work, (void)                               );
  2095. 16622 FORWARD _PROTOTYPE( void mm_init, (void)                                );
  2096. 16623
  2097. 16624 /*===========================================================================*
  2098. 16625  *                              main                                         *
  2099. 16626  *===========================================================================*/
  2100. 16627 PUBLIC void main()
  2101. 16628 {
  2102. 16629 /* Main routine of the memory manager. */
  2103. 16630
  2104. 16631   int error;
  2105. 16632
  2106. 16633   mm_init();                    /* initialize memory manager tables */
  2107. 16634
  2108. 16635   /* This is MM's main loop-  get work and do it, forever and forever. */
  2109. 16636   while (TRUE) {
  2110. 16637         /* Wait for message. */
  2111. 16638         get_work();             /* wait for an MM system call */
  2112. 16639         mp = &mproc[who];
  2113. 16640
  2114. 16641         /* Set some flags. */
  2115. 16642         error = OK;
  2116. 16643         dont_reply = FALSE;
  2117. 16644         err_code = -999;
  2118. 16645
  2119. 16646         /* If the call number is valid, perform the call. */
  2120. 16647         if (mm_call < 0 || mm_call >= NCALLS)
  2121. 16648                 error = EBADCALL;
  2122. 16649         else
  2123. 16650                 error = (*call_vec[mm_call])();
  2124. 16651
  2125. 16652         /* Send the results back to the user to indicate completion. */
  2126. 16653         if (dont_reply) continue;       /* no reply for EXIT and WAIT */
  2127. 16654         if (mm_call == EXEC && error == OK) continue;
  2128. 16655         reply(who, error, result2, res_ptr);
  2129. 16656   }
  2130. 16657 }
  2131. 16660 /*===========================================================================*
  2132. 16661  *                              get_work                                     *
  2133. 16662  *===========================================================================*/
  2134. 16663 PRIVATE void get_work()
  2135. 16664 {
  2136. 16665 /* Wait for the next message and extract useful information from it. */
  2137. 16666
  2138. 16667   if (receive(ANY, &mm_in) != OK) panic("MM receive error", NO_NUM);
  2139. 16668   who = mm_in.m_source;         /* who sent the message */
  2140. 16669   mm_call = mm_in.m_type;       /* system call number */
  2141. 16670 }
  2142. 16673 /*===========================================================================*
  2143. 16674  *                              reply                                        *
  2144. 16675  *===========================================================================*/
  2145. 16676 PUBLIC void reply(proc_nr, result, res2, respt)
  2146. 16677 int proc_nr;                    /* process to reply to */
  2147. 16678 int result;                     /* result of the call (usually OK or error #)*/
  2148. 16679 int res2;                       /* secondary result */
  2149. 16680 char *respt;                    /* result if pointer */
  2150. 16681 {
  2151. 16682 /* Send a reply to a user process. */
  2152. 16683
  2153. 16684   register struct mproc *proc_ptr;
  2154. 16685
  2155. 16686   proc_ptr = &mproc[proc_nr];
  2156. 16687   /* 
  2157. 16688    * To make MM robust, check to see if destination is still alive.  This
  2158. 16689    * validy check must be skipped if the caller is a task.
  2159. 16690    */
  2160. 16691   if ((who >=0) && ((proc_ptr->mp_flags&IN_USE) == 0 || 
  2161. 16692         (proc_ptr->mp_flags&HANGING))) return;
  2162. 16693
  2163. 16694   reply_type = result;
  2164. 16695   reply_i1 = res2;
  2165. 16696   reply_p1 = respt;
  2166. 16697   if (send(proc_nr, &mm_out) != OK) panic("MM can't reply", NO_NUM);
  2167. 16698 }
  2168. 16701 /*===========================================================================*
  2169. 16702  *                              mm_init                                      *
  2170. 16703  *===========================================================================*/
  2171. 16704 PRIVATE void mm_init()
  2172. 16705 {
  2173. 16706 /* Initialize the memory manager. */
  2174. 16707
  2175. 16708   static char core_sigs[] = {
  2176. 16709         SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
  2177. 16710         SIGEMT, SIGFPE, SIGUSR1, SIGSEGV,
  2178. 16711         SIGUSR2, 0 };
  2179. 16712   register int proc_nr;
  2180. 16713   register struct mproc *rmp;
  2181. 16714   register char *sig_ptr;
  2182. 16715   phys_clicks ram_clicks, total_clicks, minix_clicks, free_clicks, dummy;
  2183. 16716   message mess;
  2184. 16717   struct mem_map kernel_map[NR_SEGS];
  2185. 16718   int mem;
  2186. 16719
  2187. 16720   /* Build the set of signals which cause core dumps. Do it the Posix
  2188. 16721    * way, so no knowledge of bit positions is needed.
  2189. 16722    */
  2190. 16723   sigemptyset(&core_sset);
  2191. 16724   for (sig_ptr = core_sigs; *sig_ptr != 0; sig_ptr++)
  2192. 16725         sigaddset(&core_sset, *sig_ptr);
  2193. 16726
  2194. 16727   /* Get the memory map of the kernel to see how much memory it uses,
  2195. 16728    * including the gap between address 0 and the start of the kernel.
  2196. 16729    */
  2197. 16730   sys_getmap(SYSTASK, kernel_map);
  2198. 16731   minix_clicks = kernel_map[S].mem_phys + kernel_map[S].mem_len;
  2199. 16732
  2200. 16733   /* Initialize MM's tables. */
  2201. 16734   for (proc_nr = 0; proc_nr <= INIT_PROC_NR; proc_nr++) {
  2202. 16735         rmp = &mproc[proc_nr];
  2203. 16736         rmp->mp_flags |= IN_USE;
  2204. 16737         sys_getmap(proc_nr, rmp->mp_seg);
  2205. 16738         if (rmp->mp_seg[T].mem_len != 0) rmp->mp_flags |= SEPARATE;
  2206. 16739         minix_clicks += (rmp->mp_seg[S].mem_phys + rmp->mp_seg[S].mem_len)
  2207. 16740                                 - rmp->mp_seg[T].mem_phys;
  2208. 16741   }
  2209. 16742   mproc[INIT_PROC_NR].mp_pid = INIT_PID;
  2210. 16743   sigemptyset(&mproc[INIT_PROC_NR].mp_ignore);
  2211. 16744   sigemptyset(&mproc[INIT_PROC_NR].mp_catch);
  2212. 16745   procs_in_use = LOW_USER + 1;
  2213. 16746
  2214. 16747   /* Wait for FS to send a message telling the RAM disk size then go "on-line".
  2215. 16748    */
  2216. 16749   if (receive(FS_PROC_NR, &mess) != OK)
  2217. 16750         panic("MM can't obtain RAM disk size from FS", NO_NUM);
  2218. 16751
  2219. 16752   ram_clicks = mess.m1_i1;
  2220. 16753
  2221. 16754   /* Initialize tables to all physical mem. */
  2222. 16755   mem_init(&total_clicks, &free_clicks);
  2223. 16756
  2224. 16757   /* Print memory information. */
  2225. 16758   printf("nMemory size =%5dK   ", click_to_round_k(total_clicks));
  2226. 16759   printf("MINIX =%4dK   ", click_to_round_k(minix_clicks));
  2227. 16760   printf("RAM disk =%5dK   ", click_to_round_k(ram_clicks));
  2228. 16761   printf("Available =%5dKnn", click_to_round_k(free_clicks));
  2229. 16762
  2230. 16763   /* Tell FS to continue. */
  2231. 16764   if (send(FS_PROC_NR, &mess) != OK)
  2232. 16765         panic("MM can't sync up with FS", NO_NUM);
  2233. 16766
  2234. 16767   /* Tell the memory task where my process table is for the sake of ps(1). */
  2235. 16768   if ((mem = open("/dev/mem", O_RDWR)) != -1) {
  2236. 16769         ioctl(mem, MIOCSPSINFO, (void *) mproc);
  2237. 16770         close(mem);
  2238. 16771   }
  2239. 16772 }
  2240. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2241. src/mm/forkexit.c    
  2242. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2243. 16800 /* This file deals with creating processes (via FORK) and deleting them (via
  2244. 16801  * EXIT/WAIT).  When a process forks, a new slot in the 'mproc' table is
  2245. 16802  * allocated for it, and a copy of the parent's core image is made for the
  2246. 16803  * child.  Then the kernel and file system are informed.  A process is removed
  2247. 16804  * from the 'mproc' table when two events have occurred: (1) it has exited or
  2248. 16805  * been killed by a signal, and (2) the parent has done a WAIT.  If the process
  2249. 16806  * exits first, it continues to occupy a slot until the parent does a WAIT.
  2250. 16807  *
  2251. 16808  * The entry points into this file are:
  2252. 16809  *   do_fork:    perform the FORK system call
  2253. 16810  *   do_mm_exit: perform the EXIT system call (by calling mm_exit())
  2254. 16811  *   mm_exit:    actually do the exiting
  2255. 16812  *   do_wait:    perform the WAITPID or WAIT system call
  2256. 16813  */
  2257. 16814
  2258. 16815
  2259. 16816 #include "mm.h"
  2260. 16817 #include <sys/wait.h>
  2261. 16818 #include <minix/callnr.h>
  2262. 16819 #include <signal.h>
  2263. 16820 #include "mproc.h"
  2264. 16821 #include "param.h"
  2265. 16822
  2266. 16823 #define LAST_FEW            2   /* last few slots reserved for superuser */
  2267. 16824
  2268. 16825 PRIVATE pid_t next_pid = INIT_PID+1;    /* next pid to be assigned */
  2269. 16826
  2270. 16827 FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) );
  2271. 16828
  2272. 16829 /*===========================================================================*
  2273. 16830  *                              do_fork                                      *
  2274. 16831  *===========================================================================*/
  2275. 16832 PUBLIC int do_fork()
  2276. 16833 {
  2277. 16834 /* The process pointed to by 'mp' has forked.  Create a child process. */
  2278. 16835
  2279. 16836   register struct mproc *rmp;   /* pointer to parent */
  2280. 16837   register struct mproc *rmc;   /* pointer to child */
  2281. 16838   int i, child_nr, t;
  2282. 16839   phys_clicks prog_clicks, child_base = 0;
  2283. 16840   phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */
  2284. 16841
  2285. 16842  /* If tables might fill up during FORK, don't even start since recovery half
  2286. 16843   * way through is such a nuisance.
  2287. 16844   */
  2288. 16845   rmp = mp;
  2289. 16846   if (procs_in_use == NR_PROCS) return(EAGAIN);
  2290. 16847   if (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN);
  2291. 16848
  2292. 16849   /* Determine how much memory to allocate.  Only the data and stack need to
  2293. 16850    * be copied, because the text segment is either shared or of zero length.
  2294. 16851    */
  2295. 16852   prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
  2296. 16853   prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
  2297. 16854   prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
  2298. 16855   if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(EAGAIN);
  2299. 16856
  2300. 16857   /* Create a copy of the parent's core image for the child. */
  2301. 16858   child_abs = (phys_bytes) child_base << CLICK_SHIFT;
  2302. 16859   parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
  2303. 16860   i = sys_copy(ABS, 0, parent_abs, ABS, 0, child_abs, prog_bytes);
  2304. 16861   if (i < 0) panic("do_fork can't copy", i);
  2305. 16862
  2306. 16863   /* Find a slot in 'mproc' for the child process.  A slot must exist. */
  2307. 16864   for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++)
  2308. 16865         if ( (rmc->mp_flags & IN_USE) == 0) break;
  2309. 16866
  2310. 16867   /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
  2311. 16868   child_nr = (int)(rmc - mproc);        /* slot number of the child */
  2312. 16869   procs_in_use++;
  2313. 16870   *rmc = *rmp;                  /* copy parent's process slot to child's */
  2314. 16871
  2315. 16872   rmc->mp_parent = who;         /* record child's parent */
  2316. 16873   rmc->mp_flags &= ~TRACED;     /* child does not inherit trace status */
  2317. 16874   /* A separate I&D child keeps the parents text segment.  The data and stack
  2318. 16875    * segments must refer to the new copy.
  2319. 16876    */
  2320. 16877   if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base;
  2321. 16878   rmc->mp_seg[D].mem_phys = child_base;
  2322. 16879   rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
  2323. 16880                         (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
  2324. 16881   rmc->mp_exitstatus = 0;
  2325. 16882   rmc->mp_sigstatus = 0;
  2326. 16883
  2327. 16884   /* Find a free pid for the child and put it in the table. */
  2328. 16885   do {
  2329. 16886         t = 0;                  /* 't' = 0 means pid still free */
  2330. 16887         next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PID + 1);
  2331. 16888         for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
  2332. 16889                 if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) {
  2333. 16890                         t = 1;
  2334. 16891                         break;
  2335. 16892                 }
  2336. 16893         rmc->mp_pid = next_pid; /* assign pid to child */
  2337. 16894   } while (t);
  2338. 16895
  2339. 16896   /* Tell kernel and file system about the (now successful) FORK. */
  2340. 16897   sys_fork(who, child_nr, rmc->mp_pid, child_base); /* child_base is 68K only*/
  2341. 16898   tell_fs(FORK, who, child_nr, rmc->mp_pid);
  2342. 16899
  2343. 16900   /* Report child's memory map to kernel. */
  2344. 16901   sys_newmap(child_nr, rmc->mp_seg);
  2345. 16902
  2346. 16903   /* Reply to child to wake it up. */
  2347. 16904   reply(child_nr, 0, 0, NIL_PTR);
  2348. 16905   return(next_pid);              /* child's pid */
  2349. 16906 }
  2350. 16909 /*===========================================================================*
  2351. 16910  *                              do_mm_exit                                   *
  2352. 16911  *===========================================================================*/
  2353. 16912 PUBLIC int do_mm_exit()
  2354. 16913 {
  2355. 16914 /* Perform the exit(status) system call. The real work is done by mm_exit(),
  2356. 16915  * which is also called when a process is killed by a signal.
  2357. 16916  */
  2358. 16917
  2359. 16918   mm_exit(mp, status);
  2360. 16919   dont_reply = TRUE;            /* don't reply to newly terminated process */
  2361. 16920   return(OK);                   /* pro forma return code */
  2362. 16921 }
  2363. 16924 /*===========================================================================*
  2364. 16925  *                              mm_exit                                      *
  2365. 16926  *===========================================================================*/
  2366. 16927 PUBLIC void mm_exit(rmp, exit_status)
  2367. 16928 register struct mproc *rmp;     /* pointer to the process to be terminated */
  2368. 16929 int exit_status;                /* the process' exit status (for parent) */
  2369. 16930 {
  2370. 16931 /* A process is done.  Release most of the process' possessions.  If its
  2371. 16932  * parent is waiting, release the rest, else hang.
  2372. 16933  */
  2373. 16934
  2374. 16935   register int proc_nr;
  2375. 16936   int parent_waiting, right_child;
  2376. 16937   pid_t pidarg, procgrp;
  2377. 16938   phys_clicks base, size, s;            /* base and size used on 68000 only */
  2378. 16939
  2379. 16940   proc_nr = (int) (rmp - mproc);        /* get process slot number */
  2380. 16941
  2381. 16942   /* Remember a session leader's process group. */
  2382. 16943   procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
  2383. 16944
  2384. 16945   /* If the exited process has a timer pending, kill it. */
  2385. 16946   if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr, (unsigned) 0);
  2386. 16947
  2387. 16948   /* Tell the kernel and FS that the process is no longer runnable. */
  2388. 16949   tell_fs(EXIT, proc_nr, 0, 0);  /* file system can free the proc slot */
  2389. 16950   sys_xit(rmp->mp_parent, proc_nr, &base, &size);
  2390. 16951
  2391. 16952   /* Release the memory occupied by the child. */
  2392. 16953   if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
  2393. 16954         /* No other process shares the text segment, so free it. */
  2394. 16955         free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
  2395. 16956   }
  2396. 16957   /* Free the data and stack segments. */
  2397. 16958   free_mem(rmp->mp_seg[D].mem_phys,
  2398. 16959       rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
  2399. 16960
  2400. 16961   /* The process slot can only be freed if the parent has done a WAIT. */
  2401. 16962   rmp->mp_exitstatus = (char) exit_status;
  2402. 16963   pidarg = mproc[rmp->mp_parent].mp_wpid;       /* who's being waited for? */
  2403. 16964   parent_waiting = mproc[rmp->mp_parent].mp_flags & WAITING;
  2404. 16965   if (pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp)
  2405. 16966         right_child = TRUE;             /* child meets one of the 3 tests */
  2406. 16967   else
  2407. 16968         right_child = FALSE;            /* child fails all 3 tests */
  2408. 16969   if (parent_waiting && right_child)
  2409. 16970         cleanup(rmp);                   /* tell parent and release child slot */
  2410. 16971   else
  2411. 16972         rmp->mp_flags |= HANGING;       /* parent not waiting, suspend child */
  2412. 16973
  2413. 16974   /* If the process has children, disinherit them.  INIT is the new parent. */
  2414. 16975   for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
  2415. 16976         if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
  2416. 16977                 /* 'rmp' now points to a child to be disinherited. */
  2417. 16978                 rmp->mp_parent = INIT_PROC_NR;
  2418. 16979                 parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
  2419. 16980                 if (parent_waiting && (rmp->mp_flags & HANGING)) cleanup(rmp);
  2420. 16981         }
  2421. 16982   }
  2422. 16983
  2423. 16984   /* Send a hangup to the process' process group if it was a session leader. */
  2424. 16985   if (procgrp != 0) check_sig(-procgrp, SIGHUP);
  2425. 16986 }
  2426. 16989 /*===========================================================================*
  2427. 16990  *                              do_waitpid                                   *
  2428. 16991  *===========================================================================*/
  2429. 16992 PUBLIC int do_waitpid()
  2430. 16993 {
  2431. 16994 /* A process wants to wait for a child to terminate. If one is already waiting,
  2432. 16995  * go clean it up and let this WAIT call terminate.  Otherwise, really wait.
  2433. 16996  * Both WAIT and WAITPID are handled by this code.
  2434. 16997  */
  2435. 16998
  2436. 16999   register struct mproc *rp;
  2437. 17000   int pidarg, options, children, res2;
  2438. 17001
  2439. 17002   /* A process calling WAIT never gets a reply in the usual way via the
  2440. 17003    * reply() in the main loop (unless WNOHANG is set or no qualifying child
  2441. 17004    * exists).  If a child has already exited, the routine cleanup() sends 
  2442. 17005    * the reply to awaken the caller.
  2443. 17006    */
  2444. 17007
  2445. 17008   /* Set internal variables, depending on whether this is WAIT or WAITPID. */
  2446. 17009   pidarg  = (mm_call == WAIT ? -1 : pid);       /* first param of waitpid */
  2447. 17010   options = (mm_call == WAIT ?  0 : sig_nr);    /* third param of waitpid */
  2448. 17011   if (pidarg == 0) pidarg = -mp->mp_procgrp;    /* pidarg < 0 ==> proc grp */
  2449. 17012
  2450. 17013   /* Is there a child waiting to be collected? At this point, pidarg != 0:
  2451. 17014    *    pidarg  >  0 means pidarg is pid of a specific process to wait for
  2452. 17015    *    pidarg == -1 means wait for any child
  2453. 17016    *    pidarg  < -1 means wait for any child whose process group = -pidarg
  2454. 17017    */
  2455. 17018   children = 0;
  2456. 17019   for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
  2457. 17020         if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who) {
  2458. 17021                 /* The value of pidarg determines which children qualify. */
  2459. 17022                 if (pidarg  > 0 && pidarg != rp->mp_pid) continue;
  2460. 17023                 if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue;
  2461. 17024
  2462. 17025                 children++;             /* this child is acceptable */
  2463. 17026                 if (rp->mp_flags & HANGING) {
  2464. 17027                         /* This child meets the pid test and has exited. */
  2465. 17028                         cleanup(rp);    /* this child has already exited */
  2466. 17029                         dont_reply = TRUE;
  2467. 17030                         return(OK);
  2468. 17031                 }
  2469. 17032                 if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
  2470. 17033                         /* This child meets the pid test and is being traced.*/
  2471. 17034                         res2 =  0177 | (rp->mp_sigstatus << 8);
  2472. 17035                         reply(who, rp->mp_pid, res2, NIL_PTR);
  2473. 17036                         dont_reply = TRUE;
  2474. 17037                         rp->mp_sigstatus = 0;
  2475. 17038                         return(OK);
  2476. 17039                 }
  2477. 17040         }
  2478. 17041   }
  2479. 17042
  2480. 17043   /* No qualifying child has exited.  Wait for one, unless none exists. */
  2481. 17044   if (children > 0) {
  2482. 17045         /* At least 1 child meets the pid test exists, but has not exited. */
  2483. 17046         if (options & WNOHANG) return(0);    /* parent does not want to wait */
  2484. 17047         mp->mp_flags |= WAITING;             /* parent wants to wait */
  2485. 17048         mp->mp_wpid = (pid_t) pidarg;        /* save pid for later */
  2486. 17049         dont_reply = TRUE;                   /* do not reply now though */
  2487. 17050         return(OK);                          /* yes - wait for one to exit */
  2488. 17051   } else {
  2489. 17052         /* No child even meets the pid test.  Return error immediately. */
  2490. 17053         return(ECHILD);                      /* no - parent has no children */
  2491. 17054   }
  2492. 17055 }
  2493. 17058 /*===========================================================================*
  2494. 17059  *                              cleanup                                      *
  2495. 17060  *===========================================================================*/
  2496. 17061 PRIVATE void cleanup(child)
  2497. 17062 register struct mproc *child;   /* tells which process is exiting */
  2498. 17063 {
  2499. 17064 /* Finish off the exit of a process.  The process has exited or been killed
  2500. 17065  * by a signal, and its parent is waiting.
  2501. 17066  */
  2502. 17067
  2503. 17068   int exitstatus;
  2504. 17069
  2505. 17070   /* Wake up the parent. */
  2506. 17071   exitstatus = (child->mp_exitstatus << 8) | (child->mp_sigstatus & 0377);
  2507. 17072   reply(child->mp_parent, child->mp_pid, exitstatus, NIL_PTR);
  2508. 17073   mproc[child->mp_parent].mp_flags &= ~WAITING; /* parent no longer waiting */
  2509. 17074
  2510. 17075   /* Release the process table entry. */
  2511. 17076   child->mp_flags = 0;
  2512. 17077   procs_in_use--;
  2513. 17078 }
  2514. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2515. src/mm/exec.c    
  2516. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2517. 17100 /* This file handles the EXEC system call.  It performs the work as follows:
  2518. 17101  *    - see if the permissions allow the file to be executed
  2519. 17102  *    - read the header and extract the sizes
  2520. 17103  *    - fetch the initial args and environment from the user space
  2521. 17104  *    - allocate the memory for the new process
  2522. 17105  *    - copy the initial stack from MM to the process
  2523. 17106  *    - read in the text and data segments and copy to the process
  2524. 17107  *    - take care of setuid and setgid bits
  2525. 17108  *    - fix up 'mproc' table
  2526. 17109  *    - tell kernel about EXEC
  2527. 17110  *    - save offset to initial argc (for ps)
  2528. 17111  *
  2529. 17112  * The entry points into this file are:
  2530. 17113  *   do_exec:    perform the EXEC system call
  2531. 17114  *   find_share: find a process whose text segment can be shared
  2532. 17115  */
  2533. 17116
  2534. 17117 #include "mm.h"
  2535. 17118 #include <sys/stat.h>
  2536. 17119 #include <minix/callnr.h>
  2537. 17120 #include <a.out.h>
  2538. 17121 #include <signal.h>
  2539. 17122 #include <string.h>
  2540. 17123 #include "mproc.h"
  2541. 17124 #include "param.h"
  2542. 17125
  2543. 17126 FORWARD _PROTOTYPE( void load_seg, (int fd, int seg, vir_bytes seg_bytes) );
  2544. 17127 FORWARD _PROTOTYPE( int new_mem, (struct mproc *sh_mp, vir_bytes text_bytes,
  2545. 17128                 vir_bytes data_bytes, vir_bytes bss_bytes,
  2546. 17129                 vir_bytes stk_bytes, phys_bytes tot_bytes)              );
  2547. 17130 FORWARD _PROTOTYPE( void patch_ptr, (char stack [ARG_MAX ], vir_bytes base) );
  2548. 17131 FORWARD _PROTOTYPE( int read_header, (int fd, int *ft, vir_bytes *text_bytes,
  2549. 17132                 vir_bytes *data_bytes, vir_bytes *bss_bytes,
  2550. 17133                 phys_bytes *tot_bytes, long *sym_bytes, vir_clicks sc,
  2551. 17134                 vir_bytes *pc)                                          );
  2552. 17135
  2553. 17136
  2554. 17137 /*===========================================================================*
  2555. 17138  *                              do_exec                                      *
  2556. 17139  *===========================================================================*/
  2557. 17140 PUBLIC int do_exec()
  2558. 17141 {
  2559. 17142 /* Perform the execve(name, argv, envp) call.  The user library builds a
  2560. 17143  * complete stack image, including pointers, args, environ, etc.  The stack
  2561. 17144  * is copied to a buffer inside MM, and then to the new core image.
  2562. 17145  */
  2563. 17146
  2564. 17147   register struct mproc *rmp;
  2565. 17148   struct mproc *sh_mp;
  2566. 17149   int m, r, fd, ft, sn;
  2567. 17150   static char mbuf[ARG_MAX];    /* buffer for stack and zeroes */
  2568. 17151   static char name_buf[PATH_MAX]; /* the name of the file to exec */
  2569. 17152   char *new_sp, *basename;
  2570. 17153   vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
  2571. 17154   phys_bytes tot_bytes;         /* total space for program, including gap */
  2572. 17155   long sym_bytes;
  2573. 17156   vir_clicks sc;
  2574. 17157   struct stat s_buf;
  2575. 17158   vir_bytes pc;
  2576. 17159
  2577. 17160   /* Do some validity checks. */
  2578. 17161   rmp = mp;
  2579. 17162   stk_bytes = (vir_bytes) stack_bytes;
  2580. 17163   if (stk_bytes > ARG_MAX) return(ENOMEM);      /* stack too big */
  2581. 17164   if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL);
  2582. 17165
  2583. 17166   /* Get the exec file name and see if the file is executable. */
  2584. 17167   src = (vir_bytes) exec_name;
  2585. 17168   dst = (vir_bytes) name_buf;
  2586. 17169   r = sys_copy(who, D, (phys_bytes) src,
  2587. 17170                 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len);
  2588. 17171   if (r != OK) return(r);       /* file name not in user data segment */
  2589. 17172   tell_fs(CHDIR, who, FALSE, 0);        /* switch to the user's FS environ. */
  2590. 17173   fd = allowed(name_buf, &s_buf, X_BIT);        /* is file executable? */
  2591. 17174   if (fd < 0) return(fd);       /* file was not executable */
  2592. 17175
  2593. 17176   /* Read the file header and extract the segment sizes. */
  2594. 17177   sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  2595. 17178   m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 
  2596. 17179                                         &tot_bytes, &sym_bytes, sc, &pc);
  2597. 17180   if (m < 0) {
  2598. 17181         close(fd);              /* something wrong with header */
  2599. 17182         return(ENOEXEC);
  2600. 17183   }
  2601. 17184
  2602. 17185   /* Fetch the stack from the user before destroying the old core image. */
  2603. 17186   src = (vir_bytes) stack_ptr;
  2604. 17187   dst = (vir_bytes) mbuf;
  2605. 17188   r = sys_copy(who, D, (phys_bytes) src,
  2606. 17189                         MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes);
  2607. 17190   if (r != OK) {
  2608. 17191         close(fd);              /* can't fetch stack (e.g. bad virtual addr) */
  2609. 17192         return(EACCES);
  2610. 17193   }
  2611. 17194
  2612. 17195   /* Can the process' text be shared with that of one already running? */
  2613. 17196   sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime);
  2614. 17197
  2615. 17198   /* Allocate new memory and release old memory.  Fix map and tell kernel. */
  2616. 17199   r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
  2617. 17200   if (r != OK) {
  2618. 17201         close(fd);              /* insufficient core or program too big */
  2619. 17202         return(r);
  2620. 17203   }
  2621. 17204
  2622. 17205   /* Save file identification to allow it to be shared. */
  2623. 17206   rmp->mp_ino = s_buf.st_ino;
  2624. 17207   rmp->mp_dev = s_buf.st_dev;
  2625. 17208   rmp->mp_ctime = s_buf.st_ctime;
  2626. 17209
  2627. 17210   /* Patch up stack and copy it from MM to new core image. */
  2628. 17211   vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
  2629. 17212   vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
  2630. 17213   vsp -= stk_bytes;
  2631. 17214   patch_ptr(mbuf, vsp);
  2632. 17215   src = (vir_bytes) mbuf;
  2633. 17216   r = sys_copy(MM_PROC_NR, D, (phys_bytes) src,
  2634. 17217                         who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes);
  2635. 17218   if (r != OK) panic("do_exec stack copy err", NO_NUM);
  2636. 17219
  2637. 17220   /* Read in text and data segments. */
  2638. 17221   if (sh_mp != NULL) {
  2639. 17222         lseek(fd, (off_t) text_bytes, SEEK_CUR);  /* shared: skip text */
  2640. 17223   } else {
  2641. 17224         load_seg(fd, T, text_bytes);
  2642. 17225   }
  2643. 17226   load_seg(fd, D, data_bytes);
  2644. 17227
  2645. 17228
  2646. 17229   close(fd);                    /* don't need exec file any more */
  2647. 17230
  2648. 17231   /* Take care of setuid/setgid bits. */
  2649. 17232   if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
  2650. 17233         if (s_buf.st_mode & I_SET_UID_BIT) {
  2651. 17234                 rmp->mp_effuid = s_buf.st_uid;
  2652. 17235                 tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
  2653. 17236         }
  2654. 17237         if (s_buf.st_mode & I_SET_GID_BIT) {
  2655. 17238                 rmp->mp_effgid = s_buf.st_gid;
  2656. 17239                 tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
  2657. 17240         }
  2658. 17241   }
  2659. 17242
  2660. 17243   /* Save offset to initial argc (for ps) */
  2661. 17244   rmp->mp_procargs = vsp;
  2662. 17245
  2663. 17246   /* Fix 'mproc' fields, tell kernel that exec is done,  reset caught sigs. */
  2664. 17247   for (sn = 1; sn <= _NSIG; sn++) {
  2665. 17248         if (sigismember(&rmp->mp_catch, sn)) {
  2666. 17249                 sigdelset(&rmp->mp_catch, sn);
  2667. 17250                 rmp->mp_sigact[sn].sa_handler = SIG_DFL;
  2668. 17251                 sigemptyset(&rmp->mp_sigact[sn].sa_mask);
  2669. 17252         }
  2670. 17253   }
  2671. 17254
  2672. 17255   rmp->mp_flags &= ~SEPARATE;   /* turn off SEPARATE bit */
  2673. 17256   rmp->mp_flags |= ft;          /* turn it on for separate I & D files */
  2674. 17257   new_sp = (char *) vsp;
  2675. 17258
  2676. 17259   tell_fs(EXEC, who, 0, 0);     /* allow FS to handle FD_CLOEXEC files */
  2677. 17260
  2678. 17261   /* System will save command line for debugging, ps(1) output, etc. */
  2679. 17262   basename = strrchr(name_buf, '/');
  2680. 17263   if (basename == NULL) basename = name_buf; else basename++;
  2681. 17264   sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc);
  2682. 17265   return(OK);
  2683. 17266 }