Exemplo n.º 1
0
static int smtp_checkp(const char *fmt, const char *param, int code)
{
	char *answer;
	char *msg = send_mail_command(fmt, param);
	// read stdin
	// if the string has a form NNN- -- read next string. E.g. EHLO response
	// parse first bytes to a number
	// if code = -1 then just return this number
	// if code != -1 then checks whether the number equals the code
	// if not equal -> die saying msg
	while ((answer = xmalloc_fgetline(stdin)) != NULL) {
		if (verbose)
			bb_error_msg("recv:'%.*s'", (int)(strchrnul(answer, '\r') - answer), answer);
		if (strlen(answer) <= 3 || '-' != answer[3])
			break;
		free(answer);
	}
	if (answer) {
		int n = atoi(answer);
		if (timeout)
			alarm(0);
		free(answer);
		if (-1 == code || n == code) {
			free(msg);
			return n;
		}
	}
	bb_error_msg_and_die("%s failed", msg);
}
Exemplo n.º 2
0
static bool ignored_problems_file_contains(ignored_problems_t *set,
        const char *problem_id, const char *uuid, const char *duphash,
        FILE **out_fp, const char *mode)
{
    bool found = false;
    FILE *fp = fopen(set->ign_set_file_path, mode);
    if (!fp)
    {
        pwarn_msg("Can't open ignored problems '%s' in mode '%s'", set->ign_set_file_path, mode);
        goto ret_contains_end;
    }

    unsigned line_num = 0;
    while (!found)
    {
        char *line = xmalloc_fgetline(fp);
        if (!line)
            break;
        ++line_num;
        found = ignored_problems_eq(set, problem_id, uuid, duphash, line, line_num);
        free(line);
    }

 ret_contains_end:
    if (out_fp)
        *out_fp = fp;
    else if (fp)
        fclose(fp);

    return found;
}
Exemplo n.º 3
0
int cryptpw_main(int argc UNUSED_PARAM, char **argv)
{
	/* Supports: cryptpw -m sha256 PASS 'rounds=999999999$SALT' */
	char salt[MAX_PW_SALT_LEN + sizeof("rounds=999999999$")];
	char *salt_ptr;
	char *password;
	const char *opt_m, *opt_S;
	int fd;

#if ENABLE_LONG_OPTS
	static const char mkpasswd_longopts[] ALIGN1 =
		"stdin\0"       No_argument       "s"
		"password-fd\0" Required_argument "P"
		"salt\0"        Required_argument "S"
		"method\0"      Required_argument "m"
	;
	applet_long_options = mkpasswd_longopts;
#endif
	fd = STDIN_FILENO;
	opt_m = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO;
	opt_S = NULL;
	/* at most two non-option arguments; -P NUM */
	opt_complementary = "?2";
	getopt32(argv, "sP:+S:m:a:", &fd, &opt_S, &opt_m, &opt_m);
	argv += optind;

	/* have no idea how to handle -s... */

	if (argv[0] && !opt_S)
		opt_S = argv[1];

	salt_ptr = crypt_make_pw_salt(salt, opt_m);
	if (opt_S)
		/* put user's data after the "$N$" prefix */
		safe_strncpy(salt_ptr, opt_S, sizeof(salt) - (sizeof("$N$")-1));

	xmove_fd(fd, STDIN_FILENO);

	password = argv[0];
	if (!password) {
		/* Only mkpasswd, and only from tty, prompts.
		 * Otherwise it is a plain read. */
		password = (ENABLE_MKPASSWD && isatty(STDIN_FILENO) && applet_name[0] == 'm')
			? bb_ask_stdin("Password: ")
			: xmalloc_fgetline(stdin)
		;
		/* may still be NULL on EOF/error */
	}

	if (password)
		puts(pw_encrypt(password, salt, 1));

	return EXIT_SUCCESS;
}
Exemplo n.º 4
0
static void bb_dump_addfile(dumper_t *dumper, char *name)
{
	char *p;
	FILE *fp;
	char *buf;

	fp = xfopen_for_read(name);
	while ((buf = xmalloc_fgetline(fp)) != NULL) {
		p = skip_whitespace(buf);
		if (*p && (*p != '#')) {
			bb_dump_add(dumper, p);
		}
		free(buf);
	}
	fclose(fp);
}
Exemplo n.º 5
0
int cryptpw_main(int argc UNUSED_PARAM, char **argv)
{
	char salt[MAX_PW_SALT_LEN];
	char *salt_ptr;
	const char *opt_m, *opt_S;
	int fd;

#if ENABLE_LONG_OPTS
	static const char mkpasswd_longopts[] ALIGN1 =
		"stdin\0"       No_argument       "s"
		"password-fd\0" Required_argument "P"
		"salt\0"        Required_argument "S"
		"method\0"      Required_argument "m"
	;
	applet_long_options = mkpasswd_longopts;
#endif
	fd = STDIN_FILENO;
	opt_m = "d";
	opt_S = NULL;
	/* at most two non-option arguments; -P NUM */
	opt_complementary = "?2:P+";
	getopt32(argv, "sP:S:m:a:", &fd, &opt_S, &opt_m, &opt_m);
	argv += optind;

	/* have no idea how to handle -s... */

	if (argv[0] && !opt_S)
		opt_S = argv[1];

	salt_ptr = crypt_make_pw_salt(salt, opt_m);
	if (opt_S)
		safe_strncpy(salt_ptr, opt_S, sizeof(salt) - (sizeof("$N$")-1));

	xmove_fd(fd, STDIN_FILENO);

	puts(pw_encrypt(
		argv[0] ? argv[0] : (
			/* Only mkpasswd, and only from tty, prompts.
			 * Otherwise it is a plain read. */
			(isatty(STDIN_FILENO) && applet_name[0] == 'm')
			? bb_ask_stdin("Password: ")
			: xmalloc_fgetline(stdin)
		),
		salt, 1));

	return EXIT_SUCCESS;
}
Exemplo n.º 6
0
static void pop3_checkr(const char *fmt, const char *param, char **ret)
{
	const char *msg = command(fmt, param);
	char *answer = xmalloc_fgetline(stdin);
	if (answer && '+' == answer[0]) {
		if (timeout)
			alarm(0);
		if (ret) {
			// skip "+OK "
			memmove(answer, answer + 4, strlen(answer) - 4);
			*ret = answer;
		} else
			free(answer);
		return;
	}
	bb_error_msg_and_die("%s failed: %s", msg, answer);
}
Exemplo n.º 7
0
static llist_t *append_file_list_to_list(llist_t *list)
{
	FILE *src_stream;
	char *line;
	llist_t *newlist = NULL;

	while (list) {
		src_stream = xfopen_for_read(llist_pop(&list));
		while ((line = xmalloc_fgetline(src_stream)) != NULL) {
			/* kill trailing '/' unless the string is just "/" */
			char *cp = last_char_is(line, '/');
			if (cp > line)
				*cp = '\0';
			llist_add_to(&newlist, line);
		}
		fclose(src_stream);
	}
	return newlist;
}
Exemplo n.º 8
0
static void add_user_to_group(char **args,
		const char *path,
		FILE *(*fopen_func)(const char *fileName, const char *mode))
{
	char *line;
	int len = strlen(args[1]);
	llist_t *plist = NULL;
	FILE *group_file;

	group_file = fopen_func(path, "r");

	if (!group_file) return;

	while ((line = xmalloc_fgetline(group_file)) != NULL) {
		/* Find the group */
		if (!strncmp(line, args[1], len)
		 && line[len] == ':'
		) {
			/* Add the new user */
			line = xasprintf("%s%s%s", line,
						last_char_is(line, ':') ? "" : ",",
						args[0]);
		}
		llist_add_to_end(&plist, line);
	}

	if (ENABLE_FEATURE_CLEAN_UP) {
		fclose(group_file);
		group_file = fopen_func(path, "w");
		while ((line = llist_pop(&plist))) {
			if (group_file)
				fprintf(group_file, "%s\n", line);
			free(line);
		}
		if (group_file)
			fclose(group_file);
	} else {
		group_file = fopen_func(path, "w");
		if (group_file)
			while ((line = llist_pop(&plist)))
				fprintf(group_file, "%s\n", line);
	}
}
Exemplo n.º 9
0
void FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filename)
{
	FILE *fp = fopen_or_warn_stdin(filename);
	unsigned N = ns->start;
	char *line;

	while ((line = xmalloc_fgetline(fp)) != NULL) {
		if (ns->all
		 || (ns->nonempty && line[0])
		) {
			printf("%*u%s%s\n", ns->width, N, ns->sep, line);
			N += ns->inc;
		} else if (ns->empty_str)
			fputs(ns->empty_str, stdout);
		free(line);
	}
	ns->start = N;

	fclose(fp);
}
Exemplo n.º 10
0
GList *load_words_from_file(const char* filename)
{
    GList *words_list = NULL;
    GList *file_list = NULL;
    file_list = g_list_prepend(file_list, concat_path_file(CONF_DIR, filename));
    file_list = g_list_prepend(file_list, get_user_config_file_path(filename, /*don't append suffix*/NULL));
    GList *file_list_cur = file_list;

    while(file_list_cur)
    {
        char *cur_file = (char *)file_list_cur->data;
        FILE *fp = fopen(cur_file, "r");
        if (fp)
        {
            /* every line is one word
             */
            char *line;
            while ((line = xmalloc_fgetline(fp)) != NULL)
            {
                //FIXME: works only if the '#' is first char won't work for " #abcd#
                if (line[0] != '#') // if it's not comment
                    words_list = g_list_append(words_list, line);
                else
                    free(line);
            }
            fclose(fp);
        }
        else
        {
            log_warning("Can't open %s", cur_file);
        }

        file_list_cur = g_list_next(file_list_cur);
    }

    list_free_with_free(file_list);

    return words_list;
}
Exemplo n.º 11
0
static int smtp_checkp(const char *fmt, const char *param, int code)
{
	char *answer;
	const char *msg = command(fmt, param);
	// read stdin
	// if the string has a form \d\d\d- -- read next string. E.g. EHLO response
	// parse first bytes to a number
	// if code = -1 then just return this number
	// if code != -1 then checks whether the number equals the code
	// if not equal -> die saying msg
	while ((answer = xmalloc_fgetline(stdin)) != NULL)
		if (strlen(answer) <= 3 || '-' != answer[3])
			break;
	if (answer) {
		int n = atoi(answer);
		if (timeout)
			alarm(0);
		free(answer);
		if (-1 == code || n == code)
			return n;
	}
	bb_error_msg_and_die("%s failed", msg);
}
Exemplo n.º 12
0
int cryptpw_main(int argc UNUSED_PARAM, char **argv)
{
	char salt[sizeof("$N$XXXXXXXX")];
	char *opt_a;

	if (!getopt32(argv, "a:", &opt_a) || opt_a[0] != 'd') {
		salt[0] = '$';
		salt[1] = '1';
		salt[2] = '$';
		crypt_make_salt(salt + 3, 4, 0); /* md5 */
#if TESTING
		strcpy(salt + 3, "ajg./bcf");
#endif
	} else {
		crypt_make_salt(salt, 1, 0);     /* des */
#if TESTING
		strcpy(salt, "a.");
#endif
	}

	puts(pw_encrypt(argv[optind] ? argv[optind] : xmalloc_fgetline(stdin), salt, 1));

	return 0;
}
Exemplo n.º 13
0
int patch_main(int argc UNUSED_PARAM, char **argv)
{
	int opts;
	int reverse, state = 0;
	char *oldname = NULL, *newname = NULL;
	char *opt_p, *opt_i;
	long oldlen = oldlen; /* for compiler */
	long newlen = newlen; /* for compiler */

	INIT_TT();

	opts = getopt32(argv, FLAG_STR, &opt_p, &opt_i);
	argv += optind;
	reverse = opts & FLAG_REVERSE;
	TT.prefix = (opts & FLAG_PATHLEN) ? xatoi(opt_p) : 0; // can be negative!
	TT.filein = TT.fileout = -1;
	if (opts & FLAG_INPUT) {
		xmove_fd(xopen_stdin(opt_i), STDIN_FILENO);
	} else {
		if (argv[0] && argv[1]) {
			xmove_fd(xopen_stdin(argv[1]), STDIN_FILENO);
		}
	}
	if (argv[0]) {
		oldname = xstrdup(argv[0]);
		newname = xstrdup(argv[0]);
	}

	// Loop through the lines in the patch
	for(;;) {
		char *patchline;

		patchline = xmalloc_fgetline(stdin);
		if (!patchline) break;

		// Other versions of patch accept damaged patches,
		// so we need to also.
		if (!*patchline) {
			free(patchline);
			patchline = xstrdup(" ");
		}

		// Are we assembling a hunk?
		if (state >= 2) {
			if (*patchline==' ' || *patchline=='+' || *patchline=='-') {
				dlist_add(&TT.current_hunk, patchline);

				if (*patchline != '+') oldlen--;
				if (*patchline != '-') newlen--;

				// Context line?
				if (*patchline==' ' && state==2) TT.context++;
				else state=3;

				// If we've consumed all expected hunk lines, apply the hunk.

				if (!oldlen && !newlen) state = apply_one_hunk();
				continue;
			}
			fail_hunk();
			state = 0;
			continue;
		}

		// Open a new file?
		if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) {
			char *s, **name = reverse ? &newname : &oldname;
			int i;

			if (*patchline == '+') {
				name = reverse ? &oldname : &newname;
				state = 1;
			}

			finish_oldfile();

			if (!argv[0]) {
				free(*name);
				// Trim date from end of filename (if any).  We don't care.
				for (s = patchline+4; *s && *s!='\t'; s++)
					if (*s=='\\' && s[1]) s++;
				i = atoi(s);
				if (i>1900 && i<=1970)
					*name = xstrdup("/dev/null");
				else {
					*s = 0;
					*name = xstrdup(patchline+4);
				}
			}

			// We defer actually opening the file because svn produces broken
			// patches that don't signal they want to create a new file the
			// way the patch man page says, so you have to read the first hunk
			// and _guess_.

		// Start a new hunk?  Usually @@ -oldline,oldlen +newline,newlen @@
		// but a missing ,value means the value is 1.
		} else if (state == 1 && !strncmp("@@ -", patchline, 4)) {
			int i;
			char *s = patchline+4;

			// Read oldline[,oldlen] +newline[,newlen]

			TT.oldlen = oldlen = TT.newlen = newlen = 1;
			TT.oldline = strtol(s, &s, 10);
			if (*s == ',') TT.oldlen = oldlen = strtol(s+1, &s, 10);
			TT.newline = strtol(s+2, &s, 10);
			if (*s == ',') TT.newlen = newlen = strtol(s+1, &s, 10);

			if (oldlen < 1 && newlen < 1)
				bb_error_msg_and_die("Really? %s", patchline);

			TT.context = 0;
			state = 2;

			// If this is the first hunk, open the file.
			if (TT.filein == -1) {
				int oldsum, newsum, empty = 0;
				char *name;

				oldsum = TT.oldline + oldlen;
				newsum = TT.newline + newlen;

				name = reverse ? oldname : newname;

				// We're deleting oldname if new file is /dev/null (before -p)
				// or if new hunk is empty (zero context) after patching
				if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) {
					name = reverse ? newname : oldname;
					empty++;
				}

				// handle -p path truncation.
				for (i=0, s = name; *s;) {
					if ((option_mask32 & FLAG_PATHLEN) && TT.prefix == i)
						break;
					if (*s++ != '/')
						continue;
					while (*s == '/')
						s++;
						i++;
					name = s;
				}

				if (empty) {
					// File is empty after the patches have been applied
					state = 0;
					if (option_mask32 & FLAG_RMEMPTY) {
						// If flag -E or --remove-empty-files is set
						printf("removing %s\n", name);
						xunlink(name);
					} else {
						printf("patching file %s\n", name);
						xclose(xopen(name, O_WRONLY | O_TRUNC));
					}
				// If we've got a file to open, do so.
				} else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) {
					struct stat statbuf;

					// If the old file was null, we're creating a new one.
					if (!strcmp(oldname, "/dev/null") || !oldsum) {
						printf("creating %s\n", name);
						s = strrchr(name, '/');
						if (s) {
							*s = 0;
							bb_make_directory(name, -1, FILEUTILS_RECUR);
							*s = '/';
						}
						TT.filein = xopen(name, O_CREAT|O_EXCL|O_RDWR);
					} else {
						printf("patching file %s\n", name);
						TT.filein = xopen(name, O_RDONLY);
					}

					TT.tempname = xasprintf("%sXXXXXX", name);
					TT.fileout = xmkstemp(TT.tempname);
					// Set permissions of output file
					fstat(TT.filein, &statbuf);
					fchmod(TT.fileout, statbuf.st_mode);

					TT.linenum = 0;
					TT.hunknum = 0;
				}
			}

			TT.hunknum++;

			continue;
		}

		// If we didn't continue above, discard this line.
		free(patchline);
	}

	finish_oldfile();

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(oldname);
		free(newname);
	}

	return TT.exitval;
}
Exemplo n.º 14
0
int sendmail_main(int argc UNUSED_PARAM, char **argv)
{
	char *opt_connect = opt_connect;
	char *opt_from = NULL;
	char *s;
	llist_t *list = NULL;
	char *host = sane_address(safe_gethostname());
	unsigned nheaders = 0;
	int code;
	enum {
		HDR_OTHER = 0,
		HDR_TOCC,
		HDR_BCC,
	} last_hdr = 0;
	int check_hdr;
	int has_to = 0;

	enum {
	//--- standard options
		OPT_t = 1 << 0,         // read message for recipients, append them to those on cmdline
		OPT_f = 1 << 1,         // sender address
		OPT_o = 1 << 2,         // various options. -oi IMPLIED! others are IGNORED!
		OPT_i = 1 << 3,         // IMPLIED!
	//--- BB specific options
		OPT_w = 1 << 4,         // network timeout
		OPT_H = 1 << 5,         // use external connection helper
		OPT_S = 1 << 6,         // specify connection string
		OPT_a = 1 << 7,         // authentication tokens
		OPT_v = 1 << 8,         // verbosity
	};

	// init global variables
	INIT_G();

	// save initial stdin since body is piped!
	xdup2(STDIN_FILENO, 3);
	G.fp0 = xfdopen_for_read(3);

	// parse options
	// -v is a counter, -H and -S are mutually exclusive, -a is a list
	opt_complementary = "vv:w+:H--S:S--H:a::";
	// N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect
	// -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility,
	// it is still under development.
	opts = getopt32(argv, "tf:o:iw:H:S:a::v", &opt_from, NULL,
			&timeout, &opt_connect, &opt_connect, &list, &verbose);
	//argc -= optind;
	argv += optind;

	// process -a[upm]<token> options
	if ((opts & OPT_a) && !list)
		bb_show_usage();
	while (list) {
		char *a = (char *) llist_pop(&list);
		if ('u' == a[0])
			G.user = xstrdup(a+1);
		if ('p' == a[0])
			G.pass = xstrdup(a+1);
		// N.B. we support only AUTH LOGIN so far
		//if ('m' == a[0])
		//	G.method = xstrdup(a+1);
	}
	// N.B. list == NULL here
	//bb_info_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv);

	// connect to server

	// connection helper ordered? ->
	if (opts & OPT_H) {
		const char *args[] = { "sh", "-c", opt_connect, NULL };
		// plug it in
		launch_helper(args);
		// Now:
		// our stdout will go to helper's stdin,
		// helper's stdout will be available on our stdin.

		// Wait for initial server message.
		// If helper (such as openssl) invokes STARTTLS, the initial 220
		// is swallowed by helper (and not repeated after TLS is initiated).
		// We will send NOOP cmd to server and check the response.
		// We should get 220+250 on plain connection, 250 on STARTTLSed session.
		//
		// The problem here is some servers delay initial 220 message,
		// and consider client to be a spammer if it starts sending cmds
		// before 220 reached it. The code below is unsafe in this regard:
		// in non-STARTTLSed case, we potentially send NOOP before 220
		// is sent by server.
		// Ideas? (--delay SECS opt? --assume-starttls-helper opt?)
		code = smtp_check("NOOP", -1);
		if (code == 220)
			// we got 220 - this is not STARTTLSed connection,
			// eat 250 response to our NOOP
			smtp_check(NULL, 250);
		else
		if (code != 250)
			bb_error_msg_and_die("SMTP init failed");
	} else {
		// vanilla connection
		int fd;
		// host[:port] not explicitly specified? -> use $SMTPHOST
		// no $SMTPHOST? -> use localhost
		if (!(opts & OPT_S)) {
			opt_connect = getenv("SMTPHOST");
			if (!opt_connect)
				opt_connect = (char *)"127.0.0.1";
		}
		// do connect
		fd = create_and_connect_stream_or_die(opt_connect, 25);
		// and make ourselves a simple IO filter
		xmove_fd(fd, STDIN_FILENO);
		xdup2(STDIN_FILENO, STDOUT_FILENO);

		// Wait for initial server 220 message
		smtp_check(NULL, 220);
	}

	// we should start with modern EHLO
	if (250 != smtp_checkp("EHLO %s", host, -1))
		smtp_checkp("HELO %s", host, 250);

	// perform authentication
	if (opts & OPT_a) {
		smtp_check("AUTH LOGIN", 334);
		// we must read credentials unless they are given via -a[up] options
		if (!G.user || !G.pass)
			get_cred_or_die(4);
		encode_base64(NULL, G.user, NULL);
		smtp_check("", 334);
		encode_base64(NULL, G.pass, NULL);
		smtp_check("", 235);
	}

	// set sender
	// N.B. we have here a very loosely defined algorythm
	// since sendmail historically offers no means to specify secrets on cmdline.
	// 1) server can require no authentication ->
	//	we must just provide a (possibly fake) reply address.
	// 2) server can require AUTH ->
	//	we must provide valid username and password along with a (possibly fake) reply address.
	//	For the sake of security username and password are to be read either from console or from a secured file.
	//	Since reading from console may defeat usability, the solution is either to read from a predefined
	//	file descriptor (e.g. 4), or again from a secured file.

	// got no sender address? use auth name, then UID username as a last resort
	if (!opt_from) {
		opt_from = xasprintf("%s@%s",
		                     G.user ? G.user : xuid2uname(getuid()),
		                     xgethostbyname(host)->h_name);
	}
	free(host);

	smtp_checkp("MAIL FROM:<%s>", opt_from, 250);

	// process message

	// read recipients from message and add them to those given on cmdline.
	// this means we scan stdin for To:, Cc:, Bcc: lines until an empty line
	// and then use the rest of stdin as message body
	code = 0; // set "analyze headers" mode
	while ((s = xmalloc_fgetline(G.fp0)) != NULL) {
 dump:
		// put message lines doubling leading dots
		if (code) {
			// escape leading dots
			// N.B. this feature is implied even if no -i (-oi) switch given
			// N.B. we need to escape the leading dot regardless of
			// whether it is single or not character on the line
			if ('.' == s[0] /*&& '\0' == s[1] */)
				bb_putchar('.');
			// dump read line
			send_r_n(s);
			free(s);
			continue;
		}

		// analyze headers
		// To: or Cc: headers add recipients
		check_hdr = (0 == strncasecmp("To:", s, 3));
		has_to |= check_hdr;
		if (opts & OPT_t) {
			if (check_hdr || 0 == strncasecmp("Bcc:" + 1, s, 3)) {
				rcptto_list(s+3);
				last_hdr = HDR_TOCC;
				goto addheader;
			}
			// Bcc: header adds blind copy (hidden) recipient
			if (0 == strncasecmp("Bcc:", s, 4)) {
				rcptto_list(s+4);
				free(s);
				last_hdr = HDR_BCC;
				continue; // N.B. Bcc: vanishes from headers!
			}
		}
		check_hdr = (list && isspace(s[0]));
		if (strchr(s, ':') || check_hdr) {
			// other headers go verbatim
			// N.B. RFC2822 2.2.3 "Long Header Fields" allows for headers to occupy several lines.
			// Continuation is denoted by prefixing additional lines with whitespace(s).
			// Thanks (stefan.seyfried at googlemail.com) for pointing this out.
			if (check_hdr && last_hdr != HDR_OTHER) {
				rcptto_list(s+1);
				if (last_hdr == HDR_BCC)
					continue;
					// N.B. Bcc: vanishes from headers!
			} else {
				last_hdr = HDR_OTHER;
			}
 addheader:
			// N.B. we allow MAX_HEADERS generic headers at most to prevent attacks
			if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
				goto bail;
			llist_add_to_end(&list, s);
		} else {
			// a line without ":" (an empty line too, by definition) doesn't look like a valid header
			// so stop "analyze headers" mode
 reenter:
			// put recipients specified on cmdline
			check_hdr = 1;
			while (*argv) {
				char *t = sane_address(*argv);
				rcptto(t);
				//if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
				//	goto bail;
				if (!has_to) {
					const char *hdr;

					if (check_hdr && argv[1])
						hdr = "To: %s,";
					else if (check_hdr)
						hdr = "To: %s";
					else if (argv[1])
						hdr = "To: %s," + 3;
					else
						hdr = "To: %s" + 3;
					llist_add_to_end(&list,
							xasprintf(hdr, t));
					check_hdr = 0;
				}
				argv++;
			}
			// enter "put message" mode
			// N.B. DATA fails iff no recipients were accepted (or even provided)
			// in this case just bail out gracefully
			if (354 != smtp_check("DATA", -1))
				goto bail;
			// dump the headers
			while (list) {
				send_r_n((char *) llist_pop(&list));
			}
			// stop analyzing headers
			code++;
			// N.B. !s means: we read nothing, and nothing to be read in the future.
			// just dump empty line and break the loop
			if (!s) {
				send_r_n("");
				break;
			}
			// go dump message body
			// N.B. "s" already contains the first non-header line, so pretend we read it from input
			goto dump;
		}
	}
	// odd case: we didn't stop "analyze headers" mode -> message body is empty. Reenter the loop
	// N.B. after reenter code will be > 0
	if (!code)
		goto reenter;

	// finalize the message
	smtp_check(".", 250);
 bail:
	// ... and say goodbye
	smtp_check("QUIT", 221);
	// cleanup
	if (ENABLE_FEATURE_CLEAN_UP)
		fclose(G.fp0);

	return EXIT_SUCCESS;
}
Exemplo n.º 15
0
int uniq_main(int argc UNUSED_PARAM, char **argv)
{
	FILE *in, *out;
	const char *s0, *e0, *s1, *e1, *input_filename;
	unsigned long dups;
	unsigned skip_fields, skip_chars, max_chars;
	unsigned opt;
	unsigned i;

	enum {
		OPT_c = 0x1,
		OPT_d = 0x2,
		OPT_u = 0x4,
		OPT_f = 0x8,
		OPT_s = 0x10,
		OPT_w = 0x20,
	};

	skip_fields = skip_chars = 0;
	max_chars = INT_MAX;

	opt_complementary = "f+:s+:w+";
	opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars);
	argv += optind;

	input_filename = *argv;

	in = xgetoptfile_uniq_s(argv, 0);
	if (*argv) {
		++argv;
	}
	out = xgetoptfile_uniq_s(argv, 2);
	if (*argv && argv[1]) {
		bb_show_usage();
	}

	s1 = e1 = NULL; /* prime the pump */

	do {
		s0 = s1;
		e0 = e1;
		dups = 0;

		/* gnu uniq ignores newlines */
		while ((s1 = xmalloc_fgetline(in)) != NULL) {
			e1 = s1;
			for (i = skip_fields; i; i--) {
				e1 = skip_whitespace(e1);
				e1 = skip_non_whitespace(e1);
			}
			for (i = skip_chars; *e1 && i; i--) {
				++e1;
			}

			if (!s0 || strncmp(e0, e1, max_chars)) {
				break;
			}

			++dups;	 /* note: testing for overflow seems excessive. */
		}

		if (s0) {
			if (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_e) */
				fprintf(out, "\0%ld " + (opt & 1), dups + 1); /* 1 == OPT_c */
				fprintf(out, "%s\n", s0);
			}
			free((void *)s0);
		}
	} while (s1);

	die_if_ferror(in, input_filename);

	fflush_stdout_and_exit(EXIT_SUCCESS);
}
Exemplo n.º 16
0
int cryptpw_main(int argc UNUSED_PARAM, char **argv)
{
	/* $N$ + sha_salt_16_bytes + NUL */
	char salt[3 + 16 + 1];
	char *salt_ptr;
	const char *opt_m, *opt_S;
	int len;
	int fd;

#if ENABLE_LONG_OPTS
	static const char mkpasswd_longopts[] ALIGN1 =
		"stdin\0"       No_argument       "s"
		"password-fd\0" Required_argument "P"
		"salt\0"        Required_argument "S"
		"method\0"      Required_argument "m"
	;
	applet_long_options = mkpasswd_longopts;
#endif
	fd = STDIN_FILENO;
	opt_m = "d";
	opt_S = NULL;
	/* at most two non-option arguments; -P NUM */
	opt_complementary = "?2:P+";
	getopt32(argv, "sP:S:m:a:", &fd, &opt_S, &opt_m, &opt_m);
	argv += optind;

	/* have no idea how to handle -s... */

	if (argv[0] && !opt_S)
		opt_S = argv[1];

	len = 2/2;
	salt_ptr = salt;
	if (opt_m[0] != 'd') { /* not des */
		len = 8/2; /* so far assuming md5 */
		*salt_ptr++ = '$';
		*salt_ptr++ = '1';
		*salt_ptr++ = '$';
#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
		if (opt_m[0] == 's') { /* sha */
			salt[1] = '5' + (strcmp(opt_m, "sha512") == 0);
			len = 16/2;
		}
#endif
	}
	if (opt_S)
		safe_strncpy(salt_ptr, opt_S, sizeof(salt) - 3);
	else
		crypt_make_salt(salt_ptr, len, 0);

	xmove_fd(fd, STDIN_FILENO);

	puts(pw_encrypt(
		argv[0]	? argv[0] : (
			/* Only mkpasswd, and only from tty, prompts.
			 * Otherwise it is a plain read. */
			(isatty(STDIN_FILENO) && applet_name[0] == 'm')
			? bb_ask_stdin("Password: ")
			: xmalloc_fgetline(stdin)
		),
		salt, 1));

	return EXIT_SUCCESS;
}
Exemplo n.º 17
0
int chpasswd_main(int argc UNUSED_PARAM, char **argv)
{
	char *name;
	const char *algo = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO;
	int opt;

	if (getuid() != 0)
		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);

	opt = getopt32long(argv, "^" "emc:" "\0" "m--ec:e--mc:c--em",
			chpasswd_longopts,
			&algo
	);

	while ((name = xmalloc_fgetline(stdin)) != NULL) {
		char *free_me;
		char *pass;
		int rc;

		pass = strchr(name, ':');
		if (!pass)
			bb_error_msg_and_die("missing new password");
		*pass++ = '\0';

		xuname2uid(name); /* dies if there is no such user */

		free_me = NULL;
		if (!(opt & OPT_ENC)) {
			char salt[MAX_PW_SALT_LEN];

			if (opt & OPT_MD5) {
				/* Force MD5 if the -m flag is set */
				algo = "md5";
			}

			crypt_make_pw_salt(salt, algo);
			free_me = pass = pw_encrypt(pass, salt, 0);
		}

		/* This is rather complex: if user is not found in /etc/shadow,
		 * we try to find & change his passwd in /etc/passwd */
#if ENABLE_FEATURE_SHADOWPASSWDS
		rc = update_passwd(bb_path_shadow_file, name, pass, NULL);
		if (rc > 0) /* password in /etc/shadow was updated */
			pass = (char*)"x";
		if (rc >= 0)
			/* 0 = /etc/shadow missing (not an error), >0 = passwd changed in /etc/shadow */
#endif
			rc = update_passwd(bb_path_passwd_file, name, pass, NULL);
		/* LOGMODE_BOTH logs to syslog also */
		logmode = LOGMODE_BOTH;
		if (rc < 0)
			bb_error_msg_and_die("an error occurred updating password for %s", name);
		if (rc)
			bb_error_msg("password for '%s' changed", name);
		logmode = LOGMODE_STDIO;
		free(name);
		free(free_me);
	}
	return EXIT_SUCCESS;
}
Exemplo n.º 18
0
int sed_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned opt;
	llist_t *opt_e, *opt_f;
	char *opt_i;

