Ejemplo n.º 1
0
int watchdog_main(int argc, char **argv)
{
	
	char *t_arg;
	unsigned long flags;
	flags = bb_getopt_ulflags(argc, argv, "t:", &t_arg);
	if (flags & 1)
		timer_duration = bb_xgetlarg(t_arg, 10, 0, INT_MAX);

	/* We're only interested in the watchdog device .. */
	if (optind < argc - 1 || argc == 1)
		bb_show_usage();

	if (daemon(0, 1) < 0)
		bb_perror_msg_and_die("Failed forking watchdog daemon");

	signal(SIGHUP, watchdog_shutdown);
	signal(SIGINT, watchdog_shutdown);

	fd = bb_xopen(argv[argc - 1], O_WRONLY);

	while (1) {
		/*
		 * Make sure we clear the counter before sleeping, as the counter value
		 * is undefined at this point -- PFM
		 */
		write(fd, "\0", 1);
		sleep(timer_duration);
	}

	watchdog_shutdown(0);

	return EXIT_SUCCESS;
}
Ejemplo n.º 2
0
/*
 * addgroup will take a login_name as its first parameter.
 *
 * gid
 *
 * can be customized via command-line parameters.
 * ________________________________________________________________________ */
int addgroup_main(int argc, char **argv)
{
	char *group;
	char *user;
	gid_t gid = 0;

	/* get remaining args */
	if(bb_getopt_ulflags(argc, argv, "g:", &group)) {
		gid = bb_xgetlarg(group, 10, 0, LONG_MAX);
	}

	if (optind < argc) {
		group = argv[optind];
		optind++;
	} else {
		bb_show_usage();
	}

	if (optind < argc) {
		user = argv[optind];
	} else {
		user = "";
	}

	if_i_am_not_root();

	/* werk */
	return addgroup(bb_path_group_file, group, gid, user);
}
int
start_stop_daemon_main(int argc, char **argv)
{
	unsigned long opt;
	char *signame = NULL;
	char *startas = NULL;

	bb_applet_long_options = ssd_long_options;

	bb_opt_complementaly = "K~S:S~K";
	opt = bb_getopt_ulflags(argc, argv, "KSba:n:s:u:x:", 
			&startas, &cmdname, &signame, &userspec, &execname);

	/* Check one and only one context option was given */
	if ((opt & 0x80000000UL) || (opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) {
		bb_show_usage();
	}

	if (signame) {
		signal_nr = bb_xgetlarg(signame, 10, 0, NSIG);
	}

	if (!execname && !userspec)
		bb_error_msg_and_die ("need at least one of -x or -u");

	if (!startas)
		startas = execname;

	if ((opt & SSD_CTX_START) && !startas)
		bb_error_msg_and_die ("-S needs -x or -a");

	argc -= optind;
	argv += optind;

	if (userspec && sscanf(userspec, "%d", &user_id) != 1)
		user_id = my_getpwnam(userspec);

	do_procfs();

	if (opt & SSD_CTX_STOP) {
		do_stop();
		return EXIT_SUCCESS;
	}

	if (found) {
		printf("%s already running.\n%d\n", execname ,found->pid);
		return EXIT_SUCCESS;
	}
	*--argv = startas;
	if (opt & SSD_OPT_BACKGROUND) {
		if (daemon(0, 0) == -1)
			bb_perror_msg_and_die ("unable to fork");
	}
	setsid();
	execv(startas, argv);
	bb_perror_msg_and_die ("unable to start %s", startas);
}
Ejemplo n.º 4
0
int
start_stop_daemon_main(int argc, char **argv)
{
	int flags;
	char *signame = NULL;
	bb_applet_long_options = ssd_long_options;

	flags = bb_getopt_ulflags(argc, argv, "KSba:n:s:u:x:", 
			&startas, &cmdname, &signame, &userspec, &execname);

	/* Be sneaky and avoid branching */
	stop = (flags & 1);
	start = (flags & 2);
	fork_before_exec = (flags & 4);

	if (signame) {
		signal_nr = bb_xgetlarg(signame, 10, 0, NSIG);
	}

	if (start == stop)
		bb_error_msg_and_die ("need exactly one of -S or -K");

	if (!execname && !userspec)
		bb_error_msg_and_die ("need at least one of -x or -u");

	if (!startas)
		startas = execname;

	if (start && !startas)
		bb_error_msg_and_die ("-S needs -x or -a");

	argc -= optind;
	argv += optind;

	if (userspec && sscanf(userspec, "%d", &user_id) != 1)
		user_id = my_getpwnam(userspec);

	do_procfs();

	if (stop) {
		do_stop();
		return EXIT_SUCCESS;
	}

	if (found) {
		printf("%s already running.\n%d\n", execname ,found->pid);
		return EXIT_SUCCESS;
	}
	*--argv = startas;
	if (fork_before_exec) {
		if (daemon(0, 0) == -1)
			bb_perror_msg_and_die ("unable to fork");
	}
	setsid();
	execv(startas, argv);
	bb_perror_msg_and_die ("unable to start %s", startas);
}
Ejemplo n.º 5
0
int chvt_main(int argc, char **argv)
{
	int fd, num;

	if (argc != 2) {
		bb_show_usage();
	}

	fd = get_console_fd();
	num =  bb_xgetlarg(argv[1], 10, 0, INT_MAX);
	if ((-1 == ioctl(fd, VT_ACTIVATE, num))
	|| (-1 == ioctl(fd, VT_WAITACTIVE, num))) {
		bb_perror_msg_and_die("ioctl");
	}
	return EXIT_SUCCESS;
}
Ejemplo n.º 6
0
/* Process options */
int run_parts_main(int argc, char **argv)
{
	char **args = xmalloc(2 * sizeof(char *));
	unsigned char test_mode = 0;
	unsigned short argcount = 1;
	int opt;

	umask(022);

	while ((opt = getopt_long (argc, argv, "tu:a:",
					runparts_long_options, NULL)) > 0)
	{
		switch (opt) {
			/* Enable test mode */
			case 't':
				test_mode++;
				break;
			/* Set the umask of the programs executed */
			case 'u':
				/* Check and set the umask of the program executed. As stated in the original
				 * run-parts, the octal conversion in libc is not foolproof; it will take the
				 * 8 and 9 digits under some circumstances. We'll just have to live with it.
				 */
				umask(bb_xgetlarg(optarg, 8, 0, 07777));
				break;
			/* Pass an argument to the programs */
			case 'a':
				/* Add an argument to the commands that we will call.
				 * Called once for every argument. */
				args = xrealloc(args, (argcount + 2) * (sizeof(char *)));
				args[argcount++] = optarg;
				break;
			default:
				bb_show_usage();
		}
	}

	/* We require exactly one argument: the directory name */
	if (optind != (argc - 1)) {
		bb_show_usage();
	}

	args[0] = argv[optind];
	args[argcount] = 0;

	return(run_parts(args, test_mode, environ));
}
Ejemplo n.º 7
0
int openvt_main(int argc, char **argv)
{
	int fd;
	char vtname[sizeof VC_FORMAT + 2];


	if (argc < 3)
        bb_show_usage();

	/* check for Illegal vt number: < 1 or > 12 */
	sprintf(vtname, VC_FORMAT,(int)bb_xgetlarg(argv[1], 10, 1, 12));

	argv+=2;
	argc-=2;

	if(fork() == 0) {
		/* leave current vt */

#ifdef   ESIX_5_3_2_D
		if (setpgrp() < 0) {
#else
		if (setsid() < 0) {
#endif

			bb_perror_msg_and_die("Unable to set new session");	
		}
		close(0);			/* so that new vt becomes stdin */

		/* and grab new one */
		fd = bb_xopen(vtname, O_RDWR);

		/* Reassign stdout and sterr */
		close(1);
		close(2);
		dup(fd);
		dup(fd);

		execvp(argv[0], argv);
		_exit(1);
	}
	return EXIT_SUCCESS;
}
Ejemplo n.º 8
0
int nice_main(int argc, char **argv)
{
	static const char Xetpriority_msg[] = "cannot %cet priority";

	int old_priority, adjustment;

	errno = 0;			 /* Needed for getpriority error detection. */
	old_priority = getpriority(PRIO_PROCESS, 0);
	if (errno) {
		bb_perror_msg_and_die(Xetpriority_msg, 'g');
	}

	if (!*++argv) {	/* No args, so (GNU) output current nice value. */
		bb_printf("%d\n", old_priority);
		bb_fflush_stdout_and_exit(EXIT_SUCCESS);
	}

	adjustment = 10;			/* Set default adjustment. */

	if ((argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) { /* "-n" */
		if (argc < 4) {			/* Missing priority and/or utility! */
			bb_show_usage();
		}
		adjustment = bb_xgetlarg(argv[1], 10, INT_MIN, INT_MAX);
		argv += 2;
	}

	{  /* Set our priority.  Handle integer wrapping for old + adjust. */
		int new_priority = int_add_no_wrap(old_priority, adjustment);

		if (setpriority(PRIO_PROCESS, 0, new_priority) < 0) {
			bb_perror_msg_and_die(Xetpriority_msg, 's');
		}
	}

	execvp(*argv, argv);		/* Now exec the desired program. */

	/* The exec failed... */
	bb_default_error_retval = (errno == ENOENT) ? 127 : 126; /* SUSv3 */
	bb_perror_msg_and_die("%s", *argv);
}
Ejemplo n.º 9
0
extern int watchdog_main(int argc, char **argv)
{
	int opt;

	while ((opt = getopt(argc, argv, "t:")) > 0) {
		switch (opt) {
			case 't':
				timer_duration = bb_xgetlarg(optarg, 10, 0, INT_MAX);
				break;
			default:
				bb_show_usage();
		}
	}

	/* We're only interested in the watchdog device .. */
	if (optind < argc - 1 || argc == 1)
		bb_show_usage();

	if (daemon(0, 1) < 0)
		bb_perror_msg_and_die("Failed forking watchdog daemon");

	signal(SIGHUP, watchdog_shutdown);
	signal(SIGINT, watchdog_shutdown);
	signal(SIGTERM, watchdog_safe_terminate);

	fd = bb_xopen(argv[argc - 1], O_WRONLY);

	while (1) {
		/*
		 * Make sure we clear the counter before sleeping, as the counter value
		 * is undefined at this point -- PFM
		 */
		write(fd, "\0", 1);
		sleep(timer_duration);
	}

	watchdog_shutdown(0);

	return EXIT_SUCCESS;
}
Ejemplo n.º 10
0
int deallocvt_main(int argc, char *argv[])
{
	/* num = 0 deallocate all unused consoles */
	int num = 0;

	switch(argc)
	{
		case 2:
			if((num = bb_xgetlarg(argv[1], 10, 0, INT_MAX)) == 0)
				bb_error_msg_and_die("0: illegal VT number");
		/* Fallthrough */
		case 1:
			break;
		default:
			bb_show_usage();
	}

	if (-1 == ioctl( get_console_fd(), VT_DISALLOCATE, num )) {
		bb_perror_msg_and_die("VT_DISALLOCATE");
	}
	return EXIT_SUCCESS;
}
Ejemplo n.º 11
0
/*
 * addgroup will take a login_name as its first parameter.
 *
 * gid
 *
 * can be customized via command-line parameters.
 * ________________________________________________________________________ */
int addgroup_main(int argc, char **argv)
{
	char *group;
	gid_t gid = 0;
	
	/* check for min, max and missing args and exit on error */
	bb_opt_complementally = "-1:?2:?";

	if (bb_getopt_ulflags(argc, argv, "g:", &group)) {
		gid = bb_xgetlarg(group, 10, 0, LONG_MAX);
	}
	/* move past the commandline options */
	argv += optind;

	/* need to be root */
	if(geteuid()) {
		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
	}

	/* werk */
	return addgroup(argv[0], gid, (argv[1]) ? argv[1] : "");
}
Ejemplo n.º 12
0
int
start_stop_daemon_main(int argc, char **argv)
{
	unsigned long opt;
	char *signame = NULL;
	char *startas = NULL;

	bb_applet_long_options = ssd_long_options;

	/* Check required one context option was given */
	bb_opt_complementally = "K:S:?:K--S:S--K";
	opt = bb_getopt_ulflags(argc, argv, "KSbqma:n:s:u:x:p:",
		&startas, &cmdname, &signame, &userspec, &execname, &pidfile);

	
	quiet = opt & SSD_OPT_QUIET;

	if (signame) {
		signal_nr = bb_xgetlarg(signame, 10, 0, NSIG);
	}

	if (!execname && !pidfile && !userspec && !cmdname)
		bb_error_msg_and_die ("need at least one of -x, -p, -u, or -n");

	if (!startas)
		startas = execname;

	if ((opt & SSD_CTX_START) && !startas)
		bb_error_msg_and_die ("-S needs -x or -a");

	if ((opt & SSD_OPT_MAKEPID) && pidfile == NULL)
		bb_error_msg_and_die ("-m needs -p");

	argc -= optind;
	argv += optind;

	if (userspec && sscanf(userspec, "%d", &user_id) != 1)
		user_id = bb_xgetpwnam(userspec);

	if (opt & SSD_CTX_STOP) {
		do_stop();
		return EXIT_SUCCESS;
	}

	do_procinit();

	if (found) {
		if (!quiet)
			printf("%s already running.\n%d\n", execname ,found->pid);
		return EXIT_SUCCESS;
	}
	*--argv = startas;
	if (opt & SSD_OPT_BACKGROUND) {
		if (daemon(0, 0) == -1)
			bb_perror_msg_and_die ("unable to fork");
		setsid();
	}
	if (opt & SSD_OPT_MAKEPID) {
		/* user wants _us_ to make the pidfile */
		FILE *pidf = fopen(pidfile, "w");
		pid_t pidt = getpid();
		if (pidf == NULL)
			bb_perror_msg_and_die("Unable to write pidfile '%s'", pidfile);
		fprintf(pidf, "%d\n", pidt);
		fclose(pidf);
	}
	execv(startas, argv);
	bb_perror_msg_and_die ("unable to start %s", startas);
}
Ejemplo n.º 13
0
int mkswap_main(int argc, char **argv)
{
    char *tmp;
    struct stat statbuf;
    int sz;
    int maxpages;
    int goodpages;
#ifdef __sparc__
    int force = 0;
#endif

    init_signature_page();		/* get pagesize */

    bb_opt_complementally = "?"; /* call bb_show_usage internally */
    sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
    if (sz & 1)
        check = 1;
#ifdef __sparc__
    if (sz & 2)
        force = 1;
#endif
#if ENABLE_FEATURE_MKSWAP_V0
    if (sz & 4) {
        version = bb_xgetlarg(tmp, 10, 0, 1);
    } else {
        if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117))
            version = 0;
        else
            version = 1;
    }
#endif

    argv += optind;
    argc -= optind;

    goodpages = pagesize / 1024; /* cache division */
    while (argc--) {
        if (device_name) {
            PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
            argc = 0; /* ignore any surplus args.. */
        } else {
            device_name = argv[0];
            sz = get_size(device_name);
            argv++;
        }
    }

    if (!device_name) {
        bb_error_msg_and_die("error: Nowhere to set up swap on?");
    }
    if (!PAGES) {
        PAGES = sz;
    }

#if 0
    maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
#else
    if (!version)
        maxpages = V0_MAX_PAGES;
    else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1))
        maxpages = V1_MAX_PAGES;
    else {
        maxpages = V1_OLD_MAX_PAGES;
        if (maxpages > V1_MAX_PAGES)
            maxpages = V1_MAX_PAGES;
    }
