Advertisement
Guest User

faltan signals y fin

a guest
Oct 21st, 2019
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 45.99 KB | None | 0 0
  1. /*
  2. * Shell `simplesh` (basado en el shell de xv6)
  3. *
  4. * Ampliación de Sistemas Operativos
  5. * Departamento de Ingeniería y Tecnología de Computadores
  6. * Facultad de Informática de la Universidad de Murcia
  7. *
  8. * Alumnos: MERLOS ESPIN, JOSE MANUEL (PCEO)
  9. * RODRIGUEZ RODRIGUEZ,ALEJANDRO ROYHER (PCEO)
  10. *
  11. * Convocatoria: FEBRERO/JUNIO/JULIO
  12. */
  13.  
  14.  
  15. /*
  16. * Ficheros de cabecera
  17. */
  18.  
  19.  
  20. #define _POSIX_C_SOURCE 200809L /* IEEE 1003.1-2008 (véase /usr/include/features.h) */
  21. //#define NDEBUG /* Traduce asertos y DMACROS a 'no ops' */
  22.  
  23. #include <assert.h>
  24. #include <errno.h>
  25. #include <fcntl.h>
  26. #include <getopt.h>
  27. #include <stdarg.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <sys/wait.h>
  32. #include <unistd.h>
  33.  
  34. //Sesion 1
  35. #include <pwd.h>
  36. #include <sys/types.h>
  37. #include <limits.h>
  38. #include <libgen.h>
  39.  
  40.  
  41. // Biblioteca readline
  42. #include <readline/readline.h>
  43. #include <readline/history.h>
  44.  
  45.  
  46. /******************************************************************************
  47. * Constantes, macros y variables globales
  48. ******************************************************************************/
  49.  
  50.  
  51. static const char* VERSION = "0.19";
  52.  
  53. // Niveles de depuración
  54. #define DBG_CMD (1 << 0)
  55. #define DBG_TRACE (1 << 1)
  56. // . . .
  57. static int g_dbg_level = 0;
  58.  
  59. #ifndef NDEBUG
  60. #define DPRINTF(dbg_level, fmt, ...) \
  61. do { \
  62. if (dbg_level & g_dbg_level) \
  63. fprintf(stderr, "%s:%d:%s(): " fmt, \
  64. __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
  65. } while ( 0 )
  66.  
  67. #define DBLOCK(dbg_level, block) \
  68. do { \
  69. if (dbg_level & g_dbg_level) \
  70. block; \
  71. } while( 0 );
  72. #else
  73. #define DPRINTF(dbg_level, fmt, ...)
  74. #define DBLOCK(dbg_level, block)
  75. #endif
  76.  
  77. #define TRY(x) \
  78. do { \
  79. int __rc = (x); \
  80. if( __rc < 0 ) { \
  81. fprintf(stderr, "%s:%d:%s: TRY(%s) failed\n", \
  82. __FILE__, __LINE__, __func__, #x); \
  83. fprintf(stderr, "ERROR: rc=%d errno=%d (%s)\n", \
  84. __rc, errno, strerror(errno)); \
  85. exit(EXIT_FAILURE); \
  86. } \
  87. } while( 0 )
  88.  
  89.  
  90. // Número máximo de argumentos de un comando
  91. #define MAX_ARGS 16
  92.  
  93.  
  94. // Delimitadores
  95. static const char WHITESPACE[] = " \t\r\n\v";
  96. // Caracteres especiales
  97. static const char SYMBOLS[] = "<|>&;()";
  98.  
  99.  
  100. /******************************************************************************
  101. * Funciones auxiliares
  102. ******************************************************************************/
  103. //:( sesion 3, devuelve el minimo de 2 size_t
  104. size_t min(size_t a, size_t b){
  105. if (a<b) return a;
  106. else return b;
  107. }
  108. // Imprime el mensaje
  109. void info(const char *fmt, ...)
  110. {
  111. va_list arg;
  112.  
  113. fprintf(stdout, "%s: ", __FILE__);
  114. va_start(arg, fmt);
  115. vfprintf(stdout, fmt, arg);
  116. va_end(arg);
  117. }
  118.  
  119.  
  120. // Imprime el mensaje de error
  121. void error(const char *fmt, ...)
  122. {
  123. va_list arg;
  124.  
  125. fprintf(stderr, "%s: ", __FILE__);
  126. va_start(arg, fmt);
  127. vfprintf(stderr, fmt, arg);
  128. va_end(arg);
  129. }
  130.  
  131.  
  132. // Imprime el mensaje de error y aborta la ejecución
  133. void panic(const char *fmt, ...)
  134. {
  135. va_list arg;
  136.  
  137. fprintf(stderr, "%s: ", __FILE__);
  138. va_start(arg, fmt);
  139. vfprintf(stderr, fmt, arg);
  140. va_end(arg);
  141.  
  142. exit(EXIT_FAILURE);
  143. }
  144.  
  145.  
  146. // `fork()` que muestra un mensaje de error si no se puede crear el hijo
  147. int fork_or_panic(const char* s)
  148. {
  149. int pid;
  150.  
  151. pid = fork();
  152. if(pid == -1)
  153. panic("%s failed: errno %d (%s)", s, errno, strerror(errno));
  154. return pid;
  155. }
  156.  
  157.  
  158. /******************************************************************************
  159. * Estructuras de datos `cmd`
  160. ******************************************************************************/
  161.  
  162.  
  163. // Las estructuras `cmd` se utilizan para almacenar información que servirá a
  164. // simplesh para ejecutar líneas de órdenes con redirecciones, tuberías, listas
  165. // de comandos y tareas en segundo plano. El formato es el siguiente:
  166.  
  167. // |----------+--------------+--------------|
  168. // | (1 byte) | ... | ... |
  169. // |----------+--------------+--------------|
  170. // | type | otros campos | otros campos |
  171. // |----------+--------------+--------------|
  172.  
  173. // Nótese cómo las estructuras `cmd` comparten el primer campo `type` para
  174. // identificar su tipo. A partir de él se obtiene un tipo derivado a través de
  175. // *casting* forzado de tipo. Se consigue así polimorfismo básico en C.
  176.  
  177. // Valores del campo `type` de las estructuras de datos `cmd`
  178. enum cmd_type { EXEC=1, REDR=2, PIPE=3, LIST=4, BACK=5, SUBS=6, INV=7 };
  179.  
  180. //sesion 1: tipos de comandos ejecutables
  181. enum cmd_exec_type { CWD=1, EXIT=2, CD=3, PSPLIT=4, EXTERNAL=0 };
  182.  
  183. struct cmd { enum cmd_type type; };
  184.  
  185. // Comando con sus parámetros
  186. struct execcmd {
  187. enum cmd_type type;
  188. char* argv[MAX_ARGS];
  189. char* eargv[MAX_ARGS];
  190. int argc;
  191. };
  192.  
  193. // Comando con redirección
  194. struct redrcmd {
  195. enum cmd_type type;
  196. struct cmd* cmd;
  197. char* file;
  198. char* efile;
  199. int flags;
  200. mode_t mode;
  201. int fd;
  202. };
  203.  
  204. // Comandos con tubería
  205. struct pipecmd {
  206. enum cmd_type type;
  207. struct cmd* left;
  208. struct cmd* right;
  209. };
  210.  
  211. // Lista de órdenes
  212. struct listcmd {
  213. enum cmd_type type;
  214. struct cmd* left;
  215. struct cmd* right;
  216. };
  217.  
  218. // Tarea en segundo plano (background) con `&`
  219. struct backcmd {
  220. enum cmd_type type;
  221. struct cmd* cmd;
  222. };
  223.  
  224. // Subshell
  225. struct subscmd {
  226. enum cmd_type type;
  227. struct cmd* cmd;
  228. };
  229.  
  230.  
  231. /******************************************************************************
  232. * Funciones para construir las estructuras de datos `cmd`
  233. ******************************************************************************/
  234.  
  235.  
  236. // Construye una estructura `cmd` de tipo `EXEC`
  237. struct cmd* execcmd(void)
  238. {
  239. struct execcmd* cmd;
  240.  
  241. if ((cmd = malloc(sizeof(*cmd))) == NULL)
  242. {
  243. perror("execcmd: malloc");
  244. exit(EXIT_FAILURE);
  245. }
  246. memset(cmd, 0, sizeof(*cmd));
  247. cmd->type = EXEC;
  248.  
  249. return (struct cmd*) cmd;
  250. }
  251.  
  252. // Construye una estructura `cmd` de tipo `REDR`
  253. struct cmd* redrcmd(struct cmd* subcmd,
  254. char* file, char* efile,
  255. int flags, mode_t mode, int fd)
  256. {
  257. struct redrcmd* cmd;
  258.  
  259. if ((cmd = malloc(sizeof(*cmd))) == NULL)
  260. {
  261. perror("redrcmd: malloc");
  262. exit(EXIT_FAILURE);
  263. }
  264. memset(cmd, 0, sizeof(*cmd));
  265. cmd->type = REDR;
  266. cmd->cmd = subcmd;
  267. cmd->file = file;
  268. cmd->efile = efile;
  269. cmd->flags = flags;
  270. cmd->mode = mode;
  271. cmd->fd = fd;
  272.  
  273. return (struct cmd*) cmd;
  274. }
  275.  
  276. // Construye una estructura `cmd` de tipo `PIPE`
  277. struct cmd* pipecmd(struct cmd* left, struct cmd* right)
  278. {
  279. struct pipecmd* cmd;
  280.  
  281. if ((cmd = malloc(sizeof(*cmd))) == NULL)
  282. {
  283. perror("pipecmd: malloc");
  284. exit(EXIT_FAILURE);
  285. }
  286. memset(cmd, 0, sizeof(*cmd));
  287. cmd->type = PIPE;
  288. cmd->left = left;
  289. cmd->right = right;
  290.  
  291. return (struct cmd*) cmd;
  292. }
  293.  
  294. // Construye una estructura `cmd` de tipo `LIST`
  295. struct cmd* listcmd(struct cmd* left, struct cmd* right)
  296. {
  297. struct listcmd* cmd;
  298.  
  299. if ((cmd = malloc(sizeof(*cmd))) == NULL)
  300. {
  301. perror("listcmd: malloc");
  302. exit(EXIT_FAILURE);
  303. }
  304. memset(cmd, 0, sizeof(*cmd));
  305. cmd->type = LIST;
  306. cmd->left = left;
  307. cmd->right = right;
  308.  
  309. return (struct cmd*)cmd;
  310. }
  311.  
  312. // Construye una estructura `cmd` de tipo `BACK`
  313. struct cmd* backcmd(struct cmd* subcmd)
  314. {
  315. struct backcmd* cmd;
  316.  
  317. if ((cmd = malloc(sizeof(*cmd))) == NULL)
  318. {
  319. perror("backcmd: malloc");
  320. exit(EXIT_FAILURE);
  321. }
  322. memset(cmd, 0, sizeof(*cmd));
  323. cmd->type = BACK;
  324. cmd->cmd = subcmd;
  325.  
  326. return (struct cmd*)cmd;
  327. }
  328.  
  329. // Construye una estructura `cmd` de tipo `SUB`
  330. struct cmd* subscmd(struct cmd* subcmd)
  331. {
  332. struct subscmd* cmd;
  333.  
  334. if ((cmd = malloc(sizeof(*cmd))) == NULL)
  335. {
  336. perror("subscmd: malloc");
  337. exit(EXIT_FAILURE);
  338. }
  339. memset(cmd, 0, sizeof(*cmd));
  340. cmd->type = SUBS;
  341. cmd->cmd = subcmd;
  342.  
  343. return (struct cmd*) cmd;
  344. }
  345.  
  346.  
  347. /******************************************************************************
  348. * Funciones para realizar el análisis sintáctico de la línea de órdenes
  349. ******************************************************************************/
  350.  
  351.  
  352. // `get_token` recibe un puntero al principio de una cadena (`start_of_str`),
  353. // otro puntero al final de esa cadena (`end_of_str`) y, opcionalmente, dos
  354. // punteros para guardar el principio y el final del token, respectivamente.
  355. //
  356. // `get_token` devuelve un *token* de la cadena de entrada.
  357.  
  358. int get_token(char** start_of_str, char const* end_of_str,
  359. char** start_of_token, char** end_of_token)
  360. {
  361. char* s;
  362. int ret;
  363.  
  364. // Salta los espacios en blanco
  365. s = *start_of_str;
  366. while (s < end_of_str && strchr(WHITESPACE, *s))
  367. s++;
  368.  
  369. // `start_of_token` apunta al principio del argumento (si no es NULL)
  370. if (start_of_token)
  371. *start_of_token = s;
  372.  
  373. ret = *s;
  374. switch (*s)
  375. {
  376. case 0:
  377. break;
  378. case '|':
  379. case '(':
  380. case ')':
  381. case ';':
  382. case '&':
  383. case '<':
  384. s++;
  385. break;
  386. case '>':
  387. s++;
  388. if (*s == '>')
  389. {
  390. ret = '+';
  391. s++;
  392. }
  393. break;
  394.  
  395. default:
  396.  
  397. // El caso por defecto (cuando no hay caracteres especiales) es el
  398. // de un argumento de un comando. `get_token` devuelve el valor
  399. // `'a'`, `start_of_token` apunta al argumento (si no es `NULL`),
  400. // `end_of_token` apunta al final del argumento (si no es `NULL`) y
  401. // `start_of_str` avanza hasta que salta todos los espacios
  402. // *después* del argumento. Por ejemplo:
  403. //
  404. // |-----------+---+---+---+---+---+---+---+---+---+-----------|
  405. // | (espacio) | a | r | g | u | m | e | n | t | o | (espacio)
  406. // |
  407. // |-----------+---+---+---+---+---+---+---+---+---+-----------|
  408. // ^ ^
  409. // start_o|f_token end_o|f_token
  410.  
  411. ret = 'a';
  412. while (s < end_of_str &&
  413. !strchr(WHITESPACE, *s) &&
  414. !strchr(SYMBOLS, *s))
  415. s++;
  416. break;
  417. }
  418.  
  419. // `end_of_token` apunta al final del argumento (si no es `NULL`)
  420. if (end_of_token)
  421. *end_of_token = s;
  422.  
  423. // Salta los espacios en blanco
  424. while (s < end_of_str && strchr(WHITESPACE, *s))
  425. s++;
  426.  
  427. // Actualiza `start_of_str`
  428. *start_of_str = s;
  429.  
  430. return ret;
  431. }
  432.  
  433.  
  434. // `peek` recibe un puntero al principio de una cadena (`start_of_str`), otro
  435. // puntero al final de esa cadena (`end_of_str`) y un conjunto de caracteres
  436. // (`delimiter`).
  437. //
  438. // El primer puntero pasado como parámero (`start_of_str`) avanza hasta el
  439. // primer carácter que no está en el conjunto de caracteres `WHITESPACE`.
  440. //
  441. // `peek` devuelve un valor distinto de `NULL` si encuentra alguno de los
  442. // caracteres en `delimiter` justo después de los caracteres en `WHITESPACE`.
  443.  
  444. int peek(char** start_of_str, char const* end_of_str, char* delimiter)
  445. {
  446. char* s;
  447.  
  448. s = *start_of_str;
  449. while (s < end_of_str && strchr(WHITESPACE, *s))
  450. s++;
  451. *start_of_str = s;
  452.  
  453. return *s && strchr(delimiter, *s);
  454. }
  455.  
  456.  
  457. // Definiciones adelantadas de funciones
  458. struct cmd* parse_line(char**, char*);
  459. struct cmd* parse_pipe(char**, char*);
  460. struct cmd* parse_exec(char**, char*);
  461. struct cmd* parse_subs(char**, char*);
  462. struct cmd* parse_redr(struct cmd*, char**, char*);
  463. struct cmd* null_terminate(struct cmd*);
  464.  
  465.  
  466. // `parse_cmd` realiza el *análisis sintáctico* de la línea de órdenes
  467. // introducida por el usuario.
  468. //
  469. // `parse_cmd` utiliza `parse_line` para obtener una estructura `cmd`.
  470.  
  471. struct cmd* parse_cmd(char* start_of_str)
  472. {
  473. char* end_of_str;
  474. struct cmd* cmd;
  475.  
  476. DPRINTF(DBG_TRACE, "STR\n");
  477.  
  478. end_of_str = start_of_str + strlen(start_of_str);
  479.  
  480. cmd = parse_line(&start_of_str, end_of_str);
  481.  
  482. // Comprueba que se ha alcanzado el final de la línea de órdenes
  483. peek(&start_of_str, end_of_str, "");
  484. if (start_of_str != end_of_str)
  485. error("%s: error sintáctico: %s\n", __func__);
  486.  
  487. DPRINTF(DBG_TRACE, "END\n");
  488.  
  489. return cmd;
  490. }
  491.  
  492.  
  493. // `parse_line` realiza el análisis sintáctico de la línea de órdenes
  494. // introducida por el usuario.
  495. //
  496. // `parse_line` comprueba en primer lugar si la línea contiene alguna tubería.
  497. // Para ello `parse_line` llama a `parse_pipe` que a su vez verifica si hay
  498. // bloques de órdenes y/o redirecciones. A continuación, `parse_line`
  499. // comprueba si la ejecución de la línea se realiza en segundo plano (con `&`)
  500. // o si la línea de órdenes contiene una lista de órdenes (con `;`).
  501.  
  502. struct cmd* parse_line(char** start_of_str, char* end_of_str)
  503. {
  504. struct cmd* cmd;
  505. int delimiter;
  506.  
  507. cmd = parse_pipe(start_of_str, end_of_str);
  508.  
  509. while (peek(start_of_str, end_of_str, "&"))
  510. {
  511. // Consume el delimitador de tarea en segundo plano
  512. delimiter = get_token(start_of_str, end_of_str, 0, 0);
  513. assert(delimiter == '&');
  514.  
  515. // Construye el `cmd` para la tarea en segundo plano
  516. cmd = backcmd(cmd);
  517. }
  518.  
  519. if (peek(start_of_str, end_of_str, ";"))
  520. {
  521. if (cmd->type == EXEC && ((struct execcmd*) cmd)->argv[0] == 0)
  522. error("%s: error sintáctico: no se encontró comando\n", __func__);
  523.  
  524. // Consume el delimitador de lista de órdenes
  525. delimiter = get_token(start_of_str, end_of_str, 0, 0);
  526. assert(delimiter == ';');
  527.  
  528. // Construye el `cmd` para la lista
  529. cmd = listcmd(cmd, parse_line(start_of_str, end_of_str));
  530. }
  531.  
  532. return cmd;
  533. }
  534.  
  535.  
  536. // `parse_pipe` realiza el análisis sintáctico de una tubería de manera
  537. // recursiva si encuentra el delimitador de tuberías '|'.
  538. //
  539. // `parse_pipe` llama a `parse_exec` y `parse_pipe` de manera recursiva para
  540. // realizar el análisis sintáctico de todos los componentes de la tubería.
  541.  
  542. struct cmd* parse_pipe(char** start_of_str, char* end_of_str)
  543. {
  544. struct cmd* cmd;
  545. int delimiter;
  546.  
  547. cmd = parse_exec(start_of_str, end_of_str);
  548.  
  549. if (peek(start_of_str, end_of_str, "|"))
  550. {
  551. if (cmd->type == EXEC && ((struct execcmd*) cmd)->argv[0] == 0)
  552. error("%s: error sintáctico: no se encontró comando\n", __func__);
  553.  
  554. // Consume el delimitador de tubería
  555. delimiter = get_token(start_of_str, end_of_str, 0, 0);
  556. assert(delimiter == '|');
  557.  
  558. // Construye el `cmd` para la tubería
  559. cmd = pipecmd(cmd, parse_pipe(start_of_str, end_of_str));
  560. }
  561.  
  562. return cmd;
  563. }
  564.  
  565.  
  566. // `parse_exec` realiza el análisis sintáctico de un comando a no ser que la
  567. // expresión comience por un paréntesis, en cuyo caso se llama a `parse_subs`.
  568. //
  569. // `parse_exec` reconoce las redirecciones antes y después del comando.
  570.  
  571. struct cmd* parse_exec(char** start_of_str, char* end_of_str)
  572. {
  573. char* start_of_token;
  574. char* end_of_token;
  575. int token, argc;
  576. struct execcmd* cmd;
  577. struct cmd* ret;
  578.  
  579. // ¿Inicio de un bloque?
  580. if (peek(start_of_str, end_of_str, "("))
  581. return parse_subs(start_of_str, end_of_str);
  582.  
  583. // Si no, lo primero que hay en una línea de órdenes es un comando
  584.  
  585.  
  586. // Construye el `cmd` para el comando externo
  587. ret = execcmd();
  588. cmd = (struct execcmd*) ret;
  589.  
  590. // ¿Redirecciones antes del comando?
  591. ret = parse_redr(ret, start_of_str, end_of_str);
  592.  
  593. // Bucle para separar los argumentos de las posibles redirecciones
  594. argc = 0;
  595. while (!peek(start_of_str, end_of_str, "|)&;"))
  596. {
  597. if ((token = get_token(start_of_str, end_of_str,
  598. &start_of_token, &end_of_token)) == 0)
  599. break;
  600.  
  601. // El siguiente token debe ser un argumento porque el bucle
  602. // para en los delimitadores
  603. if (token != 'a')
  604. error("%s: error sintáctico: se esperaba un argumento\n", __func__);
  605.  
  606. // Almacena el siguiente argumento reconocido. El primero es
  607. // el comando
  608. cmd->argv[argc] = start_of_token;
  609. cmd->eargv[argc] = end_of_token;
  610. cmd->argc = ++argc;
  611. if (argc >= MAX_ARGS)
  612. panic("%s: demasiados argumentos\n", __func__);
  613.  
  614. // ¿Redirecciones después del comando?
  615. ret = parse_redr(ret, start_of_str, end_of_str);
  616. }
  617.  
  618. // El comando no tiene más parámetros
  619. cmd->argv[argc] = 0;
  620. cmd->eargv[argc] = 0;
  621.  
  622. return ret;
  623. }
  624.  
  625.  
  626. // `parse_subs` realiza el análisis sintáctico de un bloque de órdenes
  627. // delimitadas por paréntesis o `subshell` llamando a `parse_line`.
  628. //
  629. // `parse_subs` reconoce las redirecciones después del bloque de órdenes.
  630.  
  631. struct cmd* parse_subs(char** start_of_str, char* end_of_str)
  632. {
  633. int delimiter;
  634. struct cmd* cmd;
  635. struct cmd* scmd;
  636.  
  637. // Consume el paréntesis de apertura
  638. if (!peek(start_of_str, end_of_str, "("))
  639. error("%s: error sintáctico: se esperaba '('", __func__);
  640. delimiter = get_token(start_of_str, end_of_str, 0, 0);
  641. assert(delimiter == '(');
  642.  
  643. // Realiza el análisis sintáctico hasta el paréntesis de cierre
  644. scmd = parse_line(start_of_str, end_of_str);
  645.  
  646. // Construye el `cmd` para el bloque de órdenes
  647. cmd = subscmd(scmd);
  648.  
  649. // Consume el paréntesis de cierre
  650. if (!peek(start_of_str, end_of_str, ")"))
  651. error("%s: error sintáctico: se esperaba ')'", __func__);
  652. delimiter = get_token(start_of_str, end_of_str, 0, 0);
  653. assert(delimiter == ')');
  654.  
  655. // ¿Redirecciones después del bloque de órdenes?
  656. cmd = parse_redr(cmd, start_of_str, end_of_str);
  657.  
  658. return cmd;
  659. }
  660.  
  661.  
  662. // `parse_redr` realiza el análisis sintáctico de órdenes con
  663. // redirecciones si encuentra alguno de los delimitadores de
  664. // redirección ('<' o '>').
  665.  
  666. struct cmd* parse_redr(struct cmd* cmd, char** start_of_str, char* end_of_str)
  667. {
  668. int delimiter;
  669. char* start_of_token;
  670. char* end_of_token;
  671.  
  672. // Si lo siguiente que hay a continuación es delimitador de
  673. // redirección...
  674. while (peek(start_of_str, end_of_str, "<>"))
  675. {
  676. // Consume el delimitador de redirección
  677. delimiter = get_token(start_of_str, end_of_str, 0, 0);
  678. assert(delimiter == '<' || delimiter == '>' || delimiter == '+');
  679.  
  680. // El siguiente token tiene que ser el nombre del fichero de la
  681. // redirección entre `start_of_token` y `end_of_token`.
  682. if ('a' != get_token(start_of_str, end_of_str, &start_of_token, &end_of_token))
  683. error("%s: error sintáctico: se esperaba un fichero", __func__);
  684.  
  685. // Construye el `cmd` para la redirección
  686. switch(delimiter)
  687. {
  688. case '<':
  689. cmd = redrcmd(cmd, start_of_token, end_of_token, O_RDONLY, S_IRWXU, STDIN_FILENO);
  690. break;
  691. case '>':
  692. cmd = redrcmd(cmd, start_of_token, end_of_token, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU, STDOUT_FILENO);
  693. break;
  694. case '+': // >>
  695. cmd = redrcmd(cmd, start_of_token, end_of_token, O_RDWR|O_CREAT|O_APPEND, S_IRWXU, STDOUT_FILENO);
  696. break;
  697. }
  698. }
  699.  
  700. return cmd;
  701. }
  702.  
  703.  
  704. // Termina en NULL todas las cadenas de las estructuras `cmd`
  705. struct cmd* null_terminate(struct cmd* cmd)
  706. {
  707. struct execcmd* ecmd;
  708. struct redrcmd* rcmd;
  709. struct pipecmd* pcmd;
  710. struct listcmd* lcmd;
  711. struct backcmd* bcmd;
  712. struct subscmd* scmd;
  713. int i;
  714.  
  715. if(cmd == 0)
  716. return 0;
  717.  
  718. switch(cmd->type)
  719. {
  720. case EXEC:
  721. ecmd = (struct execcmd*) cmd;
  722. for(i = 0; ecmd->argv[i]; i++)
  723. *ecmd->eargv[i] = 0;
  724. break;
  725.  
  726. case REDR:
  727. rcmd = (struct redrcmd*) cmd;
  728. null_terminate(rcmd->cmd);
  729. *rcmd->efile = 0;
  730. break;
  731.  
  732. case PIPE:
  733. pcmd = (struct pipecmd*) cmd;
  734. null_terminate(pcmd->left);
  735. null_terminate(pcmd->right);
  736. break;
  737.  
  738. case LIST:
  739. lcmd = (struct listcmd*) cmd;
  740. null_terminate(lcmd->left);
  741. null_terminate(lcmd->right);
  742. break;
  743.  
  744. case BACK:
  745. bcmd = (struct backcmd*) cmd;
  746. null_terminate(bcmd->cmd);
  747. break;
  748.  
  749. case SUBS:
  750. scmd = (struct subscmd*) cmd;
  751. null_terminate(scmd->cmd);
  752. break;
  753.  
  754. case INV:
  755. default:
  756. panic("%s: estructura `cmd` desconocida\n", __func__);
  757. }
  758.  
  759. return cmd;
  760. }
  761.  
  762.  
  763. /******************************************************************************
  764. * Funciones para la ejecución de la línea de órdenes
  765. ******************************************************************************/
  766.  
  767. void free_cmd(struct cmd* cmd)
  768. {
  769. struct execcmd* ecmd;
  770. struct redrcmd* rcmd;
  771. struct listcmd* lcmd;
  772. struct pipecmd* pcmd;
  773. struct backcmd* bcmd;
  774. struct subscmd* scmd;
  775.  
  776. if(cmd == 0) return;
  777.  
  778. switch(cmd->type)
  779. {
  780. case EXEC:
  781. break;
  782.  
  783. case REDR:
  784. rcmd = (struct redrcmd*) cmd;
  785. free_cmd(rcmd->cmd);
  786.  
  787. free(rcmd->cmd);
  788. break;
  789.  
  790. case LIST:
  791. lcmd = (struct listcmd*) cmd;
  792.  
  793. free_cmd(lcmd->left);
  794. free_cmd(lcmd->right);
  795.  
  796. free(lcmd->right);
  797. free(lcmd->left);
  798. break;
  799.  
  800. case PIPE:
  801. pcmd = (struct pipecmd*) cmd;
  802.  
  803. free_cmd(pcmd->left);
  804. free_cmd(pcmd->right);
  805.  
  806. free(pcmd->right);
  807. free(pcmd->left);
  808. break;
  809.  
  810. case BACK:
  811. bcmd = (struct backcmd*) cmd;
  812.  
  813. free_cmd(bcmd->cmd);
  814.  
  815. free(bcmd->cmd);
  816. break;
  817.  
  818. case SUBS:
  819. scmd = (struct subscmd*) cmd;
  820.  
  821. free_cmd(scmd->cmd);
  822.  
  823. free(scmd->cmd);
  824. break;
  825.  
  826. case INV:
  827. default:
  828. panic("%s: estructura `cmd` desconocida\n", __func__);
  829. }
  830. }
  831.  
  832.  
  833. void exec_cmd(struct execcmd* ecmd)
  834. {
  835. assert(ecmd->type == EXEC);
  836.  
  837. if (ecmd->argv[0] == NULL) exit(EXIT_SUCCESS);
  838.  
  839. execvp(ecmd->argv[0], ecmd->argv);
  840.  
  841. panic("no se encontró el comando '%s'\n", ecmd->argv[0]);
  842. }
  843.  
  844. //sesion 1: Devuelve el codigo del programa a ejecutar o 0 si no es interno
  845. enum cmd_exec_type get_comand(struct execcmd* cmd) {
  846. if (!cmd->argv[0]) return EXTERNAL;
  847. if (!strcmp(cmd->argv[0], "cwd")) return CWD;
  848. if (!strcmp(cmd->argv[0], "exit")) return EXIT;
  849. if (!strcmp(cmd->argv[0], "cd")) return CD;
  850. if (!strcmp(cmd->argv[0], "psplit")) return PSPLIT;
  851. return EXTERNAL;
  852. }
  853.  
  854. //sesion 1: Imprime en la salida estandar el directorio actual
  855. void run_cwd() {
  856. char * path = malloc(_POSIX_PATH_MAX);
  857. getcwd(path, _POSIX_PATH_MAX);
  858. fprintf(stdout, "cwd: %s\n", path);
  859. free(path);
  860. }
  861.  
  862. //sesion 1: Libera el comando siendo procesado y el buffer para despues salir
  863. void run_exit(struct cmd* cmd, char* buf, int need_to_free) {
  864. if (need_to_free) {
  865. free_cmd(cmd);
  866. free(cmd);
  867. free(buf);
  868. unsetenv("OLDPWD");
  869. }
  870. exit(EXIT_SUCCESS);
  871. }
  872. int changed = 0;
  873.  
  874. //sesion 1: Cambia el directorio del proceso actual
  875. int run_cd(char **args, int u){
  876. if (!u) return 0;
  877. char ans[PATH_MAX];
  878. getcwd(ans, sizeof(ans));
  879. if (args[1] == 0 ){
  880. if (chdir(getenv("HOME"))) perror("cd");
  881. else {
  882. setenv("OLDPWD", ans, 1);
  883. changed = 1;
  884. }
  885. }else{
  886. if (!strcmp(args[1], "-")){
  887. if (!changed){
  888. printf("run_cd: Variable OLDPWD no definida\n");
  889. }
  890. else if (!chdir(getenv("OLDPWD"))){
  891. setenv("OLDPWD", ans, 1);
  892. changed = 1;
  893. }
  894. else perror("cd");
  895. }
  896. else if (args[2] !=0 ) printf("run_cd: Demasiados argumentos\n");
  897. else if (chdir(args[1]) != 0 ) printf("run_cd: No existe el directorio '%s'\n", args[1]);
  898. else {
  899. setenv("OLDPWD", ans, 1);
  900. changed = 1;
  901. }
  902. }
  903. return 0;
  904. }
  905.  
  906. //sesion 2
  907. int run_psplit(struct execcmd* ecmd) {
  908. int filein, fileout, opt, flagl, flagb, flags, flagp, flagh, l, b, PROCS;
  909. size_t BSIZE;
  910. flagl = flagb = flags = flagp = flagh = 0;
  911. char ** files;
  912. char newfile[PATH_MAX];
  913. int fno = 0;
  914. int stdun = 0;
  915. optind = 1;
  916. while((opt = getopt(ecmd->argc , ecmd->argv , "l:b:s:p:h")) != -1) {
  917. switch(opt) {
  918. case 'l':
  919. flagl = 1;
  920. l = atoi(optarg);
  921. fno+=2;
  922. break;
  923. case 'b':
  924. flagb = 1;
  925. b = atoi(optarg);
  926. fno+=2;
  927. break;
  928. case 's':
  929. flags = 1;
  930. BSIZE = atoi(optarg);
  931. if (BSIZE <= 0 || BSIZE > 1048576) {
  932. printf("psplit: Opción -s no válida\n");
  933. }
  934. fno+=2;
  935. break;
  936. case 'p':
  937. flagp = 1;
  938. PROCS = atoi(optarg);
  939. if (PROCS <= 0) {
  940. printf("psplit: Opción -p no válida\n");
  941. return 1;
  942. }
  943. fno+=2;
  944. break;
  945. case 'h':
  946. flagh = 1;
  947. fno+=2;
  948. default:
  949. break;
  950. }
  951. }
  952.  
  953. if (flagl && flagb) {
  954. printf("psplit: Opciones incompatibles\n");
  955. return 1;
  956. }
  957.  
  958. if (!flags) BSIZE = 1024;
  959. if (!flagp) PROCS = 1;
  960.  
  961. int numfiles = ecmd->argc-fno-1;
  962.  
  963. if (numfiles){
  964. files = malloc(numfiles*sizeof(char*));
  965. for (int i = 0; i < numfiles; i++) {
  966. files[i] = malloc(4096*sizeof(char));
  967. strcpy(files[i], ecmd->argv[i+1+fno]);
  968. }
  969. }
  970. else {
  971. files = malloc(sizeof(char*));
  972. files[0] = malloc(4096*sizeof(char));
  973. strcpy(files[0], "stdin");
  974. stdun = 1;
  975. numfiles = 1;
  976. }
  977. int joder=1;
  978. if (flagb && joder ) {
  979. void* buff = malloc(BSIZE);
  980. int k = 0;
  981. int i=0;
  982. size_t restantes = BSIZE;
  983. size_t trocito;
  984. size_t hastafin;
  985. size_t hayresiduo = 0;
  986. size_t trozaco = 0;
  987. int runingprocs=0;
  988. while (i < numfiles) {
  989. if (PROCS > runingprocs) {
  990. runingprocs++;
  991. if (fork_or_panic("fork psplit") == 0){
  992. if (!stdun) {
  993. if ((filein = open(files[i], O_RDONLY, S_IRWXU)) < 0) {
  994. perror("open");
  995. exit(EXIT_FAILURE);
  996. }
  997. }else filein = 0;
  998. while((hastafin = read(filein, buff, BSIZE))) {
  999. if (hayresiduo) {
  1000. trocito = b - restantes;
  1001. write(fileout, buff, min(trocito, hastafin));
  1002. if (trocito <= hastafin ) {
  1003. //fsync(fileout);
  1004. close(fileout);
  1005. k++;
  1006. restantes = hastafin-trocito;
  1007. hayresiduo=0;
  1008. trozaco=0;
  1009. }
  1010. else {
  1011. restantes += hastafin;
  1012. trozaco = 1;
  1013. }
  1014. }else restantes = hastafin;
  1015. while (restantes >= b) {
  1016. sprintf(newfile, "%s%d", files[i], k);
  1017. fileout = open(newfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
  1018. write(fileout, buff+hastafin-restantes, b);
  1019. //fsync(fileout);
  1020. close(fileout);
  1021. restantes -= b;
  1022. k++;
  1023. }
  1024. if (restantes && !trozaco) {
  1025. sprintf(newfile, "%s%d", files[i], k);
  1026. fileout = open(newfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
  1027. write(fileout, buff+hastafin-restantes, restantes);
  1028. hayresiduo=1;
  1029. }
  1030. }
  1031. if (restantes) {
  1032. //fsync(fileout);
  1033. close(fileout);
  1034. }
  1035. exit(EXIT_SUCCESS);
  1036. }else {i++;}
  1037. }else {
  1038. TRY(wait(NULL));
  1039. runingprocs--;
  1040. }
  1041. }
  1042. for (; runingprocs > 0; runingprocs--) TRY(wait(NULL));
  1043. }
  1044.  
  1045.  
  1046. if (flagl) {
  1047. char *buff = malloc(BSIZE);
  1048. int nlineas,readbytes;
  1049. nlineas = 0;
  1050. int k = 0;
  1051. int fb =0;
  1052. size_t pbuff;
  1053. int new=1;
  1054. int flaglineas = 0;
  1055. int runingprocs = 0;
  1056. int i = 0;
  1057. while (i < numfiles) {
  1058. if (PROCS > runingprocs) {
  1059. runingprocs++;
  1060. if (fork_or_panic("fork psplit") == 0) {
  1061. if (!stdun) {
  1062. if ((filein = open(files[i], O_RDONLY, S_IRWXU)) < 0) {
  1063. perror("open");
  1064. exit(EXIT_FAILURE);
  1065. }
  1066. }
  1067. else filein = 0;
  1068. readbytes =read(filein, buff, BSIZE);
  1069. while (readbytes){
  1070. pbuff = 0 ;
  1071. size_t j = 0;
  1072. for (; j < readbytes ; j++){
  1073. if ( buff[j] == '\n') {
  1074. nlineas++;
  1075. if (fb && nlineas == l){
  1076. write(fileout, buff+pbuff, j+1-pbuff);
  1077. fsync(fileout);
  1078. close(fileout);
  1079. nlineas=0;
  1080. pbuff=j+1;
  1081. fb=0;
  1082. new=1;
  1083. }
  1084. }
  1085. if ( nlineas == l){
  1086. sprintf(newfile, "%s%d",files[i],k);
  1087. k++;
  1088. fileout = open(newfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
  1089. write(fileout, buff+pbuff, j+1-pbuff );
  1090. pbuff = j+1;
  1091. fsync(fileout);
  1092. close(fileout);
  1093. nlineas=0;
  1094. if(readbytes < BSIZE) flaglineas =1;
  1095. }
  1096. }
  1097. char * baux = strdup(buff);
  1098. baux += pbuff;
  1099. readbytes = read(filein, buff, BSIZE);
  1100. if(!flaglineas && readbytes >0 ) fb=1;
  1101. if (fb || j != pbuff){
  1102. if(new) {
  1103. sprintf(newfile,"%s%d",files[i],k);
  1104. k++;
  1105. fileout = open(newfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
  1106. new=0;
  1107. }
  1108. write(fileout, baux, j-pbuff);
  1109. }
  1110. }
  1111. exit(EXIT_SUCCESS);
  1112.  
  1113. }
  1114. else i++;
  1115. }
  1116. else {
  1117. TRY(wait(NULL));
  1118. runingprocs--;
  1119. }
  1120. }
  1121. for (; runingprocs > 0; runingprocs--) TRY(wait(NULL));
  1122. free(buff);
  1123. }
  1124.  
  1125. if (flagh) {
  1126. printf("Uso: psplit [-l NLINES] [-b NBYTES] [-s BSIZE] [-p PROCS] [FILE1] [FILE2]...\n");
  1127. printf("\tOpciones:\n");
  1128. printf("\t-l NLINES Número máximo de líneas por fichero.\n");
  1129. printf("\t-l NBYTES Número máximo de bytes por fichero.\n");
  1130. printf("\t-s BSIZE Tamaño en bytes de los bloques leídos de [FILEn] o stdin.\n");
  1131. printf("\t-p PROCS Número máximo de procesos simultáneos.\n");
  1132. printf("\t-h Ayuda\n\n");
  1133. }
  1134. free(files);
  1135.  
  1136. return 0;
  1137. }
  1138.  
  1139. void run_cmd(struct cmd* cmd, struct cmd* original, char* buf, int need_to_free)
  1140. {
  1141. struct execcmd* ecmd;
  1142. struct redrcmd* rcmd;
  1143. struct listcmd* lcmd;
  1144. struct pipecmd* pcmd;
  1145. struct backcmd* bcmd;
  1146. struct subscmd* scmd;
  1147. int p[2];
  1148. int fd;
  1149. int es_exit;
  1150. int es_cd;
  1151.  
  1152. DPRINTF(DBG_TRACE, "STR\n");
  1153.  
  1154. if(cmd == 0) return;
  1155.  
  1156. switch(cmd->type)
  1157. {
  1158. case EXEC:
  1159. ecmd = (struct execcmd*) cmd;
  1160. switch(get_comand(ecmd)) {
  1161. case CWD:
  1162. run_cwd();
  1163. break;
  1164. case EXIT:
  1165. run_exit(original, buf, need_to_free);
  1166. break;
  1167. case CD:
  1168. run_cd(ecmd->argv,1);
  1169. break;
  1170. case PSPLIT:
  1171. run_psplit(ecmd);
  1172. break;
  1173. case EXTERNAL: ;
  1174. if (fork_or_panic("fork EXEC") == 0) {
  1175. exec_cmd(ecmd);
  1176. }
  1177. TRY( wait(NULL) );
  1178. }
  1179. break;
  1180.  
  1181. case REDR:
  1182. es_exit = 0;
  1183. es_cd = 0;
  1184. rcmd = (struct redrcmd*) cmd;
  1185. //En el caso de que tengamos que ejecutar un exit, el fichero debe crearse pero no podemos ejecutarla
  1186. //en el hijo pues el padre es el que debe finalizar su ejecución, por tanto lo marcamos aqui para finalizar
  1187. //tras crear el fichero
  1188. if (rcmd->cmd->type == EXEC)
  1189. es_exit = (get_comand((struct execcmd*) rcmd->cmd) == EXIT);
  1190. if (rcmd->cmd->type == EXEC)
  1191. es_cd = (get_comand((struct execcmd*) rcmd->cmd) == CD);
  1192. if (fork_or_panic("fork REDR") == 0)
  1193. {
  1194. TRY( close(rcmd->fd) );
  1195. if ((fd = open(rcmd->file, rcmd->flags, rcmd->mode)) < 0)
  1196. {
  1197. perror("open");
  1198. exit(EXIT_FAILURE);
  1199. }
  1200.  
  1201. if (rcmd->cmd->type == EXEC) {
  1202. ecmd = (struct execcmd*) rcmd->cmd;
  1203. switch(get_comand(ecmd)) {
  1204. case CWD:
  1205. run_cwd();
  1206. break;
  1207. case EXIT:
  1208. run_exit(original, buf, 0);
  1209. break;
  1210. case CD:
  1211. run_cd(ecmd->argv,0);
  1212. break;
  1213. case PSPLIT:
  1214. run_psplit(ecmd);
  1215. break;
  1216. case EXTERNAL:
  1217. exec_cmd(ecmd);
  1218. }
  1219. }
  1220. else
  1221. run_cmd(rcmd->cmd, original, buf, 0);
  1222. exit(EXIT_SUCCESS);
  1223. }
  1224. TRY( wait(NULL) );
  1225. if (es_exit) run_exit(original, buf, need_to_free);
  1226. else if (es_cd) {
  1227. ecmd = (struct execcmd*) rcmd->cmd;
  1228. run_cd(ecmd->argv, 1);
  1229. }
  1230. break;
  1231.  
  1232. case LIST:
  1233. lcmd = (struct listcmd*) cmd;
  1234. run_cmd(lcmd->left, original, buf, need_to_free);
  1235. run_cmd(lcmd->right, original, buf, need_to_free);
  1236. break;
  1237.  
  1238. case PIPE:
  1239. pcmd = (struct pipecmd*)cmd;
  1240. if (pipe(p) < 0)
  1241. {
  1242. perror("pipe");
  1243. exit(EXIT_FAILURE);
  1244. }
  1245.  
  1246. // Ejecución del hijo de la izquierda
  1247. if (fork_or_panic("fork PIPE left") == 0)
  1248. {
  1249. TRY( close(STDOUT_FILENO) );
  1250. TRY( dup(p[1]) );
  1251. TRY( close(p[0]) );
  1252. TRY( close(p[1]) );
  1253. if (pcmd->left->type == EXEC) {
  1254. ecmd = (struct execcmd*) pcmd->left;
  1255. switch(get_comand(ecmd)) {
  1256. case CWD:
  1257. run_cwd();
  1258. break;
  1259. case EXIT:
  1260. run_exit(original, buf, 0);
  1261. break;
  1262. case CD:
  1263. run_cd(ecmd->argv,1);
  1264. break;
  1265. case PSPLIT:
  1266. run_psplit(ecmd);
  1267. break;
  1268. case EXTERNAL:
  1269. exec_cmd(ecmd);
  1270. }
  1271. }
  1272. else
  1273. run_cmd(pcmd->left, original, buf, 0);
  1274. exit(EXIT_SUCCESS);
  1275. }
  1276.  
  1277. // Ejecución del hijo de la derecha
  1278. if (fork_or_panic("fork PIPE right") == 0)
  1279. {
  1280. TRY( close(STDIN_FILENO) );
  1281. TRY( dup(p[0]) );
  1282. TRY( close(p[0]) );
  1283. TRY( close(p[1]) );
  1284. if (pcmd->right->type == EXEC) {
  1285. ecmd = (struct execcmd*) pcmd->right;
  1286. switch(get_comand(ecmd)) {
  1287. case CWD:
  1288. run_cwd();
  1289. break;
  1290. case EXIT:
  1291. run_exit(original, buf, 0);
  1292. break;
  1293. case CD:
  1294. run_cd(ecmd->argv,1);
  1295. break;
  1296. case PSPLIT:
  1297. run_psplit(ecmd);
  1298. break;
  1299. case EXTERNAL:
  1300. exec_cmd(ecmd);
  1301. }
  1302. }
  1303. else
  1304. run_cmd(pcmd->right, original, buf, 0);
  1305. exit(EXIT_SUCCESS);
  1306. }
  1307. TRY( close(p[0]) );
  1308. TRY( close(p[1]) );
  1309.  
  1310. // Esperar a ambos hijos
  1311. TRY( wait(NULL) );
  1312. TRY( wait(NULL) );
  1313. break;
  1314.  
  1315. case BACK:
  1316. bcmd = (struct backcmd*)cmd;
  1317. if (fork_or_panic("fork BACK") == 0)
  1318. {
  1319. if (bcmd->cmd->type == EXEC) {
  1320. ecmd = (struct execcmd*) bcmd->cmd;
  1321. switch(get_comand(ecmd)) {
  1322. case CWD:
  1323. run_cwd();
  1324. break;
  1325. case EXIT:
  1326. run_exit(original, buf, 0);
  1327. break;
  1328. case CD:
  1329. run_cd(ecmd->argv,1);
  1330. break;
  1331. case PSPLIT:
  1332. run_psplit(ecmd);
  1333. break;
  1334. case EXTERNAL:
  1335. exec_cmd(ecmd);
  1336. }
  1337. }
  1338. else
  1339. run_cmd(bcmd->cmd, original, buf, 0);
  1340. exit(EXIT_SUCCESS);
  1341. }
  1342. break;
  1343. case SUBS:
  1344. scmd = (struct subscmd*) cmd;
  1345. if (fork_or_panic("fork SUBS") == 0)
  1346. {
  1347. run_cmd(scmd->cmd, original, buf, 0);
  1348. exit(EXIT_SUCCESS);
  1349. }
  1350. TRY( wait(NULL) );
  1351. break;
  1352.  
  1353. case INV:
  1354. default:
  1355. panic("%s: estructura `cmd` desconocida\n", __func__);
  1356. }
  1357.  
  1358. DPRINTF(DBG_TRACE, "END\n");
  1359. }
  1360.  
  1361.  
  1362. void print_cmd(struct cmd* cmd)
  1363. {
  1364. struct execcmd* ecmd;
  1365. struct redrcmd* rcmd;
  1366. struct listcmd* lcmd;
  1367. struct pipecmd* pcmd;
  1368. struct backcmd* bcmd;
  1369. struct subscmd* scmd;
  1370.  
  1371. if(cmd == 0) return;
  1372.  
  1373. switch(cmd->type)
  1374. {
  1375. case EXEC:
  1376. ecmd = (struct execcmd*) cmd;
  1377. if (ecmd->argv[0] != 0)
  1378. printf("fork( exec( %s ) )", ecmd->argv[0]);
  1379. break;
  1380.  
  1381. case REDR:
  1382. rcmd = (struct redrcmd*) cmd;
  1383. printf("fork( ");
  1384. if (rcmd->cmd->type == EXEC)
  1385. printf("exec ( %s )", ((struct execcmd*) rcmd->cmd)->argv[0]);
  1386. else
  1387. print_cmd(rcmd->cmd);
  1388. printf(" )");
  1389. break;
  1390.  
  1391. case LIST:
  1392. lcmd = (struct listcmd*) cmd;
  1393. print_cmd(lcmd->left);
  1394. printf(" ; ");
  1395. print_cmd(lcmd->right);
  1396. break;
  1397.  
  1398. case PIPE:
  1399. pcmd = (struct pipecmd*) cmd;
  1400. printf("fork( ");
  1401. if (pcmd->left->type == EXEC)
  1402. printf("exec ( %s )", ((struct execcmd*) pcmd->left)->argv[0]);
  1403. else
  1404. print_cmd(pcmd->left);
  1405. printf(" ) => fork( ");
  1406. if (pcmd->right->type == EXEC)
  1407. printf("exec ( %s )", ((struct execcmd*) pcmd->right)->argv[0]);
  1408. else
  1409. print_cmd(pcmd->right);
  1410. printf(" )");
  1411. break;
  1412.  
  1413. case BACK:
  1414. bcmd = (struct backcmd*) cmd;
  1415. printf("fork( ");
  1416. if (bcmd->cmd->type == EXEC)
  1417. printf("exec ( %s )", ((struct execcmd*) bcmd->cmd)->argv[0]);
  1418. else
  1419. print_cmd(bcmd->cmd);
  1420. printf(" )");
  1421. break;
  1422.  
  1423. case SUBS:
  1424. scmd = (struct subscmd*) cmd;
  1425. printf("fork( ");
  1426. print_cmd(scmd->cmd);
  1427. printf(" )");
  1428. break;
  1429.  
  1430. case INV:
  1431. default:
  1432. panic("%s: estructura `cmd` desconocida\n", __func__);
  1433. }
  1434. }
  1435.  
  1436.  
  1437. /******************************************************************************
  1438. * Lectura de la línea de órdenes con la biblioteca libreadline
  1439. ******************************************************************************/
  1440.  
  1441.  
  1442. // `get_cmd` muestra un *prompt* y lee lo que el usuario escribe usando la
  1443. // biblioteca readline. Ésta permite mantener el historial, utilizar las flechas
  1444. // para acceder a las órdenes previas del historial, búsquedas de órdenes, etc.
  1445.  
  1446. char* get_cmd()
  1447. {
  1448. char* buf;
  1449.  
  1450. // Lee la orden tecleada por el usuario
  1451. register uid_t uid = getuid ();
  1452. register struct passwd * pw = getpwuid (uid);
  1453. char * name = pw->pw_name;
  1454. char * path = malloc(PATH_MAX);
  1455. getcwd(path, PATH_MAX);
  1456. char * prompt = malloc(LOGIN_NAME_MAX);
  1457. sprintf(prompt, "%s@%s> ", name, basename(path));
  1458. buf = readline(prompt);
  1459. free(path);
  1460. free(prompt);
  1461.  
  1462. // Si el usuario ha escrito una orden, almacenarla en la historia.
  1463. if(buf)
  1464. add_history(buf);
  1465.  
  1466. return buf;
  1467. }
  1468.  
  1469.  
  1470. /******************************************************************************
  1471. * Bucle principal de `simplesh`
  1472. ******************************************************************************/
  1473.  
  1474.  
  1475. void help(char **argv)
  1476. {
  1477. info("Usage: %s [-d N] [-h]\n\
  1478. shell simplesh v%s\n\
  1479. Options: \n\
  1480. -d set debug level to N\n\
  1481. -h help\n\n",
  1482. argv[0], VERSION);
  1483. }
  1484.  
  1485.  
  1486. void parse_args(int argc, char** argv)
  1487. {
  1488. int option;
  1489.  
  1490. // Bucle de procesamiento de parámetros
  1491. while((option = getopt(argc, argv, "d:h")) != -1) {
  1492. switch(option) {
  1493. case 'd':
  1494. g_dbg_level = atoi(optarg);
  1495. break;
  1496. case 'h':
  1497. default:
  1498. help(argv);
  1499. exit(EXIT_SUCCESS);
  1500. break;
  1501. }
  1502. }
  1503. }
  1504.  
  1505.  
  1506. int main(int argc, char** argv)
  1507. {
  1508. unsetenv("OLDPWD");
  1509. char* buf;
  1510. struct cmd* cmd;
  1511.  
  1512. parse_args(argc, argv);
  1513.  
  1514. DPRINTF(DBG_TRACE, "STR\n");
  1515. //sesion 3
  1516. //bloqueamos SIGINT
  1517. sigset_t bloqueadas;
  1518. sigemptyset(&bloqueadas);
  1519. sigaddset(&bloqueadas, SIGINT);
  1520. sigprocmask(SIG_BLOCK, &bloqueadas, NULL);
  1521.  
  1522. //ignoramos SIGQUIT
  1523. struct sigaction act;
  1524. act.sa_handler = SIG_IGN;
  1525. sigaction(SIGQUIT, &act, NULL);
  1526.  
  1527. // Bucle de lectura y ejecución de órdenes
  1528. while ((buf = get_cmd()) != NULL)
  1529. {
  1530. // Realiza el análisis sintáctico de la línea de órdenes
  1531. cmd = parse_cmd(buf);
  1532.  
  1533. // Termina en `NULL` todas las cadenas de las estructuras `cmd`
  1534. null_terminate(cmd);
  1535.  
  1536. DBLOCK(DBG_CMD, {
  1537. info("%s:%d:%s: print_cmd: ",
  1538. __FILE__, __LINE__, __func__);
  1539. print_cmd(cmd); printf("\n"); fflush(NULL); } );
  1540.  
  1541. // Ejecuta la línea de órdenes
  1542. run_cmd(cmd, cmd, buf, 1);
  1543.  
  1544. // Libera la memoria de las estructuras `cmd`
  1545. free_cmd(cmd);
  1546. free(cmd); // sesion 0
  1547.  
  1548. // Libera la memoria de la línea de órdenes
  1549. free(buf);
  1550. }
  1551.  
  1552. DPRINTF(DBG_TRACE, "END\n");
  1553.  
  1554. return 0;
  1555. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement