You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
278 volume VI os16<br />
Script e sorgenti del kernel 279<br />
1860061 | arg = arg_data;<br />
1860062 | for (i = 0, j = 0; i < argc; i++)<br />
1860063 | {<br />
1860064 | argv[i] = (char *) j; // Relative pointer inside<br />
1860065 | // the ‘arg_data’.<br />
1860066 | size = strlen (arg);<br />
1860067 | arg += size + 1;<br />
1860068 | j += size + 1;<br />
1860069 | }<br />
1860070 | arg_data_size = j;<br />
1860071 | if (arg_data_size % 2)<br />
1860072 | {<br />
1860073 | arg_data_size++;<br />
1860074 | }<br />
1860075 | //<br />
1860076 | // Scan environment variables to calculate the full size and the<br />
1860077 | // relative pointers. The final size is rounded to 2, for the stack.<br />
1860078 | //<br />
1860079 | env = env_data;<br />
1860080 | for (i = 0, j = 0; i < envc; i++)<br />
1860081 | {<br />
1860082 | envp[i] = (char *) j; // Relative pointer inside<br />
1860083 | // the ‘env_data’.<br />
1860084 | size = strlen (env);<br />
1860085 | env += size + 1;<br />
1860086 | j += size + 1;<br />
1860087 | }<br />
1860088 | env_data_size = j;<br />
1860089 | if (env_data_size % 2)<br />
1860090 | {<br />
1860091 | env_data_size++;<br />
1860092 | }<br />
1860093 | //<br />
1860094 | // Read the inode related to the executable file name.<br />
1860095 | // Function path_inode() includes the inode get procedure.<br />
1860096 | //<br />
1860097 | inode = path_inode (pid, path);<br />
1860098 | if (inode == NULL)<br />
1860099 | {<br />
1860100 | errset (ENOENT); // No such file or directory.<br />
1860101 | return (-1);<br />
1860102 | }<br />
1860103 | //<br />
1860104 | // Check for permissions.<br />
1860105 | //<br />
1860106 | status = inode_check (inode, S_IFREG, 5, proc_table[pid].euid);<br />
1860107 | if (status != 0)<br />
1860108 | {<br />
1860109 | //<br />
1860110 | // File is not of a valid type or permission are not<br />
1860111 | // sufficient: release the executable file inode<br />
1860112 | // and return with an error.<br />
1860113 | //<br />
1860114 | inode_put (inode);<br />
1860115 | errset (EACCES); // Permission denied.<br />
1860116 | return (-1);<br />
1860117 | }<br />
1860118 | //<br />
1860119 | // Read the header from the executable file.<br />
1860120 | //<br />
1860121 | size_read = inode_file_read (inode, (off_t) 0, &header,<br />
1860122 | (sizeof header), &eof);<br />
1860123 | if (size_read != (sizeof header))<br />
1860124 | {<br />
1860125 | //<br />
1860126 | // The file is shorter than the executable header, so, it isn’t<br />
1860127 | // an executable: release the file inode and return with an<br />
1860128 | // error.<br />
1860129 | //<br />
1860130 | inode_put (inode);<br />
1860131 | errset (ENOEXEC);<br />
1860132 | return (-1);<br />
1860133 | }<br />
1860134 | if (header.magic0 != MAGIC_OS16 || header.magic1 != MAGIC_OS16_APPL)<br />
1860135 | {<br />
1860136 | //<br />
1860137 | // The header does not have the expected magic numbers, so,<br />
1860138 | // it isn’t a valid executable: release the file inode and<br />
1860139 | // return with an error.<br />
1860140 | //<br />
1860141 | inode_put (inode);<br />
1860142 | errset (ENOEXEC);<br />
1860143 | return (-1); // This is not a valid executable!<br />
1860144 | }<br />
1860145 | //<br />
1860146 | // Calculate data size.<br />
1860147 | //<br />
1860148 | s = header.ebss;<br />
1860149 | if (header.ssize == 0)<br />
1860150 | {<br />
1860151 | s += 0x10000L; // Zero means max size.<br />
1860152 | }<br />
1860153 | else<br />
1860154 | {<br />
1860155 | s += header.ssize;<br />
1860156 | }<br />
1860157 | if (s > 0xFFFF)<br />
1860158 | {<br />
1860159 | process_size_d = 0x0000; // 0x0000 means the maximum size:<br />
1860160 | // 0x10000.<br />
1860161 | new_sp = 0x0000; // 0x0000 is like 0x10000 and the first<br />
1860162 | // push moves SP to 0xFFFE.<br />
1860163 | }<br />
1860164 | else<br />
1860165 | {<br />
1860166 | process_size_d = s;<br />
1860167 | new_sp = process_size_d;<br />
1860168 | if (new_sp % 2)<br />
1860169 | {<br />
1860170 | new_sp--; // The stack pointer should be even.<br />
1860171 | }<br />
1860172 | }<br />
1860173 | //<br />
1860174 | // Calculate code size.<br />
1860175 | //<br />
1860176 | if (header.segoff == 0)<br />
1860177 | {<br />
1860178 | process_size_i = process_size_d;<br />
1860179 | }<br />
1860180 | else<br />
1860181 | {<br />
1860182 | process_size_i = header.segoff * 16;<br />
1860183 | }<br />
1860184 | //<br />
1860185 | // Allocate memory: code and data segments.<br />
1860186 | //<br />
1860187 | status = mb_alloc_size (process_size_i, &allocated_i);<br />
1860188 | if (status < 0)<br />
1860189 | {<br />
1860190 | //<br />
1860191 | // The program instructions (code segment) cannot be loaded<br />
1860192 | // into memory: release the executable file inode and return<br />
1860193 | // with an error.<br />
1860194 | //<br />
1860195 | inode_put (inode);<br />
1860196 | errset (ENOMEM); // Not enough space.<br />
1860197 | return ((pid_t) -1);<br />
1860198 | }<br />
1860199 | if (header.segoff == 0)<br />
1860200 | {<br />
1860201 | //<br />
1860202 | // Code and data segments are the same: no need<br />
1860203 | // to allocate more memory for the data segment.<br />
1860204 | //<br />
1860205 | allocated_d.address = allocated_i.address;<br />
1860206 | allocated_d.segment = allocated_i.segment;<br />
1860207 | allocated_d.size = allocated_i.size;<br />
1860208 | }<br />
1860209 | else<br />
1860210 | {<br />
1860211 | //<br />
1860212 | // Code and data segments are different: the data<br />
1860213 | // segment memory is allocated.<br />
1860214 | //<br />
1860215 | status = mb_alloc_size (process_size_d, &allocated_d);<br />
1860216 | if (status < 0)<br />
1860217 | {<br />
1860218 | //<br />
1860219 | // The separated program data (data segment) cannot be loaded<br />
1860220 | // into memory: free the already allocated memory for the<br />
1860221 | // program instructions, release the executable file inode<br />
1860222 | // and return with an error.<br />
1860223 | //<br />
1860224 | mb_free (allocated_i.address, allocated_i.size);<br />
1860225 | inode_put (inode);<br />
1860226 | errset (ENOMEM); // Not enough space.<br />
1860227 | return ((pid_t) -1);<br />
1860228 | }<br />
1860229 | }<br />
1860230 | //<br />
1860231 | // Load executable in memory.<br />
1860232 | //<br />
1860233 | if (header.segoff == 0)<br />
1860234 | {<br />
1860235 | //<br />
1860236 | // Code and data share the same segment.<br />
1860237 | //<br />
1860238 | for (eof = 0, memory_start = allocated_i.address,<br />
1860239 | inode_start = 0, size_read = 0;<br />
1860240 | inode_start < inode->size && !eof;<br />
1860241 | inode_start += size_read)<br />
1860242 | {<br />
1860243 | memory_start += size_read;<br />
1860244 | //<br />
1860245 | // Read a block of memory.<br />
1860246 | //<br />
1860247 | size_read = inode_file_read (inode, inode_start,<br />
1860248 | buffer, MEM_BLOCK_SIZE, &eof);<br />
1860249 | if (size_read < 0)<br />
1860250 | {<br />
1860251 | //<br />
1860252 | // Free memory and inode.<br />
1860253 | //<br />
1860254 | mb_free (allocated_i.address, allocated_i.size);<br />
1860255 | inode_put (inode);<br />
1860256 | errset (EIO);<br />
1860257 | return (-1);<br />
1860258 | }<br />
1860259 | //<br />
1860260 | // Copy inside the right position to be executed.<br />
1860261 | //<br />
1860262 | dev_io ((pid_t) 0, DEV_MEM, DEV_WRITE, memory_start, buffer,<br />
1860263 | (size_t) size_read, NULL);<br />
1860264 | }<br />
1860265 | }<br />
1860266 | else<br />
1860267 | {<br />
1860268 | //<br />
1860269 | // Code and data with different segments.<br />
1860270 | //<br />
1860271 | for (eof = 0, memory_start = allocated_i.address,<br />
1860272 | inode_start = 0, size_read = 0;<br />
1860273 | inode_start < process_size_i && !eof;<br />
1860274 | inode_start += size_read)<br />
1860275 | {<br />
1860276 | memory_start += size_read;<br />
1860277 | //<br />
1860278 | // Read a block of memory<br />
1860279 | //<br />
1860280 | size_read = inode_file_read (inode, inode_start,<br />
1860281 | buffer, MEM_BLOCK_SIZE, &eof);<br />
1860282 | if (size_read < 0)<br />
1860283 | {<br />
1860284 | //<br />
1860285 | // Free memory and inode.<br />
1860286 | //<br />
1860287 | mb_free (allocated_i.address, allocated_i.size);<br />
1860288 | mb_free (allocated_d.address, allocated_d.size);<br />
1860289 | inode_put (inode);<br />
1860290 | errset (EIO);<br />
1860291 | return (-1);<br />
1860292 | }