edify: Move State.script and State.errmsg to std::string.

This way we kill a few strdup() and free() calls.

Test: 1. recovery_component_test still passes;
2. Applying an update with the new updater works;
3. The error code in a script with abort("E310: xyz") is recorded into
last_install correctly.

Change-Id: Ibda4da5937346e058a0d7cc81764d6f02920010a
diff --git a/updater/updater.cpp b/updater/updater.cpp
index c222cee..74a4048 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -14,22 +14,24 @@
  * limitations under the License.
  */
 
+#include "updater.h"
+
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "edify/expr.h"
-#include "updater.h"
-#include "install.h"
-#include "blockimg.h"
-#include "minzip/Zip.h"
-#include "minzip/SysUtil.h"
-#include "config.h"
-
+#include <android-base/strings.h>
 #include <selinux/label.h>
 #include <selinux/selinux.h>
 
+#include "config.h"
+#include "edify/expr.h"
+#include "blockimg.h"
+#include "install.h"
+#include "minzip/Zip.h"
+#include "minzip/SysUtil.h"
+
 // Generated by the makefile, this function defines the
 // RegisterDeviceExtensions() function, which calls all the
 // registration functions for device-specific extensions.
@@ -140,10 +142,7 @@
     updater_info.package_zip_addr = map.addr;
     updater_info.package_zip_len = map.length;
 
-    State state;
-    state.cookie = &updater_info;
-    state.script = script;
-    state.errmsg = NULL;
+    State state(script, &updater_info);
 
     if (argc == 5) {
         if (strcmp(argv[4], "retry") == 0) {
@@ -160,22 +159,21 @@
     }
 
     if (result == NULL) {
-        if (state.errmsg == NULL) {
+        if (state.errmsg.empty()) {
             printf("script aborted (no error message)\n");
             fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
         } else {
-            printf("script aborted: %s\n", state.errmsg);
-            char* line = strtok(state.errmsg, "\n");
-            while (line) {
+            printf("script aborted: %s\n", state.errmsg.c_str());
+            const std::vector<std::string> lines = android::base::Split(state.errmsg, "\n");
+            for (const std::string& line : lines) {
                 // Parse the error code in abort message.
                 // Example: "E30: This package is for bullhead devices."
-                if (*line == 'E') {
-                    if (sscanf(line, "E%u: ", &state.error_code) != 1) {
-                         printf("Failed to parse error code: [%s]\n", line);
+                if (!line.empty() && line[0] == 'E') {
+                    if (sscanf(line.c_str(), "E%u: ", &state.error_code) != 1) {
+                         printf("Failed to parse error code: [%s]\n", line.c_str());
                     }
                 }
-                fprintf(cmd_pipe, "ui_print %s\n", line);
-                line = strtok(NULL, "\n");
+                fprintf(cmd_pipe, "ui_print %s\n", line.c_str());
             }
             fprintf(cmd_pipe, "ui_print\n");
         }
@@ -189,7 +187,6 @@
             }
         }
 
-        free(state.errmsg);
         return 7;
     } else {
         fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result);