Ejemplo n.º 1
0
Archivo: bti.c Proyecto: thesues/bti
int main(int argc, char *argv[], char *envp[])
{
	//FIXME:user could choose only a website no all website.which means --host is available.

	static const struct option options[] = {
		{"debug", 0, NULL, 'd'},
		{"verbose", 0, NULL, 'V'},
		{"action", 1, NULL, 'A'},
		{"logfile", 1, NULL, 'L'},
		{"shrink-urls", 0, NULL, 's'},
		{"help", 0, NULL, 'h'},
		{"bash", 0, NULL, 'b'},
		{"background", 0, NULL, 'B'},
		{"dry-run", 0, NULL, 'n'},
		{"page", 1, NULL, 'g'},
		{"version", 0, NULL, 'v'},
		{"config", 1, NULL, 'c'},
		{"replyto", 1, NULL, 'r'},
		{"retweet", 1, NULL, 'w'},
		{}
	};
	struct session *session;
	pid_t child;
	int retval = 0;
	int option;
	char *home;
	const char *config_file;
	time_t t;
	int page_nr;
	char *tweet;

	debug = 0;

	session = session_alloc();
	if (!session) {
		fprintf(stderr, "no more memory...\n");
		return -1;
	}

	/* get the current time so that we can log it later */
	time(&t);
	session->time = strdup(ctime(&t));
	session->time[strlen(session->time) - 1] = 0x00;

	/*
	 * Get the home directory so we can try to find a config file.
	 * If we have no home dir set up, look in /etc/bti
	 */
	home = getenv("HOME");
	if (home) {
		/* We have a home dir, so this might be a user */
		session->homedir = strdup(home);
		config_file = config_user_default;
	} else {
		session->homedir = strdup("");
		config_file = config_default;
	}

	/* set up a default config file location (traditionally ~/.bti) */
	session->configfile =
	    zalloc(strlen(session->homedir) + strlen(config_file) + 7);
	sprintf(session->configfile, "%s/%s", session->homedir, config_file);

	session_readline_init(session);

	struct account *account = parse_configfile(session);
	if (account == NULL) {
		fprintf(stderr, "parse err, goto exit\n");
		exit(-1);
	}

	while (1) {
		option = getopt_long_only(argc, argv,
					  "dp:P:H:a:A:u:c:hg:G:sr:nVvw:",
					  options, NULL);
		if (option == -1)
			break;
		switch (option) {
		case 'd':
			debug = 1;
			break;
		case 'V':
			session->verbose = 1;
			break;
		case 'g':
			page_nr = atoi(optarg);
			dbg("page = %d\n", page_nr);
			session->page = page_nr;
			break;
		case 'r':
			session->replyto = strdup(optarg);
			dbg("in_reply_to_status_id = %s\n", session->replyto);
			break;
		case 'A':
			if (strcasecmp(optarg, "update") == 0)
				session->action = ACTION_UPDATE;
			else if (strcasecmp(optarg, "friends") == 0)
				session->action = ACTION_FRIENDS;
			else if (strcasecmp(optarg, "user") == 0)
				session->action = ACTION_USER;
			else if (strcasecmp(optarg, "replies") == 0)
				session->action = ACTION_REPLIES;
			else if (strcasecmp(optarg, "public") == 0)
				session->action = ACTION_PUBLIC;
			else if (strcasecmp(optarg, "group") == 0)
				session->action = ACTION_GROUP;
			else if (strcasecmp(optarg, "retweet") == 0)
				session->action = ACTION_RETWEET;
			else
				session->action = ACTION_UNKNOWN;
			dbg("action = %d\n", session->action);
			break;
		case 'u':
			if (session->user)
				free(session->user);
			session->user = strdup(optarg);
			dbg("user = %s\n", session->user);
			break;

		case 'G':
			if (session->group)
				free(session->group);
			session->group = strdup(optarg);
			dbg("group = %s\n", session->group);
			break;
		case 'L':
			if (session->logfile)
				free(session->logfile);
			session->logfile = strdup(optarg);
			dbg("logfile = %s\n", session->logfile);
			break;
		case 's':
			session->shrink_urls = 1;
			break;
		case 'b':
			session->bash = 1;
			/* fall-through intended */
		case 'B':
			session->background = 1;
			break;
		case 'c':
			if (session->configfile)
				free(session->configfile);
			session->configfile = strdup(optarg);
			dbg("configfile = %s\n", session->configfile);

			/*
			 * read the config file now.  Yes, this could override
			 * previously set options from the command line, but
			 * the user asked for it...
			 */
			//bti_parse_configfile(session);
			break;
		case 'h':
			display_help();
			goto exit;
		case 'n':
			session->dry_run = 1;
			break;
		case 'v':
			display_version();
			goto exit;
		default:
			display_help();
			goto exit;
		}
	}

	/*
	 * Show the version to make it easier to determine what
	 * is going on here
	 */
	if (debug)
		display_version();

	if (session->action == ACTION_UNKNOWN) {
		fprintf(stderr, "Unknown action, valid actions are:\n"
			"'update', 'friends', 'public', 'replies', 'group' or 'user'.\n");
		goto exit;
	}

	dbg("config file = %s\n", session->configfile);
	dbg("action = %d\n", session->action);

	/* fork ourself so that the main shell can get on
	 * with it's life as we try to connect and handle everything
	 */
	if (session->background) {
		child = fork();
		if (child) {
			dbg("child is %d\n", child);
			exit(0);
		}
	}
	switch (session->action) {
	case ACTION_PUBLIC:
		PUBLIC(account, session, retval);
		break;
	case ACTION_UPDATE:
		if (session->background || !session->interactive)
			tweet = get_string_from_stdin();
		else
			tweet = session->readline("tweet: ");
		if (!tweet || strlen(tweet) == 0) {
			dbg("no tweet?\n");
			return -1;
		}

		if (session->shrink_urls)
			tweet = shrink_urls(tweet);
		session->tweet = zalloc(strlen(tweet) + 10);
		if (session->bash)
			sprintf(session->tweet, "%c %s",
				getuid()? '$' : '#', tweet);
		else
			sprintf(session->tweet, "%s", tweet);
		if (tweet)
			free(tweet);
		dbg("tweet = %s\n", session->tweet);
		UPDATE(account, session, retval);
		break;
	case ACTION_FRIENDS:
		FRIENDS(account, session, retval);
		break;
	case ACTION_REPLIES:
		REPLIES(account, session, retval);
		break;
	default:
		retval = -1;
		break;
	}

	//      retval = send_request(session);

	if (retval && !session->background)
		fprintf(stderr, "operation failed\n");

	/* log_session(session, retval); */
	DESTORY(account);
 exit:
	session_readline_cleanup(session);
	session_free(session);
	return retval;;
}
Ejemplo n.º 2
0
int main(int argc, char *argv[], char *envp[])
{
	static const struct option options[] = {
		{ "debug", 0, NULL, 'd' },
		{ "verbose", 0, NULL, 'V' },
		{ "account", 1, NULL, 'a' },
		{ "password", 1, NULL, 'p' },
		{ "host", 1, NULL, 'H' },
		{ "proxy", 1, NULL, 'P' },
		{ "action", 1, NULL, 'A' },
		{ "user", 1, NULL, 'u' },
		{ "group", 1, NULL, 'G' },
		{ "logfile", 1, NULL, 'L' },
		{ "shrink-urls", 0, NULL, 's' },
		{ "help", 0, NULL, 'h' },
		{ "bash", 0, NULL, 'b' },
		{ "background", 0, NULL, 'B' },
		{ "dry-run", 0, NULL, 'n' },
		{ "page", 1, NULL, 'g' },
		{ "version", 0, NULL, 'v' },
		{ "config", 1, NULL, 'c' },
		{ "replyto", 1, NULL, 'r' },
		{ "retweet", 1, NULL, 'w' },
		{ }
	};
	struct session *session;
	pid_t child;
	char *tweet;
	static char password[80];
	int retval = 0;
	int option;
	char *http_proxy;
	time_t t;
	int page_nr;

	debug = 0;

	session = session_alloc();
	if (!session) {
		fprintf(stderr, "no more memory...\n");
		return -1;
	}

	/* get the current time so that we can log it later */
	time(&t);
	session->time = strdup(ctime(&t));
	session->time[strlen(session->time)-1] = 0x00;

	/* Get the home directory so we can try to find a config file */
	session->homedir = strdup(getenv("HOME"));

	/* set up a default config file location (traditionally ~/.bti) */
	session->configfile = zalloc(strlen(session->homedir) + 7);
	sprintf(session->configfile, "%s/.bti", session->homedir);

	/* Set environment variables first, before reading command line options
	 * or config file values. */
	http_proxy = getenv("http_proxy");
	if (http_proxy) {
		if (session->proxy)
			free(session->proxy);
		session->proxy = strdup(http_proxy);
		dbg("http_proxy = %s\n", session->proxy);
	}

	bti_parse_configfile(session);

	while (1) {
		option = getopt_long_only(argc, argv,
					  "dp:P:H:a:A:u:c:hg:G:sr:nVvw:",
					  options, NULL);
		if (option == -1)
			break;
		switch (option) {
		case 'd':
			debug = 1;
			break;
		case 'V':
			session->verbose = 1;
			break;
		case 'a':
			if (session->account)
				free(session->account);
			session->account = strdup(optarg);
			dbg("account = %s\n", session->account);
			break;
		case 'g':
			page_nr = atoi(optarg);
			dbg("page = %d\n", page_nr);
			session->page = page_nr;
			break;
		case 'r':
			session->replyto = strdup(optarg);
			dbg("in_reply_to_status_id = %s\n", session->replyto);
			break;
		case 'w':
			session->retweet = strdup(optarg);
			dbg("Retweet ID = %s\n", session->retweet);
			break;
		case 'p':
			if (session->password)
				free(session->password);
			session->password = strdup(optarg);
			dbg("password = %s\n", session->password);
			break;
		case 'P':
			if (session->proxy)
				free(session->proxy);
			session->proxy = strdup(optarg);
			dbg("proxy = %s\n", session->proxy);
			break;
		case 'A':
			if (strcasecmp(optarg, "update") == 0)
				session->action = ACTION_UPDATE;
			else if (strcasecmp(optarg, "friends") == 0)
				session->action = ACTION_FRIENDS;
			else if (strcasecmp(optarg, "user") == 0)
				session->action = ACTION_USER;
			else if (strcasecmp(optarg, "replies") == 0)
				session->action = ACTION_REPLIES;
			else if (strcasecmp(optarg, "public") == 0)
				session->action = ACTION_PUBLIC;
			else if (strcasecmp(optarg, "group") == 0)
				session->action = ACTION_GROUP;
			else if (strcasecmp(optarg, "retweet") == 0)
				session->action = ACTION_RETWEET;
			else
				session->action = ACTION_UNKNOWN;
			dbg("action = %d\n", session->action);
			break;
		case 'u':
			if (session->user)
				free(session->user);
			session->user = strdup(optarg);
			dbg("user = %s\n", session->user);
			break;

		case 'G':
			if (session->group)
				free(session->group);
			session->group = strdup(optarg);
			dbg("group = %s\n", session->group);
			break;
		case 'L':
			if (session->logfile)
				free(session->logfile);
			session->logfile = strdup(optarg);
			dbg("logfile = %s\n", session->logfile);
			break;
		case 's':
			session->shrink_urls = 1;
			break;
		case 'H':
			if (session->hosturl)
				free(session->hosturl);
			if (session->hostname)
				free(session->hostname);
			if (strcasecmp(optarg, "twitter") == 0) {
				session->host = HOST_TWITTER;
				session->hosturl = strdup(twitter_host);
				session->hostname = strdup(twitter_name);
			} else if (strcasecmp(optarg, "identica") == 0) {
				session->host = HOST_IDENTICA;
				session->hosturl = strdup(identica_host);
				session->hostname = strdup(identica_name);
			} else {
				session->host = HOST_CUSTOM;
				session->hosturl = strdup(optarg);
				session->hostname = strdup(optarg);
			}
			dbg("host = %d\n", session->host);
			break;
		case 'b':
			session->bash = 1;
			/* fall-through intended */
		case 'B':
			session->background = 1;
			break;
		case 'c':
			if (session->configfile)
				free(session->configfile);
			session->configfile = strdup(optarg);
			dbg("configfile = %s\n", session->configfile);

			/*
			 * read the config file now.  Yes, this could override
			 * previously set options from the command line, but
			 * the user asked for it...
			 */
			bti_parse_configfile(session);
			break;
		case 'h':
			display_help();
			goto exit;
		case 'n':
			session->dry_run = 1;
			break;
		case 'v':
			display_version();
			goto exit;
		default:
			display_help();
			goto exit;
		}
	}

	session_readline_init(session);
	/*
	 * Show the version to make it easier to determine what
	 * is going on here
	 */
	if (debug)
		display_version();

	if (session->host == HOST_TWITTER) {
		if (!session->consumer_key || !session->consumer_secret) {
			if (session->action == ACTION_USER ||
					session->action == ACTION_PUBLIC) {
				/*
				 * Some actions may still work without
				 * authentication
				 */
				session->guest = 1;
			} else {
				fprintf(stderr,
						"Twitter no longer supports HTTP basic authentication.\n"
						"Both consumer key, and consumer secret are required"
						" for bti in order to behave as an OAuth consumer.\n");
				goto exit;
			}
		}
		if (session->action == ACTION_GROUP) {
			fprintf(stderr, "Groups only work in Identi.ca.\n");
			goto exit;
		}
	} else {
		if (!session->consumer_key || !session->consumer_secret)
			session->no_oauth = 1;
	}

	if (session->no_oauth) {
		if (!session->account) {
			fprintf(stdout, "Enter account for %s: ",
				session->hostname);
			session->account = session->readline(NULL);
		}
		if (!session->password) {
			read_password(password, sizeof(password),
				      session->hostname);
			session->password = strdup(password);
		}
	} else if (!session->guest) {
		if (!session->access_token_key ||
		    !session->access_token_secret) {
			request_access_token(session);
			goto exit;
		}
	}

	if (session->action == ACTION_UNKNOWN) {
		fprintf(stderr, "Unknown action, valid actions are:\n"
			"'update', 'friends', 'public', 'replies', 'group' or 'user'.\n");
		goto exit;
	}

	if (session->action == ACTION_GROUP && !session->group) {
		fprintf(stdout, "Enter group name: ");
		session->group = session->readline(NULL);
	}

	if (session->action == ACTION_RETWEET) {
		if (!session->retweet) {
			char *rtid;

			fprintf(stdout, "Status ID to retweet: ");
			rtid = get_string_from_stdin();
			session->retweet = zalloc(strlen(rtid) + 10);
			sprintf(session->retweet, "%s", rtid);
			free(rtid);
		}

		if (!session->retweet || strlen(session->retweet) == 0) {
			dbg("no retweet?\n");
			return -1;
		}

		dbg("retweet ID = %s\n", session->retweet);
	}

	if (session->action == ACTION_UPDATE) {
		if (session->background || !session->interactive)
			tweet = get_string_from_stdin();
		else
			tweet = session->readline("tweet: ");
		if (!tweet || strlen(tweet) == 0) {
			dbg("no tweet?\n");
			return -1;
		}

		if (session->shrink_urls)
			tweet = shrink_urls(tweet);

		session->tweet = zalloc(strlen(tweet) + 10);
		if (session->bash)
			sprintf(session->tweet, "%c %s",
				getuid() ? '$' : '#', tweet);
		else
			sprintf(session->tweet, "%s", tweet);

		free(tweet);
		dbg("tweet = %s\n", session->tweet);
	}

	if (session->page == 0)
		session->page = 1;
	dbg("config file = %s\n", session->configfile);
	dbg("host = %d\n", session->host);
	dbg("action = %d\n", session->action);

	/* fork ourself so that the main shell can get on
	 * with it's life as we try to connect and handle everything
	 */
	if (session->background) {
		child = fork();
		if (child) {
			dbg("child is %d\n", child);
			exit(0);
		}
	}

	retval = send_request(session);
	if (retval && !session->background)
		fprintf(stderr, "operation failed\n");

	log_session(session, retval);
exit:
	session_readline_cleanup(session);
	session_free(session);
	return retval;;
}