44
45
46 #include <signal.h>
47
48 # include <stropts.h>
49
50 #include <sys/errno.h>
51 #include <sys/stat.h>
52 #include <sys/types.h>
53 #include <sys/utsname.h> /* uname() */
54 #include <sys/wait.h>
55 #include <unistd.h> /* close() */
56
57 /*
58 * Defined macros
59 */
60 # define LOCALHOST "localhost"
61
62 #define MAXRULES 100
63
64 #define SEND_MTOOL_MSG(cmds)
65
66 // Sleep for .1 seconds between stat()'s
67 const int STAT_RETRY_SLEEP_TIME = 100000;
68
69 /*
70 * typedefs & structs
71 */
72
73 /*
74 * Static variables
75 */
76 static char hostName[MAXNAMELEN] = "";
77 static char userName[MAXNAMELEN] = "";
78
79
80 static int second_pass = 0;
81
82 /*
83 * File table of contents
84 */
85 extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
1756 *
1757 * Global variables used:
1758 * continue_after_error -k flag
1759 * do_not_exec_rule -n flag
1760 * report_dependencies -P flag
1761 * silent Don't echo commands before executing
1762 * temp_file_name Temp file for auto dependencies
1763 * vpath_defined If true, translate path for command
1764 */
1765 Doname
1766 execute_serial(Property line)
1767 {
1768 int child_pid = 0;
1769 Boolean printed_serial;
1770 Doname result = build_ok;
1771 Cmd_line rule, cmd_tail, command = NULL;
1772 char mbstring[MAXPATHLEN];
1773 int filed;
1774 Name target = line->body.line.target;
1775
1776 SEND_MTOOL_MSG(
1777 if (!sent_rsrc_info_msg) {
1778 if (userName[0] == '\0') {
1779 avo_get_user(userName, NULL);
1780 }
1781 if (hostName[0] == '\0') {
1782 strcpy(hostName, avo_hostname());
1783 }
1784 send_rsrc_info_msg(1, hostName, userName);
1785 sent_rsrc_info_msg = 1;
1786 }
1787 send_job_start_msg(line);
1788 job_result_msg = new Avo_MToolJobResultMsg();
1789 );
1790
1791 target->has_recursive_dependency = false;
1792 // We have to create a copy of the rules chain for processing because
1793 // the original one can be destroyed during .make.state file rereading.
1794 for (rule = line->body.line.command_used;
1795 rule != NULL;
1796 rule = rule->next) {
1797 if (command == NULL) {
1798 command = cmd_tail = ALLOC(Cmd_line);
1799 } else {
1800 cmd_tail->next = ALLOC(Cmd_line);
1801 cmd_tail = cmd_tail->next;
1802 }
1803 *cmd_tail = *rule;
1804 }
1805 if (command) {
1806 cmd_tail->next = NULL;
1807 }
1808 for (rule = command; rule != NULL; rule = rule->next) {
1809 if (posix && (touch || quest) && !rule->always_exec) {
1810 continue;
1811 }
1812 if (vpath_defined) {
1813 rule->command_line =
1814 vpath_translation(rule->command_line);
1815 }
1816 /* Echo command line, maybe. */
1817 if ((rule->command_line->hash.length > 0) &&
1818 !silent &&
1819 (!rule->silent || do_not_exec_rule) &&
1820 (report_dependencies_level == 0)) {
1821 (void) printf("%s\n", rule->command_line->string_mb);
1822 SEND_MTOOL_MSG(
1823 job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb));
1824 );
1825 }
1826 if (rule->command_line->hash.length > 0) {
1827 SEND_MTOOL_MSG(
1828 (void) sprintf(mbstring,
1829 NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"),
1830 tmpdir,
1831 getpid(),
1832 file_number++);
1833
1834 int tmp_fd = mkstemp(mbstring);
1835 if(tmp_fd) {
1836 (void) close(tmp_fd);
1837 }
1838
1839 stdout_file = strdup(mbstring);
1840 stderr_file = NULL;
1841 child_pid = pollResults(stdout_file,
1842 (char *)NULL,
1843 (char *)NULL);
1844 );
1845 /* Do assignment if command line prefixed with "=" */
1846 if (rule->assign) {
1847 result = build_ok;
1848 do_assign(rule->command_line, target);
1849 } else if (report_dependencies_level == 0) {
1850 /* Execute command line. */
1851 setvar_envvar();
1852 result = dosys(rule->command_line,
1853 (Boolean) rule->ignore_error,
1854 (Boolean) rule->make_refd,
1855 /* ds 98.04.23 bug #4085164. make should always show error messages */
1856 false,
1857 /* BOOLEAN(rule->silent &&
1858 rule->ignore_error), */
1859 (Boolean) rule->always_exec,
1860 target,
1861 send_mtool_msgs);
1862 check_state(temp_file_name);
1863 }
1864 SEND_MTOOL_MSG(
1865 append_job_result_msg(job_result_msg);
1866 if (child_pid > 0) {
1867 kill(child_pid, SIGUSR1);
1868 while (!((waitpid(child_pid, 0, 0) == -1)
1869 && (errno == ECHILD)));
1870 }
1871 child_pid = 0;
1872 (void) unlink(stdout_file);
1873 retmem_mb(stdout_file);
1874 stdout_file = NULL;
1875 );
1876 } else {
1877 result = build_ok;
1878 }
1879 if (result == build_failed) {
1880 if (silent || rule->silent) {
1881 (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"),
1882 rule->command_line->string_mb);
1883 SEND_MTOOL_MSG(
1884 job_result_msg->appendOutput(AVO_STRDUP(catgets(catd, 1, 243, "The following command caused the error:")));
1885 job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb));
1886 );
1887 }
1888 if (!rule->ignore_error && !ignore_errors) {
1889 if (!continue_after_error) {
1890 SEND_MTOOL_MSG(
1891 job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
1892 xdr_msg = (RWCollectable*)
1893 job_result_msg;
1894 xdr(&xdrs, xdr_msg);
1895 (void) fflush(mtool_msgs_fp);
1896 delete job_result_msg;
1897 );
1898 fatal(catgets(catd, 1, 244, "Command failed for target `%s'"),
1899 target->string_mb);
1900 }
1901 /*
1902 * Make sure a failing command is not
1903 * saved in .make.state.
1904 */
1905 line->body.line.command_used = NULL;
1906 break;
1907 } else {
1908 result = build_ok;
1909 }
1910 }
1911 }
1912 for (rule = command; rule != NULL; rule = cmd_tail) {
1913 cmd_tail = rule->next;
1914 free(rule);
1915 }
1916 command = NULL;
1917 SEND_MTOOL_MSG(
1918 job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
1919 xdr_msg = (RWCollectable*) job_result_msg;
1920 xdr(&xdrs, xdr_msg);
1921 (void) fflush(mtool_msgs_fp);
1922
1923 delete job_result_msg;
1924 );
1925 if (temp_file_name != NULL) {
1926 free_name(temp_file_name);
1927 }
1928 temp_file_name = NULL;
1929
1930 Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
1931 if(spro != NULL) {
1932 Name val = spro->body.macro.value;
1933 if(val != NULL) {
1934 free_name(val);
1935 spro->body.macro.value = NULL;
1936 }
1937 }
1938 spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
1939 if(spro) {
1940 char *val = spro->body.env_mem.value;
1941 if(val != NULL) {
1942 /*
1943 * Do not return memory allocated for SUNPRO_DEPENDENCIES
1944 * It will be returned in setvar_daemon() in macro.cc
2566 *
2567 * Parameters:
2568 * line The command line to update
2569 * target The target we are touching
2570 * result Initial value for the result we return
2571 *
2572 * Global variables used:
2573 * do_not_exec_rule Indicates that -n is on
2574 * silent Do not echo commands
2575 */
2576 static Doname
2577 touch_command(register Property line, register Name target, Doname result)
2578 {
2579 Name name;
2580 register Chain target_group;
2581 String_rec touch_string;
2582 wchar_t buffer[MAXPATHLEN];
2583 Name touch_cmd;
2584 Cmd_line rule;
2585
2586
2587 SEND_MTOOL_MSG(
2588 if (!sent_rsrc_info_msg) {
2589 if (userName[0] == '\0') {
2590 avo_get_user(userName, NULL);
2591 }
2592 if (hostName[0] == '\0') {
2593 strcpy(hostName, avo_hostname());
2594 }
2595 send_rsrc_info_msg(1, hostName, userName);
2596 sent_rsrc_info_msg = 1;
2597 }
2598 send_job_start_msg(line);
2599 job_result_msg = new Avo_MToolJobResultMsg();
2600 );
2601 for (name = target, target_group = NULL; name != NULL;) {
2602 if (!name->is_member) {
2603 /*
2604 * Build a touch command that can be passed
2605 * to dosys(). If KEEP_STATE is on, "make -t"
2606 * will save the proper command, not the
2607 * "touch" in .make.state.
2608 */
2609 INIT_STRING_FROM_STACK(touch_string, buffer);
2610 MBSTOWCS(wcs_buffer, NOCATGETS("touch "));
2611 append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2612 touch_cmd = name;
2613 if (name->has_vpath_alias_prop) {
2614 touch_cmd = get_prop(name->prop,
2615 vpath_alias_prop)->
2616 body.vpath_alias.alias;
2617 }
2618 APPEND_NAME(touch_cmd,
2619 &touch_string,
2620 FIND_LENGTH);
2621 touch_cmd = GETNAME(touch_string.buffer.start,
2622 FIND_LENGTH);
2623 if (touch_string.free_after_use) {
2624 retmem(touch_string.buffer.start);
2625 }
2626 if (!silent ||
2627 do_not_exec_rule &&
2628 (target_group == NULL)) {
2629 (void) printf("%s\n", touch_cmd->string_mb);
2630 SEND_MTOOL_MSG(
2631 job_result_msg->appendOutput(AVO_STRDUP(touch_cmd->string_mb));
2632 );
2633 }
2634 /* Run the touch command, or simulate it */
2635 if (!do_not_exec_rule) {
2636
2637 SEND_MTOOL_MSG(
2638 (void) sprintf(mbstring,
2639 NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"),
2640 tmpdir,
2641 getpid(),
2642 file_number++);
2643
2644 int tmp_fd = mkstemp(mbstring);
2645 if(tmp_fd) {
2646 (void) close(tmp_fd);
2647 }
2648
2649 stdout_file = strdup(mbstring);
2650 stderr_file = NULL;
2651 child_pid = pollResults(stdout_file,
2652 (char *)NULL,
2653 (char *)NULL);
2654 );
2655
2656 result = dosys(touch_cmd,
2657 false,
2658 false,
2659 false,
2660 false,
2661 name,
2662 send_mtool_msgs);
2663
2664 SEND_MTOOL_MSG(
2665 append_job_result_msg(job_result_msg);
2666 if (child_pid > 0) {
2667 kill(child_pid, SIGUSR1);
2668 while (!((waitpid(child_pid, 0, 0) == -1)
2669 && (errno == ECHILD)));
2670 }
2671 child_pid = 0;
2672 (void) unlink(stdout_file);
2673 retmem_mb(stdout_file);
2674 stdout_file = NULL;
2675 );
2676
2677 } else {
2678 result = build_ok;
2679 }
2680 } else {
2681 result = build_ok;
2682 }
2683 if (target_group == NULL) {
2684 target_group = line->body.line.target_group;
2685 } else {
2686 target_group = target_group->next;
2687 }
2688 if (target_group != NULL) {
2689 name = target_group->name;
2690 } else {
2691 name = NULL;
2692 }
2693 }
2694 SEND_MTOOL_MSG(
2695 job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE);
2696 xdr_msg = (RWCollectable*) job_result_msg;
2697 xdr(&xdrs, xdr_msg);
2698 (void) fflush(mtool_msgs_fp);
2699 delete job_result_msg;
2700 );
2701 return result;
2702 }
2703
2704 /*
2705 * update_target(line, result)
2706 *
2707 * updates the status of a target after executing its commands.
2708 *
2709 * Parameters:
2710 * line The command line block to update
2711 * result Indicates that build is OK so can update
2712 *
2713 * Global variables used:
2714 * do_not_exec_rule Indicates that -n is on
2715 * touch Fake the new timestamp if we are just touching
2716 */
2717 void
2718 update_target(Property line, Doname result)
2719 {
2720 Name target;
|
44
45
46 #include <signal.h>
47
48 # include <stropts.h>
49
50 #include <sys/errno.h>
51 #include <sys/stat.h>
52 #include <sys/types.h>
53 #include <sys/utsname.h> /* uname() */
54 #include <sys/wait.h>
55 #include <unistd.h> /* close() */
56
57 /*
58 * Defined macros
59 */
60 # define LOCALHOST "localhost"
61
62 #define MAXRULES 100
63
64 // Sleep for .1 seconds between stat()'s
65 const int STAT_RETRY_SLEEP_TIME = 100000;
66
67 /*
68 * typedefs & structs
69 */
70
71 /*
72 * Static variables
73 */
74 static char hostName[MAXNAMELEN] = "";
75 static char userName[MAXNAMELEN] = "";
76
77
78 static int second_pass = 0;
79
80 /*
81 * File table of contents
82 */
83 extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
1754 *
1755 * Global variables used:
1756 * continue_after_error -k flag
1757 * do_not_exec_rule -n flag
1758 * report_dependencies -P flag
1759 * silent Don't echo commands before executing
1760 * temp_file_name Temp file for auto dependencies
1761 * vpath_defined If true, translate path for command
1762 */
1763 Doname
1764 execute_serial(Property line)
1765 {
1766 int child_pid = 0;
1767 Boolean printed_serial;
1768 Doname result = build_ok;
1769 Cmd_line rule, cmd_tail, command = NULL;
1770 char mbstring[MAXPATHLEN];
1771 int filed;
1772 Name target = line->body.line.target;
1773
1774 target->has_recursive_dependency = false;
1775 // We have to create a copy of the rules chain for processing because
1776 // the original one can be destroyed during .make.state file rereading.
1777 for (rule = line->body.line.command_used;
1778 rule != NULL;
1779 rule = rule->next) {
1780 if (command == NULL) {
1781 command = cmd_tail = ALLOC(Cmd_line);
1782 } else {
1783 cmd_tail->next = ALLOC(Cmd_line);
1784 cmd_tail = cmd_tail->next;
1785 }
1786 *cmd_tail = *rule;
1787 }
1788 if (command) {
1789 cmd_tail->next = NULL;
1790 }
1791 for (rule = command; rule != NULL; rule = rule->next) {
1792 if (posix && (touch || quest) && !rule->always_exec) {
1793 continue;
1794 }
1795 if (vpath_defined) {
1796 rule->command_line =
1797 vpath_translation(rule->command_line);
1798 }
1799 /* Echo command line, maybe. */
1800 if ((rule->command_line->hash.length > 0) &&
1801 !silent &&
1802 (!rule->silent || do_not_exec_rule) &&
1803 (report_dependencies_level == 0)) {
1804 (void) printf("%s\n", rule->command_line->string_mb);
1805 }
1806 if (rule->command_line->hash.length > 0) {
1807 /* Do assignment if command line prefixed with "=" */
1808 if (rule->assign) {
1809 result = build_ok;
1810 do_assign(rule->command_line, target);
1811 } else if (report_dependencies_level == 0) {
1812 /* Execute command line. */
1813 setvar_envvar();
1814 result = dosys(rule->command_line,
1815 (Boolean) rule->ignore_error,
1816 (Boolean) rule->make_refd,
1817 /* ds 98.04.23 bug #4085164. make should always show error messages */
1818 false,
1819 /* BOOLEAN(rule->silent &&
1820 rule->ignore_error), */
1821 (Boolean) rule->always_exec,
1822 target);
1823 check_state(temp_file_name);
1824 }
1825 } else {
1826 result = build_ok;
1827 }
1828 if (result == build_failed) {
1829 if (silent || rule->silent) {
1830 (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"),
1831 rule->command_line->string_mb);
1832 }
1833 if (!rule->ignore_error && !ignore_errors) {
1834 if (!continue_after_error) {
1835 fatal(catgets(catd, 1, 244, "Command failed for target `%s'"),
1836 target->string_mb);
1837 }
1838 /*
1839 * Make sure a failing command is not
1840 * saved in .make.state.
1841 */
1842 line->body.line.command_used = NULL;
1843 break;
1844 } else {
1845 result = build_ok;
1846 }
1847 }
1848 }
1849 for (rule = command; rule != NULL; rule = cmd_tail) {
1850 cmd_tail = rule->next;
1851 free(rule);
1852 }
1853 command = NULL;
1854 if (temp_file_name != NULL) {
1855 free_name(temp_file_name);
1856 }
1857 temp_file_name = NULL;
1858
1859 Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
1860 if(spro != NULL) {
1861 Name val = spro->body.macro.value;
1862 if(val != NULL) {
1863 free_name(val);
1864 spro->body.macro.value = NULL;
1865 }
1866 }
1867 spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
1868 if(spro) {
1869 char *val = spro->body.env_mem.value;
1870 if(val != NULL) {
1871 /*
1872 * Do not return memory allocated for SUNPRO_DEPENDENCIES
1873 * It will be returned in setvar_daemon() in macro.cc
2495 *
2496 * Parameters:
2497 * line The command line to update
2498 * target The target we are touching
2499 * result Initial value for the result we return
2500 *
2501 * Global variables used:
2502 * do_not_exec_rule Indicates that -n is on
2503 * silent Do not echo commands
2504 */
2505 static Doname
2506 touch_command(register Property line, register Name target, Doname result)
2507 {
2508 Name name;
2509 register Chain target_group;
2510 String_rec touch_string;
2511 wchar_t buffer[MAXPATHLEN];
2512 Name touch_cmd;
2513 Cmd_line rule;
2514
2515 for (name = target, target_group = NULL; name != NULL;) {
2516 if (!name->is_member) {
2517 /*
2518 * Build a touch command that can be passed
2519 * to dosys(). If KEEP_STATE is on, "make -t"
2520 * will save the proper command, not the
2521 * "touch" in .make.state.
2522 */
2523 INIT_STRING_FROM_STACK(touch_string, buffer);
2524 MBSTOWCS(wcs_buffer, NOCATGETS("touch "));
2525 append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2526 touch_cmd = name;
2527 if (name->has_vpath_alias_prop) {
2528 touch_cmd = get_prop(name->prop,
2529 vpath_alias_prop)->
2530 body.vpath_alias.alias;
2531 }
2532 APPEND_NAME(touch_cmd,
2533 &touch_string,
2534 FIND_LENGTH);
2535 touch_cmd = GETNAME(touch_string.buffer.start,
2536 FIND_LENGTH);
2537 if (touch_string.free_after_use) {
2538 retmem(touch_string.buffer.start);
2539 }
2540 if (!silent ||
2541 do_not_exec_rule &&
2542 (target_group == NULL)) {
2543 (void) printf("%s\n", touch_cmd->string_mb);
2544 }
2545 /* Run the touch command, or simulate it */
2546 if (!do_not_exec_rule) {
2547 result = dosys(touch_cmd,
2548 false,
2549 false,
2550 false,
2551 false,
2552 name);
2553 } else {
2554 result = build_ok;
2555 }
2556 } else {
2557 result = build_ok;
2558 }
2559 if (target_group == NULL) {
2560 target_group = line->body.line.target_group;
2561 } else {
2562 target_group = target_group->next;
2563 }
2564 if (target_group != NULL) {
2565 name = target_group->name;
2566 } else {
2567 name = NULL;
2568 }
2569 }
2570 return result;
2571 }
2572
2573 /*
2574 * update_target(line, result)
2575 *
2576 * updates the status of a target after executing its commands.
2577 *
2578 * Parameters:
2579 * line The command line block to update
2580 * result Indicates that build is OK so can update
2581 *
2582 * Global variables used:
2583 * do_not_exec_rule Indicates that -n is on
2584 * touch Fake the new timestamp if we are just touching
2585 */
2586 void
2587 update_target(Property line, Doname result)
2588 {
2589 Name target;
|