#endif
    if (PAGES > maxpages) {
        PAGES = maxpages;
        bb_error_msg("warning: truncating swap area to %ldkB",
                     PAGES * goodpages);
    }

    DEV = bb_xopen3(device_name, O_RDWR, 0);
    if (fstat(DEV, &statbuf) < 0)
        bb_perror_msg_and_die("%s", device_name);
    if (!S_ISBLK(statbuf.st_mode))
        check = 0;
    else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
        bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);

#ifdef __sparc__
    if (!force && version == 0) {
        /* Don't overwrite partition table unless forced */
        unsigned char *buffer = (unsigned char *) signature_page;
        unsigned short *q, sum;

        if (read(DEV, buffer, 512) != 512)
            bb_error_msg_and_die("fatal: first page unreadable");
        if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
            q = (unsigned short *) (buffer + 510);
            for (sum = 0; q >= (unsigned short *) buffer;)
                sum ^= *q--;
            if (!sum) {
                bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
                             "This probably means creating v0 swap would destroy your partition table\n"
                             "No swap created. If you really want to create swap v0 on that device, use\n"
                             "the -f option to force it.", device_name);
                return EXIT_FAILURE;
            }
        }
    }
#endif

    if (version == 0 || check)
        check_blocks();
    if (version == 0 && !bit_test_and_clear(signature_page, 0))
        bb_error_msg_and_die("fatal: first page unreadable");
    if (version == 1) {
        p->swap_version = version;
        p->last_page = PAGES - 1;
        p->nr_badpages = badpages;
    }

    goodpages = PAGES - badpages - 1;
    if (goodpages <= 0)
        bb_error_msg_and_die("Unable to set up swap-space: unreadable");
    printf("Setting up swapspace version %d, size = %ld bytes\n",
           version, (long) (goodpages * pagesize));
    write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");

    sz = ((version == 0) ? 0 : 1024); /* offset */
    if (lseek(DEV, sz, SEEK_SET) != sz)
        bb_error_msg_and_die("unable to rewind swap-device");
    goodpages = pagesize - sz; /* cache substraction */
    if (write(DEV, (char *) signature_page + sz, goodpages)
            != goodpages)
        bb_error_msg_and_die("unable to write signature page");

    /*
     * A subsequent swapon() will fail if the signature
     * is not actually on disk. (This is a kernel bug.)
     */
    if (fsync(DEV))
        bb_error_msg_and_die("fsync failed");
    if (ENABLE_FEATURE_CLEAN_UP) {
        close(DEV);
        free(signature_page);
    }
    return EXIT_SUCCESS;
}
Ejemplo n.º 14
0
extern int fold_main(int argc, char **argv)
{
	/* If nonzero, try to break on whitespace. */
	int break_spaces;

	/* If nonzero, at least one of the files we read was standard input. */
	int have_read_stdin;

	int width = 80;
	int i;
	int optc;
	int errs = 0;

	break_spaces = count_bytes = have_read_stdin = 0;

	/* Turn any numeric options into -w options.  */
	for (i = 1; i < argc; i++) {
		char const *a = argv[i];

		if (a[0] == '-') {
			if (a[1] == '-' && !a[2])
				break;
			if (isdigit(a[1])) {
				char *s = xmalloc(strlen(a) + 2);

				s[0] = '-';
				s[1] = 'w';
				strcpy(s + 2, a + 1);
				argv[i] = s;
			}
		}
	}

	while ((optc = getopt(argc, argv, "bsw:")) > 0) {
		switch (optc) {
			case 'b':		/* Count bytes rather than columns. */
				count_bytes = 1;
				break;
			case 's':		/* Break at word boundaries. */
				break_spaces = 1;
				break;
			case 'w': {	/* Line width. */
				width = bb_xgetlarg(optarg, 10, 1, 10000);
				break;
			}
			default:
				bb_show_usage();
		}
	}

	argv += optind;
	if (!*argv) {
		*--argv = "-";
	}

	do {
		FILE *istream = bb_wfopen_input(*argv);
		if (istream != NULL) {
			int c;
			int column = 0;		/* Screen column where next char will go. */
			int offset_out = 0;	/* Index in `line_out' for next char. */
			static char *line_out = NULL;
			static int allocated_out = 0;

			while ((c = getc(istream)) != EOF) {
				if (offset_out + 1 >= allocated_out) {
					allocated_out += 1024;
					line_out = xrealloc(line_out, allocated_out);
				}

				if (c == '\n') {
					line_out[offset_out++] = c;
					fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
					column = offset_out = 0;
					continue;
				}

rescan:
				column = adjust_column(column, c);

				if (column > width) {
					/* This character would make the line too long.
			 		  Print the line plus a newline, and make this character
					   start the next line. */
					if (break_spaces) {
						/* Look for the last blank. */
						int logical_end;

						for (logical_end = offset_out - 1; logical_end >= 0; logical_end--) {
							if (isblank(line_out[logical_end])) {
								break;
							}
						}
						if (logical_end >= 0) {
							/* Found a blank.  Don't output the part after it. */
							logical_end++;
							fwrite(line_out, sizeof(char), (size_t) logical_end, stdout);
							putchar('\n');
							/* Move the remainder to the beginning of the next line.
							   The areas being copied here might overlap. */
							memmove(line_out, line_out + logical_end, offset_out - logical_end);
							offset_out -= logical_end;
							for (column = i = 0; i < offset_out; i++) {
								column = adjust_column(column, line_out[i]);
							}
							goto rescan;
						}
					} else {
						if (offset_out == 0) {
							line_out[offset_out++] = c;
							continue;
						}
					}
					line_out[offset_out++] = '\n';
					fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
					column = offset_out = 0;
					goto rescan;
				}

				line_out[offset_out++] = c;
			}

			if (offset_out) {
				fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
			}

			if (ferror(istream) || bb_fclose_nonstdin(istream)) {
				bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
				errs |= EXIT_FAILURE;
			}
		} else {
			errs |= EXIT_FAILURE;
		}
	} while (*++argv);

	bb_fflush_stdout_and_exit(errs);
}
Ejemplo n.º 15
0
int renice_main(int argc, char **argv)
{
	static const char Xetpriority_msg[] = "%d : %cetpriority";

	int retval = EXIT_SUCCESS;
	int which = PRIO_PROCESS;	/* Default 'which' value. */
	int use_relative = 0;
	int adjustment, new_priority;
	id_t who;

	++argv;

	/* Check if we are using a relative adjustment. */
	if (argv[0] && (argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) {
		use_relative = 1;
		++argv;
	}

	if (!*argv) {				/* No args?  Then show usage. */
		bb_show_usage();
	}

	/* Get the priority adjustment (absolute or relative). */
	adjustment = bb_xgetlarg(*argv, 10, INT_MIN, INT_MAX);

	while (*++argv) {
		/* Check for a mode switch. */
		if ((argv[0][0] == '-') && argv[0][1] && !argv[0][2]) {
			static const char opts[]
				= { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER };
			const char *p;
			if ((p = strchr(opts, argv[0][1]))) {
				which = p[4];
				continue;
			}
		}

		/* Process an ID arg. */
		if (which == PRIO_USER) {
			struct passwd *p;
			if (!(p = getpwnam(*argv))) {
				bb_error_msg("unknown user: %s", *argv);
				goto HAD_ERROR;
			}
			who = p->pw_uid;
		} else {
			char *e;
			errno = 0;
			who = strtoul(*argv, &e, 10);
			if (*e || (*argv == e) || errno) {
				bb_error_msg("bad value: %s", *argv);
				goto HAD_ERROR;
			}
		}

		/* Get priority to use, and set it. */
		if (use_relative) {
			int old_priority;

			errno = 0;	 /* Needed for getpriority error detection. */
			old_priority = getpriority(which, who);
			if (errno) {
				bb_perror_msg(Xetpriority_msg, who, 'g');
				goto HAD_ERROR;
			}

			new_priority = int_add_no_wrap(old_priority, adjustment);
		} else {
			new_priority = adjustment;
		}

		if (setpriority(which, who, new_priority) == 0) {
			continue;
		}

		bb_perror_msg(Xetpriority_msg, who, 's');
	HAD_ERROR:
		retval = EXIT_FAILURE;
	}

	/* No need to check for errors outputing to stderr since, if it
	 * was used, the HAD_ERROR label was reached and retval was set. */

	return retval;
}
Ejemplo n.º 16
0
extern int fold_main(int argc, char **argv)
{
	char *w_opt;
	int width = 80;
	int i;
	int errs = 0;


#ifdef CONFIG_FEATURE_SUSv2_OBSOLETE
	/* Turn any numeric options into -w options.  */
	for (i = 1; i < argc; i++) {
		char const *a = argv[i];

		if (a[0] == '-') {
			if (a[1] == '-' && !a[2])
				break;
			if (isdigit(a[1])) {
				char *s = xmalloc(strlen(a) + 2);

				s[0] = '-';
				s[1] = 'w';
				strcpy(s + 2, a + 1);
				argv[i] = s;
			}
		}
	}
#endif

	flags = bb_getopt_ulflags(argc, argv, "bsw:", &w_opt);
	if (flags & FLAG_WIDTH)
		width = bb_xgetlarg(w_opt, 10, 1, 10000);

	argv += optind;
	if (!*argv) {
		*--argv = "-";
	}

	do {
		FILE *istream = bb_wfopen_input(*argv);
		if (istream != NULL) {
			int c;
			int column = 0;		/* Screen column where next char will go. */
			int offset_out = 0;	/* Index in `line_out' for next char. */
			static char *line_out = NULL;
			static int allocated_out = 0;

			while ((c = getc(istream)) != EOF) {
				if (offset_out + 1 >= allocated_out) {
					allocated_out += 1024;
					line_out = xrealloc(line_out, allocated_out);
				}

				if (c == '\n') {
					line_out[offset_out++] = c;
					fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
					column = offset_out = 0;
					continue;
				}

rescan:
				column = adjust_column(column, c);

				if (column > width) {
					/* This character would make the line too long.
					   Print the line plus a newline, and make this character
					   start the next line. */
					if (flags & FLAG_BREAK_SPACES) {
						/* Look for the last blank. */
						int logical_end;

						for (logical_end = offset_out - 1; logical_end >= 0; logical_end--) {
							if (isblank(line_out[logical_end])) {
								break;
							}
						}
						if (logical_end >= 0) {
							/* Found a blank.  Don't output the part after it. */
							logical_end++;
							fwrite(line_out, sizeof(char), (size_t) logical_end, stdout);
							putchar('\n');
							/* Move the remainder to the beginning of the next line.
							   The areas being copied here might overlap. */
							memmove(line_out, line_out + logical_end, offset_out - logical_end);
							offset_out -= logical_end;
							for (column = i = 0; i < offset_out; i++) {
								column = adjust_column(column, line_out[i]);
							}
							goto rescan;
						}
					} else {
						if (offset_out == 0) {
							line_out[offset_out++] = c;
							continue;
						}
					}
					line_out[offset_out++] = '\n';
					fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
					column = offset_out = 0;
					goto rescan;
				}

				line_out[offset_out++] = c;
			}

			if (offset_out) {
				fwrite(line_out, sizeof(char), (size_t) offset_out, stdout);
			}

			if (ferror(istream) || bb_fclose_nonstdin(istream)) {
				bb_perror_msg("%s", *argv);	/* Avoid multibyte problems. */
				errs |= EXIT_FAILURE;
			}
		} else {
			errs |= EXIT_FAILURE;
		}
	} while (*++argv);

	bb_fflush_stdout_and_exit(errs);
}