Ejemplo n.º 1
0
int
get_slot_number(int so)
{
    char            buf[8];
    int             rv;
    int             nslot;

    if ((rv = write(so, "S", 1)) < 1) {
	warn("write");
	goto err;
    } else if (rv != 1) {
	warnc(0, "write: fail.");
	goto err;
    }

    if ((rv = read(so, buf, sizeof buf)) < 0) {
	warn("read");
	goto err;
    }
    buf[sizeof buf - 1] = 0;
    if (sscanf(buf, "%d", &nslot) != 1) {
	warnc(0, "Invalid response.");
	goto err;
    }
    return nslot;
  err:
    return -1;
}
Ejemplo n.º 2
0
int
get_slot_info(int so, int slot, char **manuf, char **version, char
	      **device, int *state)
{
    int             rc = -1;
    int             rv;
    static char     buf[1024];
    int             slen;
    char           *s;
    char           *sl;

    char           *_manuf;
    char           *_version;
    char           *_device;

    slen = snprintf(buf, sizeof buf, "N%d", slot);
    if ((rv = write(so, buf, slen)) < 0) {
	warn("write");
	goto err;
    } else if (rv != slen) {
	warnc(0, "write");
	goto err;
    }

    if ((rv = read(so, buf, sizeof buf)) < 0) {
	warn("read");
	goto err;
    }

    s = buf;
    if ((sl = strsep(&s, "~")) == NULL)
	goto parse_err;
    if (atoi(sl) != slot)
	goto parse_err;
    if ((_manuf = strsep(&s, "~")) == NULL)
	goto parse_err;
    if ((_version = strsep(&s, "~")) == NULL)
	goto parse_err;
    if ((_device = strsep(&s, "~")) == NULL)
	goto parse_err;
    if (sscanf(s, "%1d", state) != 1)
	goto parse_err;
    if (s != NULL && strchr(s, '~') != NULL)
	goto parse_err;

    *manuf = strdup(_manuf);
    *version = strdup(_version);
    *device = strdup(_device);
    if (*manuf == NULL || *version == NULL || *device == NULL) {
	warn("strdup");
	goto err;
    }

    rc = 0;
  err:
    return rc;
  parse_err:
    warnc(0, "Invalid response: %*s", rv, buf);
    return rc;
}
Ejemplo n.º 3
0
static int
read_kld(char *filename, char *kldname)
{
	struct mod_metadata md;
	struct elf_file ef;
	void **p, **orgp;
	int error, eftype, nmlen;
	long start, finish, entries;
	char kldmodname[MAXMODNAME + 1], cval[MAXMODNAME + 1], *cp;

	if (verbose || dflag)
		printf("%s\n", filename);
	error = ef_open(filename, &ef, verbose);
	if (error) {
		error = ef_obj_open(filename, &ef, verbose);
		if (error) {
			if (verbose)
				warnc(error, "elf_open(%s)", filename);
			return error;
		}
	}
	eftype = EF_GET_TYPE(&ef);
	if (eftype != EFT_KLD && eftype != EFT_KERNEL)  {
		EF_CLOSE(&ef);
		return 0;
	}
	if (!dflag) {
		cp = strrchr(kldname, '.');
		nmlen = (cp != NULL) ? cp - kldname : (int)strlen(kldname);
		if (nmlen > MAXMODNAME)
			nmlen = MAXMODNAME;
		strlcpy(kldmodname, kldname, nmlen);
/*		fprintf(fxref, "%s:%s:%d\n", kldmodname, kldname, 0);*/
	}
	do {
		check(EF_LOOKUP_SET(&ef, MDT_SETNAME, &start, &finish,
		    &entries));
		check(EF_SEG_READ_ENTRY_REL(&ef, start, sizeof(*p) * entries,
		    (void *)&p));
		orgp = p;
		while(entries--) {
			check(EF_SEG_READ_REL(&ef, (Elf_Off)*p, sizeof(md),
			    &md));
			p++;
			check(EF_SEG_READ(&ef, (Elf_Off)md.md_cval,
			    sizeof(cval), cval));
			cval[MAXMODNAME] = '\0';
			parse_entry(&md, cval, &ef, kldname);
		}
		if (error)
			warnc(error, "error while reading %s", filename);
		free(orgp);
	} while(0);
	EF_CLOSE(&ef);
	return error;
}
Ejemplo n.º 4
0
int
main(int argc, char *argv[])
{
	char *progname;
	char *ttyname;
	int fd;
	int dofree;

	dofree = 0;

	progname = basename(argv[0]);
	if (argc != 2)
		errx(EX_USAGE, "usage: %s <ttyname>\n", progname);
	if (geteuid() != 0)
		errx(EX_NOPERM, "Sorry\n");

	if (argv[1][0] == '/') {
		ttyname = argv[1];
	} else {
		size_t len, maxpath, result;

		len = strlen(argv[1]) + sizeof(DEVPATHNAME) + 1;

		maxpath = pathconf(DEVPATHNAME, _PC_PATH_MAX);
		if (len > maxpath) {
			warnc(ENAMETOOLONG, ttyname);
			exit(EX_DATAERR);
		}

		ttyname = malloc(len);
		if (ttyname == NULL) {
			warnc(ENOMEM, "malloc");
			exit(EX_OSERR);
		}
		dofree = 1;

		result = snprintf(ttyname, len, "%s/%s", DEVPATHNAME, argv[1]);
		if (result >= len)
			warnc(ENOMEM, "snprintf");
	}

	fd = open(ttyname, O_RDWR);
	if (fd == -1) {
		warnc(errno, "open %s", ttyname);
		if (dofree)
			free(ttyname);
		exit(EX_OSERR);
	}

	if (0 != ioctl(fd, TIOCNXCL, 0))
		warnc(errno, "ioctl TIOCNXCL %s", ttyname);

	if (dofree)
		free(ttyname);
	exit(0);
}
Ejemplo n.º 5
0
/* Helper function to set a drive to a given state. */
static int
drive_set_state(char *drive, U8 Action, U8 State, const char *name)
{
	CONFIG_PAGE_RAID_PHYS_DISK_0 *info;
	struct mpt_drive_list *list;
	U8 PhysDiskNum;
	int error, fd;

	fd = mpt_open(mpt_unit);
	if (fd < 0) {
		error = errno;
		warn("mpt_open");
		return (error);
	}

	list = mpt_pd_list(fd);
	if (list == NULL) {
		close(fd);
		return (errno);
	}

	if (mpt_lookup_drive(list, drive, &PhysDiskNum) < 0) {
		error = errno;
		warn("Failed to find drive %s", drive);
		close(fd);
		return (error);
	}
	mpt_free_pd_list(list);

	/* Get the info for this drive. */
	info = mpt_pd_info(fd, PhysDiskNum, NULL);
	if (info == NULL) {
		error = errno;
		warn("Failed to fetch info for drive %u", PhysDiskNum);
		close(fd);
		return (error);
	}

	/* Try to change the state. */
	if (info->PhysDiskStatus.State == State) {
		warnx("Drive %u is already in the desired state", PhysDiskNum);
		free(info);
		close(fd);
		return (EINVAL);
	}

	error = mpt_raid_action(fd, Action, 0, 0, PhysDiskNum, 0, NULL, 0, NULL,
	    NULL, 0, NULL, NULL, 0);
	if (error) {
		warnc(error, "Failed to set drive %u to %s", PhysDiskNum, name);
		free(info);
		close(fd);
		return (error);
	}

	free(info);
	close(fd);

	return (0);
}
Ejemplo n.º 6
0
/*
 * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
 * given in these files.
 */
void
set_profile(void)
{
    FILE *f;
    char        fname[BUFSIZ];
    char	*home;
    static char prof[] = ".indent.pro";

    home = getenv("HOME");
    if (home != NULL && *home != '\0') {
	if (snprintf(fname, sizeof fname, "%s/%s", home, prof) >= sizeof fname) {
	    warnc(ENAMETOOLONG, "%s/%s", home, prof);
	    return;
	}
	if ((f = fopen(option_source = fname, "r")) != NULL) {
	    scan_profile(f);
	    (void) fclose(f);
	}
    }
    if ((f = fopen(option_source = prof, "r")) != NULL) {
	scan_profile(f);
	(void) fclose(f);
    }
    option_source = "Command line";
}
Ejemplo n.º 7
0
/*
 * Parse -S option.
 */