#if ENABLE_LONG_OPTS
	static const char sed_longopts[] ALIGN1 =
		/* name             has_arg             short */
		"in-place\0"        Optional_argument   "i"
		"regexp-extended\0" No_argument         "r"
		"quiet\0"           No_argument         "n"
		"silent\0"          No_argument         "n"
		"expression\0"      Required_argument   "e"
		"file\0"            Required_argument   "f";
#endif

	INIT_G();

	/* destroy command strings on exit */
	if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff);

	/* Lie to autoconf when it starts asking stupid questions. */
	if (argv[1] && strcmp(argv[1], "--version") == 0) {
		puts("This is not GNU sed version 4.0");
		return 0;
	}

	/* do normal option parsing */
	opt_e = opt_f = NULL;
	opt_i = NULL;
	/* -i must be first, to match OPT_in_place definition */
	/* -E is a synonym of -r:
	 * GNU sed 4.2.1 mentions it in neither --help
	 * nor manpage, but does recognize it.
	 */
	opt = getopt32long(argv, "^"
			"i::rEne:*f:*"
			"\0" "nn"/*count -n*/,
			sed_longopts,
			&opt_i, &opt_e, &opt_f,
			&G.be_quiet); /* counter for -n */
	//argc -= optind;
	argv += optind;
	if (opt & OPT_in_place) { // -i
		die_func = cleanup_outname;
	}
	if (opt & (2|4))
		G.regex_type |= REG_EXTENDED; // -r or -E
	//if (opt & 8)
	//	G.be_quiet++; // -n (implemented with a counter instead)
	while (opt_e) { // -e
		add_cmd_block(llist_pop(&opt_e));
	}
	while (opt_f) { // -f
		char *line;
		FILE *cmdfile;
		cmdfile = xfopen_stdin(llist_pop(&opt_f));
		while ((line = xmalloc_fgetline(cmdfile)) != NULL) {
			add_cmd(line);
			free(line);
		}
		fclose_if_not_stdin(cmdfile);
	}
	/* if we didn't get a pattern from -e or -f, use argv[0] */
	if (!(opt & 0x30)) {
		if (!*argv)
			bb_show_usage();
		add_cmd_block(*argv++);
	}
	/* Flush any unfinished commands. */
	add_cmd("");

	/* By default, we write to stdout */
	G.nonstdout = stdout;

	/* argv[0..(argc-1)] should be names of file to process. If no
	 * files were specified or '-' was specified, take input from stdin.
	 * Otherwise, we process all the files specified. */
	G.input_file_list = argv;
	if (!argv[0]) {
		if (opt & OPT_in_place)
			bb_error_msg_and_die(bb_msg_requires_arg, "-i");
		argv[0] = (char*)bb_msg_standard_input;
		/* G.last_input_file = 0; - already is */
	} else {
		goto start;

		for (; *argv; argv++) {
			struct stat statbuf;
			int nonstdoutfd;
			sed_cmd_t *sed_cmd;

			G.last_input_file++;
 start:
			if (!(opt & OPT_in_place)) {
				if (LONE_DASH(*argv)) {
					*argv = (char*)bb_msg_standard_input;
					process_files();
				}
				continue;
			}

			/* -i: process each FILE separately: */

			if (stat(*argv, &statbuf) != 0) {
				bb_simple_perror_msg(*argv);
				G.exitcode = EXIT_FAILURE;
				G.current_input_file++;
				continue;
			}
			G.outname = xasprintf("%sXXXXXX", *argv);
			nonstdoutfd = xmkstemp(G.outname);
			G.nonstdout = xfdopen_for_write(nonstdoutfd);
			/* Set permissions/owner of output file */
			/* chmod'ing AFTER chown would preserve suid/sgid bits,
			 * but GNU sed 4.2.1 does not preserve them either */
			fchmod(nonstdoutfd, statbuf.st_mode);
			fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid);

			process_files();
			fclose(G.nonstdout);
			G.nonstdout = stdout;

			if (opt_i) {
				char *backupname = xasprintf("%s%s", *argv, opt_i);
				xrename(*argv, backupname);
				free(backupname);
			}
			/* else unlink(*argv); - rename below does this */
			xrename(G.outname, *argv); //TODO: rollback backup on error?
			free(G.outname);
			G.outname = NULL;

			/* Fix disabled range matches and mangled ",+N" ranges */
			for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
				sed_cmd->beg_line = sed_cmd->beg_line_orig;
				sed_cmd->end_line = sed_cmd->end_line_orig;
			}
		}
		/* Here, to handle "sed 'cmds' nonexistent_file" case we did:
		 * if (G.current_input_file[G.current_input_file] == NULL)
		 *	return G.exitcode;
		 * but it's not needed since process_files() works correctly
		 * in this case too. */
	}

	process_files();

	return G.exitcode;
}
Exemplo n.º 19
0
int hexdump_main(int argc, char **argv)
{
	dumper_t *dumper = alloc_dumper();
	const char *p;
	int ch;
#if ENABLE_FEATURE_HEXDUMP_REVERSE
	FILE *fp;
	smallint rdump = 0;
#endif

	if (ENABLE_HD && !applet_name[2]) { /* we are "hd" */
		ch = 'C';
		goto hd_applet;
	}

	/* We cannot use getopt32: in hexdump options are cumulative.
	 * E.g. "hexdump -C -C file" should dump each line twice */
	while ((ch = getopt(argc, argv, hexdump_opts)) > 0) {
		p = strchr(hexdump_opts, ch);
		if (!p)
			bb_show_usage();
		if ((p - hexdump_opts) < 5) {
			bb_dump_add(dumper, add_first);
			bb_dump_add(dumper, add_strings[(int)(p - hexdump_opts)]);
		}
		/* Save a little bit of space below by omitting the 'else's. */
		if (ch == 'C') {
 hd_applet:
			bb_dump_add(dumper, "\"%08.8_Ax\n\"");
			bb_dump_add(dumper, "\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ");
			bb_dump_add(dumper, "\"  |\" 16/1 \"%_p\" \"|\\n\"");
		}
		if (ch == 'e') {
			bb_dump_add(dumper, optarg);
		} /* else */
		if (ch == 'f') {
			bb_dump_addfile(dumper, optarg);
		} /* else */
		if (ch == 'n') {
			dumper->dump_length = xatoi_positive(optarg);
		} /* else */
		if (ch == 's') { /* compat: -s accepts hex numbers too */
			dumper->dump_skip = xstrtoull_range_sfx(
				optarg,
				/*base:*/ 0,
				/*lo:*/ 0, /*hi:*/ OFF_T_MAX,
				bkm_suffixes
			);
		} /* else */
		if (ch == 'v') {
			dumper->dump_vflag = ALL;
		}
#if ENABLE_FEATURE_HEXDUMP_REVERSE
		if (ch == 'R') {
			rdump = 1;
		}
#endif
	}

	if (!dumper->fshead) {
		bb_dump_add(dumper, add_first);
		bb_dump_add(dumper, "\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
	}

	argv += optind;

#if !ENABLE_FEATURE_HEXDUMP_REVERSE
	return bb_dump_dump(dumper, argv);
#else
	if (!rdump) {
		return bb_dump_dump(dumper, argv);
	}

	/* -R: reverse of 'hexdump -Cv' */
	fp = stdin;
	if (!*argv) {
		argv--;
		goto jump_in;
	}

	do {
		char *buf;
		fp = xfopen_for_read(*argv);
 jump_in:
		while ((buf = xmalloc_fgetline(fp)) != NULL) {
			p = buf;
			while (1) {
				/* skip address or previous byte */
				while (isxdigit(*p)) p++;
				while (*p == ' ') p++;
				/* '|' char will break the line */
				if (!isxdigit(*p) || sscanf(p, "%x ", &ch) != 1)
					break;
				putchar(ch);
			}
			free(buf);
		}
		fclose(fp);
	} while (*++argv);

	fflush_stdout_and_exit(EXIT_SUCCESS);
#endif
}
Exemplo n.º 20
0
int patch_main(int argc UNUSED_PARAM, char **argv)
{
	struct stat saved_stat;
	char *patch_line;
	FILE *patch_file;
	int patch_level;
	int ret = 0;
	char plus = '+';
	unsigned opt;
	enum {
		OPT_R = (1 << 2),
		OPT_N = (1 << 3),
		/*OPT_f = (1 << 4), ignored */
		/*OPT_E = (1 << 5), ignored, this is the default */
		/*OPT_g = (1 << 6), ignored */
		OPT_dry_run = (1 << 7) * ENABLE_LONG_OPTS,
	};

	xfunc_error_retval = 2;
	{
		const char *p = "-1";
		const char *i = "-"; /* compat */
#if ENABLE_LONG_OPTS
		static const char patch_longopts[] ALIGN1 =
			"strip\0"                 Required_argument "p"
			"input\0"                 Required_argument "i"
			"reverse\0"               No_argument       "R"
			"forward\0"               No_argument       "N"
		/* "Assume user knows what [s]he is doing, do not ask any questions": */
			"force\0"                 No_argument       "f" /*ignored*/
# if ENABLE_DESKTOP
			"remove-empty-files\0"    No_argument       "E" /*ignored*/
		/* "Controls actions when a file is under RCS or SCCS control,
		 * and does not exist or is read-only and matches the default version,
		 * or when a file is under ClearCase control and does not exist..."
		 * IOW: rather obscure option.
		 * But Gentoo's portage does use -g0 */
			"get\0"                   Required_argument "g" /*ignored*/
# endif
			"dry-run\0"               No_argument       "\xfd"
# if ENABLE_DESKTOP
			"backup-if-mismatch\0"    No_argument       "\xfe" /*ignored*/
			"no-backup-if-mismatch\0" No_argument       "\xff" /*ignored*/
# endif
			;
		applet_long_options = patch_longopts;
#endif
		/* -f,-E,-g are ignored */
		opt = getopt32(argv, "p:i:RN""fEg:", &p, &i, NULL);
		if (opt & OPT_R)
			plus = '-';
		patch_level = xatoi(p); /* can be negative! */
		patch_file = xfopen_stdin(i);
	}

	patch_line = xmalloc_fgetline(patch_file);
	while (patch_line) {
		FILE *src_stream;
		FILE *dst_stream;
		//char *old_filename;
		char *new_filename;
		char *backup_filename = NULL;
		unsigned src_cur_line = 1;
		unsigned dst_cur_line = 0;
		unsigned dst_beg_line;
		unsigned bad_hunk_count = 0;
		unsigned hunk_count = 0;
		smallint copy_trailing_lines_flag = 0;

		/* Skip everything upto the "---" marker
		 * No need to parse the lines "Only in <dir>", and "diff <args>"
		 */
		do {
			/* Extract the filename ugsed before the patch was generated */
			new_filename = extract_filename(patch_line, patch_level, "--- ");
			// was old_filename above
			patch_line = xmalloc_fgetline(patch_file);
			if (!patch_line) goto quit;
		} while (!new_filename);
		free(new_filename); // "source" filename is irrelevant

		new_filename = extract_filename(patch_line, patch_level, "+++ ");
		if (!new_filename) {
			bb_error_msg_and_die("invalid patch");
		}

		/* Get access rights from the file to be patched */
		if (stat(new_filename, &saved_stat) != 0) {
			char *slash = strrchr(new_filename, '/');
			if (slash) {
				/* Create leading directories */
				*slash = '\0';
				bb_make_directory(new_filename, -1, FILEUTILS_RECUR);
				*slash = '/';
			}
			src_stream = NULL;
			saved_stat.st_mode = 0644;
		} else if (!(opt & OPT_dry_run)) {
			backup_filename = xasprintf("%s.orig", new_filename);
			xrename(new_filename, backup_filename);
			src_stream = xfopen_for_read(backup_filename);
		} else
			src_stream = xfopen_for_read(new_filename);

		if (opt & OPT_dry_run) {
			dst_stream = xfopen_for_write("/dev/null");
		} else {
			dst_stream = xfopen_for_write(new_filename);
			fchmod(fileno(dst_stream), saved_stat.st_mode);
		}

		printf("patching file %s\n", new_filename);

		/* Handle all hunks for this file */
		patch_line = xmalloc_fgets(patch_file);
		while (patch_line) {
			unsigned count;
			unsigned src_beg_line;
			unsigned hunk_offset_start;
			unsigned src_last_line = 1;
			unsigned dst_last_line = 1;

			if ((sscanf(patch_line, "@@ -%u,%u +%u,%u", &src_beg_line, &src_last_line, &dst_beg_line, &dst_last_line) < 3)
			 && (sscanf(patch_line, "@@ -%u +%u,%u", &src_beg_line, &dst_beg_line, &dst_last_line) < 2)
			) {
				/* No more hunks for this file */
				break;
			}
			if (plus != '+') {
				/* reverse patch */
				unsigned tmp = src_last_line;
				src_last_line = dst_last_line;
				dst_last_line = tmp;
				tmp = src_beg_line;
				src_beg_line = dst_beg_line;
				dst_beg_line = tmp;
			}
			hunk_count++;

			if (src_beg_line && dst_beg_line) {
				/* Copy unmodified lines upto start of hunk */
				/* src_beg_line will be 0 if it's a new file */
				count = src_beg_line - src_cur_line;
				if (copy_lines(src_stream, dst_stream, count)) {
					bb_error_msg_and_die("bad src file");
				}
				src_cur_line += count;
				dst_cur_line += count;
				copy_trailing_lines_flag = 1;
			}
			src_last_line += hunk_offset_start = src_cur_line;
			dst_last_line += dst_cur_line;

			while (1) {
				free(patch_line);
				patch_line = xmalloc_fgets(patch_file);
				if (patch_line == NULL)
					break; /* EOF */
				if (!*patch_line) {
					/* whitespace-damaged patch with "" lines */
					free(patch_line);
					patch_line = xstrdup(" ");
				}
				if ((*patch_line != '-') && (*patch_line != '+')
				 && (*patch_line != ' ')
				) {
					break; /* End of hunk */
				}
				if (*patch_line != plus) { /* '-' or ' ' */
					char *src_line = NULL;
					if (src_cur_line == src_last_line)
						break;
					if (src_stream) {
						src_line = xmalloc_fgets(src_stream);
						if (src_line) {
							int diff = strcmp(src_line, patch_line + 1);
							src_cur_line++;
							free(src_line);
							if (diff)
								src_line = NULL;
						}
					}
					/* Do not patch an already patched hunk with -N */
					if (src_line == 0 && (opt & OPT_N)) {
						continue;
					}
					if (!src_line) {
						bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start);
						bad_hunk_count++;
						break;
					}
					if (*patch_line != ' ') { /* '-' */
						continue;
					}
				}
				if (dst_cur_line == dst_last_line)
					break;
				fputs(patch_line + 1, dst_stream);
				dst_cur_line++;
			} /* end of while loop handling one hunk */
		} /* end of while loop handling one file */

		/* Cleanup last patched file */
		if (copy_trailing_lines_flag) {
			copy_lines(src_stream, dst_stream, (unsigned)(-1));
		}
		if (src_stream) {
			fclose(src_stream);
		}
		fclose(dst_stream);
		if (bad_hunk_count) {
			ret = 1;
			bb_error_msg("%u out of %u hunk FAILED", bad_hunk_count, hunk_count);
		} else {
			/* It worked, we can remove the backup */
			if (backup_filename) {
				unlink(backup_filename);
			}
			if (!(opt & OPT_dry_run)
			 && ((dst_cur_line == 0) || (dst_beg_line == 0))
			) {
				/* The new patched file is empty, remove it */
				xunlink(new_filename);
				// /* old_filename and new_filename may be the same file */
				// unlink(old_filename);
			}
		}
		free(backup_filename);
		//free(old_filename);
		free(new_filename);
	} /* end of "while there are patch lines" */
 quit:
	/* 0 = SUCCESS
	 * 1 = Some hunks failed
	 * 2 = More serious problems (exited earlier)
	 */
	return ret;
}
Exemplo n.º 21
0
int main(int argc,char **argv)
{
	FILE *fp_macro = 0;
	FILE *fp_config = 0;
	FILE *fp_source = 0;
	FILE *fp_table = 0;
	char *line;
	char *line1;
	char *cp ;	
	char *url = (char*)malloc(256*sizeof(char));
	//char macros[4000][256];
	char **macros = (char **)malloc(4000*256*sizeof(char));
	//char sameoption = 0;
	
	macros[0] = xasprintf("null");
	
	int i = 0;
	fp_source = fopen(UCI_SOURCE,"r");
	if(!fp_source)
	{
		printf("file %s open failed!\n",UCI_SOURCE);
		return (-1);
	}
	fp_macro = fopen(UCI_MACRO,"w");
	if(!fp_macro)
	{
		printf("file %s open failed\n",UCI_MACRO);
		return (-1);
		
	}
	fp_config = fopen(UCI_CONFIG,"w");
	if(!fp_config)
	{
		printf("file %s open failed\n",UCI_CONFIG);
		return (-1);
		
	}
	fp_table = fopen(FUNC_TABLE,"r");
	if(!fp_table)
	{
		printf("file %s open failed\n",FUNC_TABLE);
		return (-1);
		
	}
	fprintf(fp_macro,"#ifndef __TR_UCICONFIG_H__\n");
	fprintf(fp_macro,"#define __TR_UCICONFIG_H__\n");
	fprintf(fp_macro,"\n");
	fprintf(fp_macro,"#define MS \"trconf\"\n");
	fprintf(fp_macro,"#define TRCONF MS\".\"\n");
	fprintf(fp_macro,"\n");
	
	while(1)
	{
		line  = xmalloc_fgetline(fp_source);//get a line content of the tr_uciconfig file 
		if(line)
		{
			char *option = (char *)malloc(256*sizeof(char));
			char *section = (char *)malloc(256*sizeof(char));
			char *tmp = (char *)malloc(256*sizeof(char));
			//char *tmp1 = (char *)malloc(256*sizeof(char));
			
			i++;
			
			/*get the section and the option*/
			strcpy(tmp,line);
			/*	
			cp = strchr(tmp,'');
			*cp = '\0';
			cp = strchr(tmp,' ');
			tmp = ++cp;
			*/
			cp = strchr(tmp,' ');
			cp = ++cp;
			section = xasprintf("%s",cp);
			//section = xasprintf("%s",tmp);
			
			cp = strchr(line,'_');
			cp = ++cp;
			option  = xasprintf("%s",cp);//we can refer to the option get the url of this option in the tr69_handler_table.h
			//option_argv[i] = option;
			printf("the content of the section is [%s]\n",section);
			printf("content of the option [%d]:[%s]\n",i,option);
			strcpy(option_argv[i],option);
			
			/*get the url of this option */
			while(1)
			{
				line1 = xmalloc_fgetline(fp_table);
				if(line1)
				{
					if(strstr(line1,section))
					{
						printf("get the dest section %s and the line content is %s\n",section,line1);
						cp = strchr(line1,'{');
						cp = cp + 2;
						tmp = cp;
						cp = strchr(tmp,'"');
						*cp ='\0';
						url	= xasprintf("%s",tmp);
						cp = strrchr(url,'.');
						*cp = '\0';
						tmp = xasprintf("%s",url);
						while(cp=strchr(tmp,'.'))/*xxx.xx.xxxx*/
						{
							*cp = '_';
						}
						url = xasprintf("%s",tmp);
						/*
						sameoption = option_check(option);
						
						if((!strcmp(url,macros[i-1])) && (sameoption))
						{	
							printf("the url and the option are same!\n");
							continue;
						}
						else 
						*/
						//macros[i] = xasprintf("%s",url);/*xxx_xx_xxxx*/
							break;//every time there is only one option can be deal with.
					}
					
				}
				else 
					break;
				
			}
				
			/*write the tr_uciconfig.h*/
			//fprintf(fp_macro,"%s\tTRCONF \"%s.%s\"\n",line,section,option);
			fprintf(fp_macro,"%s\t\t\tTRCONF \"%s.%s\"\n",line,url,option);
			
			/*write the trconf*/
			//if(strcmp(section,macros[i-1]))//if the current section is not same as the macros[i-1],then create the section name 
			if(strcmp(url,macros[i-1]))
			{
				fprintf(fp_config,"config tr181 \'%s\'\n",url);
				fprintf(fp_config,"\toption %s \'\'\n",option);
			}
			else
			{	
				fprintf(fp_config,"\toption %s \'\'\n",option);
			}
			//strcpy(macros[i],section);
			//macros[i] = xasprintf("%s",section);
			macros[i] = xasprintf("%s",url);/*xxx_xx_xxxx*/
				
		}
		else
		{
			break;
		}
		
	}
	fprintf(fp_macro,"#endif");
//exit:
	fclose(fp_source);
	fclose(fp_macro);
	fclose(fp_config);
	fclose(fp_table);
	return (0);
	
}
Exemplo n.º 22
0
int sed_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned opt;
	llist_t *opt_e, *opt_f;
	char *opt_i;

