/* Log information about external modification of a process, * using MessageTracer formatting. Assumes that both the caller * and target are appropriately locked. * Currently prints following information - * 1. Caller process name (truncated to 16 characters) * 2. Caller process Mach-O UUID * 3. Target process name (truncated to 16 characters) * 4. Target process Mach-O UUID */ void fslog_extmod_msgtracer(proc_t caller, proc_t target) { if ((caller != PROC_NULL) && (target != PROC_NULL)) { /* * Print into buffer large enough for "ThisIsAnApplicat(BC223DD7-B314-42E0-B6B0-C5D2E6638337)", * including space for escaping, and NUL byte included in sizeof(uuid_string_t). */ uuid_string_t uuidstr; char c_name[2*MAXCOMLEN + 2 /* () */ + sizeof(uuid_string_t)]; char t_name[2*MAXCOMLEN + 2 /* () */ + sizeof(uuid_string_t)]; strlcpy(c_name, caller->p_comm, sizeof(c_name)); uuid_unparse_upper(caller->p_uuid, uuidstr); strlcat(c_name, "(", sizeof(c_name)); strlcat(c_name, uuidstr, sizeof(c_name)); strlcat(c_name, ")", sizeof(c_name)); if (0 != escape_str(c_name, strlen(c_name), sizeof(c_name))) { return; } strlcpy(t_name, target->p_comm, sizeof(t_name)); uuid_unparse_upper(target->p_uuid, uuidstr); strlcat(t_name, "(", sizeof(t_name)); strlcat(t_name, uuidstr, sizeof(t_name)); strlcat(t_name, ")", sizeof(t_name)); if (0 != escape_str(t_name, strlen(t_name), sizeof(t_name))) { return; } #if DEBUG printf("EXTMOD: %s(%d) -> %s(%d)\n", c_name, proc_pid(caller), t_name, proc_pid(target)); #endif kern_asl_msg(LOG_DEBUG, "messagetracer", 5, "com.apple.message.domain", "com.apple.kernel.external_modification", /* 0 */ "com.apple.message.signature", c_name, /* 1 */ "com.apple.message.signature2", t_name, /* 2 */ "com.apple.message.result", "noop", /* 3 */ "com.apple.message.summarize", "YES", /* 4 */ NULL); } }
static void fr_command_zip_delete (FrCommand *comm, const char *from_file, GList *file_list) { GList *scan; fr_process_set_out_line_func (FR_COMMAND (comm)->process, process_line__common, comm); fr_process_begin_command (comm->process, "zip"); fr_process_add_arg (comm->process, "-d"); fr_process_add_arg (comm->process, comm->filename); for (scan = file_list; scan; scan = scan->next) { char *escaped; escaped = escape_str (scan->data, ZIP_SPECIAL_CHARACTERS); fr_process_add_arg (comm->process, escaped); g_free (escaped); } fr_process_end_command (comm->process); }
/* write config key/value pair to goaccessrc */ int write_conf_file (void) { char *path = NULL, *user_home = NULL, *log_format = NULL; FILE *file; if (conf.iconfigfile != NULL) path = alloc_string (conf.iconfigfile); else { user_home = getenv ("HOME"); if (user_home == NULL) return 1; path = xmalloc (snprintf (NULL, 0, "%s/.goaccessrc", user_home) + 1); sprintf (path, "%s/.goaccessrc", user_home); } file = fopen (path, "w"); /* no file available */ if (file == NULL) { free (path); return 1; } /* color scheme */ fprintf (file, "color_scheme %d\n", conf.color_scheme); /* date format */ if (tmp_date_format) fprintf (file, "date_format %s\n", tmp_date_format); else fprintf (file, "date_format %s\n", conf.date_format); if (tmp_date_format) free (tmp_date_format); /* log format */ if (tmp_log_format) log_format = tmp_log_format; else log_format = escape_str (conf.log_format); fprintf (file, "log_format %s\n", log_format); if (log_format != NULL) free (log_format); /* set target log file */ if (conf.ifile) fprintf (file, "log_file %s", conf.ifile); fclose (file); if (conf.date_format) free (conf.date_format); if (conf.log_format) free (conf.log_format); free (path); return 0; }
// Converte o arquivo pet_db.txt para SQL. void convert_pet_db(void) { FILE *fread, *fwrite; char line[1024], path[256]; int count = 0, i; sprintf(path, "%s", "db/pet_db.txt"); if (!(fread = fopen(path, "r"))) return; fwrite = fopen("sql/pet_db.sql", "w+"); while (fgets(line, sizeof(line), fread) != NULL) { char *token, **script, buf[1024], write[1024], *pos = buf; if ((line[0] == '/' && line[1] == '/') || line[0] == '\n') continue; line[strlen(line)-1] = '\0'; explode(&script, (char *)line, '{'); token = strtok(line, ","); for (i = 0; i < 22; i++) { if (i) { pos += sprintf(pos, ","); } if (i < 20) pos += ((i == 1 || i == 2)) ? sprintf(pos, "'%s'", escape_str(token)) : sprintf(pos, "%s", token); else pos += (i == 21) ? sprintf(pos, "'{%s'", escape_str(script[2])) : sprintf(pos, "'{%s'", replace_str(escape_str(script[1]), "},", "}")); token = strtok(NULL, ","); } snprintf(write, sizeof(write), "REPLACE INTO pet_db VALUES(%s);\n", buf); fprintf(fwrite, write); count++; } show_message(LIGHT_GREEN, "File %s successfully converted! rows affected: %d\n", path, count); fclose(fread); fclose(fwrite); file_count++; }
/* Escape a time format string. * * If no conf.date_format is given, NULL is returned. * On success, the newly escaped allocated string is returned. */ static char * get_input_time_format (void) { char *time_format = NULL; if (conf.time_format) time_format = escape_str (conf.time_format); return time_format; }
/* Escape a log format string. * * If no conf.date_format is given, NULL is returned. * On success, the newly escaped allocated string is returned. */ static char * get_input_log_format (void) { char *log_format = NULL; if (conf.log_format) log_format = escape_str (conf.log_format); return log_format; }
/* Escape a date format string. * * If no conf.date_format is given, NULL is returned. * On success, the newly escaped allocated string is returned. */ static char * get_input_date_format (void) { char *date_format = NULL; if (conf.date_format) date_format = escape_str (conf.date_format); return date_format; }
/* escape an argv or environment string array */ int escape_strlist(char *dst, const char **src, size_t n) { size_t i = 0; while (*src) { i += escape_str(dst + i, *src, n - i); if ((n - i > 1) && (*(src + 1))) dst[i++] = ' '; src++; } return i; }
static int auth_ldap_do(const char *user, const char *pass, int (*callback)(struct authinfo *, void *), void *arg, const char *newpass) { char *q; int i; q=escape_str(user); if (!q) return (auth_ldap_do2(user, pass, callback, arg, newpass)); i=auth_ldap_do2(q, pass, callback, arg, newpass); free(q); return (i); }
static void fr_command_unarchiver_extract (FrCommand *comm, const char *from_file, GList *file_list, const char *dest_dir, gboolean overwrite, gboolean skip_older, gboolean junk_paths) { FrCommandUnarchiver *unar_comm = FR_COMMAND_UNARCHIVER (comm); GList *scan; unar_comm->n_line = 0; fr_process_use_standard_locale (comm->process, TRUE); fr_process_set_out_line_func (comm->process, process_line__extract, comm); fr_process_begin_command (comm->process, "unar"); if (overwrite) fr_process_add_arg (comm->process, "-f"); else fr_process_add_arg (comm->process, "-s"); fr_process_add_arg (comm->process, "-D"); if ((comm->password != NULL) && (comm->password[0] != '\0')) fr_process_add_arg_concat (comm->process, "-password="******"-output-directory=", dest_dir, NULL); fr_process_add_arg (comm->process, comm->filename); for (scan = file_list; scan; scan = scan->next) { char *escaped; escaped = escape_str (scan->data, "["); fr_process_add_arg (comm->process, escaped); g_free (escaped); } fr_process_end_command (comm->process); }
// Converte o arquivo mob_skill_db.txt para SQL. void convert_mob_skill_db(void) { FILE *fread, *fwrite; char line[1024], path[256]; int count = 0, i; sprintf(path, "%s", "db/mob_skill_db.txt"); if (!(fread = fopen(path, "r"))) return; fwrite = fopen("sql/conversor/mob_skill_db.sql", "w+"); while (fgets(line, sizeof(line), fread) != NULL) { char *token, buf[1024], write[1024], *pos = buf; if ((line[0] == '/' && line[1] == '/') || line[0] == '\n') continue; line[strlen(line)-1] = '\0'; token = strtok(line, ","); for (i = 0; i < 19; i++) { if (i) { pos += sprintf(pos, ","); } if (i > 0) pos += (token == NULL) ? sprintf(pos, "%s", "NULL") : sprintf(pos, "'%s'", escape_str(token)); else pos += sprintf(pos, "%d", atoi(token)); token = strtok(NULL, ","); } snprintf(write, sizeof(write), "REPLACE INTO mob_skill_db VALUES(%s);\n", buf); fprintf(fwrite, write); count++; } ShowStatus("Arquivo %s convertido com sucesso! linhas afetadas: %d\n", path, count); fclose(fread); fclose(fwrite); file_count++; }
static void fr_command_zip_extract (FrCommand *comm, const char *from_file, GList *file_list, const char *dest_dir, gboolean overwrite, gboolean skip_older, gboolean junk_paths) { GList *scan; fr_process_set_out_line_func (FR_COMMAND (comm)->process, process_line__common, comm); fr_process_begin_command (comm->process, "unzip"); if (dest_dir != NULL) { fr_process_add_arg (comm->process, "-d"); fr_process_add_arg (comm->process, dest_dir); } if (overwrite) fr_process_add_arg (comm->process, "-o"); else fr_process_add_arg (comm->process, "-n"); if (skip_older) fr_process_add_arg (comm->process, "-u"); if (junk_paths) fr_process_add_arg (comm->process, "-j"); add_password_arg (comm, comm->password); fr_process_add_arg (comm->process, "--"); fr_process_add_arg (comm->process, comm->filename); for (scan = file_list; scan; scan = scan->next) { char *escaped; escaped = escape_str (scan->data, ZIP_SPECIAL_CHARACTERS); fr_process_add_arg (comm->process, escaped); g_free (escaped); } fr_process_end_command (comm->process); }
// Converte o arquivo item_combo_db.txt para SQL. void convert_item_combo_db(void) { FILE *fread, *fwrite; char line[1024], path[256]; int count = 0; sprintf(path, "%s", "db/item_combo_db.txt"); if (!(fread = fopen(path, "r"))) return; fwrite = fopen("sql/conversor/item_combo_db.sql", "w+"); while (fgets(line, sizeof(line), fread) != NULL) { char *token, write[1024], *row[2]; if ((line[0] == '/' && line[1] == '/') || line[0] == '\n') continue; line[strlen(line)-1] = '\0'; token = line; while (isspace(*token)) ++token; row[0] = token; token = strchr(token,','); *token = '\0'; token += 1; row[1] = escape_str(token); snprintf(write, sizeof(write), "REPLACE INTO item_combo_db VALUES('%s','%s');\n", row[0], row[1]); fprintf(fwrite, write); count++; } ShowStatus("Arquivo %s convertido com sucesso! linhas afetadas: %d\n", path, count); fclose(fread); fclose(fwrite); file_count++; }
// Converte o arquivo mob_classchange.txt para SQL. void convert_mob_classchange_db(void) { FILE *fread, *fwrite; char line[1024], path[256]; int count = 0, i; sprintf(path, "%s", "db/mob_classchange.txt"); if (!(fread = fopen(path, "r"))) return; fwrite = fopen("sql/mob_classchange.sql", "w+"); while (fgets(line, sizeof(line), fread) != NULL) { char *token, buf[1024], write[1024], *pos = buf; if ((line[0] == '/' && line[1] == '/') || line[0] == '\n') continue; line[strlen(line)-1] = '\0'; token = strtok(line, ","); for (i = 0; i < 3; i++) { if (i) { pos += sprintf(pos, ","); } pos += (i == 1) ? sprintf(pos, "'%s'", escape_str(token)) : sprintf(pos, "%s", token); token = strtok(NULL, ","); } snprintf(write, sizeof(write), "REPLACE INTO mob_classchange_db VALUES(%s);\n", buf); fprintf(fwrite, write); count++; } show_message(LIGHT_GREEN, "File %s successfully converted! rows affected: %d\n", path, count); fclose(fread); fclose(fwrite); file_count++; }
/* Initialise slots */ void setup_slots(const char *str, char ** args, int n_args) { int i; n_slots = 1; /* default to 1 slot */ /* On platforms that can report the number of CPUs this way, use that as a default. */ #if defined(_SC_NPROCESSORS_ONLN) n_slots = sysconf(_SC_NPROCESSORS_ONLN); if (trace) fprintf (trace, "forkargs: defaulting to %d slots\n", n_slots); #endif slots = calloc (sizeof (Slot), n_slots); for (i = 0; i < n_slots; i++) { slots[i].hostname = NULL; slots[i].cpid = -1; slots[i].arg = NULL; slots[i].args = args; slots[i].n_args = n_args; } /* Parse the slots string and set up additional slots. */ if (str) { const char *c = str; n_slots = 0; while (*c) { int num_slots = 1; char hostname[BUFSIZ] = "localhost"; char working_dir[BUFSIZ] = ""; while (*c && isspace(*c)) c++; /* int '*' hostname ? */ if (*c && isdigit(*c)) { const char *c2 = c; char num[BUFSIZ]; i = 0; while (*c2 && isdigit(*c2)) num[i++ % BUFSIZ] = *c2++; num[i++] = '\0'; while (*c2 && isspace(*c2)) c2++; if (*c2 && *c2 == '*') { num_slots = atol(num); c = c2+1; while (*c && isspace(*c)) c++; } else if (!*c2 || *c2 == ',') { num_slots = atol (num); c = c2; /* don't skip the ',' if there is one. */ } } if (*c && *c != ',' && *c != ':') { /* Hostname */ i = 0; while (*c && (isalnum(*c) || *c == '-' || *c == '.' || *c == '@')) hostname[i++] = *c++; hostname[i++] = '\0'; if (i == 1) { fprintf (stderr, "Bad hostname: '%s'\n", c); exit(2); } } if (*c == ':') { /* Working directory */ c++; i = 0; while (*c && *c != ',') working_dir[i++] = *c++; working_dir[i++] = '\0'; } /* Set up NUM_SLOTS slots for this entry. */ for (i = 0; i < num_slots; i++) { int a, ai; char **slot_args; char *host = NULL; char *wd = NULL; if (strcmp(hostname, "localhost") && strcmp(hostname, "-")) host = strdup(hostname); if (working_dir[0]) { wd = working_dir_str(working_dir, host != NULL); } a = 0; slot_args = calloc (n_args + 2 + 2 + 3, sizeof(*slot_args)); /* For remote slots, we set up some arguments appropriately here: constructing the SSH command arguments so they're ready to go, rather than deferring this until we're ready to exec(). */ if (host) { slot_args[a++] = "ssh"; slot_args[a++] = host; if (wd) { slot_args[a++] = "cd"; slot_args[a++] = escape_str(wd); slot_args[a++] = ";"; } for (ai = 0; ai < n_args; ai++) slot_args[a++] = escape_str (args[ai]); } else for (ai = 0; ai < n_args; ai++) slot_args[a++] = args[ai]; slots = realloc(slots, sizeof(*slots) * (++n_slots)); slots[n_slots -1].hostname = host; slots[n_slots -1].cpid = -1; slots[n_slots -1].args = slot_args; slots[n_slots -1].n_args = a; slots[n_slots -1].arg = NULL; slots[n_slots -1].remote_slot = host != NULL; slots[n_slots -1].working_dir = wd; } while (*c && isspace(*c)) c++; /* Comma separates slots */ if (*c) if (*c == ',' && *(c + 1)) c++; /* and then continue */ else { fprintf (stderr, "Bad slot description at '%s'\n", c); exit (1); } else break; } /* while (*c) */ } /* Synchronise working directory */ if (sync_working_dirs) { char **args; char *local_args[] = { "rsync", "--delete", "-ravu", "./", NULL, NULL }; const int local_args_dest_i = 4; char *remote_args[] = { "rsync", "--delete", "-e", "ssh", "-ravu", "./", NULL, NULL }; const int remote_args_dest_i = 6; assert(local_args[local_args_dest_i] == NULL && local_args[local_args_dest_i+1] == NULL); assert(remote_args[remote_args_dest_i] == NULL && remote_args[remote_args_dest_i+1] == NULL); /* Check that all slots have a specified working directory */ for (i = 0; i < n_slots; i++) { if (slots[i].working_dir == NULL) { fprintf (stderr, ("forkargs: must specify working directory " "when synchronising work dirs\n")); } } for (i = 0; i < n_slots; i++) { int j; /* Check that we haven't already encountered this host:dir pair before. */ for (j = 0; j < i; j++) if (!strcmp (slots[i].hostname, slots[j].hostname) && !strcmp (slots[i].working_dir, slots[j].working_dir)) break; if (i != j) continue; assert (0); } } }
/* render config log date/format dialog */ int verify_format (GLog * logger, GSpinner * spinner) { GMenu *menu; WINDOW *win; char *cstm_log, *cstm_date; int c, quit = 1; int invalid = 1; int y, x, h = CONF_WIN_H, w = CONF_WIN_W; int w2 = w - 2; size_t i, n, sel; /* conf dialog menu options */ const char *choices[] = { "Common Log Format (CLF)", "Common Log Format (CLF) with Virtual Host", "NCSA Combined Log Format", "NCSA Combined Log Format with Virtual Host", "W3C", "CloudFront (Download Distribution)" }; n = ARRAY_SIZE (choices); getmaxyx (stdscr, y, x); win = newwin (h, w, (y - h) / 2, (x - w) / 2); keypad (win, TRUE); wborder (win, '|', '|', '-', '-', '+', '+', '+', '+'); /* create a new instance of GMenu and make it selectable */ menu = new_gmenu (win, CONF_MENU_H, CONF_MENU_W, CONF_MENU_Y, CONF_MENU_X); menu->size = n; menu->selectable = 1; /* add items to GMenu */ menu->items = (GItem *) xcalloc (n, sizeof (GItem)); for (i = 0; i < n; ++i) { menu->items[i].name = alloc_string (choices[i]); sel = get_selected_format_idx (); menu->items[i].checked = sel == i ? 1 : 0; } post_gmenu (menu); draw_header (win, "Log Format Configuration", " %s", 1, 1, w2, 1, 0); mvwprintw (win, 2, 2, "[SPACE] to toggle - [ENTER] to proceed"); /* set log format from goaccessrc if available */ draw_header (win, "Log Format - [c] to add/edit format", " %s", 11, 1, w2, 1, 0); if (conf.log_format) { log_format = escape_str (conf.log_format); mvwprintw (win, 12, 2, "%.*s", CONF_MENU_W, log_format); if (conf.log_format) free (conf.log_format); } /* set date format from goaccessrc if available */ draw_header (win, "Date Format - [d] to add/edit format", " %s", 14, 1, w2, 1, 0); if (conf.date_format) { date_format = escape_str (conf.date_format); mvwprintw (win, 15, 2, "%.*s", CONF_MENU_W, date_format); if (conf.date_format) free (conf.date_format); } wrefresh (win); while (quit) { c = wgetch (stdscr); switch (c) { case KEY_DOWN: gmenu_driver (menu, REQ_DOWN); draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); break; case KEY_UP: gmenu_driver (menu, REQ_UP); draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); break; case 32: /* space */ gmenu_driver (menu, REQ_SEL); if (date_format) free (date_format); if (log_format) free (log_format); for (i = 0; i < n; ++i) { if (menu->items[i].checked != 1) continue; date_format = get_selected_date_str (i); log_format = get_selected_format_str (i); draw_header (win, date_format, " %s", 15, 1, CONF_MENU_W, 0, 0); draw_header (win, log_format, " %s", 12, 1, CONF_MENU_W, 0, 0); break; } break; case 99: /* c */ /* clear top status bar */ draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); wmove (win, 12, 2); /* get input string */ cstm_log = input_string (win, 12, 2, 70, log_format, 0, 0); if (cstm_log != NULL && *cstm_log != '\0') { if (log_format) free (log_format); log_format = alloc_string (cstm_log); free (cstm_log); } /* did not set an input string */ else { if (cstm_log) free (cstm_log); if (log_format) { free (log_format); log_format = NULL; } } break; case 100: /* d */ /* clear top status bar */ draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); wmove (win, 15, 0); /* get input string */ cstm_date = input_string (win, 15, 2, 14, date_format, 0, 0); if (cstm_date != NULL && *cstm_date != '\0') { if (date_format) free (date_format); date_format = alloc_string (cstm_date); free (cstm_date); } /* did not set an input string */ else { if (cstm_date) free (cstm_date); if (date_format) { free (date_format); date_format = NULL; } } break; case 274: /* F10 */ case 0x0a: case 0x0d: case KEY_ENTER: /* display status bar error messages */ if (date_format == NULL) draw_header (win, "Select a date format.", "%s", 3, 2, CONF_MENU_W, WHITE_RED, 0); if (log_format == NULL) draw_header (win, "Select a log format.", "%s", 3, 2, CONF_MENU_W, WHITE_RED, 0); if (date_format && log_format) { conf.date_format = unescape_str (date_format); conf.log_format = unescape_str (log_format); /* test log against selected settings */ if (test_format (logger)) { invalid = 1; draw_header (win, "No valid hits.", "%s", 3, 2, CONF_MENU_W, WHITE_RED, 0); free (conf.log_format); free (conf.date_format); } /* valid data, reset logger & start parsing */ else { reset_struct (logger); /* start spinner thread */ spinner->win = win; spinner->y = 3; spinner->x = 2; spinner->spin_x = CONF_MENU_W; spinner->w = CONF_MENU_W; spinner->color = BLACK_CYAN; ui_spinner_create (spinner); invalid = 0; quit = 0; } } break; case KEY_RESIZE: case 'q': quit = 0; break; } pthread_mutex_lock (&spinner->mutex); wrefresh (win); pthread_mutex_unlock (&spinner->mutex); } /* clean stuff up */ for (i = 0; i < n; ++i) free (menu->items[i].name); free (menu->items); free (menu); return invalid ? 1 : 0; }
/* escape with backslash the file name. */ char* shell_escape (const char *filename) { return escape_str (filename, "$'`\"\\!?* ()[]&|:;<>#"); }
static void launch_text_generator (text_data *d) { XtAppContext app = XtDisplayToApplicationContext (d->dpy); char buf[255]; const char *oprogram = d->program; char *s; size_t oprogram_size = strlen(oprogram); size_t len; # ifdef HAVE_COCOA /* /bin/sh on OS X 10.10 wipes out the PATH. */ const char *path = getenv("PATH"); size_t cmd_capacity = (oprogram_size + strlen(path)) * 2 + 100; char *cmd = s = malloc (cmd_capacity); strcpy (s, "export PATH="); s += strlen (s); s = escape_str (s, path); strcpy (s, "; "); s += strlen (s); # else char *cmd = s = malloc ((strlen(oprogram)) * 2 + 100); # endif strcpy (s, "( "); strcat (s, oprogram); s += strlen (s); /* Kludge! Special-case "xscreensaver-text" to tell it how wide the screen is. We used to do this by just always feeding `program' through sprintf() and setting the default value to "xscreensaver-text --cols %d", but that makes things blow up if someone ever uses a --program that includes a % anywhere. */ len = 17; /* strlen("xscreensaver-text") */ if (oprogram_size >= len && !memcmp (oprogram, "xscreensaver-text", len) && (oprogram[len] == ' ' || !oprogram[len])) { /* strstr is sloppy here. Technically, we should be parsing the command line to identify flags and their arguments. This will blow up if one of those pesky end users could set .textLiteral to "--cols". */ if (d->char_w && !strstr (oprogram, "--cols ")) sprintf (s, " --cols %d", d->char_w); if (d->max_lines && !strstr (oprogram, "--lines ")) sprintf (s, " --lines %d", d->max_lines); s += strlen(s); # ifdef HAVE_COCOA /* Also special-case "xscreensaver-text" to specify the text content on the command line. defaults(1) on macOS doesn't know about the default screenhack resources that don't make it into the ~/Library/Preferences/ByHost/org.jwz.xscreensaver.*.plist. */ char *text_mode_flag = " --date"; char *value_res = NULL; char *text_mode = get_string_resource (d->dpy, "textMode", "String"); if (text_mode) { if (!strcmp (text_mode, "1") || !strcmp (text_mode, "literal")) { text_mode_flag = " --text"; value_res = "textLiteral"; } else if (!strcmp (text_mode, "2") || !strcmp (text_mode, "file")) { text_mode_flag = " --file"; value_res = "textFile"; } else if (!strcmp (text_mode, "3") || !strcmp (text_mode, "url")) { text_mode_flag = " --url"; value_res = "textURL"; } else if (!strcmp (text_mode, "4") || !strcmp (text_mode, "program")) { text_mode_flag = " --program"; value_res = "textProgram"; } free (text_mode); } strcpy (s, text_mode_flag); s += strlen (s); if (value_res) { size_t old_s = s - cmd; char *value = get_string_resource (d->dpy, value_res, ""); if (!value) value = strdup(""); cmd = realloc(cmd, cmd_capacity + strlen(value) * 2); s = cmd + old_s; *s = ' '; ++s; s = escape_str(s, value); free(value); } # endif /* HAVE_COCOA */ } strcpy (s, " ) 2>&1"); # ifdef DEBUG fprintf (stderr, "%s: textclient: launch %s: %s\n", progname, (d->pty_p ? "pty" : "pipe"), cmd); # endif #ifdef HAVE_FORKPTY if (d->pty_p) { int fd; struct winsize ws; ws.ws_col = d->char_w; ws.ws_row = d->char_h; ws.ws_xpixel = d->pix_w; ws.ws_ypixel = d->pix_h; d->pipe = 0; # ifdef HAVE_COCOA if (getenv ("MallocScribble")) /* This is here to stop me from wasting my time trying to answer this question the next time I forget about it. */ fprintf (stderr, "%s: WARNING: forkpty hates 'Enable Guard Malloc'\n", progname); # endif if ((d->pid = forkpty(&fd, NULL, NULL, &ws)) < 0) { /* Unable to fork */ sprintf (buf, "%.100s: forkpty", progname); perror (buf); } else if (!d->pid) { /* This is the child fork. */ char *av[10]; int i = 0; if (putenv ("TERM=vt100")) abort(); av[i++] = "/bin/sh"; av[i++] = "-c"; av[i++] = cmd; av[i] = 0; # ifdef DEBUG { int j; fprintf (stderr, "%s: textclient: execvp:", progname); for (j = 0; j < i; j++) fprintf (stderr, " %s", av[j]); fprintf (stderr, "\n"); } # endif execvp (av[0], av); sprintf (buf, "%.100s: %.100s", progname, oprogram); perror (buf); exit (1); } else { /* This is the parent fork. */ if (d->pipe) abort(); d->pipe = fdopen (fd, "r+"); if (d->pipe_id) abort(); d->pipe_id = XtAppAddInput (app, fileno (d->pipe), (XtPointer) (XtInputReadMask | XtInputExceptMask), subproc_cb, (XtPointer) d); # ifdef DEBUG fprintf (stderr, "%s: textclient: pid = %d\n", progname, d->pid); # endif } } else #endif /* HAVE_FORKPTY */ { /* don't mess up controlling terminal on "-pipe -program tcsh". */ static int protected_stdin_p = 0; if (! protected_stdin_p) { fclose (stdin); open ("/dev/null", O_RDWR); /* re-allocate fd 0 */ protected_stdin_p = 1; } if (d->pipe) abort(); if ((d->pipe = popen (cmd, "r"))) { if (d->pipe_id) abort(); d->pipe_id = XtAppAddInput (app, fileno (d->pipe), (XtPointer) (XtInputReadMask | XtInputExceptMask), subproc_cb, (XtPointer) d); # ifdef DEBUG fprintf (stderr, "%s: textclient: popen\n", progname); # endif } else { sprintf (buf, "%.100s: %.100s", progname, cmd); perror (buf); } } free (cmd); }
int main (int argc, char *argv[]) { char *str; char **args; int first_arg; int line_arg; int n_active = 0; int n_faulted = 0; int cpid; int i; int slot; int error_encountered = 0; /* Defaults from environment */ str = getenv("FORKARGS_J"); if (str) slots_string = str; in_arguments = stdin; parse_args(argc, argv, &first_arg); /* Collect command arguments */ args = calloc (argc - first_arg + 2, sizeof (char *)); for (i = 0; i < argc - first_arg; i++) args[i] = argv[i + first_arg]; line_arg = i; setup_slots (slots_string, args, line_arg); if (!skip_slot_test) test_slots (argc, argv); /* Count the number of faulted slots. */ for (i = 0; i < n_slots; i++) if (slots[i].faulted) n_faulted++; if (n_slots <= 0) { fprintf (stderr, "Bad process limit (%d)\n", n_slots); exit (2); } if (trace) print_slots(trace); signal (SIGINT, interrupt); if (trace) fprintf (trace, "forkargs: processing lines\n"); while (!interrupted && (!error_encountered || continue_on_error) && (str = read_line (in_arguments)) && !interrupted) { /* Strip newline */ char *nl = strstr (str, "\n"); if (nl) *nl = '\0'; /* Wait for a free slot */ if (n_active + n_faulted >= n_slots) { int status; if (trace) fprintf (trace, ("%s: %d processes active (+%d faulted), " "waiting for one to finish\n"), argv[0], n_active, n_faulted); /* Wait for one to exit before proceeding */ cpid = wait (&status); if (cpid == -1) { perror(argv[0]); exit(1); } if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { if (verbose) fprintf (stderr, "forkargs: (%s) exited with return code %d\n", (slots[slot].hostname ? slots[slot].hostname : "localhost"), WEXITSTATUS(status)); error_encountered = 1; } if (trace) fprintf (trace, "%s: child %d terminated with status %d (rc %d)\n", argv[0], cpid, status, WEXITSTATUS(status)); /* Scan slot table and remove entry */ for (i = 0; i < n_slots; i++) if (cpid == slots[i].cpid) { slots[i].cpid = -1; if (slots[i].arg) free (slots[i].arg); break; } if (i == n_slots) { fprintf (stderr, "%s: cannot find child %d in slot table\n", argv[0], cpid); exit(1); } n_active--; } /* Scan the slot table to find a free slot. */ for (i = 0; i < n_slots; i++) if (slots[i].cpid == -1 && !slots[i].faulted) break; if (i == n_slots) { fprintf (stderr, "%s: cannot find a free slot. Miscounted?\n", argv[0]); exit(1); } slot = i; cpid = fork(); if (cpid) { /* parent */ slots[i].cpid = cpid; slots[i].arg = str; if (trace) { fprintf (trace, "Inserted in slot %d.\n", slot); print_slots(trace); } n_active++; if (trace) fprintf (trace, "%s: started child %d\n", argv[0], cpid); } else { /* Child. Execute the process. */ int status; /* Construct exec parameters */ if (slots[slot].remote_slot) slots[slot].args[slots[slot].n_args] = escape_str (str); else slots[slot].args[slots[slot].n_args] = str; slots[slot].args[slots[slot].n_args+1] = NULL; if (trace) { fprintf (trace, "%s: exec ", argv[0]); for (i = 0; i <= slots[slot].n_args; i++) fprintf (trace, "'%s' ", slots[slot].args[i]); fprintf (trace, "\n"); } if (verbose) { fprintf (stderr, "forkargs: (%s) ", (slots[slot].hostname ? slots[slot].hostname : "localhost")); for (i = 0; i <= slots[slot].n_args; i++) if (strstr(slots[slot].args[i], " ") == NULL) /* No real need to print anything fancy */ fprintf (stderr, "%s ", slots[slot].args[i]); else if (strstr(slots[slot].args[i], "'") == NULL) /* Print with '' if that'll look okay */ fprintf (stderr, "'%s' ", slots[slot].args[i]); else { /* Escape the whole thing. Looks ugly, but should be rare. */ char *e = escape_str (slots[slot].args[i]); fprintf (stderr, "%s ", e); free (e); } fprintf (stderr, "\n"); } /* Close parent's stdin */ close(STDIN_FILENO); open("/dev/null", O_RDONLY); /* Change working directory, but only if it's a local slot! */ if (slots[slot].working_dir != NULL && slots[slot].hostname == NULL) { if (trace) fprintf (trace, "forkargs: chdir to '%s'\n", slots[slot].working_dir); if (chdir(slots[slot].working_dir) == -1) { perror(slots[slot].args[0]); exit(1); } } status = execvp(slots[slot].args[0], slots[slot].args); if (status == -1) { perror(slots[slot].args[0]); exit(1); } else { exit(0); } } } if (trace) fprintf (trace, "forkargs: finished processing lines\n"); /* Wait for all children to terminate */ while (n_active) { int status; if (trace) fprintf (trace, "%s: waiting for %d children\n", argv[0], n_active); cpid = wait(&status); if (trace) fprintf (trace, "%s: child %d terminated\n", argv[0], cpid); n_active --; if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { if (verbose) fprintf (stderr, "forkargs: (%s) exited with return code %d\n", slots[slot].hostname ? slots[slot].hostname : "localhost", WEXITSTATUS(status)); error_encountered = 1; } /* Clear out the slot table */ for (i = 0; i < n_slots; i++) if (slots[i].cpid == cpid) { slots[i].cpid = -1; free (slots[i].arg); if (trace) { fprintf (trace, "Removed process from slot table entry %d\n", i); print_slots(trace); break; } } } return error_encountered? EXIT_FAILURE : EXIT_SUCCESS; }