static unsigned long long
parse_memory_buffer_value(const char *value)
{

	if (value == NULL)
		return (available_free_memory);
	else {
		char *endptr;
		unsigned long long membuf;

		endptr = NULL;
		errno = 0;
		membuf = strtoll(value, &endptr, 10);

		if (errno != 0) {
			warn("%s",getstr(4));
			membuf = available_free_memory;
		} else {
			switch (*endptr){
			case 'Y':
				membuf *= 1024;
				/* FALLTHROUGH */
			case 'Z':
				membuf *= 1024;
				/* FALLTHROUGH */
			case 'E':
				membuf *= 1024;
				/* FALLTHROUGH */
			case 'P':
				membuf *= 1024;
				/* FALLTHROUGH */
			case 'T':
				membuf *= 1024;
				/* FALLTHROUGH */
			case 'G':
				membuf *= 1024;
				/* FALLTHROUGH */
			case 'M':
				membuf *= 1024;
				/* FALLTHROUGH */
			case '\0':
			case 'K':
				membuf *= 1024;
				/* FALLTHROUGH */
			case 'b':
				break;
			case '%':
				membuf = (available_free_memory * membuf) /
				    100;
				break;
			default:
				warnc(EINVAL, "%s", optarg);
				membuf = available_free_memory;
			}
		}
		return (membuf);
	}
}
Ejemplo n.º 8
0
int
main(int argc, char *argv[])
{
	const char *ifname;
	char *driver;
	int error;
	bool ok;

	while (getopt(argc, argv, "") != -1)
		usage();
	argc -= optind;
	argv += optind;

	if (argc == 0)	
		usage();

	if (argc == 1) {
		error = ifname2drivername(*argv, &driver);
		if (error != 0)
			errc(1, error, "ifname2drivername");
		printf("%s\n", driver);
		free(driver);
		return (0);
	}

	ok = true;
	while (argc--) {
		ifname = *argv++;

		error = ifname2drivername(ifname, &driver);
		if (error != 0) {
			warnc(error, "ifname2drivername(\"%s\")", ifname);
			ok = false;
			continue;
		}
		printf("%s: %s\n", ifname, driver);
		free(driver);
	}

	if (!ok)
		return (1);

	return (0);
}
Ejemplo n.º 9
0
int
connect_to_pccardd(char **path)
{
    int             so = -1;
    int             pccardd_len;
    struct sockaddr_un pccardq;
    struct sockaddr_un pccardd;

    if ((so = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
	warn("socket");
	goto err;
    }

    snprintf(pccardq.sun_path, sizeof pccardq.sun_path,
	     "%s/%s%ld%ld", tmp_dir, prog, (long) getpid(), (long) time(0));
    pccardq.sun_family = AF_UNIX;
    pccardq.sun_len = offsetof(struct sockaddr_un, sun_path) + strlen(pccardq.sun_path);
    if (bind(so, (struct sockaddr *) &pccardq, pccardq.sun_len) < 0) {
	warn("bind: %s", pccardq.sun_path);
	goto err;
    }
    if ((*path = strdup(pccardq.sun_path)) == NULL) {
	warn("strdup");
	goto err;
    }

    pccardd_len = strlen(pccardd_file) + 1;
    if (pccardd_len > sizeof pccardd.sun_path) {
	warnc(0, "%s: too long", pccardd_file);
	goto err;
    }
    pccardd.sun_len = offsetof(struct sockaddr_un, sun_path) + pccardd_len;
    pccardd.sun_family = AF_UNIX;
    strcpy(pccardd.sun_path, pccardd_file);
    if (connect(so, (struct sockaddr *) &pccardd, pccardd.sun_len) < 0) {
	warn("connect: %s", pccardd_file);
	goto err;
    }
    return so;
  err:
    if (so >= 0)
	close(so);
    return -1;
}
Ejemplo n.º 10
0
int
proc_arg(int ac, char **av)
{
    int             rc = -1;
    int             ch;

    char           *p = strrchr(av[0], '/');
    prog = p ? p + 1 : av[0];

    tmp_dir = getenv("TMPDIR") ? getenv("TMPDIR") : tmp_dir;

    while ((ch = getopt(ac, av, "ans:")) != -1) {
	switch (ch) {
	case 'a':
	    slot_map = ~0;
	    break;
	case 'n':
	    slot_map = 0;
	    break;
	case 's':
	    {
		int             n = atoi(optarg);
		if (n < 0 || n >= CHAR_BIT * sizeof slot_map) {
		    warnc(0, "Invalid slot number.");
		    usage();
		    goto out;
		}
		if (slot_map == ~0)
		    slot_map = 0;
		slot_map |= 1 << n;
	    }
	    break;
	default:
	    usage();
	    goto out;
	}
    }

    rc = 0;
  out:
    return rc;
}
Ejemplo n.º 11
0
int
create_knlist(char *name, int fd, DB *db)
{
	int error, ksyms;

	if (strcmp(name, _PATH_KSYMS) == 0) {
		ksyms = 1;
	} else {
		ksyms = 0;
	}

	fmterr = NULL;
	kfile = name;
	/* rval of 1 means wrong executable type */
	error = __elf_knlist(fd, db, ksyms);

	if (fmterr != NULL)
		warnc(EFTYPE, "%s: %s", kfile, fmterr);

	return(error);
}
Ejemplo n.º 12
0
Archivo: banipd.c Proyecto: julp/banip
static void cleanup(void)
{
    if (NULL != buffer) {
        free(buffer);
        buffer = NULL;
    }
    if (NULL != ctxt) {
        if (NULL != engine->close) {
            engine->close(ctxt);
        }
        free(ctxt);
        ctxt = NULL;
    }
    queue_close(&queue);
    if (NULL != pidfilename) {
        if (0 != unlink(pidfilename)) {
            warnc("unlink failed");
        }
    }
    if (NULL != err_file && fileno(err_file) > 2) {
        fclose(err_file);
        err_file = NULL;
    }
}
Ejemplo n.º 13
0
/*
 * Diff directory traversal. Will be called recursively if -r was specified.
 */
void
diffdir(char *p1, char *p2, int flags)
{
	struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL;
	struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL;
	size_t dirlen1, dirlen2;
	char path1[MAXPATHLEN], path2[MAXPATHLEN];
	int pos;

	dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1));
	if (dirlen1 >= sizeof(path1) - 1) {
		warnc(ENAMETOOLONG, "%s", p1);
		status = 2;
		return;
	}
	if (path1[dirlen1 - 1] != '/') {
		path1[dirlen1++] = '/';
		path1[dirlen1] = '\0';
	}
	dirlen2 = strlcpy(path2, *p2 ? p2 : ".", sizeof(path2));
	if (dirlen2 >= sizeof(path2) - 1) {
		warnc(ENAMETOOLONG, "%s", p2);
		status = 2;
		return;
	}
	if (path2[dirlen2 - 1] != '/') {
		path2[dirlen2++] = '/';
		path2[dirlen2] = '\0';
	}

	/*
	 * Get a list of entries in each directory, skipping "excluded" files
	 * and sorting alphabetically.
	 */
	pos = scandir(path1, &dirp1, selectfile, alphasort);
	if (pos == -1) {
		if (errno == ENOENT && (Nflag || Pflag)) {
			pos = 0;
		} else {
			warn("%s", path1);
			goto closem;
		}
	}
	dp1 = dirp1;
	edp1 = dirp1 + pos;

	pos = scandir(path2, &dirp2, selectfile, alphasort);
	if (pos == -1) {
		if (errno == ENOENT && Nflag) {
			pos = 0;
		} else {
			warn("%s", path2);
			goto closem;
		}
	}
	dp2 = dirp2;
	edp2 = dirp2 + pos;

	/*
	 * If we were given a starting point, find it.
	 */
	if (start != NULL) {
		while (dp1 != edp1 && strcmp((*dp1)->d_name, start) < 0)
			dp1++;
		while (dp2 != edp2 && strcmp((*dp2)->d_name, start) < 0)
			dp2++;
	}

	/*
	 * Iterate through the two directory lists, diffing as we go.
	 */
	while (dp1 != edp1 || dp2 != edp2) {
		dent1 = dp1 != edp1 ? *dp1 : NULL;
		dent2 = dp2 != edp2 ? *dp2 : NULL;

		pos = dent1 == NULL ? 1 : dent2 == NULL ? -1 :
		    strcmp(dent1->d_name, dent2->d_name);
		if (pos == 0) {
			/* file exists in both dirs, diff it */
			diffit(dent1, path1, dirlen1, path2, dirlen2, flags);
			dp1++;
			dp2++;
		} else if (pos < 0) {
			/* file only in first dir, only diff if -N */
			if (Nflag)
				diffit(dent1, path1, dirlen1, path2, dirlen2,
				    flags);
			else if (lflag)
				dent1->d_status |= D_ONLY;
			else
				print_only(path1, dirlen1, dent1->d_name);
			dp1++;
		} else {
			/* file only in second dir, only diff if -N or -P */
			if (Nflag || Pflag)
				diffit(dent2, path1, dirlen1, path2, dirlen2,
				    flags);
			else if (lflag)
				dent2->d_status |= D_ONLY;
			else
				print_only(path2, dirlen2, dent2->d_name);
			dp2++;
		}
	}
	if (lflag) {
		path1[dirlen1] = '\0';
		path2[dirlen2] = '\0';
		for (dp1 = dirp1; (dent1 = *dp1) != NULL; dp1++) {
			print_status(dent1->d_status, path1, path2,
			    dent1->d_name);
		}
		for (dp2 = dirp2; (dent2 = *dp2) != NULL; dp2++) {
			if (dent2->d_status == D_ONLY)
				print_status(dent2->d_status, path2, NULL,
				    dent2->d_name);
		}
	}