#if ENABLE_LONG_OPTS
	static const char sed_longopts[] ALIGN1 =
		/* name             has_arg             short */
		"in-place\0"        Optional_argument   "i"
		"regexp-extended\0" No_argument         "r"
		"quiet\0"           No_argument         "n"
		"silent\0"          No_argument         "n"
		"expression\0"      Required_argument   "e"
		"file\0"            Required_argument   "f";
#endif

	int status = EXIT_SUCCESS;

	INIT_G();

	/* destroy command strings on exit */
	if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff);

	/* Lie to autoconf when it starts asking stupid questions. */
	if (argv[1] && strcmp(argv[1], "--version") == 0) {
		puts("This is not GNU sed version 4.0");
		return 0;
	}

	/* do normal option parsing */
	opt_e = opt_f = NULL;
	opt_i = NULL;
	opt_complementary = "e::f::" /* can occur multiple times */
	                    "nn"; /* count -n */

	IF_LONG_OPTS(applet_long_options = sed_longopts);

	/* -i must be first, to match OPT_in_place definition */
	opt = getopt32(argv, "i::rne:f:", &opt_i, &opt_e, &opt_f,
			    &G.be_quiet); /* counter for -n */
	//argc -= optind;
	argv += optind;
	if (opt & OPT_in_place) { // -i
		atexit(cleanup_outname);
	}
	if (opt & 0x2) G.regex_type |= REG_EXTENDED; // -r
	//if (opt & 0x4) G.be_quiet++; // -n
	while (opt_e) { // -e
		add_cmd_block(llist_pop(&opt_e));
	}
	while (opt_f) { // -f
		char *line;
		FILE *cmdfile;
		cmdfile = xfopen_for_read(llist_pop(&opt_f));
		while ((line = xmalloc_fgetline(cmdfile)) != NULL) {
			add_cmd(line);
			free(line);
		}
		fclose(cmdfile);
	}
	/* if we didn't get a pattern from -e or -f, use argv[0] */
	if (!(opt & 0x18)) {
		if (!*argv)
			bb_show_usage();
		add_cmd_block(*argv++);
	}
	/* Flush any unfinished commands. */
	add_cmd("");

	/* By default, we write to stdout */
	G.nonstdout = stdout;

	/* argv[0..(argc-1)] should be names of file to process. If no
	 * files were specified or '-' was specified, take input from stdin.
	 * Otherwise, we process all the files specified. */
	if (argv[0] == NULL) {
		if (opt & OPT_in_place)
			bb_error_msg_and_die(bb_msg_requires_arg, "-i");
		add_input_file(stdin);
	} else {
		int i;

		for (i = 0; argv[i]; i++) {
			struct stat statbuf;
			int nonstdoutfd;
			FILE *file;
			sed_cmd_t *sed_cmd;

			if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) {
				add_input_file(stdin);
				process_files();
				continue;
			}
			file = fopen_or_warn(argv[i], "r");
			if (!file) {
				status = EXIT_FAILURE;
				continue;
			}
			add_input_file(file);
			if (!(opt & OPT_in_place)) {
				continue;
			}

			/* -i: process each FILE separately: */

			G.outname = xasprintf("%sXXXXXX", argv[i]);
			nonstdoutfd = xmkstemp(G.outname);
			G.nonstdout = xfdopen_for_write(nonstdoutfd);

			/* Set permissions/owner of output file */
			fstat(fileno(file), &statbuf);
			/* chmod'ing AFTER chown would preserve suid/sgid bits,
			 * but GNU sed 4.2.1 does not preserve them either */
			fchmod(nonstdoutfd, statbuf.st_mode);
			fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid);

			process_files();
			fclose(G.nonstdout);
			G.nonstdout = stdout;

			if (opt_i) {
				char *backupname = xasprintf("%s%s", argv[i], opt_i);
				xrename(argv[i], backupname);
				free(backupname);
			}
			/* else unlink(argv[i]); - rename below does this */
			xrename(G.outname, argv[i]); //TODO: rollback backup on error?
			free(G.outname);
			G.outname = NULL;

			/* Re-enable disabled range matches */
			for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
				sed_cmd->beg_line = sed_cmd->beg_line_orig;
			}
		}
		/* Here, to handle "sed 'cmds' nonexistent_file" case we did:
		 * if (G.current_input_file >= G.input_file_count)
		 *	return status;
		 * but it's not needed since process_files() works correctly
		 * in this case too. */
	}
	process_files();

	return status;
}
Exemplo n.º 23
0
static
GList* load_bzrep_conf_file(const char *path)
{
    FILE *fp = stdin;
    if (strcmp(path, "-") != 0)
    {
        fp = fopen(path, "r");
        if (!fp)
            return NULL;
    }

    GList *sections = NULL;

    char *line;
    while ((line = xmalloc_fgetline(fp)) != NULL)
    {
        /* Skip comments */
        char first = *skip_whitespace(line);
        if (first == '#')
            goto free_line;

        /* Handle trailing backslash continuation */
 check_continuation: ;
        unsigned len = strlen(line);
        if (len && line[len-1] == '\\')
        {
            line[len-1] = '\0';
            char *next_line = xmalloc_fgetline(fp);
            if (next_line)
            {
                line = append_to_malloced_string(line, next_line);
                free(next_line);
                goto check_continuation;
            }
        }

        /* We are reusing line buffer to form temporary
         * "key\0values\0..." in its beginning
         */
        bool summary_line = false;
        char *value = NULL;
        char *src;
        char *dst;
        for (src = dst = line; *src; src++)
        {
            char c = *src;
            /* did we reach the value list? */
            if (!value && c == ':' && src[1] == ':')
            {
                *dst++ = '\0'; /* terminate key */
                src += 2;
                value = dst; /* remember where value starts */
                summary_line = (strcmp(line, "%summary") == 0);
                if (summary_line)
                {
                    value = src;
                    break;
                }
                continue;
            }
            /* skip whitespace in value list */
            if (value && isspace(c))
                continue;
            *dst++ = c; /* store next key or value char */
        }

        GList *item_list = NULL;
        if (summary_line)
        {
            /* %summary is special */
            item_list = g_list_append(NULL, xstrdup(skip_whitespace(value)));
        }
        else
        {
            *dst = '\0'; /* terminate value (or key) */
            if (value)
                item_list = split_string_on_char(value, ',');
        }

        section_t *sec = xzalloc(sizeof(*sec));
        sec->name = xstrdup(line);
        sec->items = item_list;
        sections = g_list_prepend(sections, sec);

 free_line:
        free(line);
    }

    if (fp != stdin)
        fclose(fp);

    return g_list_reverse(sections);
}
Exemplo n.º 24
0
void ignored_problems_remove_row(ignored_problems_t *set, const char *problem_id,
        const char *uuid, const char *duphash)
{
    VERB1 log("Going to remove problem '%s' from ignored problems", problem_id);

    FILE *orig_fp;
    if (!ignored_problems_file_contains(set, problem_id, uuid, duphash, &orig_fp, "r"))
    {
        if (orig_fp)
        {
            log_notice("Won't remove problem '%s' from ignored problems:"
                      " it is already removed", problem_id);
            /* Close orig_fp here becuase it looks like much simpler than
             * exetendig the set of goto labels at the end of this function */
            fclose(orig_fp);
        }
        else
        {
            /* This is not a fatal problem. We are permissive because we don't want
             * to scare users by strange error messages.
             */
            log_notice("Can't remove problem '%s' from ignored problems:"
                      " can't open the list", problem_id);
        }
        return;
    }

    /* orig_fp must be valid here because if ignored_problems_file_contains()
     * returned TRUE the function ensures that orig_fp is set to a valid FILE*.
     *
     * But the function moved the file position indicator.
     */
    rewind(orig_fp);

    char *new_tempfile_name = xasprintf("%s.XXXXXX", set->ign_set_file_path);
    int new_tempfile_fd = mkstemp(new_tempfile_name);
    if (new_tempfile_fd < 0)
    {
        perror_msg(_("Can't create temporary file '%s'"), set->ign_set_file_path);
        goto ret_close_files;
    }

    unsigned line_num = 0;
    char *line;
    while ((line = xmalloc_fgetline(orig_fp)) != NULL)
    {
        ++line_num;
        if (!ignored_problems_eq(set, problem_id, uuid, duphash, line, line_num))
        {
            ssize_t len = strlen(line);
            line[len] = '\n';
            if (full_write(new_tempfile_fd, line, len + 1) < 0)
            {
                /* Probably out of space */
                line[len] = '\0';
                perror_msg(_("Can't write to '%s'."
                        " Problem '%s' will not be removed from the ignored"
                        " problems '%s'"),
                        new_tempfile_name, problem_id, set->ign_set_file_path);
                free(line);
                goto ret_unlink_new;
            }
        }
        free(line);
    }

    if (rename(new_tempfile_name, set->ign_set_file_path) < 0)
    {
        /* Something nefarious happened */
        perror_msg(_("Can't rename '%s' to '%s'. Failed to remove problem '%s'"),
                set->ign_set_file_path, new_tempfile_name, problem_id);
 ret_unlink_new:
        unlink(new_tempfile_name);
    }

 ret_close_files:
    fclose(orig_fp);
    if (new_tempfile_fd >= 0)
        close(new_tempfile_fd);
    free(new_tempfile_name);

}
Exemplo n.º 25
0
/* Called after "Backtrace:" line was read.
 * Example (yes, stray newline before 'B' is real):
[ 86985.879]<space>
Backtrace:
[ 86985.880] 0: /usr/bin/Xorg (xorg_backtrace+0x2f) [0x462d8f]
[ 86985.880] 1: /usr/bin/Xorg (0x400000+0x67b56) [0x467b56]
[ 86985.880] 2: /lib64/libpthread.so.0 (0x30a5800000+0xf4f0) [0x30a580f4f0]
[ 86985.880] 3: /usr/lib64/xorg/modules/extensions/librecord.so (0x7ff6c225e000+0x26c3) [0x7ff6c22606c3]
[ 86985.880] 4: /usr/bin/Xorg (_CallCallbacks+0x3c) [0x43820c]
[ 86985.880] 5: /usr/bin/Xorg (WriteToClient+0x1f5) [0x466315]
[ 86985.880] 6: /usr/lib64/xorg/modules/extensions/libdri2.so (ProcDRI2WaitMSCReply+0x4f) [0x7ff6c1e4feef]
[ 86985.880] 7: /usr/lib64/xorg/modules/extensions/libdri2.so (DRI2WaitMSCComplete+0x52) [0x7ff6c1e4e6d2]
[ 86985.880] 8: /usr/lib64/xorg/modules/drivers/intel_drv.so (0x7ff6c1bfb000+0x25ae4) [0x7ff6c1c20ae4]
[ 86985.880] 9: /usr/lib64/libdrm.so.2 (drmHandleEvent+0xa3) [0x376b407513]
[ 86985.880] 10: /usr/bin/Xorg (WakeupHandler+0x6b) [0x4379db]
[ 86985.880] 11: /usr/bin/Xorg (WaitForSomething+0x1a9) [0x460289]
[ 86985.880] 12: /usr/bin/Xorg (0x400000+0x3379a) [0x43379a]
[ 86985.880] 13: /usr/bin/Xorg (0x400000+0x22dc5) [0x422dc5]
[ 86985.880] 14: /lib64/libc.so.6 (__libc_start_main+0xed) [0x30a542169d]
[ 86985.880] 15: /usr/bin/Xorg (0x400000+0x230b1) [0x4230b1]
[ 86985.880] Segmentation fault at address 0x7ff6bf09e010
 */
static void process_xorg_bt(void)
{
    char *reason = NULL;
    char *exe = NULL;
    GList *list = NULL;
    unsigned cnt = 0;
    char *line;
    while ((line = xmalloc_fgetline(stdin)) != NULL)
    {
        char *p = skip_pfx(line);

        /* xorg-server-1.12.0/os/osinit.c:
         * if (sip->si_code == SI_USER) {
         *     ErrorF("Recieved signal %d sent by process %ld, uid %ld\n",
         *             ^^^^^^^^ yes, typo here! Can't grep for this word! :(
         *            signo, (long) sip->si_pid, (long) sip->si_uid);
         * } else {
         *     switch (signo) {
         *         case SIGSEGV:
         *         case SIGBUS:
         *         case SIGILL:
         *         case SIGFPE:
         *             ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
         */
        if (*p < '0' || *p > '9')
        {
            if (strstr(p, " at address ") || strstr(p, " sent by process "))
            {
                overlapping_strcpy(line, p);
                reason = line;
                line = NULL;
            }
            /* TODO: Other cases when we have useful reason string? */
            break;
        }

        errno = 0;
        char *end;
        IGNORE_RESULT(strtoul(p, &end, 10));
        if (errno || end == p || *end != ':')
            break;

        /* This looks like bt line */

        /* Guess Xorg server's executable name from it */
        if (!exe)
        {
            char *filename = skip_whitespace(end + 1);
            char *filename_end = skip_non_whitespace(filename);
            char sv = *filename_end;
            *filename_end = '\0';
            /* Does it look like "[/usr]/[s]bin/Xfoo"? */
            if (strstr(filename, "bin/X"))
                exe = xstrdup(filename);
            *filename_end = sv;
        }

        /* Save it to list */
        overlapping_strcpy(line, p);
        list = g_list_prepend(list, line);
        line = NULL;
        if (++cnt > 255) /* prevent ridiculously large bts */
            break;
    }
    free(line);

    if (list)
    {
        list = g_list_reverse(list);
        char *bt = list2lines(list); /* frees list */
        if (g_opts & OPT_o)
            printf("%s%s%s\n", bt, reason ? reason : "", reason ? "\n" : "");
        if (g_opts & (OPT_d|OPT_D))
            if (g_bt_count <= MAX_DUMPED_DD_COUNT)
                save_bt_to_dump_dir(bt, exe, reason ? reason : "Xorg server crashed");
        free(bt);
    }
    free(reason);
    free(exe);
}
Exemplo n.º 26
0
int uniq_main(int argc UNUSED_PARAM, char **argv)
{
	const char *input_filename;
	unsigned skip_fields, skip_chars, max_chars;
	unsigned opt;
	char *cur_line;
	const char *cur_compare;

	enum {
		OPT_c = 0x1,
		OPT_d = 0x2, /* print only dups */
		OPT_u = 0x4, /* print only uniq */
		OPT_f = 0x8,
		OPT_s = 0x10,
		OPT_w = 0x20,
		OPT_i = 0x40,
	};

	skip_fields = skip_chars = 0;
	max_chars = INT_MAX;

	opt = getopt32(argv, "cduf:+s:+w:+i", &skip_fields, &skip_chars, &max_chars);
	argv += optind;

	input_filename = argv[0];
	if (input_filename) {
		const char *output;

		if (input_filename[0] != '-' || input_filename[1]) {
			close(STDIN_FILENO); /* == 0 */
			xopen(input_filename, O_RDONLY); /* fd will be 0 */
		}
		output = argv[1];
		if (output) {
			if (argv[2])
				bb_show_usage();
			if (output[0] != '-' || output[1]) {
				// Won't work with "uniq - FILE" and closed stdin:
				//close(STDOUT_FILENO);
				//xopen(output, O_WRONLY | O_CREAT | O_TRUNC);
				xmove_fd(xopen(output, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO);
			}
		}
	}

	cur_compare = cur_line = NULL; /* prime the pump */

	do {
		unsigned i;
		unsigned long dups;
		char *old_line;
		const char *old_compare;

		old_line = cur_line;
		old_compare = cur_compare;
		dups = 0;

		/* gnu uniq ignores newlines */
		while ((cur_line = xmalloc_fgetline(stdin)) != NULL) {
			cur_compare = cur_line;
			for (i = skip_fields; i; i--) {
				cur_compare = skip_whitespace(cur_compare);
				cur_compare = skip_non_whitespace(cur_compare);
			}
			for (i = skip_chars; *cur_compare && i; i--) {
				++cur_compare;
			}

			if (!old_line)
				break;
			if ((opt & OPT_i)
				? strncasecmp(old_compare, cur_compare, max_chars)
				: strncmp(old_compare, cur_compare, max_chars)
			) {
				break;
			}

			free(cur_line);
			++dups;  /* testing for overflow seems excessive */
		}

		if (old_line) {
			if (!(opt & (OPT_d << !!dups))) { /* (if dups, opt & OPT_u) */
				if (opt & OPT_c) {
					/* %7lu matches GNU coreutils 6.9 */
					printf("%7lu ", dups + 1);
				}
				puts(old_line);
			}
			free(old_line);
		}
	} while (cur_line);

	die_if_ferror(stdin, input_filename);

	fflush_stdout_and_exit(EXIT_SUCCESS);
}
Exemplo n.º 27
0
int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
{
	FILE *orig_fp;
	char *orig_fn;
	char *new_fn;
	struct stat sb;

	sb.st_mode = 0666;

	argv++;

	orig_fn = xmalloc_follow_symlinks(SHELLS_FILE);
	if (!orig_fn)
		return EXIT_FAILURE;
	orig_fp = fopen_for_read(orig_fn);
	if (orig_fp)
		xfstat(fileno(orig_fp), &sb, orig_fn);

	new_fn = xasprintf("%s.tmp", orig_fn);
	/*
	 * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better,
	 * since it prevents races. But: (1) it requires a retry loop,
	 * (2) if /etc/shells.tmp is *stale*, then retry loop
	 * with O_EXCL will never succeed - it should have a timeout,
	 * after which it should revert to O_TRUNC.
	 * For now, I settle for O_TRUNC instead.
	 */
	xmove_fd(xopen3(new_fn, O_WRONLY | O_CREAT | O_TRUNC, sb.st_mode), STDOUT_FILENO);
	/* TODO?
	xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid);
	*/

	if (orig_fp) {
		/* Copy old file, possibly skipping removed shell names */
		char *line;
		while ((line = xmalloc_fgetline(orig_fp)) != NULL) {
			char **cpp = argv;
			while (*cpp) {
				if (*cpp != dont_add && strcmp(*cpp, line) == 0) {
					/* Old file has this shell name */
					if (REMOVE_SHELL) {
						/* we are remove-shell */
						/* delete this name by not copying it */
						goto next_line;
					}
					/* we are add-shell */
					/* mark this name as "do not add" */
					*cpp = dont_add;
				}
				cpp++;
			}
			/* copy shell name from old to new file */
			puts(line);
 next_line:
			free(line);
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			fclose(orig_fp);
	}

	if (ADD_SHELL) {
		char **cpp = argv;
		while (*cpp) {
			if (*cpp != dont_add)
				puts(*cpp);
			cpp++;
		}
	}

	/* Ensure we wrote out everything */
	if (fclose(stdout) != 0) {
		xunlink(new_fn);
		bb_perror_msg_and_die("%s: write error", new_fn);
	}

	/* Small hole: if rename fails, /etc/shells.tmp is not removed */
	xrename(new_fn, orig_fn);

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(orig_fn);
		free(new_fn);
	}

	return EXIT_SUCCESS;
}
Exemplo n.º 28
0
int main(int argc, char **argv)
{
    /* I18n */
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    /* Can't keep these strings/structs static: _() doesn't support that */
    const char *program_usage_string = _(
        "& [-vsoxm] [-d DIR]/[-D] [FILE]\n"
        "\n"
        "Extract Xorg crash from FILE (or standard input)"
    );
    /* Keep OPT_z enums and order of options below in sync! */
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT_BOOL(  's', NULL, NULL, _("Log to syslog")),
        OPT_BOOL(  'o', NULL, NULL, _("Print found crash data on standard output")),
        OPT_STRING('d', NULL, &debug_dumps_dir, "DIR", _("Create problem directory in DIR for every crash found")),
        OPT_BOOL(  'D', NULL, NULL, _("Same as -d DumpLocation, DumpLocation is specified in abrt.conf")),
        OPT_BOOL(  'x', NULL, NULL, _("Make the problem directory world readable")),
        OPT_BOOL(  'm', NULL, NULL, _("Print search string(s) to stdout and exit")),
        OPT_END()
    };
    unsigned opts = g_opts = parse_opts(argc, argv, program_options, program_usage_string);

    export_abrt_envvars(0);

    msg_prefix = g_progname;
    if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
    {
        logmode = LOGMODE_JOURNAL;
    }

    if (opts & OPT_m)
    {
        puts("Backtrace");
        return 0;
    }

    if (opts & OPT_D)
    {
        if (opts & OPT_d)
            show_usage_and_die(program_usage_string, program_options);
        load_abrt_conf();
        debug_dumps_dir = g_settings_dump_location;
        g_settings_dump_location = NULL;
        free_abrt_conf_data();
    }

    argv += optind;
    if (argv[0])
        xmove_fd(xopen(argv[0], O_RDONLY), STDIN_FILENO);

    char *line;
    while ((line = xmalloc_fgetline(stdin)) != NULL)
    {
        char *p = skip_pfx(line);
        if (strcmp(p, "Backtrace:") == 0)
        {
            free(line);
            g_bt_count++;
            process_xorg_bt();
            continue;
        }
        free(line);
    }

    /* If we are run by a log watcher, this delays log rescan
     * (because log watcher waits to us to terminate)
     * and possibly prevents dreaded "abrt storm".
     */
    if (opts & (OPT_d|OPT_D))
    {
        if (g_bt_count > MAX_DUMPED_DD_COUNT)
            sleep(g_bt_count - MAX_DUMPED_DD_COUNT);
    }

    return 0;
}
Exemplo n.º 29
0
/* Returns false if open failed, else returns true.
 * TODO: better error detection?
 */