closem:
	if (dirp1 != NULL) {
		for (dp1 = dirp1; dp1 < edp1; dp1++)
			xfree(*dp1);
		xfree(dirp1);
	}
	if (dirp2 != NULL) {
		for (dp2 = dirp2; dp2 < edp2; dp2++)
			xfree(*dp2);
		xfree(dirp2);
	}
}
Ejemplo n.º 14
0
int
main(int argc, char *argv[])
{
	FTS *ftsp;
	FTSENT *p;
	void *set;
	unsigned long val;
	int oct;
	mode_t omode;
	int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval, atflags;
	uid_t uid;
	gid_t gid;
	u_int32_t fclear, fset;
	char *ep, *mode, *cp, *flags;

	if (strlen(__progname) > 2) {
		ischown = __progname[2] == 'o';
		ischgrp = __progname[2] == 'g';
		ischmod = __progname[2] == 'm';
		ischflags = __progname[2] == 'f';
	}

	uid = (uid_t)-1;
	gid = (gid_t)-1;
	Hflag = Lflag = Rflag = fflag = hflag = 0;
	while ((ch = getopt(argc, argv, "HLPRXfghorstuwx")) != -1)
		switch (ch) {
		case 'H':
			Hflag = 1;
			Lflag = 0;
			break;
		case 'L':
			Lflag = 1;
			Hflag = 0;
			break;
		case 'P':
			Hflag = Lflag = 0;
			break;
		case 'R':
			Rflag = 1;
			break;
		case 'f':		/* no longer documented. */
			fflag = 1;
			break;
		case 'h':
			hflag = 1;
			break;
		/*
		 * If this is a symbolic mode argument rather than
		 * an option, we are done with option processing.
		 */
		case 'g': case 'o': case 'r': case 's':
		case 't': case 'u': case 'w': case 'X': case 'x':
			if (!ischmod)
				usage();
			/*
			 * If getopt() moved past the argument, back up.
			 * If the argument contains option letters before
			 * mode letters, setmode() will catch them.
			 */
			if (optind > 1) {
				cp = argv[optind - 1];
				if (cp[strlen(cp) - 1] == ch)
					--optind;
			}
			goto done;
		default:
			usage();
		}
done:
	argv += optind;
	argc -= optind;

	if (argc < 2)
		usage();

	/*
	 * We alter the symlink itself if doing -h or -RP, or
	 * if doing -RH and the symlink wasn't a command line arg.
	 */
	atflags = AT_SYMLINK_NOFOLLOW;

	fts_options = FTS_PHYSICAL;
	if (Rflag) {
		if (hflag)
			errx(1,
		"the -R and -h options may not be specified together.");
		if (Hflag)
			fts_options |= FTS_COMFOLLOW;
		if (Lflag) {
			fts_options &= ~FTS_PHYSICAL;
			fts_options |= FTS_LOGICAL;
			atflags = 0;
		}
	} else if (!hflag) {
		fts_options |= FTS_COMFOLLOW;
		atflags = 0;
	}

	if (ischflags) {
		if (pledge("stdio rpath fattr", NULL) == -1)
			err(1, "pledge");

		flags = *argv;
		if (*flags >= '0' && *flags <= '7') {
			errno = 0;
			val = strtoul(flags, &ep, 8);
			if (val > UINT_MAX)
				errno = ERANGE;
			if (errno)
				err(1, "invalid flags: %s", flags);
			if (*ep)
				errx(1, "invalid flags: %s", flags);
			fset = val;
			oct = 1;
		} else {
			if (strtofflags(&flags, &fset, &fclear))
				errx(1, "invalid flag: %s", flags);
			fclear = ~fclear;
			oct = 0;
		}
	} else if (ischmod) {
		mode = *argv;
		if (*mode >= '0' && *mode <= '7') {
			errno = 0;
			val = strtoul(mode, &ep, 8);
			if (val > INT_MAX)
				errno = ERANGE;
			if (errno)
				err(1, "invalid file mode: %s", mode);
			if (*ep)
				errx(1, "invalid file mode: %s", mode);
			omode = val;
			oct = 1;
		} else {
			if ((set = setmode(mode)) == NULL)
				errx(1, "invalid file mode: %s", mode);
			oct = 0;
		}
	} else if (ischown) {
		/* Both UID and GID are given. */
		if ((cp = strchr(*argv, ':')) != NULL) {
			*cp++ = '\0';
			gid = a_gid(cp);
		}
		/*
		 * UID and GID are separated by a dot and UID exists.
		 * required for backwards compatibility pre-dating POSIX.2
		 * likely to stay here forever
		 */
		else if ((cp = strchr(*argv, '.')) != NULL &&
		    (uid = a_uid(*argv, 1)) == (uid_t)-1) {
			*cp++ = '\0';
			gid = a_gid(cp);
		}
		if (uid == (uid_t)-1)
			uid = a_uid(*argv, 0);
	} else
		gid = a_gid(*argv);

	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
		err(1, NULL);
	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
		switch (p->fts_info) {
		case FTS_D:
			if (!Rflag)
				fts_set(ftsp, p, FTS_SKIP);
			if (ischmod)
				break;
			else
				continue;
		case FTS_DNR:			/* Warn, chmod, continue. */
			warnc(p->fts_errno, "%s", p->fts_path);
			rval = 1;
			break;
		case FTS_DP:			/* Already changed at FTS_D. */
			if (ischmod)
				continue;
			else
				break;
		case FTS_ERR:			/* Warn, continue. */
		case FTS_NS:
			warnc(p->fts_errno, "%s", p->fts_path);
			rval = 1;
			continue;
		case FTS_SL:			/* Ignore. */
		case FTS_SLNONE:
			/*
			 * The only symlinks that end up here are ones that
			 * don't point to anything or that loop and ones
			 * that we found doing a physical walk.
			 */
			if (!hflag && (fts_options & FTS_LOGICAL))
				continue;
			break;
		default:
			break;
		}

		/*
		 * For -RH, the decision of how to handle symlinks depends
		 * on the level: follow it iff it's a command line arg.
		 */
		if (fts_options & FTS_COMFOLLOW) {
			atflags = p->fts_level == FTS_ROOTLEVEL ? 0 : 
			    AT_SYMLINK_NOFOLLOW;
		}

		if (ischmod) {
			if (!fchmodat(AT_FDCWD, p->fts_accpath, oct ? omode :
			    getmode(set, p->fts_statp->st_mode), atflags)
			    || fflag)
				continue;
		} else if (!ischflags) {
			if (!fchownat(AT_FDCWD, p->fts_accpath, uid, gid,
			    atflags) || fflag)
				continue;
		} else {
			if (!chflagsat(AT_FDCWD, p->fts_accpath, oct ? fset :
			    (p->fts_statp->st_flags | fset) & fclear, atflags))
				continue;
		}

		/* error case */
		warn("%s", p->fts_path);
		rval = 1;
	}
	if (errno)
		err(1, "fts_read");
	fts_close(ftsp);
	return (rval);
}
Ejemplo n.º 15
0
int
ruserpass(const char *host, char **aname, char **apass, char **aacct)
{
	char *hdir, buf[MAXPATHLEN], *tmp;
	char myname[MAXHOSTNAMELEN], *mydomain;
	int t, i, c, usedefault = 0;
	struct stat stb;

	hdir = getenv("HOME");
	if (hdir == NULL || *hdir == '\0')
		return (0);
	i = snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
	if (i < 0 || i >= sizeof(buf)) {
		warnc(ENAMETOOLONG, "%s/.netrc", hdir);
		return (0);
	}
	cfile = fopen(buf, "r");
	if (cfile == NULL) {
		if (errno != ENOENT)
			warn("%s", buf);
		return (0);
	}
	if (gethostname(myname, sizeof(myname)) < 0)
		myname[0] = '\0';
	if ((mydomain = strchr(myname, '.')) == NULL)
		mydomain = "";
next:
	while ((t = token()) > 0) switch(t) {

	case DEFAULT:
		usedefault = 1;
		/* FALLTHROUGH */

	case MACH:
		if (!usedefault) {
			if ((t = token()) == -1)
				goto bad;
			if (t != ID)
				continue;
			/*
			 * Allow match either for user's input host name
			 * or official hostname.  Also allow match of
			 * incompletely-specified host in local domain.
			 */
			if (strcasecmp(host, tokval) == 0)
				goto match;
			if (strcasecmp(hostname, tokval) == 0)
				goto match;
			if ((tmp = strchr(hostname, '.')) != NULL &&
			    strcasecmp(tmp, mydomain) == 0 &&
			    strncasecmp(hostname, tokval,
			    (size_t)(tmp - hostname)) == 0 &&
			    tokval[tmp - hostname] == '\0')
				goto match;
			if ((tmp = strchr(host, '.')) != NULL &&
			    strcasecmp(tmp, mydomain) == 0 &&
			    strncasecmp(host, tokval,
			    (size_t)(tmp - host)) == 0 &&
			    tokval[tmp - host] == '\0')
				goto match;
			continue;
		}
	match:
		while ((t = token()) > 0 &&
		    t != MACH && t != DEFAULT) switch(t) {

		case LOGIN:
			if ((t = token()) == -1)
				goto bad;
			if (t) {
				if (*aname == 0) {
					if ((*aname = strdup(tokval)) == NULL)
						err(1, "strdup");
				} else {
					if (strcmp(*aname, tokval))
						goto next;
				}
			}
			break;
		case PASSWD:
			if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
			    fstat(fileno(cfile), &stb) >= 0 &&
			    (stb.st_mode & 077) != 0) {
	warnx("Error: .netrc file is readable by others.");
	warnx("Remove password or make file unreadable by others.");
				goto bad;
			}
			if ((t = token()) == -1)
				goto bad;
			if (t && *apass == 0) {
				if ((*apass = strdup(tokval)) == NULL)
					err(1, "strdup");
			}
			break;
		case ACCOUNT:
			if (fstat(fileno(cfile), &stb) >= 0
			    && (stb.st_mode & 077) != 0) {
	warnx("Error: .netrc file is readable by others.");
	warnx("Remove account or make file unreadable by others.");
				goto bad;
			}
			if ((t = token()) == -1)
				goto bad;
			if (t && *aacct == 0) {
				if ((*aacct = strdup(tokval)) == NULL)
					err(1, "strdup");
			}
			break;
		case MACDEF:
			if (proxy) {
				(void)fclose(cfile);
				return (0);
			}
			while ((c = fgetc(cfile)) != EOF)
				if (c != ' ' && c != '\t')
					break;
			if (c == EOF || c == '\n') {
				fputs("Missing macdef name argument.\n", ttyout);
				goto bad;
			}
			if (macnum == 16) {
				fputs(
"Limit of 16 macros have already been defined.\n", ttyout);
				goto bad;
			}
			tmp = macros[macnum].mac_name;
			*tmp++ = c;
			for (i=0; i < 8 && (c = fgetc(cfile)) != EOF &&
			    !isspace(c); ++i) {
				*tmp++ = c;
			}
			if (c == EOF) {
				fputs(
"Macro definition missing null line terminator.\n", ttyout);
				goto bad;
			}
			*tmp = '\0';
			if (c != '\n') {
				while ((c = fgetc(cfile)) != EOF && c != '\n');
			}
			if (c == EOF) {
				fputs(
"Macro definition missing null line terminator.\n", ttyout);
				goto bad;
			}
			if (macnum == 0) {
				macros[macnum].mac_start = macbuf;
			}
			else {
				macros[macnum].mac_start =
				    macros[macnum-1].mac_end + 1;
			}
			tmp = macros[macnum].mac_start;
			while (tmp != macbuf + 4096) {
				if ((c = fgetc(cfile)) == EOF) {
				fputs(
"Macro definition missing null line terminator.\n", ttyout);
					goto bad;
				}
				*tmp = c;
				if (*tmp == '\n') {
					if (tmp == macros[macnum].mac_start) {
						macros[macnum++].mac_end = tmp;
						break;
					} else if (*(tmp-1) == '\0') {
						macros[macnum++].mac_end =
						    tmp - 1;
						break;
					}
					*tmp = '\0';
				}
				tmp++;
			}
			if (tmp == macbuf + 4096) {
				fputs("4K macro buffer exceeded.\n", ttyout);
				goto bad;
			}
			break;
		default:
			warnx("Unknown .netrc keyword %s", tokval);
			break;
		}
		goto done;
	}
done:
	if (t == -1)
		goto bad;
	(void)fclose(cfile);
	return (0);