bool load_conf_file(const char *path, map_string_t *settings, bool skipKeysWithoutValue)
{
    FILE *fp = stdin;
    if (strcmp(path, "-") != 0)
    {
        fp = fopen(path, "r");
        if (!fp)
            return false;
    }

    char *line;
    while ((line = xmalloc_fgetline(fp)) != NULL)
    {
        bool in_quote = false;
        /* We are reusing line buffer to form temporary
         * "key\0value\0..." in its beginning
         */
        char *value = NULL;
        char *src;
        char *dst;
        for (src = dst = line; *src; src++)
        {
            char c = *src;
            if (c == '"')
            {
                in_quote = !in_quote;
                /* skip the opening quote */
                if (in_quote)
                    continue;
            }
            if (!in_quote)
            {
                /* skip white-space unless it's inside value */
                if (isspace(c) && !(value && dst != value))
                {
                    continue;
                }
                if (c == '#' && dst == line)
                {
                    break;
                }
                if (c == '=')
                {
                    *dst++ = '\0'; /* terminate key */
                    value = dst; /* remember where value starts */
                    continue;
                }
            }
            *dst++ = c; /* store next key or value char */
        }

        /* Skip broken or empty lines. */
        if (!value)
            goto free_line;

        /* Strip trailing spaces and closing quote from value */
        while (dst > value && (isspace(dst[-1]) || dst[-1] == '"'))
        {
            dst--;
            if (*dst == '"')
                break;
        }

        *dst = '\0'; /* terminate value */

        if (skipKeysWithoutValue && value[0] == '\0')
            goto free_line;

        /* Skip lines with unclosed quotes. */
        if (in_quote)
            goto free_line;

        replace_map_string_item(settings, xstrdup(line), xstrdup(value));
 free_line:
        free(line);
    }

    if (fp != stdin)
        fclose(fp);

    return true;
}
Exemplo n.º 30
0
static void process_files(void)
{
	char *pattern_space, *next_line;
	int linenum = 0;
	char last_puts_char = '\n';
	char last_gets_char, next_gets_char;
	sed_cmd_t *sed_cmd;
	int substituted;

	/* Prime the pump */
	next_line = get_next_line(&next_gets_char, &last_puts_char);

	/* Go through every line in each file */
 again:
	substituted = 0;

	/* Advance to next line.  Stop if out of lines. */
	pattern_space = next_line;
	if (!pattern_space)
		return;
	last_gets_char = next_gets_char;

	/* Read one line in advance so we can act on the last line,
	 * the '$' address */
	next_line = get_next_line(&next_gets_char, &last_puts_char);
	linenum++;

	/* For every line, go through all the commands */
 restart:
	for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
		int old_matched, matched;

		old_matched = sed_cmd->in_match;

		/* Determine if this command matches this line: */

		dbg("match1:%d", sed_cmd->in_match);
		dbg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line
				&& !sed_cmd->beg_match && !sed_cmd->end_match));
		dbg("match3:%d", (sed_cmd->beg_line > 0
			&& (sed_cmd->end_line || sed_cmd->end_match
			    ? (sed_cmd->beg_line <= linenum)
			    : (sed_cmd->beg_line == linenum)
			    )
			));
		dbg("match4:%d", (beg_match(sed_cmd, pattern_space)));
		dbg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL));

		/* Are we continuing a previous multi-line match? */
		sed_cmd->in_match = sed_cmd->in_match
			/* Or is no range necessary? */
			|| (!sed_cmd->beg_line && !sed_cmd->end_line
				&& !sed_cmd->beg_match && !sed_cmd->end_match)
			/* Or did we match the start of a numerical range? */
			|| (sed_cmd->beg_line > 0
			    && (sed_cmd->end_line || sed_cmd->end_match
				  /* note: even if end is numeric and is < linenum too,
				   * GNU sed matches! We match too, therefore we don't
				   * check here that linenum <= end.
				   * Example:
				   * printf '1\n2\n3\n4\n' | sed -n '1{N;N;d};1p;2,3p;3p;4p'
				   * first three input lines are deleted;
				   * 4th line is matched and printed
				   * by "2,3" (!) and by "4" ranges
				   */
				? (sed_cmd->beg_line <= linenum)    /* N,end */
				: (sed_cmd->beg_line == linenum)    /* N */
				)
			    )
			/* Or does this line match our begin address regex? */
			|| (beg_match(sed_cmd, pattern_space))
			/* Or did we match last line of input? */
			|| (sed_cmd->beg_line == -1 && next_line == NULL);

		/* Snapshot the value */
		matched = sed_cmd->in_match;

		dbg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d",
			sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum);

		/* Is this line the end of the current match? */

		if (matched) {
			if (sed_cmd->end_line <= -2) {
				/* address2 is +N, i.e. N lines from beg_line */
				sed_cmd->end_line = linenum + (-sed_cmd->end_line - 2);
			}
			/* once matched, "n,xxx" range is dead, disabling it */
			if (sed_cmd->beg_line > 0) {
				sed_cmd->beg_line = -2;
			}
			dbg("end1:%d", sed_cmd->end_line ? sed_cmd->end_line == -1
						? !next_line : (sed_cmd->end_line <= linenum)
					: !sed_cmd->end_match);
			dbg("end2:%d", sed_cmd->end_match && old_matched
					&& !regexec(sed_cmd->end_match,pattern_space, 0, NULL, 0));
			sed_cmd->in_match = !(
				/* has the ending line come, or is this a single address command? */
				(sed_cmd->end_line
					? sed_cmd->end_line == -1
						? !next_line
						: (sed_cmd->end_line <= linenum)
					: !sed_cmd->end_match
				)
				/* or does this line matches our last address regex */
				|| (sed_cmd->end_match && old_matched
				     && (regexec(sed_cmd->end_match,
						pattern_space, 0, NULL, 0) == 0)
				)
			);
		}

		/* Skip blocks of commands we didn't match */
		if (sed_cmd->cmd == '{') {
			if (sed_cmd->invert ? matched : !matched) {
				unsigned nest_cnt = 0;
				while (1) {
					if (sed_cmd->cmd == '{')
						nest_cnt++;
					if (sed_cmd->cmd == '}') {
						nest_cnt--;
						if (nest_cnt == 0)
							break;
					}
					sed_cmd = sed_cmd->next;
					if (!sed_cmd)
						bb_error_msg_and_die("unterminated {");
				}
			}
			continue;
		}

		/* Okay, so did this line match? */
		if (sed_cmd->invert ? matched : !matched)
			continue; /* no */

		/* Update last used regex in case a blank substitute BRE is found */
		if (sed_cmd->beg_match) {
			G.previous_regex_ptr = sed_cmd->beg_match;
		}

		/* actual sedding */
		dbg("pattern_space:'%s' next_line:'%s' cmd:%c",
				pattern_space, next_line, sed_cmd->cmd);
		switch (sed_cmd->cmd) {

		/* Print line number */
		case '=':
			fprintf(G.nonstdout, "%d\n", linenum);
			break;

		/* Write the current pattern space up to the first newline */
		case 'P':
		{
			char *tmp = strchr(pattern_space, '\n');
			if (tmp) {
				*tmp = '\0';
				/* TODO: explain why '\n' below */
				sed_puts(pattern_space, '\n');
				*tmp = '\n';
				break;
			}
			/* Fall Through */
		}

		/* Write the current pattern space to output */
		case 'p':
			/* NB: we print this _before_ the last line
			 * (of current file) is printed. Even if
			 * that line is nonterminated, we print
			 * '\n' here (gnu sed does the same) */
			sed_puts(pattern_space, '\n');
			break;
		/* Delete up through first newline */
		case 'D':
		{
			char *tmp = strchr(pattern_space, '\n');
			if (tmp) {
				overlapping_strcpy(pattern_space, tmp + 1);
				goto restart;
			}
		}
		/* discard this line. */
		case 'd':
			goto discard_line;

		/* Substitute with regex */
		case 's':
			if (!do_subst_command(sed_cmd, &pattern_space))
				break;
			dbg("do_subst_command succeeded:'%s'", pattern_space);
			substituted |= 1;

			/* handle p option */
			if (sed_cmd->sub_p)
				sed_puts(pattern_space, last_gets_char);
			/* handle w option */
			if (sed_cmd->sw_file)
				puts_maybe_newline(
					pattern_space, sed_cmd->sw_file,
					&sed_cmd->sw_last_char, last_gets_char);
			break;

		/* Append line to linked list to be printed later */
		case 'a':
			append(xstrdup(sed_cmd->string));
			break;

		/* Insert text before this line */
		case 'i':
			sed_puts(sed_cmd->string, '\n');
			break;

		/* Cut and paste text (replace) */
		case 'c':
			/* Only triggers on last line of a matching range. */
			if (!sed_cmd->in_match)
				sed_puts(sed_cmd->string, '\n');
			goto discard_line;

		/* Read file, append contents to output */
		case 'r':
		{
			FILE *rfile;
			rfile = fopen_for_read(sed_cmd->string);
			if (rfile) {
				char *line;
				while ((line = xmalloc_fgetline(rfile))
						!= NULL)
					append(line);
				fclose(rfile);
			}

			break;
		}

		/* Write pattern space to file. */
		case 'w':
			puts_maybe_newline(
				pattern_space, sed_cmd->sw_file,
				&sed_cmd->sw_last_char, last_gets_char);
			break;

		/* Read next line from input */
		case 'n':
			if (!G.be_quiet)
				sed_puts(pattern_space, last_gets_char);
			if (next_line == NULL) {
				/* If no next line, jump to end of script and exit. */
				goto discard_line;
			}
			free(pattern_space);
			pattern_space = next_line;
			last_gets_char = next_gets_char;
			next_line = get_next_line(&next_gets_char, &last_puts_char);
			substituted = 0;
			linenum++;
			break;

		/* Quit.  End of script, end of input. */
		case 'q':
			/* Exit the outer while loop */
			free(next_line);
			next_line = NULL;
			goto discard_commands;

		/* Append the next line to the current line */
		case 'N':
		{
			int len;
			/* If no next line, jump to end of script and exit. */
			/* http://www.gnu.org/software/sed/manual/sed.html:
			 * "Most versions of sed exit without printing anything
			 * when the N command is issued on the last line of
			 * a file. GNU sed prints pattern space before exiting
			 * unless of course the -n command switch has been
			 * specified. This choice is by design."
			 */
			if (next_line == NULL) {
				//goto discard_line;
				goto discard_commands; /* GNU behavior */
			}
			/* Append next_line, read new next_line. */
			len = strlen(pattern_space);
			pattern_space = xrealloc(pattern_space, len + strlen(next_line) + 2);
			pattern_space[len] = '\n';
			strcpy(pattern_space + len+1, next_line);
			last_gets_char = next_gets_char;
			next_line = get_next_line(&next_gets_char, &last_puts_char);
			linenum++;
			break;
		}

		/* Test/branch if substitution occurred */
		case 't':
			if (!substituted) break;
			substituted = 0;
			/* Fall through */
		/* Test/branch if substitution didn't occur */
		case 'T':
			if (substituted) break;
			/* Fall through */
		/* Branch to label */
		case 'b':
			if (!sed_cmd->string) goto discard_commands;
			else sed_cmd = branch_to(sed_cmd->string);
			break;
		/* Transliterate characters */
		case 'y':
		{
			int i, j;
			for (i = 0; pattern_space[i]; i++) {
				for (j = 0; sed_cmd->string[j]; j += 2) {
					if (pattern_space[i] == sed_cmd->string[j]) {
						pattern_space[i] = sed_cmd->string[j + 1];
						break;
					}
				}
			}

			break;
		}
		case 'g':	/* Replace pattern space with hold space */
			free(pattern_space);
			pattern_space = xstrdup(G.hold_space ? G.hold_space : "");
			break;
		case 'G':	/* Append newline and hold space to pattern space */
		{
			int pattern_space_size = 2;
			int hold_space_size = 0;

			if (pattern_space)
				pattern_space_size += strlen(pattern_space);
			if (G.hold_space)
				hold_space_size = strlen(G.hold_space);
			pattern_space = xrealloc(pattern_space,
					pattern_space_size + hold_space_size);
			if (pattern_space_size == 2)
				pattern_space[0] = 0;
			strcat(pattern_space, "\n");
			if (G.hold_space)
				strcat(pattern_space, G.hold_space);
			last_gets_char = '\n';

			break;
		}
		case 'h':	/* Replace hold space with pattern space */
			free(G.hold_space);
			G.hold_space = xstrdup(pattern_space);
			break;
		case 'H':	/* Append newline and pattern space to hold space */
		{
			int hold_space_size = 2;
			int pattern_space_size = 0;

			if (G.hold_space)
				hold_space_size += strlen(G.hold_space);
			if (pattern_space)
				pattern_space_size = strlen(pattern_space);
			G.hold_space = xrealloc(G.hold_space,
					hold_space_size + pattern_space_size);

			if (hold_space_size == 2)
				*G.hold_space = 0;
			strcat(G.hold_space, "\n");
			if (pattern_space)
				strcat(G.hold_space, pattern_space);

			break;
		}
		case 'x': /* Exchange hold and pattern space */
		{
			char *tmp = pattern_space;
			pattern_space = G.hold_space ? G.hold_space : xzalloc(1);
			last_gets_char = '\n';
			G.hold_space = tmp;
			break;
		}
		} /* switch */
	} /* for each cmd */

	/*
	 * Exit point from sedding...
	 */
 discard_commands:
	/* we will print the line unless we were told to be quiet ('-n')
	   or if the line was suppressed (ala 'd'elete) */
	if (!G.be_quiet)
		sed_puts(pattern_space, last_gets_char);

	/* Delete and such jump here. */
 discard_line:
	flush_append(&last_puts_char /*,last_gets_char*/);
	free(pattern_space);

	goto again;
}