bad:
	(void)fclose(cfile);
	return (-1);
}
Ejemplo n.º 16
0
static void process_select(fd_set *rfds, fd_set *wfds, fd_set *efds)
{
	unsigned int i = 0;
	while (i < num_flows) {

		struct _flow *flow = &flows[i];

		DEBUG_MSG(LOG_DEBUG, "processing pselect() for flow %d",
			  flow->id);

		if (flow->listenfd_data != -1 &&
		    FD_ISSET(flow->listenfd_data, rfds)) {
			DEBUG_MSG(LOG_DEBUG, "ready for accept");
			if (flow->state == GRIND_WAIT_ACCEPT) {
				if (accept_data(flow) == -1) {
					DEBUG_MSG(LOG_ERR, "accept_data() "
						  "failed");
					goto remove;
				}
			}
		}

		if (flow->fd != -1) {
			if (FD_ISSET(flow->fd, efds)) {
				int error_number, rc;
				socklen_t error_number_size =
					sizeof(error_number);
				DEBUG_MSG(LOG_DEBUG, "sock of flow %d in efds",
					  flow->id);
				rc = getsockopt(flow->fd, SOL_SOCKET,
						SO_ERROR,
						(void *)&error_number,
						&error_number_size);
				if (rc == -1) {
					warn("failed to get errno for"
					     "non-blocking connect");
					goto remove;
				}
				if (error_number != 0) {
					warnc(error_number, "connect");
					goto remove;
				}
			}
			if (FD_ISSET(flow->fd, wfds))
				if (write_data(flow) == -1) {
					DEBUG_MSG(LOG_ERR, "write_data() failed");
					goto remove;
				}

			if (FD_ISSET(flow->fd, rfds))
				if (read_data(flow) == -1) {
					DEBUG_MSG(LOG_ERR, "read_data() failed");
					goto remove;
				}
		}
		i++;
		continue;
remove:
		if (flow->fd != -1) {
			flow->statistics[FINAL].has_tcp_info =
				get_tcp_info(flow,
					     &flow->statistics[FINAL].tcp_info)
					? 0 : 1;
		}
		flow->pmtu = get_pmtu(flow->fd);
		report_flow(flow, FINAL);
		uninit_flow(flow);
		remove_flow(i);
		DEBUG_MSG(LOG_ERR, "removed flow %d", flow->id);
	}
}
Ejemplo n.º 17
0
int
fastcopy(char *from, char *to, struct stat *sbp)
{
	struct timespec ts[2];
	static u_int32_t blen;
	static char *bp;
	int nread, from_fd, to_fd;
	int badchown = 0, serrno = 0;

	if (!blen) {
		blen = sbp->st_blksize;
		if ((bp = malloc(blen)) == NULL) {
			warn(NULL);
			blen = 0;
			return (1);
		}
	}

	if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
		warn("%s", from);
		return (1);
	}
	if ((to_fd = open(to, O_CREAT | O_TRUNC | O_WRONLY, 0600)) < 0) {
		warn("%s", to);
		(void)close(from_fd);
		return (1);
	}

	if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) {
		serrno = errno;
		badchown = 1;
	}
	(void) fchmod(to_fd, sbp->st_mode & ~(S_ISUID|S_ISGID));

	while ((nread = read(from_fd, bp, blen)) > 0)
		if (write(to_fd, bp, nread) != nread) {
			warn("%s", to);
			goto err;
		}
	if (nread < 0) {
		warn("%s", from);
err:		if (unlink(to))
			warn("%s: remove", to);
		(void)close(from_fd);
		(void)close(to_fd);
		return (1);
	}
	(void)close(from_fd);

	if (badchown) {
		if ((sbp->st_mode & (S_ISUID|S_ISGID)))  {
			warnc(serrno,
			    "%s: set owner/group; not setting setuid/setgid",
			    to);
			sbp->st_mode &= ~(S_ISUID|S_ISGID);
		} else if (!fflg)
			warnc(serrno, "%s: set owner/group", to);
	}
	if (fchmod(to_fd, sbp->st_mode))
		warn("%s: set mode", to);

	/*
	 * XXX
	 * NFS doesn't support chflags; ignore errors unless there's reason
	 * to believe we're losing bits.  (Note, this still won't be right
	 * if the server supports flags and we were trying to *remove* flags
	 * on a file that we copied, i.e., that we didn't create.)
	 */
	errno = 0;
	if (fchflags(to_fd, sbp->st_flags))
		if (errno != EOPNOTSUPP || sbp->st_flags != 0)
			warn("%s: set flags", to);

	ts[0] = sbp->st_atim;
	ts[1] = sbp->st_mtim;
	if (futimens(to_fd, ts))
		warn("%s: set times", to);

	if (close(to_fd)) {
		warn("%s", to);
		return (1);
	}

	if (unlink(from)) {
		warn("%s: remove", from);
		return (1);
	}

	if (vflg)
		(void)fprintf(stdout, "%s -> %s\n", from, to);

	return (0);
}
Ejemplo n.º 18
0
static int
video_mode(int argc, char **argv, int *mode_index)
{
	static struct {
		const char *name;
		unsigned long mode;
		unsigned long mode_num;
	} modes[] = {
		{ "80x25",        SW_TEXT_80x25,   M_TEXT_80x25 },
		{ "80x30",        SW_TEXT_80x30,   M_TEXT_80x30 },
		{ "80x43",        SW_TEXT_80x43,   M_TEXT_80x43 },
		{ "80x50",        SW_TEXT_80x50,   M_TEXT_80x50 },
		{ "80x60",        SW_TEXT_80x60,   M_TEXT_80x60 },
		{ "132x25",       SW_TEXT_132x25,  M_TEXT_132x25 },
		{ "132x30",       SW_TEXT_132x30,  M_TEXT_132x30 },
		{ "132x43",       SW_TEXT_132x43,  M_TEXT_132x43 },
		{ "132x50",       SW_TEXT_132x50,  M_TEXT_132x50 },
		{ "132x60",       SW_TEXT_132x60,  M_TEXT_132x60 },
		{ "VGA_40x25",    SW_VGA_C40x25,   M_VGA_C40x25 },
		{ "VGA_80x25",    SW_VGA_C80x25,   M_VGA_C80x25 },
		{ "VGA_80x30",    SW_VGA_C80x30,   M_VGA_C80x30 },
		{ "VGA_80x50",    SW_VGA_C80x50,   M_VGA_C80x50 },
		{ "VGA_80x60",    SW_VGA_C80x60,   M_VGA_C80x60 },
#ifdef SW_VGA_C90x25
		{ "VGA_90x25",    SW_VGA_C90x25,   M_VGA_C90x25 },
		{ "VGA_90x30",    SW_VGA_C90x30,   M_VGA_C90x30 },
		{ "VGA_90x43",    SW_VGA_C90x43,   M_VGA_C90x43 },
		{ "VGA_90x50",    SW_VGA_C90x50,   M_VGA_C90x50 },
		{ "VGA_90x60",    SW_VGA_C90x60,   M_VGA_C90x60 },
#endif
		{ "VGA_320x200",	SW_VGA_CG320,	M_CG320 },
		{ "EGA_80x25",		SW_ENH_C80x25,	M_ENH_C80x25 },
		{ "EGA_80x43",		SW_ENH_C80x43,	M_ENH_C80x43 },
		{ "VESA_132x25",	SW_VESA_C132x25,M_VESA_C132x25 },
		{ "VESA_132x43",	SW_VESA_C132x43,M_VESA_C132x43 },
		{ "VESA_132x50",	SW_VESA_C132x50,M_VESA_C132x50 },
		{ "VESA_132x60",	SW_VESA_C132x60,M_VESA_C132x60 },
		{ "VESA_800x600",	SW_VESA_800x600,M_VESA_800x600 },
		{ NULL, 0, 0 },
	};

	int new_mode_num = 0;
	unsigned long mode = 0;
	int cur_mode; 
	int ioerr;
	int size[3];
	int i;

	if (ioctl(0, CONS_GET, &cur_mode) < 0)
		err(1, "cannot get the current video mode");

	/*
	 * Parse the video mode argument...
	 */

	if (*mode_index < argc) {
		if (!strncmp(argv[*mode_index], "MODE_", 5)) {
			if (!isdigit(argv[*mode_index][5]))
				errx(1, "invalid video mode number");

			new_mode_num = atoi(&argv[*mode_index][5]);
		} else {
			for (i = 0; modes[i].name != NULL; ++i) {
				if (!strcmp(argv[*mode_index], modes[i].name)) {
					mode = modes[i].mode;
					new_mode_num = modes[i].mode_num;
					break;
				}
			}

			if (modes[i].name == NULL)
				return EXIT_FAILURE;
			if (ioctl(0, mode, NULL) < 0) {
				warn("cannot set videomode");
				return EXIT_FAILURE;
			}
		}

		/*
		 * Collect enough information about the new video mode...
		 */

		new_mode_info.vi_mode = new_mode_num;

		if (ioctl(0, CONS_MODEINFO, &new_mode_info) == -1) {
			revert();
			errc(1, errno, "obtaining new video mode parameters");
		}

		if (mode == 0) {
			if (new_mode_num >= M_VESA_BASE)
				mode = _IO('V', new_mode_num - M_VESA_BASE);
			else
				mode = _IO('S', new_mode_num);
		}

		/*
		 * Try setting the new mode.
		 */

		if (ioctl(0, mode, NULL) == -1) {
			revert();
			errc(1, errno, "setting video mode");
		}

		/*
		 * For raster modes it's not enough to just set the mode.
		 * We also need to explicitly set the raster mode.
		 */

		if (new_mode_info.vi_flags & V_INFO_GRAPHICS) {
			/* font size */

			if (font_height == 0)
				font_height = cur_info.console_info.font_size;

			size[2] = font_height;

			/* adjust columns */

			if ((vesa_cols * 8 > new_mode_info.vi_width) ||
			    (vesa_cols <= 0)) {
				size[0] = new_mode_info.vi_width / 8;
			} else {
				size[0] = vesa_cols;
			}

			/* adjust rows */

			if ((vesa_rows * font_height > new_mode_info.vi_height) ||
			    (vesa_rows <= 0)) {
				size[1] = new_mode_info.vi_height /
					  font_height;
			} else {
				size[1] = vesa_rows;
			}

			/* set raster mode */

			if (ioctl(0, KDRASTER, size)) {
				ioerr = errno;
				if (cur_mode >= M_VESA_BASE)
					ioctl(0,
					    _IO('V', cur_mode - M_VESA_BASE),
					    NULL);
				else
					ioctl(0, _IO('S', cur_mode), NULL);
				revert();
				warnc(ioerr, "cannot activate raster display");
				return EXIT_FAILURE;
			}
		}

		video_mode_changed = 1;

		(*mode_index)++;
	}
	return EXIT_SUCCESS;
}
Ejemplo n.º 19
0
/*
 * Set the date in the machines controlled by timedaemons by communicating the
 * new date to the local timedaemon.  If the timedaemon is in the master state,
 * it performs the correction on all slaves.  If it is in the slave state, it
 * notifies the master that a correction is needed.
 * Returns 0 on success.  Returns > 0 on failure, setting retval to 2;
 */
int
netsettime(time_t tval)
{
	struct timeval tout;
	struct servent *sp;
	struct tsp msg;
	struct sockaddr_in lsin, dest, from;
	fd_set ready;
	long waittime;
	int s, port, timed_ack, found, lerr;
	socklen_t length;
	char hostname[MAXHOSTNAMELEN];

	if ((sp = getservbyname("timed", "udp")) == NULL) {
		warnx("timed/udp: unknown service");
		return (retval = 2);
	}

	dest.sin_port = sp->s_port;
	dest.sin_family = AF_INET;
	dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s < 0) {
		if (errno != EPROTONOSUPPORT)
			warn("timed");
		return (retval = 2);
	}

	memset(&lsin, 0, sizeof(lsin));
	lsin.sin_family = AF_INET;
	for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
		lsin.sin_port = htons((u_short)port);
		if (bind(s, (struct sockaddr *)&lsin, sizeof(lsin)) >= 0)
			break;
		if (errno == EADDRINUSE)
			continue;
		if (errno != EADDRNOTAVAIL)
			warn("bind");
		goto bad;
	}
	if (port == IPPORT_RESERVED / 2) {
		warnx("all ports in use");
		goto bad;
	}
	msg.tsp_type = TSP_SETDATE;
	msg.tsp_vers = TSPVERSION;
	if (gethostname(hostname, sizeof(hostname))) {
		warn("gethostname");
		goto bad;
	}
	(void)strncpy(msg.tsp_name, hostname, sizeof(msg.tsp_name) - 1);
	msg.tsp_name[sizeof(msg.tsp_name) - 1] = '\0';
	msg.tsp_seq = htons((u_short)0);
	msg.tsp_time.tv_sec = htonl((u_long)tval);
	msg.tsp_time.tv_usec = htonl((u_long)0);
	length = sizeof(struct sockaddr_in);
	if (connect(s, (struct sockaddr *)&dest, length) < 0) {
		warn("connect");
		goto bad;
	}
	if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) {
		if (errno != ECONNREFUSED)
			warn("send");
		goto bad;
	}

	timed_ack = -1;
	waittime = WAITACK;
loop:
	tout.tv_sec = waittime;
	tout.tv_usec = 0;

	FD_ZERO(&ready);
	FD_SET(s, &ready);
	found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);

	length = sizeof(lerr);
	if (!getsockopt(s,
	    SOL_SOCKET, SO_ERROR, (char *)&lerr, &length) && lerr) {
		if (lerr != ECONNREFUSED)
			warnc(lerr, "send (delayed error)");
		goto bad;
	}

	if (found > 0 && FD_ISSET(s, &ready)) {
		length = sizeof(struct sockaddr_in);
		if (recvfrom(s, &msg, sizeof(struct tsp), 0,
		    (struct sockaddr *)&from, &length) < 0) {
			if (errno != ECONNREFUSED)
				warn("recvfrom");
			goto bad;
		}
		msg.tsp_seq = ntohs(msg.tsp_seq);
		msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
		msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
		switch (msg.tsp_type) {
		case TSP_ACK:
			timed_ack = TSP_ACK;
			waittime = WAITDATEACK;
			goto loop;
		case TSP_DATEACK:
			(void)close(s);
			return (0);
		default:
			warnx("wrong ack received from timed: %s",
			    tsptype[msg.tsp_type]);
			timed_ack = -1;
			break;
		}
	}
	if (timed_ack == -1)
		warnx("can't reach time daemon, time set locally");

bad:
	(void)close(s);
	return (retval = 2);
}
Ejemplo n.º 20
0
int
main(int argc, char *argv[])
{
	const char *errstr;
	char errbuf[_POSIX2_LINE_MAX], *kmem = NULL, *kernel = NULL;
	struct kinfo_proc *kproc;
	struct sum total_sum;
	int many, ch, rc;
	kvm_t *kd;
	pid_t pid = -1;
	gid_t gid;

	while ((ch = getopt(argc, argv, "AaD:dlmM:N:p:Prsvx")) != -1) {
		switch (ch) {
		case 'A':
			print_amap = 1;
			break;
		case 'a':
			print_all = 1;
			break;
		case 'd':
			print_ddb = 1;
			break;
		case 'D':
			debug = strtonum(optarg, 0, 0xf, &errstr);
			if (errstr)
				errx(1, "invalid debug mask");
			break;
		case 'l':
			print_maps = 1;
			break;
		case 'm':
			print_map = 1;
			break;
		case 'M':
			kmem = optarg;
			break;
		case 'N':
			kernel = optarg;
			break;
		case 'p':
			pid = strtopid(optarg);
			break;
		case 'P':
			pid = getpid();
			break;
		case 's':
			print_solaris = 1;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'r':
		case 'x':
			errx(1, "-%c option not implemented, sorry", ch);
			/*NOTREACHED*/
		default:
			usage();
		}
	}

	/*
	 * Discard setgid privileges if not the running kernel so that bad
	 * guys can't print interesting stuff from kernel memory.
	 */
	gid = getgid();
	if (kernel != NULL || kmem != NULL)
		if (setresgid(gid, gid, gid) == -1)
			err(1, "setresgid");

	argc -= optind;
	argv += optind;

	/* more than one "process" to dump? */
	many = (argc > 1 - (pid == -1 ? 0 : 1)) ? 1 : 0;

	/* apply default */
	if (print_all + print_map + print_maps + print_solaris +
	    print_ddb == 0)
		print_solaris = 1;

	/* start by opening libkvm */
	kd = kvm_openfiles(kernel, kmem, NULL, O_RDONLY, errbuf);

	if (kernel == NULL && kmem == NULL)
		if (setresgid(gid, gid, gid) == -1)
			err(1, "setresgid");

	if (kd == NULL)
		errx(1, "%s", errbuf);

	/* get "bootstrap" addresses from kernel */
	load_symbols(kd);

	memset(&total_sum, 0, sizeof(total_sum));

	do {
		struct sum sum;

		memset(&sum, 0, sizeof(sum));

		if (pid == -1) {
			if (argc == 0)
				pid = getppid();
			else {
				pid = strtopid(argv[0]);
				argv++;
				argc--;
			}
		}

		/* find the process id */
		if (pid == 0)
			kproc = NULL;
		else {
			kproc = kvm_getprocs(kd, KERN_PROC_PID, pid,
			    sizeof(struct kinfo_proc), &rc);
			if (kproc == NULL || rc == 0) {
				warnc(ESRCH, "%d", pid);
				pid = -1;
				continue;
			}
		}

		/* dump it */
		if (many) {
			if (kproc)
				printf("process %d:\n", pid);
			else
				printf("kernel:\n");
		}

		process_map(kd, pid, kproc, &sum);
		if (print_amap)
			print_sum(&sum, &total_sum);
		pid = -1;
	} while (argc > 0);

	if (print_amap)
		print_sum(&total_sum, NULL);

	/* done.  go away. */
	rc = kvm_close(kd);
	if (rc == -1)
		err(1, "kvm_close");

	return (0);
}
Ejemplo n.º 21
0
static int
writelabel(void)
{
	int i, fd, serrno;
	struct gctl_req *grq;
	char const *errstr;
	struct disklabel *lp = &lab;

	if (disable_write) {
		warnx("write to disk label suppressed - label was as follows:");
		display(stdout, NULL);
		return (0);
	}

	lp->d_magic = DISKMAGIC;
	lp->d_magic2 = DISKMAGIC;
	lp->d_checksum = 0;
	lp->d_checksum = dkcksum(lp);
	if (installboot)
		readboot();
	for (i = 0; i < lab.d_npartitions; i++)
		if (lab.d_partitions[i].p_size)
			lab.d_partitions[i].p_offset += lba_offset;
	bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * lab.d_secsize,
	    lp);

	fd = open(specname, O_RDWR);
	if (fd < 0) {
		if (is_file) {
			warn("cannot open file %s for writing label", specname);
			return(1);
		} else
			serrno = errno;

		if (geom_class_available("PART") != 0) {
			/*
			 * Since we weren't able open provider for
			 * writing, then recommend user to use gpart(8).
			 */
			warnc(serrno,
			    "cannot open provider %s for writing label",
			    specname);
			warnx("Try to use gpart(8).");
			return (1);
		}

		/* Give up if GEOM_BSD is not available. */
		if (geom_class_available("BSD") == 0) {
			warnc(serrno, "%s", specname);
			return (1);
		}

		grq = gctl_get_handle();
		gctl_ro_param(grq, "verb", -1, "write label");
		gctl_ro_param(grq, "class", -1, "BSD");
		gctl_ro_param(grq, "geom", -1, pname);
		gctl_ro_param(grq, "label", 148+16*8,
			bootarea + labeloffset + labelsoffset * lab.d_secsize);
		errstr = gctl_issue(grq);
		if (errstr != NULL) {
			warnx("%s", errstr);
			gctl_free(grq);
			return(1);
		}
		gctl_free(grq);
		if (installboot) {
			grq = gctl_get_handle();
			gctl_ro_param(grq, "verb", -1, "write bootcode");
			gctl_ro_param(grq, "class", -1, "BSD");
			gctl_ro_param(grq, "geom", -1, pname);
			gctl_ro_param(grq, "bootcode", BBSIZE, bootarea);
			errstr = gctl_issue(grq);
			if (errstr != NULL) {
				warnx("%s", errstr);
				gctl_free(grq);
				return (1);
			}
			gctl_free(grq);
		}
	} else {
		if (write(fd, bootarea, bbsize) != bbsize) {
			warn("write %s", specname);
			close (fd);
			return (1);
		}
		close (fd);
	}
	return (0);
}
Ejemplo n.º 22
0
Archivo: ln.c Proyecto: Open343/bitrig
 /*
  * Nomenclature warning!
  *
  * In this source "target" and "source" are used the opposite way they
  * are used in the ln(1) manual.  Here "target" is the existing file and
  * "source" specifies the to-be-created link to "target".
  */
int
linkit(char *target, char *source, int isdir)
{
	struct stat sb;
	char *p, path[PATH_MAX];
	int (*statf)(const char *, struct stat *);
	int exists, n;

	if (!sflag) {
		/* If target doesn't exist, quit now. */
		if ((Pflag ? lstat : stat)(target, &sb)) {
			warn("%s", target);
			return (1);
		}
		/* Only symbolic links to directories. */
		if (S_ISDIR(sb.st_mode)) {
			warnc(EISDIR, "%s", target);
			return (1);
		}
	}

	statf = hflag ? lstat : stat;

	/* If the source is a directory, append the target's name. */
	if (isdir || (!statf(source, &sb) && S_ISDIR(sb.st_mode))) {
		if ((p = basename(target)) == NULL) {
			warn("%s", target);
			return (1);
		}
		n = snprintf(path, sizeof(path), "%s/%s", source, p);
		if (n < 0 || n >= sizeof(path)) {
			warnc(ENAMETOOLONG, "%s/%s", source, p);
			return (1);
		}
		source = path;
	}

	exists = (lstat(source, &sb) == 0);
	/*
	 * If doing hard links and the source (destination) exists and it
	 * actually is the same file like the target (existing file), we
	 * complain that the files are identical.  If -f is specified, we
	 * accept the job as already done and return with success.
	 */
	if (exists && !sflag) {
		struct stat tsb;

		if ((Pflag ? lstat : stat)(target, &tsb)) {
			warn("%s: disappeared", target);
			return (1);
		}

		if (tsb.st_dev == sb.st_dev && tsb.st_ino == sb.st_ino) {
			if (fflag)
				return (0);
			else {
				warnx("%s and %s are identical (nothing done).",
				    target, source);
				return (1);
			}
		}
	}
	/*
	 * If the file exists, and -f was specified, unlink it.
	 * Attempt the link.
	 */
	if ((fflag && unlink(source) < 0 && errno != ENOENT) ||
	    sflag ? symlink(target, source) :
	    linkat(AT_FDCWD, target, AT_FDCWD, source,
	    Pflag ? 0 : AT_SYMLINK_FOLLOW)) {
		warn("%s", source);
		return (1);
	}

	return (0);
}
Ejemplo n.º 23
0
int
getnfsargs(char *spec, struct nfs_args *nfsargsp)
{
	CLIENT *clp;
	struct hostent *hp;
	static struct sockaddr_in saddr;
	struct timeval pertry, try;
	enum clnt_stat clnt_stat;
	int so = RPC_ANYSOCK, i, nfsvers, mntvers, orgcnt;
	char *hostp, *delimp;
	u_short tport;
	static struct nfhret nfhret;
	static char nam[MNAMELEN + 1];

	if (strlcpy(nam, spec, sizeof(nam)) >= sizeof(nam)) {
		errx(1, "hostname too long");
	}

	if ((delimp = strchr(spec, '@')) != NULL) {
		hostp = delimp + 1;
	} else if ((delimp = strchr(spec, ':')) != NULL) {
		hostp = spec;
		spec = delimp + 1;
	} else {
		warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
		return (0);
	}
	*delimp = '\0';

	/*
	 * Handle an internet host address
	 */
	if (inet_aton(hostp, &saddr.sin_addr) == 0) {
		hp = gethostbyname(hostp);
		if (hp == NULL) {
			warnx("can't resolve address for host %s", hostp);
			return (0);
		}
		memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
	}

	if (force2) {
		nfsvers = NFS_VER2;
		mntvers = RPCMNT_VER1;
	} else {
		nfsvers = NFS_VER3;
		mntvers = RPCMNT_VER3;
	}
	orgcnt = retrycnt;
tryagain:
	nfhret.stat = EACCES;	/* Mark not yet successful */
	while (retrycnt > 0) {
		saddr.sin_family = AF_INET;
		saddr.sin_port = htons(PMAPPORT);
		if ((tport = port_no ? port_no : pmap_getport(&saddr,
		    RPCPROG_NFS, nfsvers, nfsargsp->sotype == SOCK_STREAM ?
		    IPPROTO_TCP : IPPROTO_UDP)) == 0) {
			if ((opflags & ISBGRND) == 0)
				clnt_pcreateerror("NFS Portmap");
		} else {
			saddr.sin_port = 0;
			pertry.tv_sec = 10;
			pertry.tv_usec = 0;
			if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
			    clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
				&so, 0, 0);
			else
			    clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
				pertry, &so);
			if (clp == NULL) {
				if ((opflags & ISBGRND) == 0)
					clnt_pcreateerror("Cannot MNT RPC");
			} else {
				clp->cl_auth = authunix_create_default();
				try.tv_sec = 10;
				try.tv_usec = 0;
				nfhret.auth = RPCAUTH_UNIX;
				nfhret.vers = mntvers;
				clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
				    xdr_dir, spec, xdr_fh, &nfhret, try);
				if (clnt_stat != RPC_SUCCESS) {
					if (clnt_stat == RPC_PROGVERSMISMATCH) {
						if (nfsvers == NFS_VER3 &&
						    !force3) {
							retrycnt = orgcnt;
							nfsvers = NFS_VER2;
							mntvers = RPCMNT_VER1;
							nfsargsp->flags &=
							    ~NFSMNT_NFSV3;
							goto tryagain;
						} else {
							warnx("%s",
							    clnt_sperror(clp,
								"MNT RPC"));
						}
					}
					if ((opflags & ISBGRND) == 0)
						warnx("%s", clnt_sperror(clp,
						    "bad MNT RPC"));
				} else {
					auth_destroy(clp->cl_auth);
					clnt_destroy(clp);
					retrycnt = 0;
				}
			}
		}
		if (--retrycnt > 0) {
			if (opflags & BGRND) {
				opflags &= ~BGRND;
				if ((i = fork())) {
					if (i == -1)
						err(1, "fork");
					exit(0);
				}
				(void) setsid();
				(void) close(STDIN_FILENO);
				(void) close(STDOUT_FILENO);
				(void) close(STDERR_FILENO);
				(void) chdir("/");
				opflags |= ISBGRND;
			}
			sleep(60);
		}
	}
	if (nfhret.stat) {
		if (opflags & ISBGRND)
			exit(1);
		warnc(nfhret.stat, "can't access %s", spec);
		return (0);
	}
	saddr.sin_port = htons(tport);
	nfsargsp->addr = (struct sockaddr *) &saddr;
	nfsargsp->addrlen = sizeof (saddr);
	nfsargsp->fh = nfhret.nfh;
	nfsargsp->fhsize = nfhret.fhsize;
	nfsargsp->hostname = nam;
	return (1);
}
Ejemplo n.º 24
0
int
copy(char *argv[], enum op type, int fts_options)
{
	struct stat to_stat;
	FTS *ftsp;
	FTSENT *curr;
	int base, nlen, rval;
	char *p, *target_mid;
	base = 0;

	if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL)
		err(1, NULL);
	for (rval = 0; (curr = fts_read(ftsp)) != NULL;) {
		switch (curr->fts_info) {
		case FTS_NS:
		case FTS_DNR:
		case FTS_ERR:
			warnx("%s: %s",
			    curr->fts_path, strerror(curr->fts_errno));
			rval = 1;
			continue;
		case FTS_DC:
			warnx("%s: directory causes a cycle", curr->fts_path);
			rval = 1;
			continue;
		}

		/*
		 * If we are in case (2) or (3) above, we need to append the
		 * source name to the target name.
		 */
		if (type != FILE_TO_FILE) {
			/*
			 * Need to remember the roots of traversals to create
			 * correct pathnames.  If there's a directory being
			 * copied to a non-existent directory, e.g.
			 *	cp -R a/dir noexist
			 * the resulting path name should be noexist/foo, not
			 * noexist/dir/foo (where foo is a file in dir), which
			 * is the case where the target exists.
			 *
			 * Also, check for "..".  This is for correct path
			 * concatenation for paths ending in "..", e.g.
			 *	cp -R .. /tmp
			 * Paths ending in ".." are changed to ".".  This is
			 * tricky, but seems the easiest way to fix the problem.
			 *
			 * XXX
			 * Since the first level MUST be FTS_ROOTLEVEL, base
			 * is always initialized.
			 */
			if (curr->fts_level == FTS_ROOTLEVEL) {
				if (type != DIR_TO_DNE) {
					p = find_last_component(curr->fts_path);
					base = p - curr->fts_path;
					
					if (!strcmp(&curr->fts_path[base],
					    ".."))
						base += 1;
				} else
					base = curr->fts_pathlen;
			}

			p = &curr->fts_path[base];
			nlen = curr->fts_pathlen - base;
			target_mid = to.target_end;
			if (*p != '/' && target_mid[-1] != '/')
				*target_mid++ = '/';
			*target_mid = '\0';
			if (target_mid - to.p_path + nlen >= PATH_MAX) {
				warnx("%s%s: name too long (not copied)",
				    to.p_path, p);
				rval = 1;
				continue;
			}
			(void)strncat(target_mid, p, nlen);
			to.p_end = target_mid + nlen;
			*to.p_end = '\0';
		}

		/* Not an error but need to remember it happened */
		if (stat(to.p_path, &to_stat) == -1) {
			if (curr->fts_info == FTS_DP)
				continue;
			/*
			 * We use fts_pointer as a boolean to indicate that
			 * we created this directory ourselves.  We'll use
			 * this later on via the fts_dne macro to decide
			 * whether or not to set the directory mode during
			 * the post-order pass.
			 */
			curr->fts_pointer = (void *)1;
		} else {
			/*
			 * Set directory mode/user/times on the post-order
			 * pass.  We can't do this earlier because the mode
			 * may not allow us write permission.  Furthermore,
			 * if we set the times during the pre-order pass,
			 * they will get changed later when the directory
			 * is populated.
			 */
			if (curr->fts_info == FTS_DP) {
				if (!S_ISDIR(to_stat.st_mode))
					continue;
				/*
				 * If not -p and directory didn't exist, set
				 * it to be the same as the from directory,
				 * unmodified by the umask; arguably wrong,
				 * but it's been that way forever.
				 */
				if (pflag && setfile(curr->fts_statp, -1))
					rval = 1;
				else if (fts_dne(curr))
					(void)chmod(to.p_path,
					    curr->fts_statp->st_mode);
				continue;
			}
			if (to_stat.st_dev == curr->fts_statp->st_dev &&
			    to_stat.st_ino == curr->fts_statp->st_ino) {
				warnx("%s and %s are identical (not copied).",
				    to.p_path, curr->fts_path);
				rval = 1;
				if (S_ISDIR(curr->fts_statp->st_mode))
					(void)fts_set(ftsp, curr, FTS_SKIP);
				continue;
			}
			if (!S_ISDIR(curr->fts_statp->st_mode) &&
			    S_ISDIR(to_stat.st_mode)) {
		warnx("cannot overwrite directory %s with non-directory %s",
				    to.p_path, curr->fts_path);
				rval = 1;
				continue;
			}
		}

		switch (curr->fts_statp->st_mode & S_IFMT) {
		case S_IFLNK:
			if (copy_link(curr, !fts_dne(curr)))
				rval = 1;
			break;
		case S_IFDIR:
			if (!Rflag && !rflag) {
				warnx("%s is a directory (not copied).",
				    curr->fts_path);
				(void)fts_set(ftsp, curr, FTS_SKIP);
				rval = 1;
				break;
			}
			/*
			 * If the directory doesn't exist, create the new
			 * one with the from file mode plus owner RWX bits,
			 * modified by the umask.  Trade-off between being
			 * able to write the directory (if from directory is
			 * 555) and not causing a permissions race.  If the
			 * umask blocks owner writes, we fail..
			 */
			if (fts_dne(curr)) {
				if (mkdir(to.p_path,
				    curr->fts_statp->st_mode | S_IRWXU) < 0)
					err(1, "%s", to.p_path);
			} else if (!S_ISDIR(to_stat.st_mode))
				errc(1, ENOTDIR, "%s", to.p_path);
			break;
		case S_IFBLK:
		case S_IFCHR:
			if (Rflag) {
				if (copy_special(curr->fts_statp, !fts_dne(curr)))
					rval = 1;
			} else
				if (copy_file(curr, fts_dne(curr)))
					rval = 1;
			break;
		case S_IFIFO:
			if (Rflag) {
				if (copy_fifo(curr->fts_statp, !fts_dne(curr)))
					rval = 1;
			} else
				if (copy_file(curr, fts_dne(curr)))
					rval = 1;
			break;
		case S_IFSOCK:
			warnc(EOPNOTSUPP, "%s", curr->fts_path);
			break;
		default:
			if (copy_file(curr, fts_dne(curr)))
				rval = 1;
			break;
		}
	}
	if (errno)
		err(1, "fts_read");
	(void)fts_close(ftsp);
	return (rval);
}
Ejemplo n.º 25
0
int
main(int argc, char *argv[])
{
	char *domain, *p, *ttyn, *shell, *fullname, *instance;
	char *lipaddr, *script, *ripaddr, *style, *type, *fqdn;
	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
	char localhost[MAXHOSTNAMELEN], *copyright;
	char mail[sizeof(_PATH_MAILDIR) + 1 + NAME_MAX];
	int ask, ch, cnt, fflag, pflag, quietlog, rootlogin, lastchance;
	int error, homeless, needto, authok, tries, backoff;
	struct addrinfo *ai, hints;
	struct rlimit cds, scds;
	quad_t expire, warning;
	struct utmp utmp;
	struct group *gr;
	struct stat st;
	uid_t uid;

	openlog("login", LOG_ODELAY, LOG_AUTH);

	fqdn = lipaddr = ripaddr = fullname = type = NULL;
	authok = 0;
	tries = 10;
	backoff = 3;

	domain = NULL;
	if (gethostname(localhost, sizeof(localhost)) < 0) {
		syslog(LOG_ERR, "couldn't get local hostname: %m");
		strlcpy(localhost, "localhost", sizeof(localhost));
	} else if ((domain = strchr(localhost, '.'))) {
		domain++;
		if (*domain && strchr(domain, '.') == NULL)
			domain = localhost;
	}

	if ((as = auth_open()) == NULL) {
		syslog(LOG_ERR, "auth_open: %m");
		err(1, "unable to initialize BSD authentication");
	}
	auth_setoption(as, "login", "yes");

	/*
	 * -p is used by getty to tell login not to destroy the environment
	 * -f is used to skip a second login authentication
	 * -h is used by other servers to pass the name of the remote
	 *    host to login so that it may be placed in utmp and wtmp
	 */
	fflag = pflag = 0;
	uid = getuid();
	while ((ch = getopt(argc, argv, "fh:pu:L:R:")) != -1)
		switch (ch) {
		case 'f':
			fflag = 1;
			break;
		case 'h':
			if (uid) {
				warnc(EPERM, "-h option");
				quickexit(1);
			}
			free(fqdn);
			if ((fqdn = strdup(optarg)) == NULL) {
				warn(NULL);
				quickexit(1);
			}
			auth_setoption(as, "fqdn", fqdn);
			if (domain && (p = strchr(optarg, '.')) &&
			    strcasecmp(p+1, domain) == 0)
				*p = 0;
			hostname = optarg;
			auth_setoption(as, "hostname", hostname);
			break;
		case 'L':
			if (uid) {
				warnc(EPERM, "-L option");
				quickexit(1);
			}
			if (lipaddr) {
				warnx("duplicate -L option");
				quickexit(1);
			}
			lipaddr = optarg;
			memset(&hints, 0, sizeof(hints));
			hints.ai_family = PF_UNSPEC;
			hints.ai_flags = AI_CANONNAME;
			error = getaddrinfo(lipaddr, NULL, &hints, &ai);
			if (!error) {
				strlcpy(localhost, ai->ai_canonname,
				    sizeof(localhost));
				freeaddrinfo(ai);
			} else
				strlcpy(localhost, lipaddr, sizeof(localhost));
			auth_setoption(as, "local_addr", lipaddr);
			break;
		case 'p':
			pflag = 1;
			break;
		case 'R':
			if (uid) {
				warnc(EPERM, "-R option");
				quickexit(1);
			}
			if (ripaddr) {
				warnx("duplicate -R option");
				quickexit(1);
			}
			ripaddr = optarg;
			auth_setoption(as, "remote_addr", ripaddr);
			break;
		case 'u':
			if (uid) {
				warnc(EPERM, "-u option");
				quickexit(1);
			}
			rusername = optarg;
			break;
		default:
			if (!uid)
				syslog(LOG_ERR, "invalid flag %c", ch);
			(void)fprintf(stderr,
			    "usage: login [-fp] [-h hostname] [-L local-addr] "
			    "[-R remote-addr] [-u username]\n\t[user]\n");
			quickexit(1);
		}
	argc -= optind;
	argv += optind;

	if (*argv) {
		username = *argv;
		ask = 0;
	} else
		ask = 1;

	/*
	 * If effective user is not root, just run su(1) to emulate login(1).
	 */
	if (geteuid() != 0) {
		char *av[5], **ap;

		auth_close(as);
		closelog();
		closefrom(STDERR_FILENO + 1);

		ap = av;
		*ap++ = _PATH_SU;
		*ap++ = "-L";
		if (!pflag)
			*ap++ = "-l";
		if (!ask)
			*ap++ = username;
		*ap = NULL;
		execv(_PATH_SU, av);
		warn("unable to exec %s", _PATH_SU);
		_exit(1);
	}

	ttyn = ttyname(STDIN_FILENO);
	if (ttyn == NULL || *ttyn == '\0') {
		(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
		ttyn = tname;
	}
	if ((tty = strrchr(ttyn, '/')))
		++tty;
	else
		tty = ttyn;

	/*
	 * Since login deals with sensitive information, turn off coredumps.
	 */
	if (getrlimit(RLIMIT_CORE, &scds) < 0) {
		syslog(LOG_ERR, "couldn't get core dump size: %m");
		scds.rlim_cur = scds.rlim_max = QUAD_MIN;
	}
	cds.rlim_cur = cds.rlim_max = 0;
	if (setrlimit(RLIMIT_CORE, &cds) < 0) {
		syslog(LOG_ERR, "couldn't set core dump size to 0: %m");
		scds.rlim_cur = scds.rlim_max = QUAD_MIN;
	}

	(void)signal(SIGALRM, timedout);
	if (argc > 1) {
		needto = 0;
		(void)alarm(timeout);
	} else
		needto = 1;
	(void)signal(SIGQUIT, SIG_IGN);
	(void)signal(SIGINT, SIG_IGN);
	(void)signal(SIGHUP, SIG_IGN);
	(void)setpriority(PRIO_PROCESS, 0, 0);

#ifdef notyet
	/* XXX - we don't (yet) support per-tty auth stuff */
	/* BSDi uses a ttys.conf file but we could just overload /etc/ttys */
	/*
	 * Classify the attempt.
	 * By default we use the value in the ttys file.
	 * If there is a classify script we run that as
	 *
	 *	classify [-f] [username]
	 */
	if (type = getttyauth(tty))
		auth_setoption(as, "auth_type", type);
#endif

	/* get the default login class */
	if ((lc = login_getclass(0)) == NULL) { /* get the default class */
		warnx("Failure to retrieve default class");
		quickexit(1);
	}
	timeout = (u_int)login_getcapnum(lc, "login-timeout", 300, 300);
	if ((script = login_getcapstr(lc, "classify", NULL, NULL)) != NULL) {
		unsetenv("AUTH_TYPE");
		unsetenv("REMOTE_NAME");
		if (script[0] != '/') {
			syslog(LOG_ERR, "Invalid classify script: %s", script);
			warnx("Classification failure");
			quickexit(1);
		}
		shell = strrchr(script, '/') + 1;
		auth_setstate(as, AUTH_OKAY);
		auth_call(as, script, shell,
		    fflag ? "-f" : username, fflag ? username : 0, (char *)0);
		if (!(auth_getstate(as) & AUTH_ALLOW))
			quickexit(1);
		auth_setenv(as);
		if ((p = getenv("AUTH_TYPE")) != NULL &&
		    strncmp(p, "auth-", 5) == 0)
			type = p;
		if ((p = getenv("REMOTE_NAME")) != NULL)
			hostname = p;
		/*
		 * we may have changed some values, reset them
		 */
		auth_clroptions(as);
		if (type)
			auth_setoption(as, "auth_type", type);
		if (fqdn)
			auth_setoption(as, "fqdn", fqdn);
		if (hostname)
			auth_setoption(as, "hostname", hostname);
		if (lipaddr)
			auth_setoption(as, "local_addr", lipaddr);
		if (ripaddr)
			auth_setoption(as, "remote_addr", ripaddr);
	}

	/*
	 * Request the things like the approval script print things
	 * to stdout (in particular, the nologins files)
	 */
	auth_setitem(as, AUTHV_INTERACTIVE, "True");

	for (cnt = 0;; ask = 1) {
		/*
		 * Clean up our current authentication session.
		 * Options are not cleared so we need to clear any
		 * we might set below.
		 */
		auth_clean(as);
		auth_clroption(as, "style");
		auth_clroption(as, "lastchance");

		lastchance = 0;

		if (ask) {
			fflag = 0;
			getloginname();
		}
		if (needto) {
			needto = 0;
			alarm(timeout);
		}
		if ((style = strchr(username, ':')) != NULL)
			*style++ = '\0';
		if (fullname)
			free(fullname);
		if (auth_setitem(as, AUTHV_NAME, username) < 0 ||
		    (fullname = strdup(username)) == NULL) {
			syslog(LOG_ERR, "%m");
			warn(NULL);
			quickexit(1);
		}
		rootlogin = 0;
		if ((instance = strchr(username, '/')) != NULL) {
			if (strncmp(instance + 1, "root", 4) == 0)
				rootlogin = 1;
			*instance++ = '\0';
		} else
			instance = "";

		if (strlen(username) > UT_NAMESIZE)
			username[UT_NAMESIZE] = '\0';

		/*
		 * Note if trying multiple user names; log failures for
		 * previous user name, but don't bother logging one failure
		 * for nonexistent name (mistyped username).
		 */
		if (failures && strcmp(tbuf, username)) {
			if (failures > (pwd ? 0 : 1))
				badlogin(tbuf);
			failures = 0;
		}
		(void)strlcpy(tbuf, username, sizeof(tbuf));

		if ((pwd = getpwnam(username)) != NULL &&
		    auth_setpwd(as, pwd) < 0) {
			syslog(LOG_ERR, "%m");
			warn(NULL);
			quickexit(1);
		}

		lc = login_getclass(pwd ? pwd->pw_class : NULL);
		if (!lc)
			goto failed;

		style = login_getstyle(lc, style, type);
		if (!style)
			goto failed;

		/*
		 * We allow "login-tries" attempts to login but start
		 * slowing down after "login-backoff" attempts.
		 */
		tries = (int)login_getcapnum(lc, "login-tries", 10, 10);
		backoff = (int)login_getcapnum(lc, "login-backoff", 3, 3);

		/*
		 * Turn off the fflag if we have an invalid user
		 * or we are not root and we are trying to change uids.
		 */
		if (!pwd || (uid && uid != pwd->pw_uid))
			fflag = 0;

		if (pwd && pwd->pw_uid == 0)
			rootlogin = 1;

		/*
		 * If we do not have the force flag authenticate the user
		 */
		if (!fflag) {
			lastchance =
			    login_getcaptime(lc, "password-dead", 0, 0) != 0;
			if (lastchance)
				auth_setoption(as, "lastchance", "yes");
			/*
			 * Once we start asking for a password
			 *  we want to log a failure on a hup.
			 */
			signal(SIGHUP, sighup);
			auth_verify(as, style, NULL, lc->lc_class, NULL);
			authok = auth_getstate(as);
			/*
			 * If their password expired and it has not been
			 * too long since then, give the user one last
			 * chance to change their password
			 */
			if ((authok & AUTH_PWEXPIRED) && lastchance) {
				authok = AUTH_OKAY;
			} else
				lastchance = 0;
			if ((authok & AUTH_ALLOW) == 0)
				goto failed;
			if (auth_setoption(as, "style", style) < 0) {
				syslog(LOG_ERR, "%m");
				warn(NULL);
				quickexit(1);
			}
		}
		/*
		 * explicitly reject users without password file entries
		 */
		if (pwd == NULL)
			goto failed;

		/*
		 * If trying to log in as root on an insecure terminal,
		 * refuse the login attempt unless the authentication
		 * style explicitly says a root login is okay.
		 */
		if (pwd && rootlogin && !rootterm(tty))
			goto failed;

		if (fflag) {
			type = 0;
			style = "forced";
		}
		break;

failed:
		if (authok & AUTH_SILENT)
			quickexit(0);
		if (rootlogin && !rootterm(tty)) {
			warnx("%s login refused on this terminal.",
			    fullname);
			if (hostname)
				syslog(LOG_NOTICE,
				    "LOGIN %s REFUSED FROM %s%s%s ON TTY %s",
				    fullname, rusername ? rusername : "",
				    rusername ? "@" : "", hostname, tty);
			else
				syslog(LOG_NOTICE,
				    "LOGIN %s REFUSED ON TTY %s",
				    fullname, tty);
		} else {
			if (!as || (p = auth_getvalue(as, "errormsg")) == NULL)
				p = "Login incorrect";
			(void)printf("%s\n", p);
		}
		failures++;
		if (pwd)
			log_failedlogin(pwd->pw_uid, hostname, rusername, tty);
		/*
		 * By default, we allow 10 tries, but after 3 we start
		 * backing off to slow down password guessers.
		 */
		if (++cnt > backoff) {
			if (cnt >= tries) {
				badlogin(username);
				sleepexit(1);
			}
			sleep((u_int)((cnt - backoff) * tries / 2));
		}
	}

	/* committed to login -- turn off timeout */
	(void)alarm(0);

	endpwent();

	shell = login_getcapstr(lc, "shell", pwd->pw_shell, pwd->pw_shell);
	if (*shell == '\0')
		shell = _PATH_BSHELL;
	else if (strlen(shell) >= MAXPATHLEN) {
		syslog(LOG_ERR, "shell path too long: %s", shell);
		warnx("invalid shell");
		quickexit(1);
	}

	/* Destroy environment unless user has requested its preservation. */
	if (!pflag) {
		if ((environ = calloc(1, sizeof (char *))) == NULL)
			err(1, "calloc");
	} else {
		char **cpp, **cpp2;

		for (cpp2 = cpp = environ; *cpp; cpp++) {
			if (strncmp(*cpp, "LD_", 3) &&
			    strncmp(*cpp, "ENV=", 4) &&
			    strncmp(*cpp, "BASH_ENV=", 9) &&
			    strncmp(*cpp, "IFS=", 4))
				*cpp2++ = *cpp;
		}
		*cpp2 = 0;
	}
	/* Note: setusercontext(3) will set PATH */
	if (setenv("HOME", pwd->pw_dir, 1) == -1 ||
	    setenv("SHELL", pwd->pw_shell, 1) == -1) {
		warn("unable to setenv()");
		quickexit(1);
	}
	if (term[0] == '\0')
		(void)strlcpy(term, stypeof(tty), sizeof(term));
	(void)snprintf(mail, sizeof(mail), "%s/%s", _PATH_MAILDIR,
		pwd->pw_name);
	if (setenv("TERM", term, 0) == -1 ||
	    setenv("LOGNAME", pwd->pw_name, 1) == -1 ||
	    setenv("USER", pwd->pw_name, 1) == -1 ||
	    setenv("MAIL", mail, 1) == -1) {
		warn("unable to setenv()");
		quickexit(1);
	}
	if (hostname) {
		if (setenv("REMOTEHOST", hostname, 1) == -1) {
			warn("unable to setenv()");
			quickexit(1);
		}
	}
	if (rusername) {
		if (setenv("REMOTEUSER", rusername, 1) == -1) {
			warn("unable to setenv()");
			quickexit(1);
		}
	}

	if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH)) {
		warn("unable to set user context");
		quickexit(1);
	}
	auth_setenv(as);

	/* if user not super-user, check for disabled logins */
	if (!rootlogin)
		auth_checknologin(lc);

	setegid(pwd->pw_gid);
	seteuid(pwd->pw_uid);

	homeless = chdir(pwd->pw_dir);
	if (homeless) {
		if (login_getcapbool(lc, "requirehome", 0)) {
			(void)printf("No home directory %s!\n", pwd->pw_dir);
			quickexit(1);
		}
		if (chdir("/"))
			quickexit(0);
	}

	quietlog = ((strcmp(pwd->pw_shell, "/sbin/nologin") == 0) ||
	    login_getcapbool(lc, "hushlogin", 0) ||
	    (access(_PATH_HUSHLOGIN, F_OK) == 0));

	seteuid(0);
	setegid(0);	/* XXX use a saved gid instead? */

	if ((p = auth_getvalue(as, "warnmsg")) != NULL)
		(void)printf("WARNING: %s\n\n", p);

	expire = auth_check_expire(as);
	if (expire < 0) {
		(void)printf("Sorry -- your account has expired.\n");
		quickexit(1);
	} else if (expire > 0 && !quietlog) {
		warning = login_getcaptime(lc, "expire-warn",
		    2 * DAYSPERWEEK * SECSPERDAY, 2 * DAYSPERWEEK * SECSPERDAY);
		if (expire < warning)
			(void)printf("Warning: your account expires on %s",
			    ctime(&pwd->pw_expire));
	}

	/* Nothing else left to fail -- really log in. */
	(void)signal(SIGHUP, SIG_DFL);
	memset(&utmp, 0, sizeof(utmp));
	(void)time(&utmp.ut_time);
	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
	if (hostname)
		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
	login(&utmp);

	if (!quietlog)
		(void)check_failedlogin(pwd->pw_uid);
	dolastlog(quietlog);

	login_fbtab(tty, pwd->pw_uid, pwd->pw_gid);

	(void)chown(ttyn, pwd->pw_uid,
	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);

	/* If fflag is on, assume caller/authenticator has logged root login. */
	if (rootlogin && fflag == 0) {
		if (hostname)
			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s%s%s",
			    username, tty, rusername ? rusername : "",
			    rusername ? "@" : "", hostname);
		else
			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
	}

	if (!quietlog) {
		if ((copyright =
		    login_getcapstr(lc, "copyright", NULL, NULL)) != NULL)
			auth_cat(copyright);
		motd();
		if (stat(mail, &st) == 0 && st.st_size != 0)
			(void)printf("You have %smail.\n",
			    (st.st_mtime > st.st_atime) ? "new " : "");
	}

	(void)signal(SIGALRM, SIG_DFL);
	(void)signal(SIGQUIT, SIG_DFL);
	(void)signal(SIGHUP, SIG_DFL);
	(void)signal(SIGINT, SIG_DFL);
	(void)signal(SIGTSTP, SIG_IGN);

	tbuf[0] = '-';
	(void)strlcpy(tbuf + 1, (p = strrchr(shell, '/')) ?
	    p + 1 : shell, sizeof(tbuf) - 1);

	if ((scds.rlim_cur != QUAD_MIN || scds.rlim_max != QUAD_MIN) &&
	    setrlimit(RLIMIT_CORE, &scds) < 0)
		syslog(LOG_ERR, "couldn't reset core dump size: %m");

	if (lastchance)
		(void)printf("WARNING: Your password has expired."
		    "  You must change your password, now!\n");

	if (setusercontext(lc, pwd, rootlogin ? 0 : pwd->pw_uid,
	    LOGIN_SETALL & ~LOGIN_SETPATH) < 0) {
		warn("unable to set user context");
		quickexit(1);
	}

	if (homeless) {
		(void)printf("No home directory %s!\n", pwd->pw_dir);
		(void)printf("Logging in with home = \"/\".\n");
		(void)setenv("HOME", "/", 1);
	}

	if (auth_approval(as, lc, NULL, "login") == 0) {
		if (auth_getstate(as) & AUTH_EXPIRED)
			(void)printf("Sorry -- your account has expired.\n");
		else
			(void)printf("approval failure\n");
		quickexit(1);
	}

	/*
	 * The last thing we do is discard all of the open file descriptors.
	 * Last because the C library may have some open.
	 */
	closefrom(STDERR_FILENO + 1);

	/*
	 * Close the authentication session, make sure it is marked
	 * as okay so no files are removed.
	 */
	auth_setstate(as, AUTH_OKAY);
	auth_close(as);

	execlp(shell, tbuf, (char *)NULL);
	err(1, "%s", shell);
}
Ejemplo n.º 26
0
int
main(int argc, char *argv[])
{
	int ch, exitval, success, pflag;
	mode_t omode, *set = (mode_t *)NULL;
	char *mode;

	pflag = 0;
	mode = NULL;
	while ((ch = getopt(argc, argv, "m:pv")) != -1)
		switch(ch) {
		case 'm':
			mode = optarg;
			break;
		case 'p':
			pflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
		case '?':
		default:
			usage();
		}

//	argc -= optind;
	argv += optind;
	if (argv[0] == NULL)
		usage();

	if (mode == NULL) {
		omode = S_IRWXU | S_IRWXG | S_IRWXO;
	} else {
		if ((set = setmode(mode)) == NULL)
			errx(1, "invalid file mode: %s", mode);
		omode = getmode(set, S_IRWXU | S_IRWXG | S_IRWXO);
		free(set);
	}

	for (exitval = 0; *argv != NULL; ++argv) {
		success = 1;
		if (pflag) {
			int status = mkpath_np(*argv, omode);
			if (status && status != EEXIST) {
				warnc(status, "%s", *argv);
				success = 0;
			}
		} else if (mkdir(*argv, omode) < 0) {
			if (errno == ENOTDIR || errno == ENOENT)
				warn("%s", dirname(*argv));
			else
				warn("%s", *argv);
			success = 0;
		} else if (vflag)
			(void)printf("mkdir: created directory '%s'\n", *argv);
		
		if (!success)
			exitval = 1;
		/*
		 * The mkdir() and umask() calls both honor only the low
		 * nine bits, so if you try to set a mode including the
		 * sticky, setuid, setgid bits you lose them.  Don't do
		 * this unless the user has specifically requested a mode,
		 * as chmod will (obviously) ignore the umask.
		 */
		if (success && mode != NULL && chmod(*argv, omode) == -1) {
			warn("%s", *argv);
			exitval = 1;
		}
	}
	exit(exitval);
}
Ejemplo n.º 27
0
Archivo: banipd.c Proyecto: julp/banip
int main(int argc, char **argv)
{
    gid_t gid;
    addr_t addr;
    struct sigaction sa;
    int c, dFlag, vFlag;
    unsigned long max_message_size;
    const char *queuename, *tablename;

    ctxt = NULL;
    gid = (gid_t) -1;
    vFlag = dFlag = 0;
    tablename = queuename = NULL;
    if (NULL == (queue = queue_init())) {
        errx("queue_init failed"); // TODO: better
    }
    atexit(cleanup);
    sa.sa_handler = &on_signal;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sa.sa_flags = SA_RESTART;
    sigaction(SIGUSR1, &sa, NULL);
    if (NULL == (engine = get_default_engine())) {
        errx("no engine available for your system");
    }
    while (-1 != (c = getopt_long(argc, argv, optstr, long_options, NULL))) {
        switch (c) {
            case 'b':
            {
                unsigned long val;

                if (parse_ulong(optarg, &val)) {
                    queue_set_attribute(queue, QUEUE_ATTR_MAX_MESSAGE_SIZE, val); // TODO: check returned value
                }
                break;
            }
            case 'd':
                dFlag = 1;
                break;
            case 'e':
            {
                if (NULL == (engine = get_engine_by_name(optarg))) {
                    errx("unknown engine '%s'", optarg);
                }
                break;
            }
            case 'g':
            {
                struct group *grp;

                if (NULL == (grp = getgrnam(optarg))) {
                    errc("getgrnam failed");
                }
                gid = grp->gr_gid;
                break;
            }
            case 'l':
            {
                logfilename = optarg;
                if (NULL == (err_file = fopen(logfilename, "a"))) {
                    err_file = NULL;
                    warnc("fopen '%s' failed, falling back to stderr", logfilename);
                }
                break;
            }
            case 'p':
                pidfilename = optarg;
                break;
            case 'q':
                queuename = optarg;
                break;
            case 's':
            {
                unsigned long val;

                if (parse_ulong(optarg, &val)) {
                    queue_set_attribute(queue, QUEUE_ATTR_MAX_MESSAGE_IN_QUEUE, val); // TODO: check returned value
                }
                break;
            }
            case 't':
                tablename = optarg;
                break;
            case 'v':
                vFlag++;
                break;
            case 'h':
            default:
                usage();
        }
    }
    argc -= optind;
    argv += optind;

    if (0 != argc || NULL == queuename || NULL == tablename) {
        usage();
    }

    if (dFlag) {
        if (0 != daemon(0, !vFlag)) {
            errc("daemon failed");
        }
    }
    if (NULL != pidfilename) {
        FILE *fp;

        if (NULL == (fp = fopen(pidfilename, "w"))) {
            warnc("can't create pid file '%s'", pidfilename);
        } else {
            fprintf(fp, "%ld\n", (long) getpid());
            fclose(fp);
        }
    }

    if (((gid_t) -1) != gid) {
        if (0 != setgid(gid)) {
            errc("setgid failed");
        }
        if (0 != setgroups(1, &gid)) {
            errc("setgroups failed");
        }
    }
    CAP_RIGHTS_LIMIT(STDOUT_FILENO, CAP_WRITE);
    CAP_RIGHTS_LIMIT(STDERR_FILENO, CAP_WRITE);
    if (NULL != err_file/* && fileno(err_file) > 2*/) {
        CAP_RIGHTS_LIMIT(fileno(err_file), CAP_WRITE);
    }
    if (QUEUE_ERR_OK != queue_open(queue, queuename, QUEUE_FL_OWNER)) {
        errx("queue_open failed"); // TODO: better
    }
    if (QUEUE_ERR_OK != queue_get_attribute(queue, QUEUE_ATTR_MAX_MESSAGE_SIZE, &max_message_size)) {
        errx("queue_get_attribute failed"); // TODO: better
    }
    if (NULL == (buffer = calloc(++max_message_size, sizeof(*buffer)))) {
        errx("calloc failed");
    }
    if (NULL != engine->open) {
        ctxt = engine->open(tablename);
    }
    if (0 == getuid() && engine->drop_privileges) {
        struct passwd *pwd;

        if (NULL == (pwd = getpwnam("nobody"))) {
            if (NULL == (pwd = getpwnam("daemon"))) {
                errx("no nobody or daemon user accounts found on this system");
            }
        }
        if (0 != setuid(pwd->pw_uid)) {
            errc("setuid failed");
        }
    }
    CAP_ENTER();
    while (1) {
        ssize_t read;

        if (-1 == (read = queue_receive(queue, buffer, max_message_size))) {
            errc("queue_receive failed"); // TODO: better
        } else {
            if (!parse_addr(buffer, &addr)) {
                errx("parsing of '%s' failed", buffer); // TODO: better
            } else {
                engine->handle(ctxt, tablename, addr);
            }
        }
    }
    /* not reached */

    return BANIPD_EXIT_SUCCESS;
}