big <utmp.h>-inspired netbsd switch

import/switch of:
init, getty, reboot, halt, shutdown, wall, last

changes:
	. change reboot() call to netbsd prototype and args
	. allows pristine <utmp.h>
	. use clean <sys/reboot.h> instead of <minix/reboot.h>
	. implement TIOCSCTTY for use by getty so getty can get
	  controlling terminal from init's child(ren)
	. allow NULL envp for exec

Change-Id: I5ca02cb4230857140c08794bbfeba7df982c58a3
This commit is contained in:
Ben Gras 2013-09-09 13:20:18 +00:00 committed by Lionel Sambuc
parent fa06ff0ee3
commit a06e2ab395
93 changed files with 8096 additions and 2465 deletions

View file

@ -10,18 +10,18 @@ SUBDIR= add_route arp ash at backup btrace \
dhrystone diff diskctl \
eject factor fbdctl \
find fix format fortune fsck.mfs \
gcov-pull getty grep host \
gcov-pull grep host \
hostaddr ifconfig ifdef \
intr ipcrm ipcs irdpd isoread last \
intr ipcrm ipcs irdpd isoread \
less loadkeys loadramdisk logger look lp \
lpd lspci mail MAKEDEV \
mined \
mount mt netconf \
nonamed patch \
ping postinstall poweroff prep printroot \
ping postinstall prep printroot \
profile progressbar pr_routes ps pwdauth \
ramdisk rarpd rawspeed rcp readclock \
reboot remsync rget rlogin \
remsync rget rlogin \
rotate rsh rshd service setup shar \
sleep slip spell sprofalyze sprofdiff srccrc \
stty svclog svrctl swifi synctree sysenv \

View file

@ -1,5 +0,0 @@
PROG= getty
BINDIR= /bin
MAN=
.include <bsd.prog.mk>

View file

@ -1,210 +0,0 @@
/* getty - get tty speed Author: Fred van Kempen */
/*
* GETTY - Initialize and serve a login-terminal for INIT.
* Also, select the correct speed. The STTY() code
* was taken from stty(1).c; which was written by
* Andrew S. Tanenbaum.
*
* Usage: getty [speed]
*
* Version: 3.4 02/17/90
*
* Author: F. van Kempen, MicroWalt Corporation
*
* Modifications:
* All the good stuff removed to get a minimal getty, because
* many modems don't like all that fancy speed detection stuff.
* 03/03/91 Kees J. Bot (kjb@cs.vu.nl)
*
* Uname(), termios. More nonsense removed. (The result has
* only 10% of the original functionality, but a 10x chance of
* working.)
* 12/12/92 Kees J. Bot
*
* Customizable login banner.
* 11/13/95 Kees J. Bot
*
* Suspend/resume signals removed.
* 2001-04-04 Kees J. Bot
*
* Removed unused custom banner and returned speed option
* functionality (by simply calling stty).
* 2012-09-24 T. Veerman
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/utsname.h>
#include <stdio.h>
char LOGIN[] = "/usr/bin/login";
char SHELL[] = "/bin/sh";
char *tty_name; /* name of the line */
/* Crude indication of a tty being physically secure: */
#define securetty(dev) ((unsigned) ((dev) - 0x0400) < (unsigned) 8)
void std_out(const char *s)
{
write(1, s, strlen(s));
}
/* Read one character from stdin.
*/
int readch(void)
{
int st;
char ch1;
/* read character from TTY */
st = read(0, &ch1, 1);
if (st == 0) {
std_out("\n");
exit(0);
}
if (st < 0) {
std_out("getty: ");
std_out(tty_name);
std_out(": read error\n");
exit(1);
}
return(ch1 & 0xFF);
}
/* Handle the process of a GETTY.
*/
void do_getty(char *name, size_t len, char **args, const char *ttyname)
{
register char *np, *s, *s0;
int ch;
struct utsname utsname;
char **banner, *t;
static char *def_banner[] = { "%s/%p (%t)\n\n%n login: ", 0 };
/* Clean up tty name. */
if((t = strrchr(ttyname, '/'))) ttyname = t + 1;
if (args[0] != NULL) {
char cmd[5+6+1]; /* "stty " + "115200" + '\0' */
int speed;
speed = atoi(args[0]);
snprintf(cmd, sizeof(cmd), "stty %d\n", speed);
system(cmd);
}
/* Display prompt. */
ch = ' ';
*name = '\0';
while (ch != '\n') {
/* Get data about this machine. */
uname(&utsname);
/* Print the banner. */
for (banner = def_banner; *banner != NULL; banner++) {
std_out(banner == args ? "\n" : " ");
s0 = *banner;
for (s = *banner; *s != 0; s++) {
if (*s == '\\') {
write(1, s0, s-s0);
s0 = s+2;
switch (*++s) {
case 'n': std_out("\n"); break;
case 's': std_out(" "); break;
case 't': std_out("\t"); break;
case 0: goto leave;
default: s0 = s;
}
} else
if (*s == '%') {
write(1, s0, s-s0);
s0 = s+2;
switch (*++s) {
case 's': std_out(utsname.sysname); break;
case 'n': std_out(utsname.nodename); break;
case 'r': std_out(utsname.release); break;
case 'v': std_out(utsname.version); break;
case 'm': std_out(utsname.machine); break;
case 'p': std_out(utsname.arch); break;
case 't': std_out(ttyname); break;
#if __minix_vmd
case 'k': std_out(utsname.kernel); break;
case 'h': std_out(utsname.hostname); break;
case 'b': std_out(utsname.bus); break;
#endif
case 0: goto leave;
default: s0 = s-1;
}
}
}
leave:
write(1, s0, s-s0);
}
np = name;
while ((ch = readch()) != '\n') {
if (np < name + len) *np++ = ch;
}
*np = '\0';
if (*name == '\0') ch = ' '; /* blank line typed! */
}
}
/* Execute the login(1) command with the current
* username as its argument. It will reply to the
* calling user by typing "Password: "...
*/
void do_login(char *name)
{
struct stat st;
execl(LOGIN, LOGIN, name, (char *) NULL);
/* Failed to exec login. Impossible, but true. Try a shell, but only if
* the terminal is more or less secure, because it will be a root shell.
*/
std_out("getty: can't exec ");
std_out(LOGIN);
std_out("\n");
if (fstat(0, &st) == 0 && S_ISCHR(st.st_mode) && securetty(st.st_rdev)) {
execl(SHELL, SHELL, (char *) NULL);
}
}
int main(int argc, char **argv)
{
char name[30];
struct sigaction sa;
/* Don't let QUIT dump core. */
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = exit;
sigaction(SIGQUIT, &sa, NULL);
tty_name = ttyname(0);
if (tty_name == NULL) {
std_out("getty: tty name unknown\n");
pause();
return(1);
}
chown(tty_name, 0, 0); /* set owner of TTY to root */
chmod(tty_name, 0600); /* mode to max secure */
do_getty(name, sizeof(name), argv+1, tty_name); /* handle getty() */
name[29] = '\0'; /* make sure the name fits! */
do_login(name); /* and call login(1) if OK */
return(1); /* never executed */
}

View file

@ -1,6 +0,0 @@
PROG= last
MAN=
LINKS+= ${BINDIR}/last ${BINDIR}/uptime
.include <bsd.prog.mk>

View file

@ -1,482 +0,0 @@
/* last - display login history Author: Terrence W. Holm */
/* last- Display the user log-in history.
* Last(1) searches backwards through the file of log-in
* records (/usr/adm/wtmp), displaying the length of
* log-in sessions as requested by the options:
*
* Usage: last [-r] [-count] [-f file] [name] [tty] ...
*
* -r Search backwards only until the last reboot
* record.
*
* -count Only print out <count> records. Last(1) stops
* when either -r or -count is satisfied, or at
* the end of the file if neither is given.
*
* -f file Use "file" instead of "/usr/adm/wtmp".
*
* name Print records for the user "name".
*
* tty Print records for the terminal "tty". Actually,
* a list of names may be given and all records
* that match either the user or tty name are
* printed. If no names are given then all records
* are displayed.
*
* A sigquit (^\) causes last(1) to display how far it
* has gone back in the log-in record file, it then
* continues. This is used to check on the progress of
* long running searches. A sigint will stop last(1).
*
* Author: Terrence W. Holm May 1988
*
* Revision:
* Fred van Kempen, October 1989
* -Adapted to MSS.
* -Adapted to new utmp database.
*
* Fred van Kempen, December 1989
* -Adapted to POSIX (MINIX 1.5)
*
* Fred van Kempen, January 1990
* -Final edit for 1.5
*
* Philip Homburg, March 1992
* -Include host in output
*
* Kees J. Bot, July 1997
* -Approximate system uptime from last reboot record
*/
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <utmp.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <paths.h>
#define FALSE 0
#define TRUE 1
#define RLOGIN 1
#define BUFFER_SIZE 4096 /* Room for wtmp records */
#define MAX_WTMP_COUNT ( BUFFER_SIZE / sizeof(struct utmp) )
#define min( a, b ) ( (a < b) ? a : b )
#define max( a, b ) ( (a > b) ? a : b )
typedef struct logout { /* A logout time record */
char line[12]; /* The terminal name */
long time; /* The logout time */
struct logout *next; /* Next in linked list */
} logout;
static char *Version = "@(#) LAST 1.7 (10/24/92)";
/* command-line option flags */
char boot_limit = FALSE; /* stop on latest reboot */
char count_limit = FALSE; /* stop after print_count */
char tell_uptime = FALSE; /* tell uptime since last reboot */
int print_count;
char *prog; /* name of this program */
int arg_count; /* used to select specific */
char **args; /* users and ttys */
/* global variables */
long boot_time = 0; /* Zero means no reboot yet */
char *boot_down; /* "crash" or "down " flag */
logout *first_link = NULL; /* List of logout times */
int interrupt = FALSE; /* If sigint or sigquit occurs */
int main(int argc, char **argv);
void Sigint(int sig);
void Sigquit(int sig);
void usage(void);
void Process(struct utmp *wtmp);
int Print_Record(struct utmp *wtmp);
void Print_Duration(long from, long to);
void Print_Uptime(void);
void Record_Logout_Time(struct utmp *wtmp);
/* Sigint() and Sigquit() Flag occurrence of an interrupt. */
void Sigint(sig)
int sig;
{
interrupt = SIGINT;
}
void Sigquit(sig)
int sig;
{
interrupt = SIGQUIT;
}
void usage()
{
fprintf(stderr,
"Usage: last [-r] [-u] [-count] [-f file] [name] [tty] ...\n");
exit(-1);
}
/* A log-in record format file contains four types of records.
*
* [1] generated on a system reboot:
*
* line="~", name="reboot", host="", time=date()
*
*
* [2] generated after a shutdown:
*
* line="~", name="shutdown", host="", time=date()
*
*
* [3] generated on a successful login(1)
*
* line=ttyname(), name=cuserid(), host=, time=date()
*
*
* [4] generated by init(8) on a logout
*
* line=ttyname(), name="", host="", time=date()
*
*
* Note: This version of last(1) does not recognize the '|' and '}' time
* change records. Last(1) pairs up line login's and logout's to
* generate four types of output lines:
*
* [1] a system reboot or shutdown
*
* reboot ~ Mon May 16 14:16
* shutdown ~ Mon May 16 14:15
*
* [2] a login with a matching logout
*
* edwin tty1 Thu May 26 20:05 - 20:32 (00:27)
*
* [3] a login followed by a reboot or shutdown
*
* root tty0 Mon May 16 13:57 - crash (00:19)
* root tty1 Mon May 16 13:45 - down (00:30)
*
* [4] a login not followed by a logout or reboot
*
* terry tty0 Thu May 26 21:19 still logged in
*/
void Process(wtmp)
struct utmp *wtmp;
{
logout *link;
logout *next_link;
char is_reboot;
/* suppress the job number on an "ftp" line */
if (!strncmp(wtmp->ut_line, "ftp", (size_t)3)) strncpy(wtmp->ut_line, "ftp", (size_t)8);
if (!strcmp(wtmp->ut_line, "~")) {
/* A reboot or shutdown record */
if (boot_limit) exit(0);
if (Print_Record(wtmp)) putchar('\n');
boot_time = wtmp->ut_time;
is_reboot = !strcmp(wtmp->ut_name, "reboot");
if (is_reboot)
boot_down = "crash";
else
boot_down = "down ";
if (tell_uptime) {
if (!is_reboot) {
fprintf(stderr,
"%s: no reboot record added to wtmp file on system boot!\n",
prog);
exit(1);
}
Print_Uptime();
exit(0);
}
/* remove any logout records */
for (link = first_link; link != NULL; link = next_link) {
next_link = link->next;
free(link);
}
first_link = NULL;
} else if (wtmp->ut_name[0] == '\0') {
/* A logout record */
Record_Logout_Time(wtmp);
} else {
/* A login record */
for (link = first_link; link != NULL; link = link->next)
if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {
/* found corresponding logout record */
if (Print_Record(wtmp)) {
printf("- %.5s ", ctime(&link->time) + 11);
Print_Duration(wtmp->ut_time, link->time);
}
/* record login time */
link->time = wtmp->ut_time;
return;
}
/* could not find a logout record for this login tty */
if (Print_Record(wtmp))
if (boot_time == 0) /* still on */
printf(" still logged in\n");
else { /* system crashed while on */
printf("- %s ", boot_down);
Print_Duration(wtmp->ut_time, boot_time);
}
Record_Logout_Time(wtmp); /* Needed in case of 2
* consecutive logins */
}
}
/* Print_Record(wtmp) If the record was requested, then print out
* the user name, terminal, host and time.
*/
int Print_Record(wtmp)
struct utmp *wtmp;
{
int i;
char print_flag = FALSE;
/* just interested in the uptime? */
if (tell_uptime) return(FALSE);
/* check if we have already printed the requested number of records */
if (count_limit && print_count == 0) exit(0);
for (i = 0; i < arg_count; ++i)
if (!strncmp(args[i], wtmp->ut_name, sizeof(wtmp->ut_name)) ||
!strncmp(args[i], wtmp->ut_line, sizeof(wtmp->ut_line)))
print_flag = TRUE;
if (arg_count == 0 || print_flag) {
#ifdef RLOGIN
printf("%-8.8s %-8.8s %-16.16s %.16s ",
wtmp->ut_name, wtmp->ut_line, wtmp->ut_host,
ctime(&wtmp->ut_time));
#else
printf("%-8.8s %-8.8s %.16s ",
wtmp->ut_name, wtmp->ut_line, ctime(&wtmp->ut_time));
#endif
--print_count;
return(TRUE);
}
return(FALSE);
}
/* Print_Duration(from, to) Calculate and print the days and hh:mm between
* the log-in and the log-out.
*/
void Print_Duration(from, to)
long from;
long to;
{
long delta, days, hours, minutes;
delta = max(to - from, 0);
days = delta / (24L * 60L * 60L);
delta = delta % (24L * 60L * 60L);
hours = delta / (60L * 60L);
delta = delta % (60L * 60L);
minutes = delta / 60L;
if (days > 0)
printf("(%ld+", days);
else
printf(" (");
printf("%02ld:%02ld)\n", hours, minutes);
}
/* Print_Uptime() Calculate and print the "uptime" between the last recorded
* boot and the current time.
*/
void Print_Uptime()
{
#define NLOADS 3
int nloads;
double loads[NLOADS];
char *utmp_file = _PATH_UTMP;
unsigned nusers;
struct utmp ut;
FILE *uf;
time_t now;
struct tm *tm;
unsigned long up;
/* Count the number of active users in the utmp file. */
if ((uf = fopen(utmp_file, "r")) == NULL) {
fprintf(stderr, "%s: %s: %s\n", prog, utmp_file, strerror(errno));
exit(1);
}
nusers = 0;
while (fread(&ut, sizeof(ut), 1, uf) == 1) {
#ifdef USER_PROCESS
if (ut.ut_type == USER_PROCESS) nusers++;
#else
if (ut.ut_name[0] != 0 && ut.ut_line[0] != 0) nusers++;
#endif
}
fclose(uf);
/* Current time. */
now = time((time_t *) NULL);
tm = localtime(&now);
/* Uptime. */
up = now - boot_time;
printf(" %d:%02d up", tm->tm_hour, tm->tm_min);
if (up >= 24 * 3600L) {
unsigned long days = up / (24 * 3600L);
printf(" %lu day%s,", days, days == 1 ? "" : "s");
}
printf(" %lu:%02lu,", (up % (24 * 3600L)) / 3600, (up % 3600) / 60);
printf(" %u user%s", nusers, nusers == 1 ? "" : "s");
if((nloads = getloadavg(loads, NLOADS)) > 0) {
int i;
printf(", load averages:");
for(i = 0; i < nloads; i++)
printf("%s %.2f", (i > 0) ? "," : "", loads[i]);
}
printf("\n");
}
/* Record_Logout_Time(wtmp) A linked list of "last logout time" is kept.
* Each element of the list is for one terminal.
*/
void Record_Logout_Time(wtmp)
struct utmp *wtmp;
{
logout *link;
/* see if the terminal is already in the list */
for (link = first_link; link != NULL; link = link->next)
if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {
link->time = wtmp->ut_time;
return;
}
/* allocate a new logout record, for a tty not previously encountered */
link = (logout *) malloc(sizeof(logout));
if (link == NULL) {
fprintf(stderr, "%s: malloc failure\n", prog);
exit(1);
}
strncpy(link->line, wtmp->ut_line, (size_t)8);
link->time = wtmp->ut_time;
link->next = first_link;
first_link = link;
}
int main(argc, argv)
int argc;
char *argv[];
{
char *wtmp_file = _PATH_WTMP;
FILE *f;
long size; /* Number of wtmp records in the file */
int wtmp_count; /* How many to read into wtmp_buffer */
struct utmp wtmp_buffer[MAX_WTMP_COUNT];
if ((prog = strrchr(argv[0], '/')) == NULL) prog = argv[0]; else prog++;
--argc;
++argv;
while (argc > 0 && *argv[0] == '-') {
if (!strcmp(argv[0], "-r"))
boot_limit = TRUE;
else
if (!strcmp(argv[0], "-u"))
tell_uptime = TRUE;
else if (argc > 1 && !strcmp(argv[0], "-f")) {
wtmp_file = argv[1];
--argc;
++argv;
} else if ((print_count = atoi(argv[0] + 1)) > 0)
count_limit = TRUE;
else
usage();
--argc;
++argv;
}
arg_count = argc;
args = argv;
if (!strcmp(prog, "uptime")) tell_uptime = TRUE;
if ((f = fopen(wtmp_file, "r")) == NULL) {
perror(wtmp_file);
exit(1);
}
if (fseek(f, 0L, 2) != 0 || (size = ftell(f)) % sizeof(struct utmp) != 0) {
fprintf(stderr, "%s: invalid wtmp file\n", prog);
exit(1);
}
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
signal(SIGINT, Sigint);
signal(SIGQUIT, Sigquit);
}
size /= sizeof(struct utmp); /* Number of records in wtmp */
if (size == 0) wtmp_buffer[0].ut_time = time((time_t *)0);
while (size > 0) {
wtmp_count = (int) min(size, MAX_WTMP_COUNT);
size -= (long) wtmp_count;
fseek(f, size * sizeof(struct utmp), 0);
if (fread(&wtmp_buffer[0], sizeof(struct utmp), (size_t)wtmp_count, f)
!= wtmp_count) {
fprintf(stderr, "%s: read error on wtmp file\n", prog);
exit(1);
}
while (--wtmp_count >= 0) {
Process(&wtmp_buffer[wtmp_count]);
if (interrupt) {
printf("\ninterrupted %.16s \n",
ctime(&wtmp_buffer[wtmp_count].ut_time));
if (interrupt == SIGINT) exit(2);
interrupt = FALSE;
signal(SIGQUIT, Sigquit);
}
}
} /* end while(size > 0) */
if (tell_uptime) {
fprintf(stderr,
"%s: no reboot record in wtmp file to compute uptime from\n",
prog);
return(1);
}
printf("\nwtmp begins %.16s \n", ctime(&wtmp_buffer[0].ut_time));
return(0);
}

View file

@ -1,4 +0,0 @@
SCRIPTS= poweroff.sh
MAN=
.include <bsd.prog.mk>

View file

@ -1,13 +0,0 @@
#!/bin/sh
#
# poweroff 1.0 - power off the system Author: David van Moolenbroek
# 12 Jun 2009
if [ $# -gt 0 ]; then
echo "usage: poweroff" >&2
exit 1
fi
PATH=/usr/bin:$PATH
exec shutdown -p

View file

@ -1,15 +0,0 @@
# Makefile for shutdown / halt / reboot.
PROGS= shutdown halt
SRCS.shutdown= shutdown.c sh_wall.c log.c
SRCS.halt= halt.c log.c
BINDIR=/bin
BINMODE= 4754
SYMLINKS+= ${BINDIR}/halt ${BINDIR}/reboot
SYMLINKS+= ${BINDIR}/halt /usr/bin/halt
SYMLINKS+= ${BINDIR}/shutdown /usr/bin/shutdown
SYMLINKS+= ${BINDIR}/reboot /usr/bin/reboot
MAN.shutdown=
MAN.halt=
.include <bsd.prog.mk>

View file

@ -1,52 +0,0 @@
This a new implementation of a shutdown procedure. It allows
the system to go down graciously with informing the
users. This package contains 3 programs:
- halt = Immediately stop the system, no info to users
- shutdown = Inform users, close down the system properly
- wall = Vincent Archer's implementation of wall (Write all)
Installing
Shutdown and halt use a new systemcall, which I've added to
MM. Therefor there are several diff's which should be applied:
callnr.hd - New callnr for reboot(2)
Diff against /usr/include/minix/callnr.h.
Those of you using a symlink package should
change the number and mm/table.c into a free
number. I used 54, LSTAT.
param.hd - Defines reboot_flag as a part of the messages
proto.hd - Add's prototype for do_reboot()
table.cd - Interpretation of the systemcall to MM
mm.cd - I have added the do_reboot code to mm/getset.c but
I couldn't find a getset.c to create a useable diff :-(
So you can add where you want it. It is pure code, no diff.
Now edit log.c and search for ``host''. Change this into your
systemname or make it empty.
Shutdown and halt log their actions in /usr/adm/log, edit the
makefile and undefine -DLOG if you don't want this (this at the end of
the makefile). You can change SHUT_LOG in shutdown.c and log.c if you
want it in another file.
Then type a `make'. This will take a minute or so (13 sec. with bcc :-).
Remember to build a new image and update the ps_database.
Type `make install' to place the program's where I've got them.
Use them, try them and let me now if you've got problems running
something.
I have tested to sources both on 16-bits and 32-bits MINIX. I have compiled
it with gcc, bcc and ACK, so that shouldn't really give a problem. Maybe
the standard MINIX-make chokes on the makefile, atleast mine did.
NOTE:
Make install does not place the man-pages somewhere. You should
do this yourself.
--
Edvard Tuinder ed@pulstar.NL.mugnet.org v892231@si.hhs.NL
Student Computer Science
Haagse Hogeschool, The Hague, The Netherlands

View file

@ -1,126 +0,0 @@
/* halt / reboot - halt or reboot system (depends on name)
halt - calling reboot() with RBT_HALT
reboot - calling reboot() with RBT_REBOOT
author: Edvard Tuinder v892231@si.hhs.NL
This program calls the library function reboot(2) which performs
the system-call do_reboot.
*/
#define _POSIX_SOURCE 1
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <minix/reboot.h>
#include "wtmp.h"
void write_log( char *fn );
void usage( void );
int main( int argc, char *argv[] );
char *prog;
void
usage()
{
fprintf(stderr, "Usage: %s [-hrRfpd]\n", prog);
exit(1);
}
int
main(argc,argv)
int argc;
char **argv;
{
int flag = -1; /* default action unknown */
int fast = 0; /* fast halt/reboot, don't bother being nice. */
int i;
struct stat dummy;
pid_t pid;
if ((prog = strrchr(argv[0],'/')) == NULL) prog = argv[0]; else prog++;
if (strcmp(prog, "halt") == 0) flag = RBT_HALT;
if (strcmp(prog, "reboot") == 0) flag = RBT_REBOOT;
i = 1;
while (i < argc && argv[i][0] == '-') {
char *opt = argv[i++] + 1;
if (*opt == '-' && opt[1] == 0) break; /* -- */
while (*opt != 0) switch (*opt++) {
case 'h': flag = RBT_HALT; break;
case 'r': flag = RBT_REBOOT; break;
case 'R': flag = RBT_RESET; break;
case 'd': flag = RBT_DEFAULT; break;
case 'p': flag = RBT_POWEROFF; break;
case 'f': fast = 1; break;
default:
usage();
}
}
if (i != argc) usage();
if (flag == -1) {
fprintf(stderr, "Don't know what to do when named '%s'\n", prog);
exit(1);
}
if (stat("/usr/bin", &dummy) < 0) {
/* It seems that /usr isn't present, let's assume "-f." */
fast = 1;
}
signal(SIGHUP, SIG_IGN);
signal(SIGTERM, SIG_IGN);
/* Skip this part for fast shut down. */
if (! fast) {
/* Run the shutdown scripts. */
switch ((pid = fork())) {
case -1:
fprintf(stderr, "%s: can't fork(): %s\n", prog, strerror(errno));
exit(1);
case 0:
execl("/bin/sh", "sh", "/etc/rc", "down", (char *) NULL);
fprintf(stderr, "%s: can't execute: /bin/sh: %s\n",
prog, strerror(errno));
exit(1);
default:
while (waitpid(pid, NULL, 0) != pid) {}
}
}
/* Tell init to stop spawning getty's. */
kill(1, SIGTERM);
/* Extra sync for the case where SIGTERM causes deadlock */
sync();
/* Give everybody a chance to die peacefully. */
printf("Sending SIGTERM to all processes ...\n");
kill(-1, SIGTERM);
sleep(1);
write_log(STR_WTMP);
write_log(STR_ROOT_WTMP);
sync();
reboot(flag);
fprintf(stderr, "%s: reboot(): %s\n", prog, strerror(errno));
return 1;
}

View file

@ -1,77 +0,0 @@
/*
log - log the shutdown's and the halt's
Author: Edvard Tuinder <v892231@si.hhs.NL>
shutdown is logged in /usr/adm/wtmp and in /usr/adm/log (if desired)
halt is logged only in /usr/adm/wtmp as `halt' to prevent last from
reporting halt's as crashes.
*/
#define _POSIX_SOURCE 1
#include <sys/types.h>
#include <stdio.h>
#include <utmp.h>
#include <pwd.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <sys/utsname.h>
static char SHUT_LOG[] = "/usr/adm/log";
char who[8];
extern char *prog;
static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
void write_log(char *wtmpfile)
{
int fd;
static struct utmp wtmp;
static struct passwd *pwd;
char mes[90];
struct tm *tm;
time_t now;
struct utsname utsname;
char *host = "localhost";
time(&now);
tm = localtime(&now);
if (uname(&utsname) >= 0) host = utsname.nodename;
pwd = getpwuid(getuid());
if (pwd == (struct passwd *)0)
strcpy (who,"root");
else
strcpy (who,pwd->pw_name);
fd = open(wtmpfile,O_APPEND|O_WRONLY|O_CREAT,1);
if (fd) {
if (strcmp(prog,"reboot"))
strcpy (wtmp.ut_name, prog);
else
strcpy (wtmp.ut_name, "shutdown"); /* last ... */
strcpy (wtmp.ut_id, "~~");
strcpy (wtmp.ut_line, "~");
wtmp.ut_pid = 0;
wtmp.ut_type = BOOT_TIME;
wtmp.ut_time = now;
wtmp.ut_host[0]= '\0';
write (fd, (char *) &wtmp,sizeof(struct utmp));
close(fd);
}
fd = open(SHUT_LOG,O_APPEND|O_WRONLY,1);
if (!fd)
perror ("open");
else {
sprintf (mes,"%s %02d %02d:%02d:%02d %s: system %s by %s@%s\n",
month[tm->tm_mon],tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
prog,prog,who,host);
write (fd,mes,strlen(mes));
close(fd);
}
return;
}

View file

@ -1,109 +0,0 @@
/* wall - write to all logged in users Author: V. Archer */
/*
Edvard Tuinder v892231@si.hhs.NL
Modified some things to include this with my shutdown/halt
package
*/
#define _POSIX_SOURCE 1
#include <sys/types.h>
#include <fcntl.h>
#include <pwd.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <utmp.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#undef UTMP
static char UTMP[] = "/etc/utmp"; /* Currently logged in users. */
void wall( char *when, char *extra );
void crnlcat( char *message, char *more );
void
wall(when, extra)
char *when; /* When is shutdown */
char *extra; /* If non-nil, why is the shutdown */
{
struct utmp utmp;
char utmptty[5 + sizeof(utmp.ut_line) + 2];
char message[1024];
struct passwd *pw;
int utmpfd, ttyfd;
char *ourtty, *ourname;
time_t now;
struct utsname utsname;
struct stat con_st, tty_st;
if ((ourtty = ttyname(1))) {
if ((ourname = strrchr(ourtty, '/'))) ourtty = ourname+1;
} else ourtty = "system task";
if ((pw = getpwuid(getuid()))) ourname = pw->pw_name;
else ourname = "unknown";
time(&now);
if (uname(&utsname) != 0) strcpy(utsname.nodename, "?");
sprintf(message, "\r\nBroadcast message from %s@%s (%s)\r\n%.24s...\r\n",
ourname, utsname.nodename, ourtty, ctime(&now));
crnlcat(message, when);
crnlcat(message, extra);
/* Search the UTMP database for all logged-in users. */
if ((utmpfd = open(UTMP, O_RDONLY)) < 0) {
fprintf(stderr, "Cannot open utmp file\r\n");
return;
}
/* first the console */
strcpy(utmptty, "/dev/console");
if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
perror(utmptty);
} else {
fstat(ttyfd, &con_st);
write(ttyfd, message, strlen(message));
close(ttyfd);
}
while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
/* is this the user we are looking for? */
if (utmp.ut_type != USER_PROCESS) continue;
strncpy(utmptty+5, utmp.ut_line, sizeof(utmp.ut_line));
utmptty[5 + sizeof(utmp.ut_line) + 1] = 0;
if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
perror(utmptty);
continue;
}
fstat(ttyfd, &tty_st);
if (tty_st.st_rdev != con_st.st_rdev)
write(ttyfd, message, strlen(message));
close(ttyfd);
}
close(utmpfd);
return;
}
void
crnlcat(message, more)
char *message, *more;
{
char *p = message;
char *m = more;
char *end = message + 1024 - 1;
while (p < end && *p != 0) p++;
while (p < end && *m != 0) {
if (*m == '\n' && (p == message || p[-1] != '\n')) {
*p++ = '\r';
if (p == end) p--;
}
*p++ = *m++;
}
*p = 0;
}

View file

@ -1,393 +0,0 @@
/*
shutdown - close down the system graciously
Author: Edvard Tuinder <v892231@si.hhs.NL>
This program informs the users that the system is going
down, when and why. After that a shutdown notice is written in
both /usr/adm/wtmp and by syslog(3). Then reboot(2) is called
to really close the system.
This actually is a ``nice'' halt(8).
Options are supposed to be as with BSD
-h: shutdown and halt the system
-r: shutdown and reboot
-k: stop an already running shutdown
-o: obsolete: not implemented
New Minix options:
-C: crash check, i.e. is the last wtmp entry a shutdown entry?
-R: reset the system
-d: default CTRL-ALT-DEL shutdown for current bootloader
*/
#define _POSIX_SOURCE 1
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <utmp.h>
#include <errno.h>
#include <minix/reboot.h>
#include "wtmp.h"
static char SHUT_PID[] = "/usr/run/shutdown.pid";
static char NOLOGIN[] = "/etc/nologin";
#ifndef __STDC__
#define inform_user_time inf_time
#define inform_user inf_user
#endif
void usage( void );
void write_pid( void );
int inform_user_time( void );
void inform_user( void );
void terminate( void );
void wall( char *when, char *extra );
int crash_check( void );
void parse_time( char *arg );
void get_message( void );
int main( int argc, char *argv[] );
char *itoa( int n );
long wait_time=0L;
char message[1024];
char info[80];
int reboot_flag='h'; /* default is halt */
int info_min, info_hour;
char *prog;
void parse_time (arg)
char *arg;
{
char *p = arg;
int hours, minutes;
time_t now;
struct tm *tm;
int delta = 0;
int bad = 0;
if (p[0] == '+') { delta = 1; p++; }
hours = strtoul(p, &p, 10);
if (*p == 0 && delta) {
minutes = hours;
hours = 0;
} else {
if (*p != ':' && *p != '.')
bad = 1;
else
p++;
minutes = strtoul(p, &p, 10);
if (*p != 0) bad = 1;
}
if (bad) {
fprintf(stderr,"Invalid time specification `%s'\n",arg);
usage();
}
time(&now);
tm = localtime(&now);
if (!delta) {
hours -= tm->tm_hour;
minutes -= tm->tm_min;
}
if (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) hours += 24; /* Time after midnight. */
tm->tm_hour += hours;
tm->tm_min += minutes;
(void) mktime(tm);
info_hour = tm->tm_hour;
info_min = tm->tm_min;
sprintf(info,
"The system will shutdown in %d hour%s and %d minute%s at %02d:%02d\n\n",
hours,hours==1?"":"s",minutes,minutes==1?"":"s",info_hour,info_min);
wait_time += hours * 3600 + minutes * 60;
return;
}
int main(argc,argv)
int argc;
char *argv[];
{
int i, now = 0, nologin = 0, want_terminate = 0, want_message = 0, check = 0;
char *opt;
int tty;
static char HALT1[] = "-?";
static char *HALT[] = { "shutdown", HALT1, NULL };
/* Parse options. */
for (i = 1; i < argc && argv[i][0] == '-'; i++) {
if (argv[i][1] == '-' && argv[i][2] == 0) {
/* -- */
i++;
break;
}
for (opt = argv[i] + 1; *opt != 0; opt++) {
switch (*opt) {
case 'k':
want_terminate = 1;
break;
case 'h':
case 'r':
case 'p':
case 'd':
case 'R':
reboot_flag = *opt;
break;
case 'm':
want_message = 1;
break;
case 'C':
check = 1;
break;
default:
fprintf (stderr,"shutdown: invalid option '-%c'\n",*opt);
usage();
break;
}
}
}
if ((argc - i) > 2) usage();
if (check) exit(crash_check() ? 0 : 2);
if (i == argc) {
/* No timespec, assume "now". */
now = 1;
} else {
if (!strcmp(argv[i], "now"))
now++;
else
parse_time(argv[i]);
}
if ((argc - i) == 2) {
/* One line message */
strcat(message, argv[i+1]);
strcat(message, "\n");
}
if (want_terminate) terminate();
if (want_message) get_message();
puts(info);
prog = strrchr(*argv,'/');
if (prog == (char *)0)
prog = *argv;
else
prog++;
if (!now) {
/* Daemonize. */
switch (fork()) {
case 0:
break;
case -1:
fprintf(stderr, "%s: can't fork\n", prog);
exit(1);
default:
exit(0);
}
/* Detach from the terminal (if any). */
if ((tty = open("/dev/tty", O_RDONLY)) != -1) {
close(tty);
setsid();
}
write_pid();
}
for (;;) {
if (wait_time <= 5 * 60 && !nologin && !now) {
close(creat(NOLOGIN,00644));
nologin = 1;
}
if (wait_time <= 60) break;
if(inform_user_time())
inform_user();
sleep (60);
wait_time -= 60;
}
if (!now) {
inform_user();
sleep (30); /* Last minute before shutdown */
wait_time -= 30;
inform_user();
sleep (30); /* Last 30 seconds before shutdown */
}
wait_time = 0;
inform_user();
unlink(SHUT_PID); /* No way of stopping anymore */
unlink(NOLOGIN);
HALT[1][1] = reboot_flag;
#if __minix_vmd
execv("/usr/sbin/halt", HALT);
#else
execv("/usr/bin/halt", HALT);
#endif
if (errno != ENOENT)
fprintf(stderr, "Can't execute 'halt': %s\n", strerror(errno));
sleep(2);
reboot(RBT_HALT);
fprintf(stderr, "Reboot call failed: %s\n", strerror(errno));
return(1);
}
void usage()
{
fputs("Usage: shutdown [-hrRpmkd] [time [message]]\n", stderr);
fputs(" -h -> halt system after shutdown\n", stderr);
fputs(" -r -> reboot system after shutdown\n", stderr);
fputs(" -R -> reset system after shutdown\n", stderr);
fputs(" -p -> power system off after shutdown\n", stderr);
fputs(" -d -> default CTRL-ALT-DEL shutdown for current bootloader\n", stderr);
fputs(" -m -> read a shutdown message from standard input\n", stderr);
fputs(" -k -> stop an already running shutdown\n", stderr);
fputs(" time -> keyword ``now'', minutes before shutdown ``+5'',\n", stderr);
fputs(" or absolute time specification ``11:20''\n", stderr);
fputs(" message -> short shutdown message\n", stderr);
exit(1);
}
void terminate()
{
FILE *in;
pid_t pid;
char c_pid[5];
in = fopen(SHUT_PID,"r");
if (in == (FILE *)0) {
fputs ("Can't get pid of shutdown process, probably not running shutdown\n", stderr);
exit(1);
}
fgets(c_pid,5,in);
fclose(in);
pid = atoi(c_pid);
if (kill(pid,9) == -1)
fputs("Can't kill the shutdown process, probably not running anymore\n",stderr);
else
puts("Shutdown process terminated");
unlink(SHUT_PID);
unlink(NOLOGIN);
exit(0);
}
void get_message()
{
char line[80];
puts ("Type your message. End with ^D at an empty line");
fputs ("shutdown> ",stdout);fflush(stdout);
while (fgets(line,80,stdin) != (char *)0) {
strcat (message,line);
bzero(line,strlen(line));
fputs ("shutdown> ",stdout);fflush(stdout);
}
putc('\n',stdout);fflush(stdout);
}
int inform_user_time()
{
int min;
min = wait_time /60;
if (min == 60 || min == 30 || min == 15 || min == 10 || min <= 5)
return 1;
else
return 0;
}
void inform_user()
{
int hour, minute;
char mes[80];
hour = 0;
minute = wait_time / 60;
while (minute >= 60) {
minute -= 60;
hour++;
}
if (hour)
sprintf(mes,
"\nThe system will shutdown in %d hour%s and %d minute%s at %.02d:%.02d\n\n",
hour,hour==1?"":"s",minute,minute==1?"":"s",info_hour,info_min);
else
if (minute > 1)
sprintf(mes,
"\nThe system will shutdown in %d minutes at %.02d:%.02d\n\n",
minute,info_hour,info_min);
else
if (wait_time > 1)
sprintf(mes,
"\nThe system will shutdown in %ld seconds\n\n",
wait_time);
else
sprintf(mes,
"\nThe system will shutdown NOW\n\n");
wall(mes,message);
}
void write_pid()
{
char pid[5];
int fd;
fd = creat(SHUT_PID,00600);
if (!fd)
return;
strncpy (pid,itoa(getpid()), sizeof(pid));
write (fd,pid,sizeof(pid));
close(fd);
return;
}
int crash_check()
{
struct utmp last;
int fd = -1, crashed;
struct stat st;
if (stat(STR_ROOT_WTMP, &st) < 0 || st.st_size == 0) {
if (stat(STR_WTMP, &st) < 0 || st.st_size == 0) {
return 0;
}
if ((fd = open(STR_WTMP, O_RDONLY)) < 0) return 0;
} else if ((fd = open(STR_ROOT_WTMP, O_RDONLY)) < 0) return 0;
crashed = (lseek(fd, - (off_t) sizeof(last), SEEK_END) == -1
|| read(fd, (void *) &last, sizeof(last)) != sizeof(last)
|| last.ut_line[0] != '~'
|| (strncmp(last.ut_name, "shutdown", sizeof(last.ut_name))
&& strncmp(last.ut_name, "halt", sizeof(last.ut_name)))
);
close(fd);
return crashed;
}

View file

@ -1,3 +0,0 @@
static char STR_WTMP[] = "/usr/adm/wtmp";
static char STR_ROOT_WTMP[] = "/etc/wtmp";

View file

@ -4,7 +4,7 @@
#
PROG= in.telnetd
SRCS= main.c telnet.c term.c pty.c wtmp.c
SRCS= main.c telnet.c term.c pty.c
MAN=
.include <bsd.prog.mk>

View file

@ -45,7 +45,6 @@ int opt_d = 0; /* debugging output flag */
void usage(void);
int main(int argc, char *argv[]);
void wtmp(int type, int linenr, char *line, pid_t pid, char *host);
void usage()
{
@ -144,14 +143,10 @@ char *hostname;
return(-1);
}
wtmp(LOGIN_PROCESS, lineno, tty_name+5, pid, hostname);
term_inout(pty_fd);
(void) close(pty_fd);
wtmp(DEAD_PROCESS, lineno, tty_name+5, pid, hostname);
chown(tty_name, 0, 0);
chmod(tty_name, 0666);

View file

@ -1,112 +0,0 @@
/*
* TNET A server program for MINIX which implements the TCP/IP
* suite of networking protocols. It is based on the
* TCP/IP code written by Phil Karn et al, as found in
* his NET package for Packet Radio communications.
*
* This file contains an implementation of the "server"
* for the TELNET protocol. This protocol can be used to
* remote-login on other systems, just like a normal TTY
* session.
*
* Usage: telnetd [-dv]
*
* Version: @(#)telnetd.c 1.00 07/26/92
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
* Michael Temari, <temari@temari.ae.ge.com>
*/
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <utmp.h>
#include <time.h>
#include <stdio.h>
#include "telnetd.h"
static char PATH_UTMP[] = "/etc/utmp";
static char PATH_WTMP[] = "/usr/adm/wtmp";
void wtmp(int type, int linenr, char *line, pid_t pid, char *host);
void report(char *label);
void wtmp(type, linenr, line, pid, host)
int type; /* type of entry */
int linenr; /* line number in ttytab */
char *line; /* tty name (only good on login) */
pid_t pid; /* pid of process */
char *host; /* name of the remote host */
{
/* Log an event into the UTMP and WTMP files. */
struct utmp utmp; /* UTMP/WTMP User Accounting */
int fd;
/* Clear the utmp record. */
memset((void *) &utmp, 0, sizeof(utmp));
/* Fill in utmp. */
switch (type) {
case LOGIN_PROCESS:
/* A new login, fill in line and host name. */
strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
strncpy(utmp.ut_host, host, sizeof(utmp.ut_host));
break;
case DEAD_PROCESS:
/* A logout. Use the current utmp entry, but make sure it is a
* user process exiting, and not getty or login giving up.
*/
if ((fd = open(PATH_UTMP, O_RDONLY)) < 0) {
if (errno != ENOENT) report(PATH_UTMP);
return;
}
if (lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
|| read(fd, &utmp, sizeof(utmp)) == -1
) {
report(PATH_UTMP);
close(fd);
return;
}
close(fd);
if (utmp.ut_type != USER_PROCESS) return;
strncpy(utmp.ut_name, "", sizeof(utmp.ut_name));
break;
}
/* Finish new utmp entry. */
utmp.ut_pid = pid;
utmp.ut_type = type;
utmp.ut_time = time((time_t *) 0);
/* Write new entry to utmp. */
if ((fd = open(PATH_UTMP, O_WRONLY)) < 0
|| lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
|| write(fd, &utmp, sizeof(utmp)) == -1
) {
if (errno != ENOENT) report(PATH_UTMP);
}
if (fd != -1) close(fd);
if (type == DEAD_PROCESS) {
/* Add new wtmp entry. */
if ((fd = open(PATH_WTMP, O_WRONLY | O_APPEND)) < 0
|| write(fd, &utmp, sizeof(utmp)) == -1
) {
if (errno != ENOENT) report(PATH_WTMP);
}
if (fd != -1) close(fd);
}
}
void report(label)
char *label;
{
char message[128];
sprintf(message, "telnetd: %i: %s\r\n", errno, strerror(errno));
(void) write(1, message, strlen(message));
}

View file

@ -24,8 +24,8 @@
./bin/expr minix-sys
./bin/false minix-sys
./bin/getopts minix-sys
./bin/getty minix-sys
./bin/halt minix-sys
./bin/getty minix-sys obsolete
./bin/halt minix-sys obsolete
./bin/intr minix-sys
./bin/kill minix-sys
./bin/ksh minix-sys
@ -42,14 +42,14 @@
./bin/pwd minix-sys
./bin/read minix-sys
./bin/readclock minix-sys
./bin/reboot minix-sys
./bin/reboot minix-sys obsolete
./bin/rm minix-sys
./bin/rmdir minix-sys
./bin/sed minix-sys
./bin/service minix-sys
./bin/setup minix-sys
./bin/sh minix-sys
./bin/shutdown minix-sys
./bin/shutdown minix-sys obsolete
./bin/sync minix-sys
./bin/sysenv minix-sys
./bin/tar minix-sys
@ -117,6 +117,8 @@
./etc/termcap minix-sys
./etc/ttys minix-sys
./etc/utmp minix-sys
./etc/gettytab minix-sys
./etc/rc.shutdown minix-sys
./home minix-sys
./home/ast minix-sys
./home/ast/.exrc minix-sys
@ -146,6 +148,8 @@
./sbin/fsck_ext2fs minix-sys
./sbin/fsck.mfs minix-sys
./sbin/input minix-sys
./sbin/halt minix-sys
./sbin/init minix-sys
./sbin/is minix-sys
./sbin/isofs minix-sys
./sbin/mfs minix-sys
@ -155,8 +159,11 @@
./sbin/newfs_ext2 minix-sys
./sbin/newfs_ext2fs minix-sys
./sbin/nologin minix-sys
./sbin/poweroff minix-sys
./sbin/procfs minix-sys
./sbin/readclock.drv minix-sys
./sbin/reboot minix-sys
./sbin/shutdown minix-sys
./sys minix-sys
./tmp minix-sys
./usr minix-sys
@ -336,7 +343,7 @@
./usr/bin/gzcat minix-sys
./usr/bin/gzexe minix-sys
./usr/bin/gzip minix-sys
./usr/bin/halt minix-sys
./usr/bin/halt minix-sys obsolete
./usr/bin/head minix-sys
./usr/bin/hexdump minix-sys
./usr/bin/host minix-sys
@ -437,7 +444,7 @@
./usr/bin/pkgin_cd minix-sys
./usr/bin/playwave minix-sys
./usr/bin/postinstall minix-sys
./usr/bin/poweroff minix-sys
./usr/bin/poweroff minix-sys obsolete
./usr/bin/pr minix-sys
./usr/bin/prep minix-sys
./usr/bin/printenv minix-sys
@ -456,8 +463,8 @@
./usr/bin/readall minix-sys obsolete
./usr/bin/readelf minix-sys binutils
./usr/bin/readlink minix-sys
./usr/bin/reboot minix-sys
./usr/bin/recwave minix-sys
./usr/bin/reboot minix-sys obsolete
./usr/bin/ref minix-sys obsolete
./usr/bin/remsync minix-sys
./usr/bin/repartition minix-sys
@ -479,7 +486,7 @@
./usr/bin/shar minix-sys
./usr/bin/shlock minix-sys
./usr/bin/shuffle minix-sys
./usr/bin/shutdown minix-sys
./usr/bin/shutdown minix-sys obsolete
./usr/bin/size minix-sys binutils
./usr/bin/sleep minix-sys
./usr/bin/slip minix-sys
@ -540,8 +547,8 @@
./usr/bin/unxz minix-sys
./usr/bin/unzip minix-sys
./usr/bin/update minix-sys
./usr/bin/uptime minix-sys
./usr/bin/users minix-sys
./usr/bin/uptime minix-sys obsolete
./usr/bin/uud minix-sys
./usr/bin/uudecode minix-sys
./usr/bin/uue minix-sys
@ -552,6 +559,7 @@
./usr/bin/view minix-sys
./usr/bin/vis minix-sys
./usr/bin/vol minix-sys
./usr/bin/wall minix-sys
./usr/bin/wc minix-sys
./usr/bin/what minix-sys
./usr/bin/whatis minix-sys
@ -1201,7 +1209,7 @@
./usr/include/minix/procfs.h minix-sys
./usr/include/minix/profile.h minix-sys
./usr/include/minix/queryparam.h minix-sys
./usr/include/minix/reboot.h minix-sys
./usr/include/minix/reboot.h minix-sys obsolete
./usr/include/minix/rs.h minix-sys
./usr/include/minix/safecopies.h minix-sys
./usr/include/minix/sched.h minix-sys
@ -1938,6 +1946,7 @@
./usr/libexec/atf-check minix-sys atf
./usr/libexec/fingerd minix-sys
./usr/libexec/ftpd minix-sys
./usr/libexec/getty minix-sys
./usr/libexec/kyua-atf-tester minix-sys kyua
./usr/libexec/kyua-plain-tester minix-sys kyua
./usr/libexec/ld.elf_so minix-sys
@ -2282,6 +2291,7 @@
./usr/man/man1/view.1 minix-sys
./usr/man/man1/vis.1 minix-sys
./usr/man/man1/vol.1 minix-sys
./usr/man/man1/wall.1 minix-sys
./usr/man/man1/wait.1 minix-sys
./usr/man/man1/wc.1 minix-sys
./usr/man/man1/what.1 minix-sys
@ -4696,6 +4706,7 @@
./usr/man/man5/ftpchroot.5 minix-sys
./usr/man/man5/ftpd.conf.5 minix-sys
./usr/man/man5/ftpusers.5 minix-sys
./usr/man/man5/gettytab.5 minix-sys
./usr/man/man5/group.5 minix-sys
./usr/man/man5/hosts.5 minix-sys
./usr/man/man5/httpd.conf.5 minix-sys
@ -4724,6 +4735,7 @@
./usr/man/man5/termcap.5 minix-sys
./usr/man/man5/terminfo.5 minix-sys
./usr/man/man5/texinfo.5 minix-sys
./usr/man/man5/ttys.5 minix-sys
./usr/man/man5/ttytab.5 minix-sys
./usr/man/man5/TZ.5 minix-sys
./usr/man/man5/tzfile.5 minix-sys
@ -4863,7 +4875,7 @@
./usr/sbin/groupmod minix-sys
./usr/sbin/i2cscan minix-sys
./usr/sbin/inet minix-sys
./usr/sbin/init minix-sys
./usr/sbin/init minix-sys obsolete
./usr/sbin/installboot_nbsd minix-sys
./usr/sbin/ipc minix-sys
./usr/sbin/kernel minix-sys

View file

@ -3,7 +3,8 @@
#include <minix/i2c.h>
#include <minix/i2cdriver.h>
#include <minix/log.h>
#include <minix/reboot.h>
#include <sys/signal.h>
/* Register Addresses */
#define CHIPID_REG 0x00
@ -155,7 +156,7 @@ enable_pwr_off(void)
/* enable power off via the PWR_EN pin. just do the setup here.
* the kernel will do the work to toggle the pin when the
* system is ready to be powered off. Should be called during startup
* so that shutdown(8) can do power-off with reboot(RBT_POWEROFF).
* so that shutdown(8) can do power-off with reboot().
*/
r = i2creg_write8(bus_endpoint, address, STATUS_REG, PWR_OFF_MASK);
if (r != OK) {
@ -228,10 +229,8 @@ intr_handler(void)
if ((val & PBI_MASK) != 0) {
log_info(&log, "Power Button Pressed\n");
reboot(RBT_POWEROFF);
log_warn(&log, "Failed to power off the system.");
sys_irqenable(&irq_hook_kernel_id);
return -1;
kill(1, SIGUSR1); /* tell init to powerdwn */
return OK;
}
/* re-enable interrupt */

View file

@ -10,6 +10,7 @@
#include <sys/ioctl.h>
#include <sys/kbdio.h>
#include <sys/time.h>
#include <sys/reboot.h>
#include <sys/select.h>
#include <termios.h>
#include <signal.h>
@ -18,7 +19,6 @@
#include <minix/com.h>
#include <minix/input.h>
#include <minix/keymap.h>
#include <minix/reboot.h>
#include <minix/ds.h>
#include <assert.h>
#include "tty.h"
@ -295,7 +295,7 @@ static unsigned make_break(int scode)
{
if (++CAD_count == 3) {
cons_stop();
sys_abort(RBT_DEFAULT);
sys_abort(RB_AUTOBOOT);
}
sys_kill(INIT_PROC_NR, SIGABRT);
rebooting = 1;

View file

@ -700,6 +700,10 @@ static int do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
if (isconsole(tp)) r = con_loadfont(endpt, grant);
break;
case TIOCSCTTY:
tp->tty_pgrp = user_endpt;
break;
/* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is
* not defined.
*/

View file

@ -97,7 +97,7 @@ BIN1+= boot.cfg.default \
protocols rc rc.cd rc.subr \
rc.daemons.dist rs.inet rs.single \
services shells syslog.conf \
termcap utmp
termcap utmp gettytab rc.shutdown
.else
BIN1+= bootptab changelist csh.cshrc csh.login \
csh.logout daily daily.conf dm.conf envsys.conf floppytab ftpchroot \

154
etc/gettytab Normal file
View file

@ -0,0 +1,154 @@
# $NetBSD: gettytab,v 1.18 2006/01/08 22:23:46 dsl Exp $
# from: @(#)gettytab 8.2 (Berkeley) 4/20/94
#
# Most of the table entries here are just copies of the old getty table,
# it is by no means certain, or even likely, that any of them are optimal
# for any purpose whatever. Nor is it likely that more than a couple are
# even correct.
#
# The default gettytab entry, used to set defaults for all other
# entries, and in cases where getty is called with no table name
#
default:\
:ce:ck:np:im=\r\n%s/%m (%h) (%t)\r\n\r\n:
#
# Fixed speed entries
#
# The "std.NNN" names are known to the special case
# portselector code in getty, however they can
# be assigned to any table desired.
# The "NNN-baud" names are known to the special case
# autobaud code in getty, and likewise can
# be assigned to any table desired (hopefully the same speed).
#
std.110|110-baud:\
:sp#110:
std.300|300-baud:\
:sp#300:
std.600|600-baud:\
:sp#600:
std.1200|1200-baud:\
:sp#1200:
std.2400|2400-baud:\
:sp#2400:
std.4800|4800-baud:\
:sp#4800:
std.9600|9600-baud:\
:sp#9600:
std.19200|19200-baud:\
:sp#19200:
std.38400|38400-baud:\
:sp#38400:
std.57600|57600-baud:\
:sp#57600:
std.115200|115200-baud:\
:sp#115200:
# PPP network link login
#
# these entries can be used by ISPs or others who want to be able
# to offer both a "shell" and a PPP login on the same port. Setting
# the "pp" attribute allows getty(8) to recognize a PPP link start
# negotiation, and invoke the program listed, in addition to normal
# login(1).
#
# N.B.: if PPP is recognized, this bypasses normal login/password
# exchange; the expectation is that you'll configure pppd (or whatever)
# to require a PAP or CHAP handshake for authentication after PPP is
# started up.
#
# It is also recommended that you use hardware (CTS/RTS) flow control
# on the port, and run the port as fast as possible, to allow modems
# extra time to do data compression, if enabled.
#
ppp:np:ce:ck:pp=/usr/sbin/pppd:
#
ppp.19200|PPP-19200:sp#19200:tc=ppp:
ppp.38400|PPP-38400:sp#38400:tc=ppp:
ppp.57600|PPP-57600:sp#57600:tc=ppp:
ppp.115200|PPP-115200:sp#115200:tc=ppp:
ppp.230400|PPP-230400:sp#230400:tc=ppp:
#
# Dial in rotary tables, speed selection via 'break'
#
d1200|Dial-1200:\
:nx=d300:sp#1200:
d300|Dial-300:\
:nx=d1200:sp#300:
#
# Fast dialup terminals, 2400/1200/300 rotary (can start either way)
#
D2400|d2400|Fast-Dial-2400:\
:nx=D1200:tc=2400-baud:
D1200|Fast-Dial-1200:\
:nx=D300:tc=1200-baud:
D300|Fast-Dial-300:\
:nx=D2400:tc=300-baud:
#
#telebit (19200)
#
t19200:\
:nx=t2400:tc=19200-baud:
t2400:\
:nx=t1200:tc=2400-baud:
t1200:\
:nx=t19200:tc=1200-baud:
#
#telebit (9600)
#
t9600:\
:nx=t2400a:tc=19200-baud:
t2400a:\
:nx=t1200a:tc=2400-baud:
t1200a:\
:nx=t9600:tc=1200-baud:
#
# Odd special case terminals
#
Console|Console Decwriter II:\
:rw:tc=300-baud:
Console-1200|Console Decwriter III:\
:rw:tc=1200-baud:
X|Xwindow|X window system:\
:rw:sp#9600:
Pc|Pc console:\
:np:ig:ht:
# 8 bit clean Sun console
suncons|Sun Console:\
:np:sp#9600:
#
# Plugboard, and misc other terminals
#
plug-9600|Plugboard-9600:\
:pf#1:tc=9600-baud:
P9600|Plugboard-9600-rotary:\
:pf#1:nx=P300:tc=9600-baud:
P300|Plugboard-300:\
:pf#1:nx=P1200:tc=300-baud:
P1200|Plugboard-1200:\
:pf#1:nx=P9600:tc=1200-baud:
#
# XXXX Port selector
#
DSW|Port Selector:\
:ps:sp#2400:
#
# Auto-baud speed detect entry for Micom 600.
# Special code in getty will switch this out
# to one of the NNN-baud entries.
#
Auto-baud:\
:ab:sp#2400:f0#040:

30
etc/rc
View file

@ -21,7 +21,7 @@ ARCH="`sysenv arch`"
usage()
{
echo >&2 "Usage: $0 [-saf] start|stop|down"
echo >&2 "Usage: $0 [-saf] autoboot|start|stop|down"
exec intr sh
}
@ -54,8 +54,12 @@ edit()
service=$1
shift
# Assume binaries are always in /usr/sbin
service $opt edit /usr/sbin/$service -label $service "$@"
# Assume binaries are always in /sbin or /usr/sbin
binlocation=/usr/sbin/$service
if [ ! -x $binlocation ]
then binlocation=/sbin/$service
fi
service $opt edit $binlocation -label $service "$@"
}
while getopts 'saf' opt
@ -70,14 +74,14 @@ done
shift `expr $OPTIND - 1`
case "$#:$1" in
1:start|1:stop|1:down)
1:start|1:stop|1:down|1:autoboot)
action=$1
;;
*) usage
esac
case $action in
start)
autoboot|start)
# National keyboard?
test -f /etc/keymap && loadkeys /etc/keymap
@ -104,8 +108,12 @@ start)
up readclock.drv
readclock -q || date 201301010000
# We are not shutting down.
rm -f /etc/nologin
# Initialize files.
>/etc/utmp # /etc/utmp keeps track of logins
>/var/run/utmp # /etc/utmp keeps track of logins
>/var/run/utmpx # /etc/utmpx keeps track of logins
# Use MFS binary only from kernel image?
if [ "`sysenv bin_img`" = 1 ]
@ -147,10 +155,6 @@ start)
edit init
fi
# This file is necessary for above 'shutdown -C' check.
# (Silence stderr in case of running from cd.)
touch /usr/adm/wtmp /etc/wtmp 2>/dev/null
if [ "$sflag" ]
then
echo "Single user. Press ^D to resume multiuser startup."
@ -212,6 +216,10 @@ test -f /usr/etc/rc && sh /usr/etc/rc $action
test -f /usr/local/etc/rc && sh /usr/local/etc/rc $action
# Any messages?
test "$action" = start -a -f /etc/issue && cat /etc/issue
if [ "$action" = start -o "$action" = autoboot ]
then if [ -f /etc/issue ]
then cat /etc/issue
fi
fi
exit 0

3
etc/rc.shutdown Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
sh /etc/rc stop

View file

@ -638,7 +638,7 @@ service tda19988
service tps65217
{
uid 0; # needed for doing reboot(RBT_POWEROFF)
uid 0; # needed for doing reboot()
system IRQCTL PRIVCTL;
irq 7; # NNMI pin on BeagleBone / BeagleBone Black
ipc SYSTEM RS DS PM i2c;

View file

@ -3,10 +3,10 @@
#
# name getty type status comments
#
console getty minix on secure
ttyc1 getty minix on secure
ttyc2 getty minix on secure
ttyc3 getty minix on secure
console "/usr/libexec/getty default" minix on secure
ttyc1 "/usr/libexec/getty default" minix on secure
ttyc2 "/usr/libexec/getty default" minix on secure
ttyc3 "/usr/libexec/getty default" minix on secure
tty00 "" unknown off secure
tty01 "" unknown off secure

View file

@ -25,10 +25,13 @@ fi
bootcd="`/bin/sysenv bootcd`"
case "$#:$1" in
1:autoboot)
action=start
;;
1:start|1:stop|1:down)
action=$1
;;
*) echo >&2 "Usage: $0 start|stop|down"
*) echo >&2 "Usage: $0 autoboot|start|stop|down"
exit 1
esac
@ -158,7 +161,7 @@ capemgr() {
DAEMONS=/etc/rc.daemons
case $action in
start)
start|autoboot)
# Select console font.
test -f /etc/font && loadfont /etc/font </dev/console

View file

@ -16,7 +16,7 @@ INCS+= acpi.h audio_fw.h bitmap.h \
keymap.h log.h mmio.h mount.h mthread.h minlib.h \
netdriver.h optset.h padconf.h partition.h portio.h \
priv.h procfs.h profile.h queryparam.h \
reboot.h rs.h safecopies.h sched.h sef.h sffs.h \
rs.h safecopies.h sched.h sef.h sffs.h \
sound.h spin.h sys_config.h sysinfo.h \
syslib.h sysutil.h termios.h timers.h type.h \
u64.h usb.h usb_ch9.h vbox.h \

View file

@ -1,15 +0,0 @@
#ifndef _MINIX_REBOOT_H
#define _MINIX_REBOOT_H
/* How to exit the system. */
#define RBT_HALT 0 /* shut down the system */
#define RBT_REBOOT 1 /* reboot the system */
#define RBT_PANIC 2 /* the system panics */
#define RBT_POWEROFF 3 /* power off, reset if not possible */
#define RBT_RESET 4 /* hard reset the system */
#define RBT_DEFAULT 5 /* perform the default action du jour */
#define RBT_INVALID 6 /* first invalid reboot flag */
int reboot(int);
#endif /* _MINIX_REBOOT_H */

View file

@ -152,6 +152,12 @@ int tcsetattr(int _filedes, int _opt_actions, const struct termios
#define VLNEXT 12 /* cc_c[VLNEXT] (^V) */
#define VDISCARD 13 /* cc_c[VDISCARD] (^O) */
/* Non-functional additions */
#define VDSUSP 14
#define VWERASE 15
#define VSTATUS 16
#define VEOL2 17
/* Extensions to baud rate settings. */
#if defined(__minix) && defined(_NETBSD_SOURCE)
#define B57600 0x0100 /* 57600 baud */

View file

@ -22,6 +22,7 @@
#define TIOCSWINSZ _IOW('T', 17, struct winsize)
#define TIOCGPGRP _IOW('T', 18, int)
#define TIOCSPGRP _IOW('T', 19, int)
#define TIOCSCTTY _IO ('T', 20) /* controlling tty */
#define TIOCSFON _IOW_BIG(1, u8_t [8192])
/* Keyboard ioctls. */

View file

@ -376,8 +376,8 @@ int profil(char *, size_t, u_long, u_int);
void psignal(int, const char *);
#endif /* __PSIGNAL_DECLARED */
int rcmd(char **, int, const char *, const char *, const char *, int *);
#ifndef __minix
int reboot(int, char *);
#ifndef __minix
int revoke(const char *);
#endif
int rresvport(int *);

View file

@ -39,26 +39,12 @@
#ifndef _UTMP_H_
#define _UTMP_H_
#ifdef __minix
#define _PATH_UTMP "/etc/utmp"
#define _PATH_WTMP "/usr/adm/wtmp"
#define _PATH_BTMP "/usr/adm/btmp"
#define _PATH_LASTLOG "/usr/adm/lastlog"
#define UTMP _PATH_UTMP
#define WTMP _PATH_WTMP
#define BTMP _PATH_BTMP
#else
#define _PATH_UTMP "/var/run/utmp"
#define _PATH_WTMP "/var/log/wtmp"
#define _PATH_LASTLOG "/var/log/lastlog"
#endif
#define UT_NAMESIZE 8
#ifdef __minix
#define UT_LINESIZE 12
#else
#define UT_LINESIZE 8
#endif
#define UT_HOSTSIZE 16
struct lastlog {
@ -67,34 +53,12 @@ struct lastlog {
char ll_host[UT_HOSTSIZE];
};
#ifdef __minix
struct utmp {
char ut_name[UT_NAMESIZE]; /* user name */
char ut_id[4]; /* /etc/inittab ID */
char ut_line[UT_LINESIZE]; /* terminal name */
char ut_host[UT_HOSTSIZE]; /* host name, when remote */
short ut_pid; /* process id */
short int ut_type; /* type of entry */
time_t ut_time; /* login/logout time */
};
/* Definitions for ut_type. */
#define RUN_LVL 1 /* this is a RUN_LEVEL record */
#define BOOT_TIME 2 /* this is a REBOOT record */
#define INIT_PROCESS 5 /* this process was spawned by INIT */
#define LOGIN_PROCESS 6 /* this is a 'getty' process waiting */
#define USER_PROCESS 7 /* any other user process */
#define DEAD_PROCESS 8 /* this process has died (wtmp only) */
#else /* !__minix */
struct utmp {
char ut_line[UT_LINESIZE];
char ut_name[UT_NAMESIZE];
char ut_host[UT_HOSTSIZE];
time_t ut_time;
};
#endif /* __minix */
__BEGIN_DECLS
int utmpname(const char *);

View file

@ -9,8 +9,9 @@
#include <machine/vm.h>
#include <io.h>
#include <minix/reboot.h>
#include <minix/board.h>
#include <sys/reboot.h>
#include <minix/u64.h>
#include "archconst.h"
@ -51,25 +52,23 @@ poweroff(void)
__dead void
arch_shutdown(int how)
{
switch (how) {
case RBT_HALT:
/* Hang */
for (; ; ) halt_cpu();
NOT_REACHABLE;
case RBT_POWEROFF:
if((how & RB_POWERDOWN) == RB_POWERDOWN) {
/* Power off if possible, hang otherwise */
poweroff();
NOT_REACHABLE;
}
default:
case RBT_DEFAULT:
case RBT_REBOOT:
case RBT_RESET:
/* Reset the system */
reset();
if(how & RB_HALT) {
/* Hang */
for (; ; ) halt_cpu();
NOT_REACHABLE;
}
/* Reset the system */
reset();
NOT_REACHABLE;
while (1);
}

View file

@ -10,7 +10,7 @@
#include <minix/com.h>
#include <sys/types.h>
#include <sys/param.h>
#include <minix/reboot.h>
#include <sys/reboot.h>
#include "string.h"
#include "arch_proto.h"
#include "direct_utils.h"
@ -412,7 +412,7 @@ kinfo_t *pre_init(int argc, char **argv)
* longer used and the "real" implementations are visible
*/
void send_diag_sig(void) { }
void minix_shutdown(minix_timer_t *t) { arch_shutdown(RBT_PANIC); }
void minix_shutdown(minix_timer_t *t) { arch_shutdown(0); }
void busy_delay_ms(int x) { }
int raise(int n) { panic("raise(%d)\n", n); }
int kern_phys_map_ptr( phys_bytes base_address, vir_bytes io_size,

View file

@ -8,7 +8,7 @@
#include <machine/cpu.h>
#include <minix/portio.h>
#include <minix/cpufeature.h>
#include <minix/reboot.h>
#include <sys/reboot.h>
#include <assert.h>
#include <signal.h>
#include <machine/vm.h>
@ -135,29 +135,23 @@ __dead void arch_shutdown(int how)
reset();
}
switch (how) {
case RBT_HALT:
/* Hang */
for (; ; ) halt_cpu();
NOT_REACHABLE;
case RBT_POWEROFF:
/* Power off if possible, hang otherwise */
poweroff();
NOT_REACHABLE;
default:
case RBT_DEFAULT:
case RBT_REBOOT:
case RBT_RESET:
/* Reset the system by forcing a processor shutdown.
* First stop the BIOS memory test by setting a soft
* reset flag.
*/
reset();
NOT_REACHABLE;
if((how & RB_POWERDOWN) == RB_POWERDOWN) {
/* Power off if possible, hang otherwise */
poweroff();
NOT_REACHABLE;
}
if(how & RB_HALT) {
/* Hang */
for (; ; ) halt_cpu();
NOT_REACHABLE;
}
/* Reset the system by forcing a processor shutdown.
* First stop the BIOS memory test by setting a soft
* reset flag.
*/
reset();
NOT_REACHABLE;
}

View file

@ -11,7 +11,7 @@
#include <minix/com.h>
#include <sys/types.h>
#include <sys/param.h>
#include <minix/reboot.h>
#include <sys/reboot.h>
#include <machine/partition.h>
#include "string.h"
#include "arch_proto.h"
@ -246,6 +246,6 @@ kinfo_t *pre_init(u32_t magic, u32_t ebx)
}
void send_diag_sig(void) { }
void minix_shutdown(minix_timer_t *t) { arch_shutdown(RBT_PANIC); }
void minix_shutdown(minix_timer_t *t) { arch_shutdown(0); }
void busy_delay_ms(int x) { }
int raise(int sig) { panic("raise(%d)\n", sig); }

View file

@ -18,7 +18,7 @@
#include <minix/u64.h>
#include <minix/board.h>
#include <minix/type.h>
#include <minix/reboot.h>
#include <sys/reboot.h>
#include "clock.h"
#include "direct_utils.h"
#include "hw_intr.h"
@ -357,8 +357,7 @@ void prepare_shutdown(const int how)
void minix_shutdown(minix_timer_t *tp)
{
/* This function is called from prepare_shutdown or stop_sequence to bring
* down MINIX. How to shutdown is in the argument: RBT_HALT (return to the
* monitor), RBT_RESET (hard reset).
* down MINIX.
*/
int how;
@ -376,25 +375,17 @@ void minix_shutdown(minix_timer_t *tp)
hw_intr_disable_all();
stop_local_timer();
how = tp ? tmr_arg(tp)->ta_int : RBT_PANIC;
how = tp ? tmr_arg(tp)->ta_int : 0;
/* Show shutdown message */
direct_cls();
switch(how) {
case RBT_HALT:
if((how & RB_POWERDOWN) == RB_POWERDOWN)
direct_print("MINIX has halted and will now power off.\n");
else if(how & RB_HALT)
direct_print("MINIX has halted. "
"It is safe to turn off your computer.\n");
break;
case RBT_POWEROFF:
direct_print("MINIX has halted and will now power off.\n");
break;
case RBT_DEFAULT:
case RBT_REBOOT:
case RBT_RESET:
default:
else
direct_print("MINIX will now reset.\n");
break;
}
arch_shutdown(how);
}

View file

@ -355,20 +355,14 @@ updwtmpx(const char *file, const struct utmpx *utx)
#else
if ((fd = open(file, O_CREAT|O_WRONLY, 0644)) < 0)
return -1;
if (flock(fd, LOCK_EX) < 0)
return -1;
#endif
(void)memset(&ut, 0, sizeof(ut));
ut.ut_type = SIGNATURE;
(void)memcpy(ut.ut_user, vers, sizeof(vers));
if (write(fd, &ut, sizeof(ut)) == -1)
goto failed;
} else {
#ifdef __minix
if (flock(fd, LOCK_SH) < 0 )
return -1;
#endif
}
if (write(fd, utx, sizeof(*utx)) == -1)
goto failed;
if (close(fd) == -1)
@ -455,10 +449,6 @@ getlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
if (db == NULL)
return NULL;
#ifdef __minix
if (flock(db->fd(db), LOCK_SH) < 0)
return NULL;
#endif
key.data = &uid;
key.size = sizeof(uid);
@ -503,10 +493,6 @@ updlastlogx(const char *fname, uid_t uid, struct lastlogx *ll)
if (db == NULL)
return -1;
#ifdef __minix
if (flock(db->fd(db), LOCK_EX) < 0)
return -1;
#endif
key.data = &uid;
key.size = sizeof(uid);
data.data = ll;

View file

@ -11,7 +11,7 @@
#include <string.h>
#include <sys/reboot.h>
int reboot(int how)
int reboot(int how, char *bootstr)
{
message m;

View file

@ -99,7 +99,7 @@ void minix_stack_params(const char *path, char * const *argv, char * const *envp
(*argc)++;
}
for (p = envp; *p != NULL; p++) {
for (p = envp; p && *p != NULL; p++) {
size_t const n = sizeof(*p) + strlen(*p) + 1;
*stack_size += n;
if (*stack_size < n) {
@ -156,7 +156,7 @@ void minix_stack_fill(const char *path, int argc, char * const *argv,
}
*fpw++ = NULL;
for (p = envp; *p != NULL; p++) {
for (p = envp; p && *p != NULL; p++) {
size_t const n = strlen(*p) + 1;
*fpw++= (char *)(*vsp + (fp - frame));
memcpy(fp, *p, n);

View file

@ -244,7 +244,7 @@ MAN+= accept.2 access.2 acct.2 bind.2 brk.2 chdir.2 \
mprotect.2 mremap.2 msgctl.2 msgget.2 msgrcv.2 msgsnd.2 msync.2 \
munmap.2 nanosleep.2 nfssvc.2 ntp_adjtime.2 open.2 pathconf.2 pipe.2
.else
MAN+= adjtime.2 clock_settime.2 getvfsstat.2 pipe.2 getrusage.2
MAN+= adjtime.2 clock_settime.2 getvfsstat.2 pipe.2 getrusage.2 reboot.2
.endif # !defined(__MINIX)
.if !defined(__MINIX)
MAN+= pmc_control.2 poll.2 posix_fadvise.2 profil.2 ptrace.2 __quotactl.2 \

View file

@ -146,10 +146,11 @@ CPPFLAGS.${i}+= -I${LIBCDIR}/locale
.for i in access.c brk.c close.c environ.c execve.c fork.c fsync.c \
getgid.c getpid.c geteuid.c getuid.c gettimeofday.c getvfsstat.c \
init.c link.c loadname.c lseek.c lseek64.c _mcontext.c mknod.c \
mmap.c nanosleep.c open.c pread.c pwrite.c read.c reboot.c sbrk.c \
mmap.c nanosleep.c open.c pread.c pwrite.c read.c sbrk.c \
select.c setuid.c sigprocmask.c stack_utils.c stat.c stime.c \
syscall.c _ucontext.c umask.c unlink.c waitpid.c write.c \
brksize.S _do_kernel_call_intr.S get_minix_kerninfo.S _ipc.S ucontext.S
brksize.S _do_kernel_call_intr.S get_minix_kerninfo.S _ipc.S ucontext.S \
kill.c
.PATH.c: ${LIBCDIR}/sys-minix
.PATH.S: ${ARCHDIR}/sys-minix
SRCS+= ${i}

View file

@ -42,7 +42,7 @@ SRCS+= efun.c \
passwd.c pw_scan.c pidfile.c pidlock.c pty.c \
raise_default_signal.c \
secure_path.c stat_flags.c \
strpct.c ttyaction.c \
strpct.c ttyaction.c ttymsg.c \
MAN= efun.3 \
getmntopts.3 \

View file

@ -5,7 +5,8 @@
SUBDIR= \
fingerd ftpd \
ld.elf_so
ld.elf_so \
getty
.if defined(__MINIX)
SUBDIR+= makewhatis

12
libexec/getty/Makefile Normal file
View file

@ -0,0 +1,12 @@
# $NetBSD: Makefile,v 1.19 2010/02/03 15:34:43 roy Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/4/93
WARNS?= 2 # XXX: many const & sign-compare issues
PROG= getty
SRCS= main.c init.c subr.c
DPADD+= ${LIBUTIL} ${LIBTERMINFO}
LDADD+= -lutil -lterminfo
MAN= getty.8 gettytab.5 ttys.5
.include <bsd.prog.mk>

52
libexec/getty/extern.h Normal file
View file

@ -0,0 +1,52 @@
/* $NetBSD: extern.h,v 1.6 2003/08/07 09:46:41 agc Exp $ */
/*
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)extern.h 8.1 (Berkeley) 6/4/93
*/
struct delayval;
int adelay(int, struct delayval *);
char *autobaud(void);
int delaybits(void);
void edithost(char *);
void gendefaults(void);
int getent(char *, char *);
int getflag(char *);
long getnum(char *);
char *getstr(char *, char **);
void gettable(char *, char *);
void makeenv(char *[]);
char *portselector(void);
void set_ttydefaults(int);
void setchars(void);
void setdefaults(void);
void setflags(int);
int speed(int);

177
libexec/getty/getty.8 Normal file
View file

@ -0,0 +1,177 @@
.\" $NetBSD: getty.8,v 1.17 2003/08/07 09:46:42 agc Exp $
.\"
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)getty.8 8.1 (Berkeley) 6/4/93
.\"
.Dd December 12, 1998
.Dt GETTY 8
.Os
.Sh NAME
.Nm getty ,
.Nm uugetty
.Nd set terminal modes for system access
.Sh SYNOPSIS
.Nm
.Oo
.Ar type
.Op Ar tty
.Oc
.Nm uugetty
.Oo
.Ar type
.Op Ar tty
.Oc
.Sh DESCRIPTION
The
.Nm
program
is called by
.Xr init 8
to open and initialize the tty line, read a login name, and invoke
.Xr login 1 .
The devices on which to run
.Nm
are normally determined by
.Xr ttys 5 .
.Pp
The
.Nm
program can also recognize a Point to Point Protocol
.Pq Tn PPP
negotiation, and, if the
.Sy pp
attribute in
.Xr gettytab 5
is set, invoke the program given by that string, e.g.,
.Xr pppd 8 ,
instead of
.Xr login 1 .
This makes it possible to use a single serial port for either a
.Qq shell
account with command line interface, or a
.Tn PPP
network link.
.Pp
The argument
.Ar tty
is the special device file in
.Pa /dev
to open for the terminal
.Po
for example,
.Qq ttyh0
.Pc .
If there is no argument or the argument is
.Ql Fl ,
the tty line is assumed to be open as file descriptor 0.
.Pp
The
.Ar type
argument can be used to make
.Nm
treat the terminal line specially.
This argument is used as an index into the
.Xr gettytab 5
database, to determine the characteristics of the line.
If there is no argument, or there is no such table, the
.Em default
table is used.
If there is no
.Pa /etc/gettytab
a set of system defaults is used.
If indicated by the table located,
.Nm
will clear the terminal screen,
print a banner heading,
and prompt for a login name.
Usually either the banner or the login prompt will include
the system hostname.
.Pp
.Nm
uses the
.Xr ttyaction 3
facility with an action of
.Qq getty
and user
.Qq root
to execute site-specific commands when it starts.
.Pp
Most of the default actions of
.Nm
can be circumvented, or modified, by a suitable
.Xr gettytab 5
table.
.Pp
The
.Nm
program can be set to timeout after some interval,
which will cause dial up lines to hang up
if the login name is not entered reasonably quickly.
.Pp
The
.Nm uugetty
program is the same, except that it uses
.Xr pidlock 3
to respect the locks in
.Pa /var/spool/lock
of processes that dial out on that tty.
.Sh FILES
.Bl -tag -width /var/spool/lock/LCK..ttyXX -compact
.It Pa /etc/gettytab
.It Pa /etc/ttys
.It Pa /var/spool/lock/LCK..ttyXX
.El
.Sh DIAGNOSTICS
.Bl -diag
.It "ttyxx: No such device or address."
.It "ttyxx: No such file or address."
A terminal which is turned on in the
.Xr ttys 5
file cannot be opened, likely because the requisite
lines are either not configured into the system, the associated device
was not attached during boot-time system configuration,
or the special file in
.Pa /dev
does not exist.
.El
.Sh SEE ALSO
.Xr login 1 ,
.Xr ioctl 2 ,
.Xr pidlock 3 ,
.Xr ttyaction 3 ,
.Xr tty 4 ,
.Xr gettytab 5 ,
.Xr ttys 5 ,
.Xr init 8 ,
.Xr pppd 8
.Sh HISTORY
A
.Nm
program appeared in
.At v6 .

423
libexec/getty/gettytab.5 Normal file
View file

@ -0,0 +1,423 @@
.\" $NetBSD: gettytab.5,v 1.36 2012/04/21 12:27:28 roy Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)gettytab.5 8.4 (Berkeley) 4/19/94
.\"
.Dd April 5, 2012
.Dt GETTYTAB 5
.Os
.Sh NAME
.Nm gettytab
.Nd terminal configuration data base
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
The
.Nm
file
is a simplified version of the
.Xr capfile 5
data base
used to describe terminal lines.
The initial terminal login process
.Xr getty 8
accesses the
.Nm
file each time it starts, allowing simpler
reconfiguration of terminal characteristics.
Each entry in the data base
is used to describe one class of terminals.
.Pp
Where to run
.Xr getty 8
processes is normally defined by
.Xr ttys 5 .
.Pp
There is a default terminal class,
.Em default ,
that is used to set global defaults for all other classes.
(That is, the
.Em default
entry is read, then the entry for the class required
is used to override particular settings.)
The
.Em default
entry is also normally read by other programs that present login prompts
to the user, such as
.Xr telnetd 8 ,
in order to retrieve the values of the
.Em he ,
.Em hn ,
.Em im ,
and
.Em if
capabilities.
.Sh CAPABILITIES
Refer to
.Xr capfile 5
for a description of the file layout.
The
.Em default
column below lists defaults obtained if there is
no entry in the table obtained, nor one in the special
.Em default
table.
.Bl -column Namexx /usr/bin/login Default
.It Sy Name Type Default Description
.It "ab bool false Auto-baud speed select mechanism for the Micom 600 portselector. Selection is done by looking at how the character `\er' is garbled at 300, 1200, 4800, and 9600 baud."
.It "al str NULL user to auto-login instead of prompting"
.It "ap bool false terminal uses any parity"
.It "bk str 0377 alternative end of line character (input break)"
.It "b2 str 0377 alternative end of line character (input break)"
.It "c0 num unused tty control flags to write messages"
.It "c1 num unused tty control flags to read login name"
.It "c2 num unused tty control flags to leave terminal as"
.It "ce bool false use crt erase algorithm"
.It "ck bool false use crt kill algorithm"
.It "cl str" Ta Dv NULL Ta
.No "screen clear sequence"
.It "co bool false console - add"
.Ql \er\en
after login prompt
.It "cs bool false clear screen based on terminal type in /etc/ttys"
.It "ds str" Ta So Li ^Y Sc Ta
.No "delayed suspend character"
.It "dx bool false set"
.Dv DECCTLQ
.It "ec bool false leave echo"
.Tn OFF
.It "ep bool false terminal uses even parity"
.It "er str" Ta So Li ^? Sc Ta
.No "erase character"
.It "et str" Ta So Li ^D Sc Ta
.No "end of text"
.Pq Dv EOF
character
.It "ev str" Ta Dv NULL Ta
.No "initial environment"
.It "f0 num unused tty mode flags to write messages"
.It "f1 num unused tty mode flags to read login name"
.It "f2 num unused tty mode flags to leave terminal as"
.It "fl str" Ta So Li ^O Sc Ta
.No "output flush character"
.It "hc bool false do"
.Tn NOT
hangup line on last close
.It "he str" Ta Dv NULL Ta
.No "hostname editing string"
.It "hn str hostname hostname"
.It "ht bool false terminal has real tabs"
.It "i0 num unused tty input flags to write messages"
.It "i1 num unused tty input flags to read login name"
.It "i2 num unused tty input flags to leave terminal as"
.It "if str NULL display named file before prompt, like /etc/issue"
.It "ig bool false ignore garbage characters in login name"
.It "im str" Ta Dv NULL Ta
.No "initial (banner) message"
.It "in str" Ta So Li ^C Sc Ta
.No "interrupt character"
.It "is num unused input speed"
.It "kl str" Ta So Li ^U Sc Ta
.No "kill character"
.It "l0 num unused tty local flags to write messages"
.It "l1 num unused tty local flags to read login name"
.It "l2 num unused tty local flags to leave terminal as"
.It "lc bool false terminal has lower case"
.It "lm str login: login prompt"
.It "ln str" Ta So Li ^V Sc Ta
.No "``literal next'' character"
.It "lo str" Ta Pa /usr/bin/login Ta
.No "program to exec when name obtained"
.It "mb bool false do flow control based on carrier"
.It "nl bool false terminal has (or might have) a newline character"
.It "nn bool false do not prompt for a login name"
.It "np bool false terminal uses no parity (i.e. 8-bit characters)"
.It "nx str default next table (for auto speed selection)"
.It "o0 num unused tty output flags to write messages"
.It "o1 num unused tty output flags to read login name"
.It "o2 num unused tty output flags to leave terminal as"
.It "op bool false terminal uses odd parity"
.It "os num unused output speed"
.It "pc str" Ta So Li \e0 Sc Ta
.No "pad character"
.It "pe bool false use printer (hard copy) erase algorithm"
.It "pf num 0 delay"
between first prompt and following flush (seconds)
.It "pp str unused PPP authentication program"
.It "ps bool false line connected to a"
.Tn MICOM
port selector
.It "qu str" Ta So Li \&^\e Sc Ta
.No "quit character"
.It "rp str" Ta So Li ^R Sc Ta
.No "line retype character"
.It "rw bool false do"
.Tn NOT
use raw for input, use cbreak
.It "sp num unused line speed (input and output)"
.It "st str" Ta So Li ^T Sc Ta
.No "status character"
.It "su str" Ta So Li ^Z Sc Ta
.No "suspend character"
.It "tc str none table continuation"
.It "to num 0 timeout (seconds)"
.It "tt str" Ta Dv NULL Ta
.No "terminal type (for environment)"
.It "ub bool false do unbuffered output (of prompts etc)"
.It "we str" Ta So Li ^W Sc Ta
.No "word erase character"
.It "xc bool false do"
.Tn NOT
echo control chars as
.Ql ^X
.It "xf str" Ta So Li ^S Sc Ta Dv XOFF
(stop output) character
.It "xn str" Ta So Li ^Q Sc Ta Dv XON
(start output) character
.El
.Pp
The following capabilities are no longer supported by
.Xr getty 8 :
.Bl -column Namexx /usr/bin/login Default
.It "bd num 0 backspace delay"
.It "cb bool false use crt backspace mode"
.It "cd num 0 carriage-return delay"
.It "fd num 0 form-feed (vertical motion) delay"
.It "nd num 0 newline (line-feed) delay"
.It "uc bool false terminal is known upper case only"
.El
.Pp
If no line speed is specified, speed will not be altered
from that which prevails when getty is entered.
Specifying an input or output speed will override
line speed for stated direction only.
.Pp
Terminal modes to be used for the output of the message,
for input of the login name,
and to leave the terminal set as upon completion,
are derived from the boolean flags specified.
If the derivation should prove inadequate,
any (or all) of these three may be overridden
with one of the
.Em \&c0 ,
.Em \&c1 ,
.Em \&c2 ,
.Em \&i0 ,
.Em \&i1 ,
.Em \&i2 ,
.Em \&l0 ,
.Em \&l1 ,
.Em \&l2 ,
.Em \&o0 ,
.Em \&o1 ,
or
.Em \&o2
numeric specifications, which can be used to specify
(usually in octal, with a leading '0')
the exact values of the flags.
These flags correspond to the termios
.Em c_cflag ,
.Em c_iflag ,
.Em c_lflag ,
and
.Em c_oflag
fields, respectively.
Each these sets must be completely specified to be effective.
The
.Em \&f0 ,
.Em \&f1 ,
and
.Em \&f2
are excepted for backwards compatibility with a previous incarnation of
the TTY sub-system.
In these flags the bottom 16 bits of the (32 bits) value contain the sgttyb
.Em sg_flags
field, while the top 16 bits represent the local mode word.
.Pp
Should
.Xr getty 8
receive a null character
(presumed to indicate a line break)
it will restart using the table indicated by the
.Em nx
entry.
If there is none, it will re-use its original table.
.Pp
Delays are specified in milliseconds, the nearest possible
delay available in the tty driver will be used.
Should greater certainty be desired, delays
with values 0, 1, 2, and 3 are interpreted as
choosing that particular delay algorithm from the driver.
.Pp
The
.Em \&cl
screen clear string may be preceded by a (decimal) number
of milliseconds of delay required (a la termcap).
This delay is simulated by repeated use of the pad character
.Em \&pc .
.Pp
The initial message, and login message,
.Em \&im
and
.Em \&lm
may include any of the following character sequences, which expand to
information about the environment in which
.Xr getty 8
is running.
.Pp
.Bl -tag -width \&%xxx -compact
.It \&%d
The current date.
.It \&%h
The hostname of the machine, which is normally obtained from the
system using
.Xr gethostname 3 ,
but may also be overridden by the
.Em \&hn
table entry.
In either case it may be edited with the
.Em \&he
string.
A '@' in the
.Em \&he
string causes one character from the real hostname to
be copied to the final hostname.
A '#' in the
.Em \&he
string causes the next character of the real hostname
to be skipped.
Each character that
is neither '@' nor '#' is copied into the final hostname.
Surplus '@' and '#' characters are ignored.
.It \&%t
The tty name.
.It "\&%m, \&%r, \&%s, \&%v"
The type of machine, release of the operating system, name of the
operating system, and version of the kernel, respectively, as
returned by
.Xr uname 3 .
.It \&%%
A
.Dq %
character.
.El
.Pp
When getty execs the login process, given
in the
.Em \&lo
string (usually
.Dq Pa /usr/bin/login ) ,
it will have set
the environment to include the terminal type, as indicated
by the
.Em \&tt
string (if it exists).
The
.Em \&ev
string, can be used to enter additional data into
the environment.
It is a list of comma separated strings, each of which
will presumably be of the form
.Em name=value .
.Pp
If a non-zero timeout is specified, with
.Em \&to ,
then getty will exit within the indicated
number of seconds, either having
received a login name and passed control
to
.Xr login 1 ,
or having received an alarm signal, and exited.
This may be useful to hangup dial in lines.
.Pp
Output from
.Xr getty 8
is even parity unless
.Em \&op
or
.Em \&np
is specified.
The
.Em \&op
string
may be specified with
.Em \&ap
to allow any parity on input, but generate odd parity output.
Note: this only applies while getty is being run,
terminal driver limitations prevent a more complete
implementation.
.Xr getty 8
does not check parity of input characters in
.Dv RAW
mode.
.Pp
If
.Em \&pp
string is specified and a Point to Point Protocol
.Pq Tn PPP
link bringup sequence is recognized,
.Xr getty 8
will invoke the program referenced by the
.Em \&pp
string, e.g.
.Xr pppd 8 .
This can be used to handle incoming
.Tn PPP
calls.
.Sh SEE ALSO
.Xr login 1 ,
.Xr gethostname 3 ,
.Xr uname 3 ,
.Xr capfile 5 ,
.Xr ttys 5 ,
.Xr getty 8 ,
.Xr pppd 8 ,
.Xr telnetd 8
.Sh HISTORY
The
.Nm
file format appeared in
.Bx 4.2 .
.Sh BUGS
The special characters (erase, kill, etc.) are reset to system defaults
by
.Xr login 1 .
In
.Em all
cases, '#' or '^H' typed in a login name will be treated as
an erase character, and '@' will be treated as a kill character.
.Pp
The delay stuff is a real crock.
Apart from its general lack of flexibility, some
of the delay algorithms are not implemented.
The terminal driver should support sane delay settings.
.Pp
The
.Em \&he
capability is stupid.

173
libexec/getty/gettytab.h Normal file
View file

@ -0,0 +1,173 @@
/* $NetBSD: gettytab.h,v 1.16 2006/11/16 04:31:24 christos Exp $ */
/*
* Copyright (c) 1983, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)gettytab.h 8.2 (Berkeley) 3/30/94
*/
/*
* Getty description definitions.
*/
struct gettystrs {
char *field; /* name to lookup in gettytab */
char *defalt; /* value we find by looking in defaults */
char *value; /* value that we find there */
};
struct gettynums {
char *field; /* name to lookup */
long defalt; /* number we find in defaults */
long value; /* number we find there */
int set; /* we actually got this one */
};
struct gettyflags {
char *field; /* name to lookup */
char invrt; /* name existing in gettytab --> false */
char defalt; /* true/false in defaults */
char value; /* true/false flag */
char set; /* we found it */
};
/*
* See init.c for the arrays indexed by these values.
*/
/*
* String values.
*/
#define NX gettystrs[0].value
#define CL gettystrs[1].value
#define IM gettystrs[2].value
#define LM gettystrs[3].value
#define ER gettystrs[4].value
#define KL gettystrs[5].value
#define ET gettystrs[6].value
#define PC gettystrs[7].value
#define TT gettystrs[8].value
#define EV gettystrs[9].value
#define LO gettystrs[10].value
#define HN gettystrs[11].value
#define HE gettystrs[12].value
#define IN gettystrs[13].value
#define QU gettystrs[14].value
#define XN gettystrs[15].value
#define XF gettystrs[16].value
#define BK gettystrs[17].value
#define SU gettystrs[18].value
#define DS gettystrs[19].value
#define RP gettystrs[20].value
#define FL gettystrs[21].value
#define WE gettystrs[22].value
#define LN gettystrs[23].value
#define ST gettystrs[24].value
#define B2 gettystrs[25].value
#define PP gettystrs[26].value
#define IF gettystrs[27].value
#define AL gettystrs[28].value
/*
* Numeric definitions.
*/
#define IS gettynums[0].value
#define OS gettynums[1].value
#define SP gettynums[2].value
#define ND gettynums[3].value
#define CD gettynums[4].value
#define TD gettynums[5].value
#define FD gettynums[6].value
#define BD gettynums[7].value
#define TO gettynums[8].value
#define F0 gettynums[9].value
#define F0set gettynums[9].set
#define F1 gettynums[10].value
#define F1set gettynums[10].set
#define F2 gettynums[11].value
#define F2set gettynums[11].set
#define PF gettynums[12].value
#define C0 gettynums[13].value
#define C0set gettynums[13].set
#define C1 gettynums[14].value
#define C1set gettynums[14].set
#define C2 gettynums[15].value
#define C2set gettynums[15].set
#define I0 gettynums[16].value
#define I0set gettynums[16].set
#define I1 gettynums[17].value
#define I1set gettynums[17].set
#define I2 gettynums[18].value
#define I2set gettynums[18].set
#define L0 gettynums[19].value
#define L0set gettynums[19].set
#define L1 gettynums[20].value
#define L1set gettynums[20].set
#define L2 gettynums[21].value
#define L2set gettynums[21].set
#define O0 gettynums[22].value
#define O0set gettynums[22].set
#define O1 gettynums[23].value
#define O1set gettynums[23].set
#define O2 gettynums[24].value
#define O2set gettynums[24].set
/*
* Boolean values.
*/
#define HT gettyflags[0].value
#define NL gettyflags[1].value
#define EP gettyflags[2].value
#define EPset gettyflags[2].set
#define OP gettyflags[3].value
#define OPset gettyflags[3].set
#define AP gettyflags[4].value
#define APset gettyflags[4].set
#define EC gettyflags[5].value
#define CO gettyflags[6].value
#define CB gettyflags[7].value
#define CK gettyflags[8].value
#define CE gettyflags[9].value
#define PE gettyflags[10].value
#define RW gettyflags[11].value
#define XC gettyflags[12].value
#define LC gettyflags[13].value
#define UC gettyflags[14].value
#define IG gettyflags[15].value
#define PS gettyflags[16].value
#define HC gettyflags[17].value
#define UB gettyflags[18].value
#define AB gettyflags[19].value
#define DX gettyflags[20].value
#define NP gettyflags[21].value
#define MB gettyflags[22].value
#define CS gettyflags[23].value
#define NN gettyflags[24].value
extern struct gettyflags gettyflags[];
extern struct gettynums gettynums[];
extern struct gettystrs gettystrs[];

146
libexec/getty/init.c Normal file
View file

@ -0,0 +1,146 @@
/* $NetBSD: init.c,v 1.17 2007/12/03 09:54:24 isaki Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)init.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: init.c,v 1.17 2007/12/03 09:54:24 isaki Exp $");
#endif
#endif /* not lint */
/*
* Getty table initializations.
*
* Melbourne getty.
*/
#include <termios.h>
#include "gettytab.h"
#include "pathnames.h"
extern struct termios tmode;
extern char hostname[];
#define M(a) ((char *)&tmode.c_cc[a])
struct gettystrs gettystrs[] = {
{ "nx" }, /* next table */
{ "cl" }, /* screen clear characters */
{ "im" }, /* initial message */
{ "lm", "login: " }, /* login message */
{ "er", M(VERASE) }, /* erase character */
{ "kl", M(VKILL) }, /* kill character */
{ "et", M(VEOF) }, /* eof chatacter (eot) */
{ "pc", "" }, /* pad character */
{ "tt" }, /* terminal type */
{ "ev" }, /* environment */
{ "lo", _PATH_LOGIN }, /* login program */
{ "hn", hostname }, /* host name */
{ "he" }, /* host name edit */
{ "in", M(VINTR) }, /* interrupt char */
{ "qu", M(VQUIT) }, /* quit char */
{ "xn", M(VSTART) }, /* XON (start) char */
{ "xf", M(VSTOP) }, /* XOFF (stop) char */
{ "bk", M(VEOL) }, /* brk char (alt \n) */
{ "su", M(VSUSP) }, /* suspend char */
{ "ds", M(VDSUSP) }, /* delayed suspend */
{ "rp", M(VREPRINT) }, /* reprint char */
{ "fl", M(VDISCARD) }, /* flush output */
{ "we", M(VWERASE) }, /* word erase */
{ "ln", M(VLNEXT) }, /* literal next */
{ "st", M(VSTATUS) }, /* status */
{ "b2", M(VEOL2) }, /* alt brk char */
{ "pp" }, /* ppp login program */
{ "if" }, /* sysv-like 'issue' filename */
{ "al" }, /* user to auto-login */
{ 0 }
};
struct gettynums gettynums[] = {
{ "is" }, /* input speed */
{ "os" }, /* output speed */
{ "sp" }, /* both speeds */
{ "nd" }, /* newline delay */
{ "cd" }, /* carriage-return delay */
{ "td" }, /* tab delay */
{ "fd" }, /* form-feed delay */
{ "bd" }, /* backspace delay */
{ "to" }, /* timeout */
{ "f0" }, /* output flags */
{ "f1" }, /* input flags */
{ "f2" }, /* user mode flags */
{ "pf" }, /* delay before flush at 1st prompt */
{ "c0" }, /* output c_flags */
{ "c1" }, /* input c_flags */
{ "c2" }, /* user mode c_flags */
{ "i0" }, /* output i_flags */
{ "i1" }, /* input i_flags */
{ "i2" }, /* user mode i_flags */
{ "l0" }, /* output l_flags */
{ "l1" }, /* input l_flags */
{ "l2" }, /* user mode l_flags */
{ "o0" }, /* output o_flags */
{ "o1" }, /* input o_flags */
{ "o2" }, /* user mode o_flags */
{ 0 }
};
struct gettyflags gettyflags[] = {
{ "ht", 0 }, /* has tabs */
{ "nl", 1 }, /* has newline char */
{ "ep", 0 }, /* even parity */
{ "op", 0 }, /* odd parity */
{ "ap", 0 }, /* any parity */
{ "ec", 1 }, /* no echo */
{ "co", 0 }, /* console special */
{ "cb", 0 }, /* crt backspace */
{ "ck", 0 }, /* crt kill */
{ "ce", 0 }, /* crt erase */
{ "pe", 0 }, /* printer erase */
{ "rw", 1 }, /* don't use raw */
{ "xc", 1 }, /* don't ^X ctl chars */
{ "lc", 0 }, /* terminal las lower case */
{ "uc", 0 }, /* terminal has no lower case */
{ "ig", 0 }, /* ignore garbage */
{ "ps", 0 }, /* do port selector speed select */
{ "hc", 1 }, /* don't set hangup on close */
{ "ub", 0 }, /* unbuffered output */
{ "ab", 0 }, /* auto-baud detect with '\r' */
{ "dx", 0 }, /* set decctlq */
{ "np", 0 }, /* no parity at all (8bit chars) */
{ "mb", 0 }, /* do MDMBUF flow control */
{ "cs", 0 }, /* clear screen based on term type */
{ "nn", 0 }, /* don't prompt for login name */
{ 0 }
};

707
libexec/getty/main.c Normal file
View file

@ -0,0 +1,707 @@
/* $NetBSD: main.c,v 1.59 2012/06/28 08:55:10 roy Exp $ */
/*-
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";
#else
__RCSID("$NetBSD: main.c,v 1.59 2012/06/28 08:55:10 roy Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <term.h>
#include <time.h>
#include <ttyent.h>
#include <unistd.h>
#include <util.h>
#include "gettytab.h"
#include "pathnames.h"
#include "extern.h"
extern char editedhost[];
/*
* Set the amount of running time that getty should accumulate
* before deciding that something is wrong and exit.
*/
#define GETTY_TIMEOUT 60 /* seconds */
/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */
#define PPP_FRAME 0x7e /* PPP Framing character */
#define PPP_STATION 0xff /* "All Station" character */
#define PPP_ESCAPE 0x7d /* Escape Character */
#define PPP_CONTROL 0x03 /* PPP Control Field */
#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */
#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */
#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */
struct termios tmode, omode;
int crmod, digit_or_punc, lower, upper;
char hostname[MAXHOSTNAMELEN + 1];
struct utsname kerninfo;
char name[LOGIN_NAME_MAX];
char dev[] = _PATH_DEV;
char ttyn[32];
char lockfile[512];
uid_t ttyowner;
char *rawttyn;
#define OBUFSIZ 128
#define TABBUFSIZ 512
char defent[TABBUFSIZ];
char tabent[TABBUFSIZ];
char *env[128];
const unsigned char partab[] = {
0001,0201,0201,0001,0201,0001,0001,0201,
0202,0004,0003,0205,0005,0206,0201,0001,
0201,0001,0001,0201,0001,0201,0201,0001,
0001,0201,0201,0001,0201,0001,0001,0201,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0200,
0200,0000,0000,0200,0000,0200,0200,0000,
0200,0000,0000,0200,0000,0200,0200,0000,
0000,0200,0200,0000,0200,0000,0000,0201
};
#define ERASE tmode.c_cc[VERASE]
#define KILL tmode.c_cc[VKILL]
#define EOT tmode.c_cc[VEOF]
static void clearscreen(void);
jmp_buf timeout;
static void
/*ARGSUSED*/
dingdong(int signo)
{
(void)alarm(0);
(void)signal(SIGALRM, SIG_DFL);
longjmp(timeout, 1);
}
jmp_buf intrupt;
static void
/*ARGSUSED*/
interrupt(int signo)
{
(void)signal(SIGINT, interrupt);
longjmp(intrupt, 1);
}
#ifndef __minix
/*
* Action to take when getty is running too long.
*/
static void
/*ARGSUSED*/
timeoverrun(int signo)
{
syslog(LOG_ERR, "getty exiting due to excessive running time");
exit(1);
}
#endif
static int getname(void);
static void oflush(void);
static void prompt(void);
static int putchr(int);
static void putf(const char *);
static void xputs(const char *);
#define putpad(s) tputs(s, 1, putchr)
int
main(int argc, char *argv[], char *envp[])
{
const char *progname;
char *tname;
int repcnt = 0, failopenlogged = 0, uugetty = 0, first_time = 1;
struct rlimit limit;
struct passwd *pw;
int rval;
(void)signal(SIGINT, SIG_IGN);
openlog("getty", LOG_PID, LOG_AUTH);
(void)gethostname(hostname, sizeof(hostname));
hostname[sizeof(hostname) - 1] = '\0';
if (hostname[0] == '\0')
(void)strlcpy(hostname, "Amnesiac", sizeof(hostname));
(void)uname(&kerninfo);
progname = getprogname();
if (progname[0] == 'u' && progname[1] == 'u')
uugetty = 1;
/*
* Find id of uucp login (if present) so we can chown tty properly.
*/
if (uugetty && (pw = getpwnam("uucp")))
ttyowner = pw->pw_uid;
else
ttyowner = 0;
/*
* Limit running time to deal with broken or dead lines.
*/
#ifndef __minix
(void)signal(SIGXCPU, timeoverrun);
limit.rlim_max = RLIM_INFINITY;
limit.rlim_cur = GETTY_TIMEOUT;
(void)setrlimit(RLIMIT_CPU, &limit);
#endif
/*
* The following is a work around for vhangup interactions
* which cause great problems getting window systems started.
* If the tty line is "-", we do the old style getty presuming
* that the file descriptors are already set up for us.
* J. Gettys - MIT Project Athena.
*/
if (argc <= 2 || strcmp(argv[2], "-") == 0) {
(void)strlcpy(ttyn, ttyname(0), sizeof(ttyn));
}
else {
int i;
rawttyn = argv[2];
(void)strlcpy(ttyn, dev, sizeof(ttyn));
(void)strlcat(ttyn, argv[2], sizeof(ttyn));
if (uugetty) {
(void)chown(ttyn, ttyowner, 0);
(void)strlcpy(lockfile, _PATH_LOCK,
sizeof(lockfile));
(void)strlcat(lockfile, argv[2],
sizeof(lockfile));
/*
* wait for lockfiles to go away before we try
* to open
*/
if (pidlock(lockfile, 0, 0, 0) != 0) {
syslog(LOG_ERR,
"%s: can't create lockfile", ttyn);
exit(1);
}
(void)unlink(lockfile);
}
if (strcmp(argv[0], "+") != 0) {
(void)chown(ttyn, ttyowner, 0);
(void)chmod(ttyn, 0600);
#ifndef __minix
(void)revoke(ttyn);
#endif
if (ttyaction(ttyn, "getty", "root"))
syslog(LOG_WARNING, "%s: ttyaction failed",
ttyn);
/*
* Delay the open so DTR stays down long enough
* to be detected.
*/
(void)sleep(2);
while ((i = open(ttyn, O_RDWR)) == -1) {
if ((repcnt % 10 == 0) &&
(errno != ENXIO || !failopenlogged)) {
syslog(LOG_WARNING, "%s: %m", ttyn);
closelog();
failopenlogged = 1;
}
repcnt++;
(void)sleep(60);
}
if (uugetty && pidlock(lockfile, 0, 0, 0) != 0) {
syslog(LOG_ERR, "%s: can't create lockfile",
ttyn);
exit(1);
}
if (uugetty)
(void)chown(lockfile, ttyowner, 0);
(void)login_tty(i);
}
}
/* Start with default tty settings */
if (tcgetattr(0, &tmode) < 0) {
syslog(LOG_ERR, "%s: %m", ttyn);
exit(1);
}
omode = tmode;
gettable("default", defent);
gendefaults();
tname = "default";
if (argc > 1)
tname = argv[1];
for (;;) {
int off;
rval = 0;
gettable(tname, tabent);
if (OPset || EPset || APset)
APset++, OPset++, EPset++;
setdefaults();
off = 0;
(void)tcflush(0, TCIOFLUSH); /* clear out the crap */
#ifndef __minix
(void)ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
(void)ioctl(0, FIOASYNC, &off); /* ditto for async mode */
#endif
if (IS)
(void)cfsetispeed(&tmode, (speed_t)IS);
else if (SP)
(void)cfsetispeed(&tmode, (speed_t)SP);
if (OS)
(void)cfsetospeed(&tmode, (speed_t)OS);
else if (SP)
(void)cfsetospeed(&tmode, (speed_t)SP);
setflags(0);
setchars();
if (tcsetattr(0, TCSANOW, &tmode) < 0) {
syslog(LOG_ERR, "%s: %m", ttyn);
exit(1);
}
if (AB) {
tname = autobaud();
continue;
}
if (PS) {
tname = portselector();
continue;
}
if (CS)
clearscreen();
if (CL && *CL)
putpad(CL);
edithost(HE);
/*
* If this is the first time through this, and an
* issue file has been given, then send it.
*/
if (first_time != 0 && IF != NULL) {
char buf[_POSIX2_LINE_MAX];
FILE *fp;
if ((fp = fopen(IF, "r")) != NULL) {
while (fgets(buf, sizeof(buf) - 1, fp) != NULL)
putf(buf);
(void)fclose(fp);
}
}
first_time = 0;
if (IM && *IM)
putf(IM);
oflush();
if (setjmp(timeout)) {
tmode.c_ispeed = tmode.c_ospeed = 0;
(void)tcsetattr(0, TCSANOW, &tmode);
exit(1);
}
if (TO) {
(void)signal(SIGALRM, dingdong);
(void)alarm((unsigned int)TO);
}
if (NN) {
name[0] = '\0';
lower = 1;
upper = digit_or_punc = 0;
} else if (AL) {
const char *p = AL;
char *q = name;
while (*p && q < &name[sizeof name - 1]) {
if (isupper((unsigned char)*p))
upper = 1;
else if (islower((unsigned char)*p))
lower = 1;
else if (isdigit((unsigned char)*p))
digit_or_punc = 1;
*q++ = *p++;
}
} else if ((rval = getname()) == 2) {
setflags(2);
(void)execle(PP, "ppplogin", ttyn, (char *) 0, env);
syslog(LOG_ERR, "%s: %m", PP);
exit(1);
}
if (rval || AL || NN) {
int i;
oflush();
(void)alarm(0);
(void)signal(SIGALRM, SIG_DFL);
if (name[0] == '-') {
xputs("user names may not start with '-'.");
continue;
}
if (!(upper || lower || digit_or_punc))
continue;
setflags(2);
if (crmod) {
tmode.c_iflag |= ICRNL;
tmode.c_oflag |= ONLCR;
}
#if XXX
if (upper || UC)
tmode.sg_flags |= LCASE;
if (lower || LC)
tmode.sg_flags &= ~LCASE;
#endif
if (tcsetattr(0, TCSANOW, &tmode) < 0) {
syslog(LOG_ERR, "%s: %m", ttyn);
exit(1);
}
(void)signal(SIGINT, SIG_DFL);
for (i = 0; envp[i] != NULL; i++)
env[i] = envp[i];
makeenv(&env[i]);
limit.rlim_max = RLIM_INFINITY;
limit.rlim_cur = RLIM_INFINITY;
#ifndef __minix
(void)setrlimit(RLIMIT_CPU, &limit);
#endif
if (NN)
(void)execle(LO, "login", AL ? "-fp" : "-p",
NULL, env);
else
(void)execle(LO, "login", AL ? "-fp" : "-p",
"--", name, NULL, env);
syslog(LOG_ERR, "%s: %m", LO);
exit(1);
}
(void)alarm(0);
(void)signal(SIGALRM, SIG_DFL);
(void)signal(SIGINT, SIG_IGN);
if (NX && *NX)
tname = NX;
if (uugetty)
(void)unlink(lockfile);
}
}
static int
getname(void)
{
int c;
char *np;
unsigned char cs;
int ppp_state, ppp_connection;
/*
* Interrupt may happen if we use CBREAK mode
*/
if (setjmp(intrupt)) {
(void)signal(SIGINT, SIG_IGN);
return (0);
}
(void)signal(SIGINT, interrupt);
setflags(1);
prompt();
if (PF > 0) {
oflush();
(void)sleep((unsigned int)PF);
PF = 0;
}
if (tcsetattr(0, TCSANOW, &tmode) < 0) {
syslog(LOG_ERR, "%s: %m", ttyn);
exit(1);
}
crmod = digit_or_punc = lower = upper = 0;
ppp_state = ppp_connection = 0;
np = name;
for (;;) {
oflush();
if (read(STDIN_FILENO, &cs, 1) <= 0)
exit(0);
if ((c = cs&0177) == 0)
return (0);
/*
* PPP detection state machine..
* Look for sequences:
* PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or
* PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC)
* See RFC1662.
* Derived from code from Michael Hancock <michaelh@cet.co.jp>
* and Erik 'PPP' Olson <eriko@wrq.com>
*/
if (PP && cs == PPP_FRAME) {
ppp_state = 1;
} else if (ppp_state == 1 && cs == PPP_STATION) {
ppp_state = 2;
} else if (ppp_state == 2 && cs == PPP_ESCAPE) {
ppp_state = 3;
} else if ((ppp_state == 2 && cs == PPP_CONTROL) ||
(ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) {
ppp_state = 4;
} else if (ppp_state == 4 && cs == PPP_LCP_HI) {
ppp_state = 5;
} else if (ppp_state == 5 && cs == PPP_LCP_LOW) {
ppp_connection = 1;
break;
} else {
ppp_state = 0;
}
if (c == EOT)
exit(1);
if (c == '\r' || c == '\n' ||
np >= &name[LOGIN_NAME_MAX - 1]) {
*np = '\0';
putf("\r\n");
break;
}
if (islower(c))
lower = 1;
else if (isupper(c))
upper = 1;
else if (c == ERASE || c == '#' || c == '\b') {
if (np > name) {
np--;
if (cfgetospeed(&tmode) >= 1200)
xputs("\b \b");
else
putchr(cs);
}
continue;
} else if (c == KILL || c == '@') {
putchr(cs);
putchr('\r');
if (cfgetospeed(&tmode) < 1200)
putchr('\n');
/* this is the way they do it down under ... */
else if (np > name)
xputs(
" \r");
prompt();
np = name;
continue;
} else if (isdigit(c) || c == '_')
digit_or_punc = 1;
if (IG && (c <= ' ' || c > 0176))
continue;
*np++ = c;
putchr(cs);
/*
* An MS-Windows direct connect PPP "client" won't send its
* first PPP packet until we respond to its "CLIENT" poll
* with a CRLF sequence. We cater to yet another broken
* implementation of a previously-standard protocol...
*/
*np = '\0';
if (strstr(name, "CLIENT"))
putf("\r\n");
}
(void)signal(SIGINT, SIG_IGN);
*np = 0;
if (c == '\r')
crmod = 1;
if ((upper && !lower && !LC) || UC)
for (np = name; *np; np++)
*np = tolower((unsigned char)*np);
return (1 + ppp_connection);
}
static void
xputs(const char *s)
{
while (*s)
putchr(*s++);
}
char outbuf[OBUFSIZ];
size_t obufcnt = 0;
static int
putchr(int cc)
{
unsigned char c;
c = cc;
if (!NP) {
c |= partab[c&0177] & 0200;
if (OP)
c ^= 0200;
}
if (!UB) {
outbuf[obufcnt++] = c;
if (obufcnt >= OBUFSIZ)
oflush();
return 1;
}
return write(STDOUT_FILENO, &c, 1);
}
static void
oflush(void)
{
if (obufcnt)
(void)write(STDOUT_FILENO, outbuf, obufcnt);
obufcnt = 0;
}
static void
prompt(void)
{
putf(LM);
if (CO)
putchr('\n');
}
static void
putf(const char *cp)
{
time_t t;
char *slash, db[100];
while (*cp) {
if (*cp != '%') {
putchr(*cp++);
continue;
}
switch (*++cp) {
case 't':
if ((slash = strstr(ttyn, "/pts/")) == NULL)
slash = strrchr(ttyn, '/');
if (slash == NULL)
xputs(ttyn);
else
xputs(&slash[1]);
break;
case 'h':
xputs(editedhost);
break;
case 'd':
(void)time(&t);
(void)strftime(db, sizeof(db),
"%l:%M%p on %A, %d %B %Y", localtime(&t));
xputs(db);
break;
case 's':
xputs(kerninfo.sysname);
break;
case 'm':
xputs(kerninfo.machine);
break;
case 'r':
xputs(kerninfo.release);
break;
case 'v':
xputs(kerninfo.version);
break;
case '%':
putchr('%');
break;
}
if (*cp)
cp++;
}
}
static void
clearscreen(void)
{
struct ttyent *typ;
int err;
if (rawttyn == NULL)
return;
typ = getttynam(rawttyn);
if ((typ == NULL) || (typ->ty_type == NULL) ||
(typ->ty_type[0] == 0))
return;
if (setupterm(typ->ty_type, 0, &err) == ERR)
return;
if (clear_screen)
putpad(clear_screen);
del_curterm(cur_term);
cur_term = NULL;
}

37
libexec/getty/pathnames.h Normal file
View file

@ -0,0 +1,37 @@
/* $NetBSD: pathnames.h,v 1.9 2008/02/04 15:27:20 christos Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
~ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 8.1 (Berkeley) 6/4/93
*/
#include <paths.h>
#define _PATH_LOGIN "/usr/bin/login"
#define _PATH_LOCK "/var/spool/lock/LCK.."

743
libexec/getty/subr.c Normal file
View file

@ -0,0 +1,743 @@
/* $NetBSD: subr.c,v 1.33 2006/11/16 04:31:24 christos Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)subr.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: subr.c,v 1.33 2006/11/16 04:31:24 christos Exp $");
#endif
#endif /* not lint */
/*
* Melbourne getty.
*/
#ifndef __minix
#define COMPAT_43
#endif
#include <sys/param.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <poll.h>
#include "extern.h"
#include "gettytab.h"
#include "pathnames.h"
extern struct termios tmode, omode;
#ifndef __minix
static void compatflags(long);
#endif
/*
* Get a table entry.
*/
void
gettable(char *name, char *buf)
{
struct gettystrs *sp;
struct gettynums *np;
struct gettyflags *fp;
long n;
const char *dba[2];
dba[0] = _PATH_GETTYTAB;
dba[1] = 0;
if (cgetent(&buf, dba, name) != 0)
return;
for (sp = gettystrs; sp->field; sp++)
(void)cgetstr(buf, sp->field, &sp->value);
for (np = gettynums; np->field; np++) {
if (cgetnum(buf, np->field, &n) == -1)
np->set = 0;
else {
np->set = 1;
np->value = n;
}
}
for (fp = gettyflags; fp->field; fp++) {
if (cgetcap(buf, fp->field, ':') == NULL)
fp->set = 0;
else {
fp->set = 1;
fp->value = 1 ^ fp->invrt;
}
}
#ifdef DEBUG
printf("name=\"%s\", buf=\"%s\"\n", name, buf);
for (sp = gettystrs; sp->field; sp++)
printf("cgetstr: %s=%s\n", sp->field, sp->value);
for (np = gettynums; np->field; np++)
printf("cgetnum: %s=%d\n", np->field, np->value);
for (fp = gettyflags; fp->field; fp++)
printf("cgetflags: %s='%c' set='%c'\n", fp->field,
fp->value + '0', fp->set + '0');
exit(1);
#endif /* DEBUG */
}
void
gendefaults(void)
{
struct gettystrs *sp;
struct gettynums *np;
struct gettyflags *fp;
for (sp = gettystrs; sp->field; sp++)
if (sp->value)
sp->defalt = sp->value;
for (np = gettynums; np->field; np++)
if (np->set)
np->defalt = np->value;
for (fp = gettyflags; fp->field; fp++)
if (fp->set)
fp->defalt = fp->value;
else
fp->defalt = fp->invrt;
}
void
setdefaults(void)
{
struct gettystrs *sp;
struct gettynums *np;
struct gettyflags *fp;
for (sp = gettystrs; sp->field; sp++)
if (!sp->value)
sp->value = sp->defalt;
for (np = gettynums; np->field; np++)
if (!np->set)
np->value = np->defalt;
for (fp = gettyflags; fp->field; fp++)
if (!fp->set)
fp->value = fp->defalt;
}
static char **
charnames[] = {
&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
&SU, &DS, &RP, &FL, &WE, &LN, &ST, &B2, 0
};
static cc_t *
charvars[] = {
&tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], &tmode.c_cc[VSTATUS],
&tmode.c_cc[VEOL2], 0
};
void
setchars(void)
{
int i;
char *p;
for (i = 0; charnames[i]; i++) {
p = *charnames[i];
if (p && *p)
*charvars[i] = *p;
else
*charvars[i] = _POSIX_VDISABLE;
}
}
/* Macros to clear/set/test flags. */
#define SET(t, f) (t) |= (f)
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
void
setflags(int n)
{
tcflag_t iflag, oflag, cflag, lflag;
#ifdef COMPAT_43
switch (n) {
case 0:
if (F0set) {
compatflags(F0);
return;
}
break;
case 1:
if (F1set) {
compatflags(F1);
return;
}
break;
default:
if (F2set) {
compatflags(F2);
return;
}
break;
}
#endif
switch (n) {
case 0:
if (C0set && I0set && L0set && O0set) {
tmode.c_cflag = C0;
tmode.c_iflag = I0;
tmode.c_lflag = L0;
tmode.c_oflag = O0;
return;
}
break;
case 1:
if (C1set && I1set && L1set && O1set) {
tmode.c_cflag = C1;
tmode.c_iflag = I1;
tmode.c_lflag = L1;
tmode.c_oflag = O1;
return;
}
break;
default:
if (C2set && I2set && L2set && O2set) {
tmode.c_cflag = C2;
tmode.c_iflag = I2;
tmode.c_lflag = L2;
tmode.c_oflag = O2;
return;
}
break;
}
iflag = omode.c_iflag;
oflag = omode.c_oflag;
cflag = omode.c_cflag;
lflag = omode.c_lflag;
if (NP) {
CLR(cflag, CSIZE|PARENB);
SET(cflag, CS8);
CLR(iflag, ISTRIP|INPCK|IGNPAR);
} else if (AP || EP || OP) {
CLR(cflag, CSIZE);
SET(cflag, CS7|PARENB);
SET(iflag, ISTRIP);
if (OP && !EP) {
SET(iflag, INPCK|IGNPAR);
SET(cflag, PARODD);
if (AP)
CLR(iflag, INPCK);
} else if (EP && !OP) {
SET(iflag, INPCK|IGNPAR);
CLR(cflag, PARODD);
if (AP)
CLR(iflag, INPCK);
} else if (AP || (EP && OP)) {
CLR(iflag, INPCK|IGNPAR);
CLR(cflag, PARODD);
}
} /* else, leave as is */
#if 0
if (UC)
f |= LCASE;
#endif
if (HC)
SET(cflag, HUPCL);
else
CLR(cflag, HUPCL);
#ifndef __minix
if (MB)
SET(cflag, MDMBUF);
else
CLR(cflag, MDMBUF);
#endif
if (NL) {
SET(iflag, ICRNL);
SET(oflag, ONLCR|OPOST);
} else {
CLR(iflag, ICRNL);
CLR(oflag, ONLCR);
}
#ifndef __minix
if (!HT)
SET(oflag, OXTABS|OPOST);
else
CLR(oflag, OXTABS);
#endif
#ifdef XXX_DELAY
SET(f, delaybits());
#endif
if (n == 1) { /* read mode flags */
if (RW) {
iflag = 0;
CLR(oflag, OPOST);
CLR(cflag, CSIZE|PARENB);
SET(cflag, CS8);
lflag = 0;
} else {
CLR(lflag, ICANON);
}
goto out;
}
if (n == 0)
goto out;
#if 0
if (CB)
SET(f, CRTBS);
#endif
if (CE)
SET(lflag, ECHOE);
else
CLR(lflag, ECHOE);
#ifndef __minix
if (CK)
SET(lflag, ECHOKE);
else
CLR(lflag, ECHOKE);
if (PE)
SET(lflag, ECHOPRT);
else
CLR(lflag, ECHOPRT);
#endif
if (EC)
SET(lflag, ECHO);
else
CLR(lflag, ECHO);
#ifndef __minix
if (XC)
SET(lflag, ECHOCTL);
else
CLR(lflag, ECHOCTL);
#endif
if (DX)
SET(lflag, IXANY);
else
CLR(lflag, IXANY);
out:
tmode.c_iflag = iflag;
tmode.c_oflag = oflag;
tmode.c_cflag = cflag;
tmode.c_lflag = lflag;
}
#ifdef COMPAT_43
/*
* Old TTY => termios, snatched from <sys/kern/tty_compat.c>
*/
void
compatflags(long flags)
{
tcflag_t iflag, oflag, cflag, lflag;
iflag = BRKINT|ICRNL|IMAXBEL|IXON|IXANY;
oflag = OPOST|ONLCR|OXTABS;
cflag = CREAD;
lflag = ICANON|ISIG|IEXTEN;
if (ISSET(flags, TANDEM))
SET(iflag, IXOFF);
else
CLR(iflag, IXOFF);
if (ISSET(flags, ECHO))
SET(lflag, ECHO);
else
CLR(lflag, ECHO);
if (ISSET(flags, CRMOD)) {
SET(iflag, ICRNL);
SET(oflag, ONLCR);
} else {
CLR(iflag, ICRNL);
CLR(oflag, ONLCR);
}
if (ISSET(flags, XTABS))
SET(oflag, OXTABS);
else
CLR(oflag, OXTABS);
if (ISSET(flags, RAW)) {
iflag &= IXOFF;
CLR(lflag, ISIG|ICANON|IEXTEN);
CLR(cflag, PARENB);
} else {
SET(iflag, BRKINT|IXON|IMAXBEL);
SET(lflag, ISIG|IEXTEN);
if (ISSET(flags, CBREAK))
CLR(lflag, ICANON);
else
SET(lflag, ICANON);
switch (ISSET(flags, ANYP)) {
case 0:
CLR(cflag, PARENB);
break;
case ANYP:
SET(cflag, PARENB);
CLR(iflag, INPCK);
break;
case EVENP:
SET(cflag, PARENB);
SET(iflag, INPCK);
CLR(cflag, PARODD);
break;
case ODDP:
SET(cflag, PARENB);
SET(iflag, INPCK);
SET(cflag, PARODD);
break;
}
}
/* Nothing we can do with CRTBS. */
if (ISSET(flags, PRTERA))
SET(lflag, ECHOPRT);
else
CLR(lflag, ECHOPRT);
if (ISSET(flags, CRTERA))
SET(lflag, ECHOE);
else
CLR(lflag, ECHOE);
#ifndef __minix
/* Nothing we can do with TILDE. */
if (ISSET(flags, MDMBUF))
SET(cflag, MDMBUF);
else
CLR(cflag, MDMBUF);
#endif
if (ISSET(flags, NOHANG))
CLR(cflag, HUPCL);
else
SET(cflag, HUPCL);
#ifndef __minix
if (ISSET(flags, CRTKIL))
SET(lflag, ECHOKE);
else
CLR(lflag, ECHOKE);
#endif
if (ISSET(flags, CTLECH))
SET(lflag, ECHOCTL);
else
CLR(lflag, ECHOCTL);
if (!ISSET(flags, DECCTQ))
SET(iflag, IXANY);
else
CLR(iflag, IXANY);
CLR(lflag, TOSTOP|FLUSHO|PENDIN|NOFLSH);
SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH));
if (ISSET(flags, RAW|LITOUT|PASS8)) {
CLR(cflag, CSIZE);
SET(cflag, CS8);
if (!ISSET(flags, RAW|PASS8))
SET(iflag, ISTRIP);
else
CLR(iflag, ISTRIP);
if (!ISSET(flags, RAW|LITOUT))
SET(oflag, OPOST);
else
CLR(oflag, OPOST);
} else {
CLR(cflag, CSIZE);
SET(cflag, CS7);
SET(iflag, ISTRIP);
SET(oflag, OPOST);
}
tmode.c_iflag = iflag;
tmode.c_oflag = oflag;
tmode.c_cflag = cflag;
tmode.c_lflag = lflag;
}
#endif
#ifdef XXX_DELAY
struct delayval {
unsigned delay; /* delay in ms */
int bits;
};
/*
* below are random guesses, I can't be bothered checking
*/
struct delayval crdelay[] = {
{ 1, CR1 },
{ 2, CR2 },
{ 3, CR3 },
{ 83, CR1 },
{ 166, CR2 },
{ 0, CR3 },
};
struct delayval nldelay[] = {
{ 1, NL1 }, /* special, calculated */
{ 2, NL2 },
{ 3, NL3 },
{ 100, NL2 },
{ 0, NL3 },
};
struct delayval bsdelay[] = {
{ 1, BS1 },
{ 0, 0 },
};
struct delayval ffdelay[] = {
{ 1, FF1 },
{ 1750, FF1 },
{ 0, FF1 },
};
struct delayval tbdelay[] = {
{ 1, TAB1 },
{ 2, TAB2 },
{ 3, XTABS }, /* this is expand tabs */
{ 100, TAB1 },
{ 0, TAB2 },
};
int
delaybits(void)
{
int f;
f = adelay(CD, crdelay);
f |= adelay(ND, nldelay);
f |= adelay(FD, ffdelay);
f |= adelay(TD, tbdelay);
f |= adelay(BD, bsdelay);
return (f);
}
int
adelay(int ms, struct delayval *dp)
{
if (ms == 0)
return (0);
while (dp->delay && ms > dp->delay)
dp++;
return (dp->bits);
}
#endif
char editedhost[MAXHOSTNAMELEN];
void
edithost(char *pat)
{
char *host = HN;
char *res = editedhost;
if (!pat)
pat = "";
while (*pat) {
switch (*pat) {
case '#':
if (*host)
host++;
break;
case '@':
if (*host)
*res++ = *host++;
break;
default:
*res++ = *pat;
break;
}
if (res == &editedhost[sizeof editedhost - 1]) {
*res = '\0';
return;
}
pat++;
}
if (*host)
(void)strncpy(res, host,
sizeof editedhost - (res - editedhost) - 1);
else
*res = '\0';
editedhost[sizeof editedhost - 1] = '\0';
}
void
makeenv(char *env[])
{
static char termbuf[128] = "TERM=";
char *p, *q;
char **ep;
ep = env;
if (TT && *TT) {
(void)strlcat(termbuf, TT, sizeof(termbuf));
*ep++ = termbuf;
}
if ((p = EV) != NULL) {
q = p;
while ((q = strchr(q, ',')) != NULL) {
*q++ = '\0';
*ep++ = p;
p = q;
}
if (*p)
*ep++ = p;
}
*ep = (char *)0;
}
/*
* This speed select mechanism is written for the Develcon DATASWITCH.
* The Develcon sends a string of the form "B{speed}\n" at a predefined
* baud rate. This string indicates the user's actual speed.
* The routine below returns the terminal type mapped from derived speed.
*/
struct portselect {
char *ps_baud;
char *ps_type;
} portspeeds[] = {
{ "B110", "std.110" },
{ "B134", "std.134" },
{ "B150", "std.150" },
{ "B300", "std.300" },
{ "B600", "std.600" },
{ "B1200", "std.1200" },
{ "B2400", "std.2400" },
{ "B4800", "std.4800" },
{ "B9600", "std.9600" },
{ "B19200", "std.19200" },
{ 0 }
};
char *
portselector(void)
{
char c, baud[20], *type = "default";
struct portselect *ps;
int len;
(void)alarm(5*60);
for (len = 0; len < sizeof (baud) - 1; len++) {
if (read(STDIN_FILENO, &c, 1) <= 0)
break;
c &= 0177;
if (c == '\n' || c == '\r')
break;
if (c == 'B')
len = 0; /* in case of leading garbage */
baud[len] = c;
}
baud[len] = '\0';
for (ps = portspeeds; ps->ps_baud; ps++)
if (strcmp(ps->ps_baud, baud) == 0) {
type = ps->ps_type;
break;
}
(void)sleep(2); /* wait for connection to complete */
return (type);
}
/*
* This auto-baud speed select mechanism is written for the Micom 600
* portselector. Selection is done by looking at how the character '\r'
* is garbled at the different speeds.
*/
#include <sys/time.h>
char *
autobaud(void)
{
struct pollfd set[1];
struct timespec timeout;
char c, *type = "9600-baud";
(void)tcflush(0, TCIOFLUSH);
set[0].fd = STDIN_FILENO;
set[0].events = POLLIN;
if (poll(set, 1, 5000) <= 0)
return (type);
if (read(STDIN_FILENO, &c, 1) != 1)
return (type);
timeout.tv_sec = 0;
timeout.tv_nsec = 20000;
(void)nanosleep(&timeout, NULL);
(void)tcflush(0, TCIOFLUSH);
switch (c & 0377) {
case 0200: /* 300-baud */
type = "300-baud";
break;
case 0346: /* 1200-baud */
type = "1200-baud";
break;
case 015: /* 2400-baud */
case 0215:
type = "2400-baud";
break;
default: /* 4800-baud */
type = "4800-baud";
break;
case 0377: /* 9600-baud */
type = "9600-baud";
break;
}
return (type);
}

227
libexec/getty/ttys.5 Normal file
View file

@ -0,0 +1,227 @@
.\" $NetBSD: ttys.5,v 1.18 2012/04/21 12:27:28 roy Exp $
.\"
.\" Copyright (c) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)ttys.5 8.1 (Berkeley) 6/4/93
.\"
.Dd April 5, 2012
.Dt TTYS 5
.Os
.Sh NAME
.Nm ttys
.Nd terminal initialization information
.Sh DESCRIPTION
The file
.Nm
contains information that is used by various routines to initialize
and control the use of terminal special files.
This information is read with the
.Xr getttyent 3
library routines.
.Pp
There is one line in the
.Nm
file per special device file.
Fields are separated by tabs and/or spaces.
Fields comprising more than one word should be enclosed in double
quotes (``"'').
Blank lines and comments may appear anywhere in the file; comments
are delimited by hash marks (``#'') and new lines.
Any unspecified fields will default to null.
.Pp
Each line in
.Nm
has the format:
.Dl tty command type flags
.Pp
The first field is the
name of the terminal special file as it is found in
.Pa /dev .
.Pp
The second field of the file is the command to execute for the line,
usually
.Xr getty 8 ,
which initializes and opens the line, setting the speed, waiting for
a user name and executing the
.Xr login 1
program.
However, it can be any desired command, for example the start up
for a window system terminal emulator or some other daemon process,
and can contain multiple words if quoted.
.Pp
The third field is the type of terminal usually connected to that
tty line, normally the one found in the
.Xr terminfo 5
data base file.
The environment variable
.Dv TERM
is initialized with the value by either
.Xr getty 8
or
.Xr login 1 .
.Pp
The remaining fields set flags in the
.Fa ty_status
entry (see
.Xr getttyent 3 )
or specify a window system process that
.Xr init 8
will maintain for the terminal line
or a key into a database of tty attributes (currently unused).
.Pp
.Bl -tag -width softcar
.It Sy on No or Sy off
.Xr init 8
should (or should not) execute the command given in the second field.
.It Sy secure
If
.Sy on
is specified, allows users with a uid of 0
.Pq e.g. Qq root
to login on this line.
.It Sy local
Sets the
.Dv TIOCFLAG_CLOCAL
.Xr tty 4
flag for the device.
This will cause the
.Xr termios 4
.Dv CLOCAL
flag to be set on every open and thus modem control signal lines will be
ignored by default.
.It Sy softcar
Causes the driver to ignore hardware carrier on the line (by setting the
.Dv TIOCFLAG_SOFTCAR
.Xr tty 4
flag).
.It Sy rtscts
Sets the
.Dv TIOCFLAG_CRTSCTS
.Xr tty 4
flag for the device to enable
.Tn RTS /
.Tn CTS
.Qq hardware
flow control by default.
.It Sy mdmbuf
Sets the
.Dv TIOCFLAG_MDMBUF
.Xr tty 4
flag for the device to enable
.Tn DTR /
.Tn DCD
.Qq hardware
flow control by default.
.El
.Pp
The flags
.Qq local ,
.Qq rtscts ,
.Qq mdmbuf ,
and
.Qq softcar
modify the default behaviour of the terminal line, and their actions
are device driver dependent.
These flag fields should not be quoted.
.Pp
The string ``window='' may be followed by a quoted command
string which
.Xr init 8
will execute
.Em before
starting the command specified by the second field.
.Pp
The string ``class='' may be followed by a quoted string used
as a key into a database of attributes for that category of tty.
See
.Xr getttynam 3
for more information on this feature.
.Pp
After changing the
.Nm
file a
.Dv SIGHUP
signal can be sent to
.Xr init 8
with the command
.Dq Li "kill \-s HUP 1" .
On receipt of this signal,
.Xr init 8
will re-read the
.Nm
file and spawn any necessary
.Xr getty 8
processes.
.Pp
.Sy Nota Bene :
Sending
.Dv SIGHUP
to
.Xr init 8
does
.Em not
change the state of the various
.Xr tty 4
device flags listed above; the
.Xr ttyflags 8
program must be run for changes in those flags to take effect on the devices.
.Sh FILES
.Bl -tag -width /etc/ttys -compact
.It Pa /etc/ttys
.El
.Sh EXAMPLES
.Bd -literal
# root login on console at 1200 baud
console "/usr/libexec/getty std.1200" vt100 on secure
# dialup at 1200 baud, no root logins
ttyd0 "/usr/libexec/getty d1200" dialup on # 555-1234
# Mike's terminal: hp2621
ttyh0 "/usr/libexec/getty std.9600" hp2621-nl on # 457 Evans
# John's terminal: vt100
ttyh1 "/usr/libexec/getty std.9600" vt100 on # 459 Evans
# terminal emulate/window system
ttyv0 "/usr/new/xterm -L :0" vs100 on window="/usr/new/Xvs100 0"
# Network pseudo ttys -- don't enable getty
ttyp0 none network
ttyp1 none network off
.Ed
.Sh SEE ALSO
.Xr login 1 ,
.Xr getttyent 3 ,
.Xr ttyslot 3 ,
.Xr tty 4 ,
.Xr gettytab 5 ,
.Xr terminfo 5 ,
.Xr getty 8 ,
.Xr init 8 ,
.Xr ttyflags 8
.Sh HISTORY
A
.Nm
file appeared in
.At v6 .

View file

@ -8,7 +8,7 @@ MAN= ash.1 at.1 \
flexdoc.1 format.1 fortune.1 \
fsck.mfs.1 host.1 hostaddr.1 ifdef.1 \
isodir.1 isoinfo.1 isoread.1 \
last.1 loadfont.1 loadkeys.1 logger.1 \
loadfont.1 loadkeys.1 logger.1 \
look.1 lp.1 lspci.1 mail.1 \
mixer.1 \
mkproto.1 mount.1 mt.1 \

View file

@ -1,60 +0,0 @@
.TH LAST 1
.SH NAME
last, uptime \- display recent on-line session records, show uptime
.SH SYNOPSIS
\fBlast\fR [\fB\-f \fIfile\fR]\fR [\fB\-r\fR] [\fB\-\fIn\fR] [\fIname\fR] [\fItty\fR] ...\fR
.br
\fBuptime\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH OPTIONS
.TP 5
.B \-f
# Use \fIfile\fR instead of /usr/adm/wtmp
.TP 5
.B \-r
# Search backwards only to last reboot
.TP 5
.B \-u
# Print uptime since last reboot
.TP 5
.B \-\fIn\fP
# Print a maximum of \fIn\fR lines
.SH EXAMPLES
.TP 20
.B last reboot
# When was the system last rebooted?
.TP 20
.B last ast
# When was the last login for ast?
.TP 20
.B last \-10 tty00 tty01
# Display last 10 logins on tty00 or tty01
.TP 20
.B uptime
# Display uptime (likewise \fBlast \-u\fR)
.SH DESCRIPTION
.PP
.I Last
Searches backward through the login administration file (default is
\fI/usr/adm/wtmp\fR), printing information about previous logins and
reboots.
During a long search, the SIGQUIT signal (CTRL-\\) causes \fIlast\fR to
display how far back it has gone; it then continues.
.PP
.IR Uptime ,
an alias for
.IR "last \-u" ,
displays the time the system is running since the last reboot.
.SH "SEE ALSO"
.BR who (1),
.BR utmp (5).

View file

@ -4,7 +4,7 @@ MAN= accept.2 access.2 bind.2 brk.2 chdir.2 chmod.2 chown.2 \
getpeername.2 getpid.2 getpriority.2 getsockname.2 getsockopt.2 \
gettimeofday.2 getuid.2 intro.2 ioctl.2 kill.2 link.2 listen.2 \
lseek.2 mkdir.2 mknod.2 mount.2 open.2 ptrace.2 \
read.2 readlink.2 reboot.2 recv.2 recvfrom.2 recvmsg.2 rename.2 \
read.2 readlink.2 recv.2 recvfrom.2 recvmsg.2 rename.2 \
rmdir.2 select.2 send.2 sendmsg.2 sendto.2 setsid.2 \
setsockopt.2 setuid.2 shutdown.2 sigaction.2 sigpending.2 \
sigprocmask.2 sigsuspend.2 socket.2 socketpair.2 \

View file

@ -1,51 +0,0 @@
.TH REBOOT 2
.SH NAME
reboot \- close down the system or reboot
.SH SYNTAX
.ft B
.nf
#include <minix/reboot.h>
int reboot(int \fIhow\fP)
.fi
.ft P
.SH DESCRIPTION
.B Reboot()
is used to close down the system. It allows several ways of shutting
down depending on
.IR how :
.PP
.TP 5
.BI "reboot(RBT_DEFAULT)"
Default shut-down action, the same as used when CTRL+ALT+DEL is pressed
on the keyboard.
.TP
.BI "reboot(RBT_HALT)"
Halt the system.
.TP
.BI "reboot(RBT_PANIC)"
Cause a system panic. This is not normally done from user mode.
.TP
.BI "reboot(RBT_POWEROFF)"
Power off the system if possible, reset otherwise.
.TP
.BI "reboot(RBT_REBOOT)"
Reboot the system with a software reset (currently not supported, so
a hardware reset is used).
.TP
.BI "reboot(RBT_RESET)"
Reboot the system with a hardware reset.
.PP
.B Reboot()
may only be executed by the super-user.
.SH DIAGNOSTICS
If the call succeeds, it never returns. If something went wrong,
the return value is -1 and an error is indicated by
.BR errno .
.SH SEE ALSO
.BR shutdown (8),
.BR reboot (8),
.BR halt (8),
.BR sync (2).
.SH AUTHOR
Edvard Tuinder (v892231@si.hhs.NL)

View file

@ -5,8 +5,8 @@ MAN= add_route.8 backup.8 boot.8 btrace.8 \
intr.8 irdpd.8 loadramdisk.8 \
netconf.8 newroot.8 nonamed.8 \
ossdevlinks.8 part.8 partition.8 \
poweroff.8 printroot.8 pr_routes.8 pwdauth.8 rarpd.8 \
readclock.8 reboot.8 repartition.8 \
printroot.8 pr_routes.8 pwdauth.8 rarpd.8 \
readclock.8 repartition.8 \
rshd.8 screendump.8 serial-ip.8 \
setup.8 shutdown.8 slip.8 srccrc.8 syslogd.8 tcpd.8 \
unix.8 update.8 usage.8 vbfs.8

View file

@ -1,13 +0,0 @@
.TH POWEROFF 1
.SH NAME
poweroff \- power off the machine
.SH SYNOPSIS
.B poweroff
.SH DESCRIPTION
This command powers off the machine, by calling
.B shutdown
and passing the
.I off
directive to the boot monitor.
.SH "SEE ALSO"
.BR shutdown (8).

View file

@ -1,49 +0,0 @@
.TH REBOOT 8
.SH NAME
reboot \- reboot the system immediately
.SH SYNOPSIS
\fBreboot\fP [\fB\-f\fP]
.SH DESCRIPTION
.B Reboot
can be used to reboot the system after installing a new kernel. It does
not inform the users, but does log it's actions in
.B /usr/adm/wtmp
and
.BR /usr/adm/log .
The system is then rebooted with the
.BR reboot (2)
systemcall.
.PP
If the
.B \-f
flag is not given then all processes are sent terminate
signals to give them a chance to die peacefully before the
.B reboot()
call.
.PP
If the wtmp file exists,
.B reboot
logs itself as if it were a shutdown. This is done to prevent
.BR last (1)
from talking about system-crashes.
.B Reboot
is registered as is in the log file.
.PP
.B Reboot
can only be executed by the super-user. Any other caller will be
refused, either by
.BR reboot (8)
or by
.BR reboot (2).
.SH "SEE ALSO"
.BR reboot (2),
.BR shutdown (8),
.BR halt(8),
.BR boot (8).
.SH BUGS
The error message's given by
.B reboot
are not always useful. There are several routines that can fail, but which
are not fatal for the program.
.SH AUTHOR
Edvard Tuinder (v892231@si.hhs.NL)

View file

@ -28,7 +28,7 @@ PROGRAMS+= ${PROGROOT}/drivers/tty/tty
PROGRAMS+= ${PROGROOT}/servers/mfs/mfs
PROGRAMS+= ${PROGROOT}/servers/vm/vm
PROGRAMS+= ${PROGROOT}/servers/pfs/pfs
PROGRAMS+= ${PROGROOT}/servers/init/init
PROGRAMS+= ${PROGROOT}/sbin/init/init
usage:
@echo " " >&2
@ -68,10 +68,13 @@ kernel: libraries
servers: libraries
${MAKE} -C ../servers all install
sbin: libraries
${MAKE} -C ../sbin all install
drivers: libraries servers
${MAKE} -C ../drivers all install
services: kernel servers drivers
services: kernel servers drivers sbin
.gitignore: Makefile
echo ${GEN_FILES} | tr ' ' '\n' >.gitignore

View file

@ -178,11 +178,14 @@ ${CROSS_PREFIX}objcopy ${OBJ}/kernel/kernel -O binary ${OBJ}/kernel.bin
mcopy -bsp -i ${IMG_DIR}/fat.img ${OBJ}/kernel.bin ::kernel.bin
for f in vm rs pm sched vfs ds mfs pfs init
for f in servers/vm/vm servers/rs/rs servers/pm/pm servers/sched/sched \
servers/vfs/vfs servers/ds/ds servers/mfs/mfs servers/pfs/pfs \
sbin/init/init
do
cp ${OBJ}/servers/${f}/${f} ${OBJ}/${f}.elf
${CROSS_PREFIX}strip -s ${OBJ}/${f}.elf
mcopy -bsp -i ${IMG_DIR}/fat.img ${OBJ}/${f}.elf ::${f}.elf
fn=`basename $f`.elf
cp ${OBJ}/${f} ${OBJ}/${fn}
${CROSS_PREFIX}strip -s ${OBJ}/${fn}
mcopy -bsp -i ${IMG_DIR}/fat.img ${OBJ}/${fn} ::${fn}
done
for f in tty memory

View file

@ -73,6 +73,7 @@
2012/10/17 12:00:00,include
2013/05/31 12:00:00,libexec/fingerd
2012/10/17 12:00:00,libexec/ftpd
2012/10/17 12:00:00,libexec/getty
2012/10/17 12:00:00,libexec/ld.elf_so
2012/10/17 12:00:00,libexec/Makefile
2012/10/17 12:00:00,libexec/Makefile.inc
@ -97,6 +98,9 @@
2012/10/17 12:00:00,Makefile
2011/06/09 21:23:29,sbin/fsck
2011/09/16 16:13:18,sbin/fsck_ext2fs
2012/10/17 12:00:00,sbin/init
2012/10/17 12:00:00,sbin/reboot
2012/10/17 12:00:00,sbin/shutdown
2012/10/17 12:00:00,sbin/Makefile
2012/10/17 12:00:00,sbin/Makefile.inc
2012/10/10 16:16:12,sbin/mknod
@ -188,6 +192,7 @@
2012/10/17 12:00:00,usr.bin/join
2012/10/17 12:00:00,usr.bin/jot
2012/10/17 12:00:00,usr.bin/lam
2012/10/17 12:00:00,usr.bin/last
2011/01/17 18:11:10,usr.bin/ldd
2013/10/18 12:00:00,usr.bin/leave
2012/10/17 12:00:00,usr.bin/lock
@ -248,11 +253,12 @@
2013/10/14 12:00:00,usr.bin/users
2013/10/23 12:00:00,usr.bin/uuidgen
2012/10/17 12:00:00,usr.bin/vis
2012/10/17 12:00:00,usr.bin/wall
2012/10/17 12:00:00,usr.bin/wc
2012/10/17 12:00:00,usr.bin/what
2013/03/22 12:00:00,usr.bin/whatis
2013/03/15 12:00:00,usr.bin/who
2012/10/17 12:00:00,usr.bin/whois
2013/03/22 12:00:00,usr.bin/whatis
2012/10/17 12:00:00,usr.bin/write
2012/10/17 12:00:00,usr.bin/xinstall
2012/10/17 12:00:00,usr.bin/xstr

View file

@ -9,7 +9,12 @@
SUBDIR= \
\
fsck \
mknod nologin
mknod \
nologin \
mknod \
init \
reboot \
shutdown
# support for various file systems
SUBDIR+= newfs_ext2fs fsck_ext2fs

18
sbin/init/Makefile Normal file
View file

@ -0,0 +1,18 @@
# $NetBSD: Makefile,v 1.38 2009/04/11 07:58:12 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 7/19/93
PROG= init
MAN= init.8
DPADD= ${LIBUTIL}
LDADD= -lutil
CPPFLAGS+= -DMFS_DEV_IF_NO_CONSOLE -DSUPPORT_UTMP -DSUPPORT_UTMPX
.ifdef SMALLPROG
CPPFLAGS+= -DLETS_GET_SMALL
.else
CPPFLAGS+= -DALTSHELL -DSECURE -DCHROOT
DPADD+= ${LIBCRYPT}
LDADD+= -lcrypt
.endif
.include <bsd.prog.mk>

119
sbin/init/NOTES Normal file
View file

@ -0,0 +1,119 @@
$NetBSD: NOTES,v 1.3 2006/04/18 11:40:26 salo Exp $
POSIX and init:
--------------
POSIX.1 does not define 'init' but it mentions it in a few places.
B.2.2.2, p205 line 873:
This is part of the extensive 'job control' glossary entry.
This specific reference says that 'init' must by default provide
protection from job control signals to jobs it starts --
it sets SIGTSTP, SIGTTIN and SIGTTOU to SIG_IGN.
B.2.2.2, p206 line 889:
Here is a reference to 'vhangup'. It says, 'POSIX.1 does
not specify how controlling terminal access is affected by
a user logging out (that is, by a controlling process
terminating).' vhangup() is recognized as one way to handle
the problem. I'm not clear what happens in Reno; I have
the impression that when the controlling process terminates,
references to the controlling terminal are converted to
references to a 'dead' vnode. I don't know whether vhangup()
is required.
B.2.2.2, p206 line 921:
Orphaned process groups bear indirectly on this issue. A
session leader's process group is considered to be orphaned;
that is, it's immune to job control signals from the terminal.
B.2.2.2, p233 line 2055:
'Historically, the implementation-dependent process that
inherits children whose parents have terminated without
waiting on them is called "init" and has a process ID of 1.'
It goes on to note that it used to be the case that 'init'
was responsible for sending SIGHUP to the foreground process
group of a tty whose controlling process has exited, using
vhangup(). It is now the responsibility of the kernel to
do this when the controlling process calls _exit(). The
kernel is also responsible for sending SIGCONT to stopped
process groups that become orphaned. This is like old BSD
but entire process groups are signaled instead of individual
processes.
In general it appears that the kernel now automatically
takes care of orphans, relieving 'init' of any responsibility.
Specifics are listed on the _exit() page (p50).
On setsid():
-----------
It appears that neither getty nor login call setsid(), so init must
do this -- seems reasonable. B.4.3.2 p 248 implies that this is the
way that 'init' should work; it says that setsid() should be called
after forking.
Process group leaders cannot call setsid() -- another reason to
fork! Of course setsid() causes the current process to become a
process group leader, so we can only call setsid() once. Note that
the controlling terminal acquires the session leader's process
group when opened.
Controlling terminals:
---------------------
B.7.1.1.3 p276: 'POSIX.1 does not specify a mechanism by which to
allocate a controlling terminal. This is normally done by a system
utility (such as 'getty') and is considered ... outside the scope
of POSIX.1.' It goes on to say that historically the first open()
of a tty in a session sets the controlling terminal. P130 has the
full details; nothing particularly surprising.
The glossary p12 describes a 'controlling process' as the first
process in a session that acquires a controlling terminal. Access
to the terminal from the session is revoked if the controlling
process exits (see p50, in the discussion of process termination).
Design notes:
------------
your generic finite state machine
we are fascist about which signals we elect to receive,
even signals purportedly generated by hardware
handle fatal errors gracefully if possible (we reboot if we goof!!)
if we get a segmentation fault etc., print a message on the console
and spin for a while before rebooting
(this at least decreases the amount of paper consumed :-)
apply hysteresis to rapidly exiting gettys
check wait status of children we reap
don't wait for stopped children
don't use SIGCHILD, it's too expensive
but it may close windows and avoid races, sigh
look for EINTR in case we need to change state
init is responsible for utmp and wtmp maintenance (ick)
maybe now we can consider replacements? maintain them in parallel
init only removes utmp and closes out wtmp entries...
necessary states and state transitions (gleaned from the man page):
1: single user shell (with password checking?); on exit, go to 2
2: run rc script, on exit 0 check if init.root sysctl != "/", if it
differs then fork + chroot into the value of init.root and run
/etc/rc inside the chroot: on exit 0, go to 3; on exit N (error),
go to 1 (applies also to /etc/rc when init.root == "/")
3: read ttys file: on completion, go to 4. If we did chroot in
state 2, we chroot after forking each getty to the same dir
(init.root is not re-read)
4: multi-user operation: on SIGTERM, go to 7; on SIGHUP, go to 5;
on SIGTSTP, go to 6
5: clean up mode (re-read ttys file, killing off controlling processes
on lines that are now 'off', starting them on lines newly 'on')
on completion, go to 4
6: boring mode (no new sessions); signals as in 4
7: death: send SIGHUP to all controlling processes, reap for 30 seconds,
then go to 1 (warn if not all processes died, i.e. wait blocks)
Given the -s flag, we start at state 1; otherwise state 2

374
sbin/init/init.8 Normal file
View file

@ -0,0 +1,374 @@
.\" $NetBSD: init.8,v 1.57 2009/05/18 14:17:31 wiz Exp $
.\"
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Donn Seeley at Berkeley Software Design, Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)init.8 8.6 (Berkeley) 5/26/95
.\"
.Dd November 10, 2008
.Dt INIT 8
.Os
.Sh NAME
.Nm init
.Nd process control initialization
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
The
.Nm
program is the last stage of the boot process (after the kernel loads
and initializes all the devices).
It normally begins multi-user operation.
.Pp
The following table describes the state machine used by
.Nm :
.Bl -enum
.It
Single user shell.
.Nm
may be passed
.Fl s
from the boot program to prevent the system from going multi-user and
to instead execute a single user shell without starting the normal
daemons.
If the kernel is in a secure mode,
.Nm
will downgrade it to securelevel 0 (insecure mode).
The system is then quiescent for maintenance work and may
later be made to go to state 2 (multi-user) by exiting the single-user
shell (with ^D).
.It
Multi-user boot (default operation).
Executes
.Pa /etc/rc
(see
.Xr rc 8 ) .
If this was the first state entered (as opposed to entering here after
state 1), then
.Pa /etc/rc
will be invoked with its first argument being
.Sq autoboot .
If
.Pa /etc/rc
exits with a non-zero (error) exit code, commence single user
operation by giving the super-user a shell on the console by going
to state 1 (single user).
Otherwise, proceed to state 3.
.Pp
If value of the
.Dq init.root
sysctl node is not equal to
.Pa /
at this point, the
.Pa /etc/rc
process will be run inside a
.Xr chroot 2
indicated by sysctl with the same error handling as above.
.Pp
If the administrator has not set the security level to \-1
to indicate that the kernel should not run multiuser in secure
mode, and the
.Pa /etc/rc
script has not set a higher level of security
than level 1, then
.Nm
will put the kernel into securelevel mode 1.
See
.Xr rc.conf 5
and
.Xr secmodel_securelevel 9
for more information.
.It
Set up ttys as specified in
.Xr ttys 5 .
See below for more information.
On completion, continue to state 4.
If we did chroot in state 2, each
.Xr getty 8
process will be run in the same
.Xr chroot 2
path as in 2 (that is, the value of
.Dq init.root
sysctl is not re-read).
.It
Multi-user operation.
Depending upon the signal received, change state appropriately;
on
.Dv SIGTERM ,
go to state 7;
on
.Dv SIGHUP ,
go to state 5;
on
.Dv SIGTSTP ,
go to state 6.
.It
Clean-up mode; re-read
.Xr ttys 5 ,
killing off the controlling processes on lines that are now
.Sq off ,
and starting processes that are newly
.Sq on .
On completion, go to state 4.
.It
.Sq Boring
mode; no new sessions.
Signals as per state 4.
.It
Shutdown mode.
Send
.Dv SIGHUP
to all controlling processes, reap the processes for 30 seconds,
and then go to state 1 (single user); warning if not all the processes died.
.El
.Pp
If the
.Sq console
entry in the
.Xr ttys 5
file is marked
.Dq insecure ,
then
.Nm
will require that the superuser password be
entered before the system will start a single-user shell.
The password check is skipped if the
.Sq console
is marked as
.Dq secure .
.Pp
It should be noted that while
.Nm
has the ability to start multi-user operation inside a
.Xr chroot 2
environment, the
.Nm
process itself will always run in the
.Dq original root directory .
This also implies that single-user mode is always started in the original
root, giving the possibility to create multi-user sessions in different
root directories over time.
The
.Dq init.root
sysctl node is fabricated by
.Nm
at startup and re-created any time it's found to be missing.
Type of the node is string capable of holding full pathname, and
is only accessible by the superuser (unless explicitly destroyed
and re-created with different specification).
.Pp
In multi-user operation,
.Nm
maintains
processes for the terminal ports found in the file
.Xr ttys 5 .
.Nm
reads this file, and executes the command found in the second field.
This command is usually
.Xr getty 8 ;
it opens and initializes the tty line and executes the
.Xr login 1
program.
The
.Xr login 1
program, when a valid user logs in, executes a shell for that user.
When this shell dies, either because the user logged out or an
abnormal termination occurred (a signal), the
.Nm
program wakes up, deletes the user from the
.Xr utmp 5
and
.Xr utmpx 5
files of current users and records the logout in the
.Xr wtmp 5
and
.Xr wtmpx 5
files.
The cycle is
then restarted by
.Nm
executing a new
.Xr getty 8
for the line.
.Pp
Line status (on, off, secure, getty, or window information)
may be changed in the
.Xr ttys 5
file without a reboot by sending the signal
.Dv SIGHUP
to
.Nm
with the command
.Dq Li "kill \-s HUP 1" .
This is referenced in the table above as state 5.
On receipt of this signal,
.Nm
re-reads the
.Xr ttys 5
file.
When a line is turned off in
.Xr ttys 5 ,
.Nm
will send a
.Dv SIGHUP
signal to the controlling process
for the session associated with the line.
For any lines that were previously turned off in the
.Xr ttys 5
file and are now on,
.Nm
executes a new
.Xr getty 8
to enable a new login.
If the getty or window field for a line is changed,
the change takes effect at the end of the current
login session (e.g., the next time
.Nm
starts a process on the line).
If a line is commented out or deleted from
.Xr ttys 5 ,
.Nm
will not do anything at all to that line.
However, it will complain that the relationship between lines
in the
.Xr ttys 5
file and records in the
.Xr utmp 5
file is out of sync,
so this practice is not recommended.
.Pp
.Nm
will terminate multi-user operations and resume single-user mode
if sent a terminate
.Pq Dv TERM
signal, for example,
.Dq Li "kill \-s TERM 1" .
If there are processes outstanding that are deadlocked (because of
hardware or software failure),
.Nm
will not wait for them all to die (which might take forever), but
will time out after 30 seconds and print a warning message.
.Pp
.Nm
will cease creating new
.Xr getty 8 Ns 's
and allow the system to slowly die away, if it is sent a terminal stop
.Pq Dv TSTP
signal, i.e.
.Dq Li "kill \-s TSTP 1" .
A later hangup will resume full
multi-user operations, or a terminate will start a single user shell.
This hook is used by
.Xr reboot 8
and
.Xr halt 8 .
.Pp
The role of
.Nm
is so critical that if it dies, the system will reboot itself
automatically.
If, at bootstrap time, the
.Nm
process cannot be located, or exits during its initialisation,
the system will panic with the message
.Dq panic: init died (signal %d, exit %d) .
.Pp
If
.Pa /dev/console
does not exist,
.Nm
will cd to
.Pa /dev
and run
.Dq Li "MAKEDEV -MM init" .
.Xr MAKEDEV 8
will use
.Xr mount_tmpfs 8
or
.Xr mount_mfs 8
to create a memory file system mounted over
.Pa /dev
that contains the standard devices considered necessary to boot the system.
.Sh FILES
.Bl -tag -width /var/log/wtmp{,x} -compact
.It Pa /dev/console
System console device.
.It Pa /dev/tty*
Terminal ports found in
.Xr ttys 5 .
.It Pa /var/run/utmp{,x}
Record of current users on the system.
.It Pa /var/log/wtmp{,x}
Record of all logins and logouts.
.It Pa /etc/ttys
The terminal initialization information file.
.It Pa /etc/rc
System startup commands.
.El
.Sh DIAGNOSTICS
.Bl -diag
.It "getty repeating too quickly on port %s, sleeping"
A process being started to service a line is exiting quickly
each time it is started.
This is often caused by a ringing or noisy terminal line.
.Em "Init will sleep for 10 seconds" ,
.Em "then continue trying to start the process" .
.Pp
.It "some processes would not die; ps axl advised."
A process is hung and could not be killed when the system was
shutting down.
This condition is usually caused by a process that is stuck in a
device driver because of a persistent device error condition.
.El
.Sh SEE ALSO
.Xr config 1 ,
.Xr kill 1 ,
.Xr login 1 ,
.Xr sh 1 ,
.Xr options 4 ,
.Xr ttys 5 ,
.Xr getty 8 ,
.Xr halt 8 ,
.Xr MAKEDEV 8 ,
.Xr MAKEDEV.local 8 ,
.Xr mount_mfs 8 ,
.Xr mount_tmpfs 8 ,
.Xr rc 8 ,
.Xr reboot 8 ,
.Xr rescue 8 ,
.Xr shutdown 8 ,
.Xr sysctl 8 ,
.Xr secmodel_bsd44 9 ,
.Xr secmodel_securelevel 9
.Sh HISTORY
A
.Nm
command appeared in
.At v6 .

1910
sbin/init/init.c Normal file

File diff suppressed because it is too large Load diff

40
sbin/init/pathnames.h Normal file
View file

@ -0,0 +1,40 @@
/* $NetBSD: pathnames.h,v 1.6 2003/08/07 10:04:25 agc Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Donn Seeley at Berkeley Software Design, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/5/93
*/
#include <paths.h>
#define _PATH_SLOGGER "/sbin/session_logger"
#define _PATH_RUNCOM "/etc/rc"

14
sbin/reboot/Makefile Normal file
View file

@ -0,0 +1,14 @@
# $NetBSD: Makefile,v 1.18 2002/08/02 15:05:57 wiz Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= reboot
DPADD= ${LIBUTIL}
LDADD= -lutil
CPPFLAGS+= -DSUPPORT_UTMP -DSUPPORT_UTMPX
MAN= reboot.8
MLINKS= reboot.8 halt.8 \
reboot.8 poweroff.8
LINKS= ${BINDIR}/reboot ${BINDIR}/halt \
${BINDIR}/reboot ${BINDIR}/poweroff
.include <bsd.prog.mk>

168
sbin/reboot/reboot.8 Normal file
View file

@ -0,0 +1,168 @@
.\" $NetBSD: reboot.8,v 1.29 2011/02/16 19:32:26 wiz Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)reboot.8 8.1 (Berkeley) 6/9/93
.\"
.Dd February 16, 2011
.Dt REBOOT 8
.Os
.Sh NAME
.Nm reboot ,
.Nm poweroff ,
.Nm halt
.Nd restarting, powering down and stopping the system
.Sh SYNOPSIS
.Nm halt
.Op Fl dlnpqvxz
.Nm poweroff
.Op Fl dlnqvxz
.Nm
.Op Fl dlnqvxz
.Op Ar arg ...
.Sh DESCRIPTION
The
.Nm poweroff ,
.Nm halt
and
.Nm
utilities flush the file system cache to disk, send all running processes
a
.Dv SIGTERM ,
wait for up to 30 seconds for them to die, send a
.Dv SIGKILL
to the survivors and, respectively, power down, halt or restart the system.
The action is logged, including entering a shutdown record into the login
accounting file and sending a message via
.Xr syslog 3 .
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl d
Create a dump before halting or restarting.
This option is useful for debugging system dump procedures or
capturing the state of a corrupted or misbehaving system.
.It Fl l
Suppress sending a message via
.Xr syslog 3
before halting or restarting.
.It Fl n
Do not flush the file system cache.
This option should be used with extreme caution.
It can be used if a disk or a processor is on fire.
.It Fl p
Attempt to powerdown the system.
If the powerdown fails, or the system does not support
software powerdown, the system will halt.
This option is only valid for
.Nm halt .
.It Fl v
To enable verbose messages on the console, pass the
.Xr boothowto 9
flag
.Dv AB_VERBOSE
to
.Xr reboot 2 .
.It Fl x
To enable debugging messages on the console, pass the
.Xr boothowto 9
flag
.Dv AB_DEBUG
to
.Xr reboot 2 .
.It Fl z
To silence some shutdown messages on the console, pass the
.Xr boothowto 9
flag
.Dv AB_SILENT
to
.Xr reboot 2 .
.It Fl q
Do not give processes a chance to shut down before halting or restarting.
This option should not normally be used.
.El
.Pp
If there are any arguments passed to
.Nm reboot
they are concatenated with spaces and passed as
.Fa bootstr
to the
.Xr reboot 2
system call.
The string is passed to the firmware on platforms that support it.
.Pp
Normally, the
.Xr shutdown 8
utility is used when the system needs to be halted or restarted, giving
users advance warning of their impending doom.
.Sh SEE ALSO
.Xr reboot 2 ,
.Xr syslog 3 ,
.Xr utmp 5 ,
.Xr boot 8 ,
.Xr init 8 ,
.Xr rescue 8 ,
.Xr shutdown 8 ,
.Xr sync 8
.Sh HISTORY
A
.Nm
command appeared in
.At v6 .
.Pp
The
.Nm poweroff
command first appeared in
.Nx 1.5 .
.Sh CAVEATS
Once the command has begun its work, stopping it before it completes
will probably result in a system so crippled it must be
physically reset.
To prevent premature termination, the command
blocks many signals early in its execution.
However, nothing can defend against deliberate attempts to evade this.
.Pp
This command will stop the system without running any
.Xr shutdown 8
scripts.
Amongst other things, this means that swapping will not be
disabled so that
.Xr raid 4
can shutdown cleanly.
You should normally use
.Xr shutdown 8
unless you are running in single user mode.
.Sh BUGS
The single user shell will ignore the
.Dv SIGTERM
signal.
To avoid waiting for the timeout when
rebooting or halting from the single user shell, you have to
.Ic exec reboot
or
.Ic exec halt .

264
sbin/reboot/reboot.c Normal file
View file

@ -0,0 +1,264 @@
/* $NetBSD: reboot.c,v 1.39 2011/08/27 18:46:19 joerg Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)reboot.c 8.1 (Berkeley) 6/5/93";
#else
__RCSID("$NetBSD: reboot.c,v 1.39 2011/08/27 18:46:19 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/reboot.h>
#include <err.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <util.h>
__dead static void usage(void);
static int dohalt;
static int dopoweroff;
int
main(int argc, char *argv[])
{
const char *progname;
/* int i; */
struct passwd *pw;
int ch, howto, lflag, nflag, qflag, sverrno, len;
const char *user;
char *bootstr, **av;
progname = getprogname();
if (progname[0] == '-')
progname++;
if (strcmp(progname, "halt") == 0) {
dohalt = 1;
howto = RB_HALT;
} else if (strcmp(progname, "poweroff") == 0) {
dopoweroff = 1;
howto = RB_HALT | RB_POWERDOWN;
} else
howto = 0;
lflag = nflag = qflag = 0;
while ((ch = getopt(argc, argv, "dlnpqvxz")) != -1)
switch(ch) {
case 'd':
howto |= RB_DUMP;
break;
case 'l':
lflag = 1;
break;
case 'n':
nflag = 1;
howto |= RB_NOSYNC;
break;
case 'p':
if (dohalt == 0)
usage();
howto |= RB_POWERDOWN;
break;
case 'q':
qflag = 1;
break;
case 'v':
howto |= AB_VERBOSE;
break;
case 'x':
howto |= AB_DEBUG;
break;
case 'z':
howto |= AB_SILENT;
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc) {
for (av = argv, len = 0; *av; av++)
len += strlen(*av) + 1;
bootstr = malloc(len + 1);
*bootstr = '\0'; /* for first strcat */
for (av = argv; *av; av++) {
strcat(bootstr, *av);
strcat(bootstr, " ");
}
bootstr[len - 1] = '\0'; /* to kill last space */
howto |= RB_STRING;
} else
bootstr = NULL;
if (geteuid())
errx(1, "%s", strerror(EPERM));
if (qflag) {
reboot(howto, bootstr);
err(1, "reboot");
}
/* Log the reboot. */
if (!lflag) {
if ((user = getlogin()) == NULL)
user = (pw = getpwuid(getuid())) ?
pw->pw_name : "???";
if (dohalt) {
openlog("halt", LOG_CONS, LOG_AUTH);
syslog(LOG_CRIT, "halted by %s", user);
} else if (dopoweroff) {
openlog("poweroff", LOG_CONS, LOG_AUTH);
syslog(LOG_CRIT, "powered off by %s", user);
} else {
openlog("reboot", LOG_CONS, LOG_AUTH);
if (bootstr)
syslog(LOG_CRIT, "rebooted by %s: %s", user,
bootstr);
else
syslog(LOG_CRIT, "rebooted by %s", user);
}
}
#ifdef SUPPORT_UTMP
logwtmp("~", "shutdown", "");
#endif
#ifdef SUPPORT_UTMPX
logwtmpx("~", "shutdown", "", INIT_PROCESS, 0);
#endif
/*
* Do a sync early on, so disks start transfers while we're off
* killing processes. Don't worry about writes done before the
* processes die, the reboot system call syncs the disks.
*/
if (!nflag)
sync();
/*
* Ignore signals that we can get as a result of killing
* parents, group leaders, etc.
*/
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGTERM, SIG_IGN);
(void)signal(SIGTSTP, SIG_IGN);
/*
* If we're running in a pipeline, we don't want to die
* after killing whatever we're writing to.
*/
(void)signal(SIGPIPE, SIG_IGN);
/* Just stop init -- if we fail, we'll restart it. */
#if 0 && defined(__minix)
if (kill(1, SIGTERM) == -1)
err(1, "SIGTERM init");
#else
if (kill(1, SIGTSTP) == -1)
err(1, "SIGTSTP init");
#endif
/* Send a SIGTERM first, a chance to save the buffers. */
if (kill(-1, SIGTERM) == -1) {
/*
* If ESRCH, everything's OK: we're the only non-system
* process! That can happen e.g. via 'exec reboot' in
* single-user mode.
*/
if (errno != ESRCH) {
warn("SIGTERM all processes");
goto restart;
}
}
/*
* After the processes receive the signal, start the rest of the
* buffers on their way. Wait 5 seconds between the SIGTERM and
* the SIGKILL to pretend to give everybody a chance.
*/
sleep(2);
if (!nflag)
sync();
sleep(3);
#ifndef __minix
for (i = 1;; ++i) {
if (kill(-1, SIGKILL) == -1) {
if (errno == ESRCH)
break;
warn("SIGKILL all processes");
goto restart;
}
if (i > 5) {
warnx("WARNING: some process(es) wouldn't die");
break;
}
(void)sleep(2 * i);
}
#endif
reboot(howto, bootstr);
warn("reboot()");
/* FALLTHROUGH */
restart:
sverrno = errno;
errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
strerror(sverrno));
/* NOTREACHED */
}
static void
usage(void)
{
const char *pflag = dohalt ? "p" : "";
(void)fprintf(stderr, "usage: %s [-dln%sqvxz] [-- <boot string>]\n",
getprogname(), pflag);
exit(1);
}

15
sbin/shutdown/Makefile Normal file
View file

@ -0,0 +1,15 @@
# $NetBSD: Makefile,v 1.11 2009/04/11 07:58:13 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
USE_FORT?=yes # setuid
PROG= shutdown
MAN= shutdown.8
BINOWN= root
BINGRP= operator
BINMODE=4554
.if defined(__MINIX)
WARNS=2
.endif
.include <bsd.prog.mk>

45
sbin/shutdown/pathnames.h Normal file
View file

@ -0,0 +1,45 @@
/* $NetBSD: pathnames.h,v 1.9 2004/08/19 22:30:10 christos Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/5/93
*/
#include <paths.h>
#define _PATH_FASTBOOT "/fastboot"
#ifdef RESCUEDIR
#define _PATH_HALT RESCUEDIR "/halt"
#define _PATH_REBOOT RESCUEDIR "/reboot"
#else
#define _PATH_HALT "/sbin/halt"
#define _PATH_REBOOT "/sbin/reboot"
#endif
#define _PATH_WALL "/usr/bin/wall"
#define _PATH_RCSHUTDOWN "/etc/rc.shutdown"

243
sbin/shutdown/shutdown.8 Normal file
View file

@ -0,0 +1,243 @@
.\" $NetBSD: shutdown.8,v 1.31 2011/10/04 07:25:34 dholland Exp $
.\"
.\" Copyright (c) 1988, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)shutdown.8 8.2 (Berkeley) 4/27/95
.\"
.Dd October 4, 2011
.Dt SHUTDOWN 8
.Os
.Sh NAME
.Nm shutdown
.Nd close down the system at a given time
.Sh SYNOPSIS
.Nm
.Op Fl Ddfhknprvxz
.Op Fl b Ar bootstr
.Ar time
.Op Ar message ... | Ar -
.Sh DESCRIPTION
.Nm
provides an automated shutdown procedure for super-users
to nicely notify users when the system is shutting down,
saving them from system administrators, hackers, and gurus, who
would otherwise not bother with such niceties.
.Pp
Available friendlinesses:
.Bl -tag -width bootstr
.It Fl b Ar bootstr
The given
.Ar bootstr
is passed to
.Xr reboot 8
for the benefit of those systems that can pass boot arguments to the
firmware.
Currently, this only affects sun3 and sparc machines.
.It Fl d
.Nm
will pass the
.Fl d
flag to
.Xr reboot 8
or
.Xr halt 8
to request a kernel core dump.
If neither the
.Fl h
or
.Fl r
flags are specified, then
.Fl d
also implies
.Fl r .
.It Fl f
.Nm
arranges, in the manner of
.Xr fastboot 8 ,
for the file systems
.Em not to be
checked on reboot.
.It Fl h
The system is halted at the specified
.Ar time ,
using
.Xr halt 8 .
.It Fl k
Kick everybody off.
The
.Fl k
option
does not actually halt the system, but leaves the
system multi-user with logins disabled (for all but super-user).
.It Fl n
Prevent the normal
.Xr sync 2
before stopping.
.It Fl p
The system is powered down at the specified
.Ar time ,
using
.Xr poweroff 8 .
If the powerdown fails, or the system does not support software powerdown,
the system will simply halt instead.
.It Fl r
The system is rebooted at the specified
.Ar time ,
using
.Xr reboot 8 .
.It Fl v
To enable verbose messages on the console, pass
.Fl v
to
.Xr reboot 8
or
.Xr halt 8 .
.It Fl x
To enable debugging messages on the console, pass
.Fl x
to
.Xr reboot 8
or
.Xr halt 8 .
.It Fl z
To silence some shutdown messages on the console, pass
.Fl z
to
.Xr reboot 8
or
.Xr halt 8 .
.It Fl D
Prevents
.Nm
from detaching from the tty with
.Xr fork 2 Ns /
.Xr exit 3 .
.It Ar time
.Ar Time
is the time at which
.Nm
will bring the system down and
may be the word
.Ar now
or a future time in one of two formats:
.Ar +number ,
or
.Ar [[[[[cc]yy]mm]dd]hh]mm ,
where the century, year, month, day, and hour may be defaulted
to the current system values.
The first form brings the system down
.Ar number
minutes from the current time; the second brings the system down at the
absolute time specified.
If the century is not specified, it defaults to 1900 for years between 69
and 99, or 2000 for years between 0 and 68.
A leading zero in the
.Dq yy
value is
.Em not
optional.
.It Ar message ...
Any other arguments comprise the warning message that is broadcast
to users currently logged into the system.
.It Ar -
If
.Ar -
is supplied as the only argument after the time, the warning message is read
from the standard input.
.El
.Sh BEHAVIOR
.Pp
At intervals, becoming more frequent as apocalypse approaches
and starting at ten hours before shutdown, warning messages are displayed
on the terminals of all users logged in.
Five minutes before shutdown, or immediately if shutdown is in less
than 5 minutes, logins are disabled by creating
.Pa /etc/nologin
and copying the warning message there.
If this file exists when a user attempts to log in,
.Xr login 1
prints its contents and exits.
The file is removed just before
.Nm
exits.
.Pp
At shutdown time, a message is written in the system log containing the
time of shutdown, who initiated the shutdown, and the reason.
Next a message is printed announcing the start of the system shutdown hooks.
Then the shutdown hooks in
.Pa /etc/rc.shutdown
are run, and a message is printed indicating that they have completed.
After a short delay,
.Nm
runs
.Xr halt 8
or
.Xr reboot 8 ,
or sends a terminate
signal to
.Xr init 8
to bring the system down to single-user mode, depending on the choice
of options.
.Pp
The time of the shutdown and the warning message are placed in
.Pa /etc/nologin
and should be used to tell the users why the system is
going down, when it will be back up, and to share any other pertinent
information.
.Sh FILES
.Bl -tag -width /etc/rc.shutdown -compact
.It Pa /etc/nologin
tells
.Xr login 1
not to let anyone log in
.It Pa /fastboot
tells
.Xr rc 8
not to run
.Xr fsck 8
when rebooting
.It Pa /etc/rc.shutdown
System shutdown commands
.El
.Sh SEE ALSO
.Xr login 1 ,
.Xr wall 1 ,
.Xr fastboot 8 ,
.Xr halt 8 ,
.Xr init 8 ,
.Xr poweroff 8 ,
.Xr reboot 8 ,
.Xr rescue 8
.Sh BACKWARD COMPATIBILITY
The hours and minutes in the second time format may be separated by
a colon (``:'') for backward compatibility.
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.0 .

592
sbin/shutdown/shutdown.c Normal file
View file

@ -0,0 +1,592 @@
/* $NetBSD: shutdown.c,v 1.55 2011/08/27 18:54:39 joerg Exp $ */
/*
* Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1988, 1990, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)shutdown.c 8.4 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: shutdown.c,v 1.55 2011/08/27 18:54:39 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/syslog.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <tzfile.h>
#include <unistd.h>
#include <errno.h>
#include "pathnames.h"
#ifdef DEBUG
#undef _PATH_NOLOGIN
#define _PATH_NOLOGIN "./nologin"
#undef _PATH_FASTBOOT
#define _PATH_FASTBOOT "./fastboot"
#endif
#define H *60*60
#define M *60
#define S *1
#define NOLOG_TIME 5*60
static const struct interval {
time_t timeleft, timetowait;
} tlist[] = {
{ 10 H, 5 H }, { 5 H, 3 H }, { 2 H, 1 H }, { 1 H, 30 M },
{ 30 M, 10 M }, { 20 M, 10 M }, { 10 M, 5 M }, { 5 M, 3 M },
{ 2 M, 1 M }, { 1 M, 30 S }, { 30 S, 30 S },
{ 0, 0 }
};
#undef H
#undef M
#undef S
static time_t offset, shuttime;
static int dofast, dohalt, doreboot, killflg, nofork, nosync, dodump;
static size_t mbuflen;
static int dopowerdown;
static int dodebug, dosilent, doverbose;
static const char *whom;
static char mbuf[BUFSIZ];
static char *bootstr;
static void badtime(void) __dead;
static void die_you_gravy_sucking_pig_dog(void) __dead;
static void doitfast(void);
static void dorcshutdown(void);
static void finish(int) __dead;
static void getoffset(char *);
static void loop(void) __dead;
static void nolog(void);
static void timeout(int) __dead;
static void timewarn(time_t);
static void usage(void) __dead;
int
main(int argc, char *argv[])
{
char *p, *endp;
struct passwd *pw;
size_t arglen, len;
int ch;
(void)setprogname(argv[0]);
#ifndef DEBUG
if (geteuid())
errx(1, "%s: Not super-user", strerror(EPERM));
#endif
while ((ch = getopt(argc, argv, "b:Ddfhknprvxz")) != -1)
switch (ch) {
case 'b':
bootstr = optarg;
break;
case 'd':
dodump = 1;
break;
case 'D':
nofork = 1;
break;
case 'f':
dofast = 1;
break;
case 'p':
dopowerdown = 1;
/* FALLTHROUGH */
case 'h':
dohalt = 1;
break;
case 'k':
killflg = 1;
break;
case 'n':
nosync = 1;
break;
case 'r':
doreboot = 1;
break;
case 'v':
doverbose = 1;
break;
case 'x':
dodebug = 1;
break;
case 'z':
dosilent = 1;
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc < 1)
usage();
if (dodump && !dohalt && !doreboot)
doreboot = 1;
if (dofast && nosync) {
warnx("Incompatible options -f and -n");
usage();
}
if (dohalt && doreboot) {
const char *which_flag = dopowerdown ? "p" : "h";
warnx("Incompatible options -%s and -r", which_flag);
usage();
}
getoffset(*argv++);
if (argv[0]) {
if (strcmp(argv[0], "-") || argv[1]) {
for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) {
arglen = strlen(*argv);
if ((len -= arglen) <= 2)
break;
if (p != mbuf)
*p++ = ' ';
(void)memmove(p, *argv, arglen);
p += arglen;
}
*p = '\n';
*++p = '\0';
} else {
p = mbuf;
endp = mbuf + sizeof(mbuf) - 2;
for (;;) {
if (!fgets(p, endp - p + 1, stdin))
break;
for (; *p && p < endp; ++p);
if (p == endp) {
*p = '\n';
*++p = '\0';
break;
}
}
}
}
mbuflen = strlen(mbuf);
if (offset)
(void)printf("Shutdown at %.24s.\n", ctime(&shuttime));
else
(void)printf("Shutdown NOW!\n");
if (!(whom = getlogin()))
whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
#ifdef DEBUG
(void)putc('\n', stdout);
#else
(void)setpriority(PRIO_PROCESS, 0, PRIO_MIN);
if (nofork == 0) {
int forkpid;
forkpid = fork();
if (forkpid == -1) {
perror("shutdown: fork");
exit(1);
}
if (forkpid) {
(void)printf("shutdown: [pid %d]\n", forkpid);
exit(0);
}
(void)setsid();
}
#endif
openlog("shutdown", LOG_CONS, LOG_AUTH);
loop();
/* NOTREACHED */
#ifdef __GNUC__
return 1;
#endif
}
static void
loop(void)
{
const struct interval *tp;
u_int sltime;
int logged;
if (offset <= NOLOG_TIME) {
logged = 1;
nolog();
}
else
logged = 0;
tp = tlist;
if (tp->timeleft < offset)
(void)sleep((u_int)(offset - tp->timeleft));
else {
while (offset < tp->timeleft)
++tp;
/*
* Warn now, if going to sleep more than a fifth of
* the next wait time.
*/
if ((sltime = offset - tp->timeleft) != 0) {
if (sltime > tp->timetowait / 5)
timewarn(offset);
(void)sleep(sltime);
}
}
for (;; ++tp) {
timewarn(tp->timeleft);
if (!logged && tp->timeleft <= NOLOG_TIME) {
logged = 1;
nolog();
}
(void)sleep((u_int)tp->timetowait);
if (!tp->timeleft)
break;
}
die_you_gravy_sucking_pig_dog();
}
static jmp_buf alarmbuf;
static void
timewarn(time_t timeleft)
{
static int first;
static char hostname[MAXHOSTNAMELEN + 1];
FILE *pf;
char wcmd[MAXPATHLEN + 4];
if (!first++) {
(void)gethostname(hostname, sizeof(hostname));
hostname[sizeof(hostname) - 1] = '\0';
}
/* undoc -n option to wall suppresses normal wall banner */
(void)snprintf(wcmd, sizeof wcmd, "%s -n", _PATH_WALL);
if ((pf = popen(wcmd, "w")) == NULL) {
syslog(LOG_ERR, "%s: Can't find `%s' (%m)", getprogname(),
_PATH_WALL);
return;
}
(void)fprintf(pf,
"\007*** %sSystem shutdown message from %s@%s ***\007\n",
timeleft ? "": "FINAL ", whom, hostname);
if (timeleft > 10*60)
(void)fprintf(pf, "System going down at %5.5s\n\n",
ctime(&shuttime) + 11);
else if (timeleft > 59)
(void)fprintf(pf, "System going down in %ld minute%s\n\n",
(long)timeleft / 60, (timeleft > 60) ? "s" : "");
else if (timeleft)
(void)fprintf(pf, "System going down in 30 seconds\n\n");
else
(void)fprintf(pf, "System going down IMMEDIATELY\n\n");
if (mbuflen)
(void)fwrite(mbuf, sizeof(*mbuf), mbuflen, pf);
/*
* play some games, just in case wall doesn't come back
* probably unnecessary, given that wall is careful.
*/
if (!setjmp(alarmbuf)) {
(void)signal(SIGALRM, timeout);
(void)alarm((u_int)30);
(void)pclose(pf);
(void)alarm((u_int)0);
(void)signal(SIGALRM, SIG_DFL);
}
}
static void
/*ARGSUSED*/
timeout(int signo)
{
longjmp(alarmbuf, 1);
}
static void
die_you_gravy_sucking_pig_dog(void)
{
const char *what;
if (doreboot) {
what = "reboot";
} else if (dohalt && dopowerdown) {
what = "poweroff";
} else if (dohalt) {
what = "halt";
} else {
what = "shutdown";
}
syslog(LOG_NOTICE, "%s by %s: %s", what, whom, mbuf);
(void)sleep(2);
(void)printf("\r\nSystem shutdown time has arrived\007\007\r\n");
if (killflg) {
(void)printf("\rbut you'll have to do it yourself\r\n");
finish(0);
}
if (dofast)
doitfast();
dorcshutdown();
if (doreboot || dohalt) {
const char *args[20];
const char **arg, *path;
#ifndef DEBUG
int serrno;
#endif
arg = &args[0];
if (doreboot) {
path = _PATH_REBOOT;
*arg++ = "reboot";
} else {
path = _PATH_HALT;
*arg++ = "halt";
}
if (doverbose)
*arg++ = "-v";
if (dodebug)
*arg++ = "-x";
if (dosilent)
*arg++ = "-z";
if (dodump)
*arg++ = "-d";
if (nosync)
*arg++ = "-n";
if (dopowerdown)
*arg++ = "-p";
*arg++ = "-l";
if (bootstr)
*arg++ = bootstr;
*arg++ = 0;
#ifndef DEBUG
(void)unlink(_PATH_NOLOGIN);
(void)execve(path, __UNCONST(args), NULL);
serrno = errno;
syslog(LOG_ERR, "Can't exec `%s' (%m)", path);
errno = serrno;
warn("Can't exec `%s'", path);
#else
printf("%s", path);
for (arg = &args[0]; *arg; arg++)
printf(" %s", *arg);
printf("\n");
#endif
} else {
#ifndef DEBUG
(void)kill(1, SIGTERM); /* to single user */
#else
printf("kill 1\n");
#endif
}
finish(0);
}
#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
static void
getoffset(char *timearg)
{
struct tm *lt;
char *p;
time_t now;
int yearset;
(void)time(&now);
if (!strcasecmp(timearg, "now")) { /* now */
offset = 0;
shuttime = now;
return;
}
if (*timearg == '+') { /* +minutes */
if (!isdigit((unsigned char)*++timearg))
badtime();
offset = atoi(timearg) * 60;
shuttime = now + offset;
return;
}
/* handle hh:mm by getting rid of the colon */
for (p = timearg; *p; ++p)
if (!isascii(*p) || !isdigit((unsigned char)*p)) {
if (*p == ':' && strlen(p) == 3) {
p[0] = p[1];
p[1] = p[2];
p[2] = '\0';
}
else
badtime();
}
(void)unsetenv("TZ"); /* OUR timezone */
lt = localtime(&now); /* current time val */
lt->tm_sec = 0;
yearset = 0;
switch (strlen(timearg)) {
case 12:
lt->tm_year = ATOI2(timearg) * 100 - TM_YEAR_BASE;
yearset = 1;
/* FALLTHROUGH */
case 10:
if (yearset) {
lt->tm_year += ATOI2(timearg);
} else {
yearset = ATOI2(timearg);
if (yearset < 69)
lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
else
lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
}
/* FALLTHROUGH */
case 8:
lt->tm_mon = ATOI2(timearg);
--lt->tm_mon;
/* FALLTHROUGH */
case 6:
lt->tm_mday = ATOI2(timearg);
/* FALLTHROUGH */
case 4:
lt->tm_hour = ATOI2(timearg);
/* FALLTHROUGH */
case 2:
lt->tm_min = ATOI2(timearg);
break;
default:
badtime();
}
if ((shuttime = mktime(lt)) == -1)
badtime();
if ((offset = shuttime - now) < 0)
errx(1, "time is already past");
}
static void
dorcshutdown(void)
{
(void)printf("\r\nAbout to run shutdown hooks...\r\n");
#ifndef DEBUG
(void)setuid(0);
(void)system(". " _PATH_RCSHUTDOWN);
#endif
(void)sleep(5); /* Give operator a chance to abort this. */
(void)printf("\r\nDone running shutdown hooks.\r\n");
}
#define FSMSG "fastboot file for fsck\n"
static void
doitfast(void)
{
int fastfd;
if ((fastfd = open(_PATH_FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC,
0664)) >= 0) {
(void)write(fastfd, FSMSG, sizeof(FSMSG) - 1);
(void)close(fastfd);
}
}
#define NOMSG "\n\nNO LOGINS: System going down at "
static void
nolog(void)
{
int logfd;
char *ct;
(void)unlink(_PATH_NOLOGIN); /* in case linked to another file */
(void)signal(SIGINT, finish);
(void)signal(SIGHUP, finish);
(void)signal(SIGQUIT, finish);
(void)signal(SIGTERM, finish);
if ((logfd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC,
0664)) >= 0) {
(void)write(logfd, NOMSG, sizeof(NOMSG) - 1);
ct = ctime(&shuttime);
(void)write(logfd, ct + 11, 5);
(void)write(logfd, "\n\n", 2);
(void)write(logfd, mbuf, strlen(mbuf));
(void)close(logfd);
}
}
static void
/*ARGSUSED*/
finish(int signo)
{
if (!killflg)
(void)unlink(_PATH_NOLOGIN);
exit(0);
}
static void
badtime(void)
{
warnx("illegal time format");
usage();
}
static void
usage(void)
{
(void)fprintf(stderr,
"Usage: %s [-Ddfhknprvxz] [-b bootstr] time [message ... | -]\n",
getprogname());
exit(1);
}

View file

@ -5,11 +5,11 @@
.if ${MKIMAGEONLY} == "yes"
SUBDIR= ds init input mfs pfs pm rs sched vfs vm
SUBDIR= ds input mfs pfs pm rs sched vfs vm
.else
SUBDIR= ds ext2 inet init input ipc is iso9660fs \
SUBDIR= ds ext2 inet input ipc is iso9660fs \
mfs pfs pm procfs rs sched vfs vm devman
.if ${MACHINE_ARCH} == "i386"

View file

@ -1,11 +0,0 @@
# Makefile for the init program (INIT)
.include <bsd.own.mk>
PROG= init
SRCS= init.c
MAN=
BINDIR?= /usr/sbin
.include <bsd.prog.mk>

View file

@ -1,475 +0,0 @@
/* This process is the father (mother) of all Minix user processes. When
* Minix comes up, this is process number 2, and has a pid of 1. It
* executes the /etc/rc shell file, and then reads the /etc/ttytab file to
* determine which terminals need a login process.
*
* If the files /usr/adm/wtmp and /etc/utmp exist and are writable, init
* (with help from login) will maintain login accounting. Sending a
* signal 1 (SIGHUP) to init will cause it to rescan /etc/ttytab and start
* up new shell processes if necessary. It will not, however, kill off
* login processes for lines that have been turned off; do this manually.
* Signal 15 (SIGTERM) makes init stop spawning new processes, this is
* used by shutdown and friends when they are about to close the system
* down.
*/
#include <minix/type.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/svrctl.h>
#include <ttyent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <utmp.h>
#include <minix/reboot.h>
/* Different ttyent structure. */
struct ttyent TT_REBOOT = { "console", "shutdown -d now CTRL-ALT_DEL", "-"};
char PATH_UTMP[] = "/etc/utmp"; /* current logins */
char PATH_WTMP[] = "/usr/adm/wtmp"; /* login/logout history */
char PATH_ROOT_WTMP[] = "/etc/wtmp"; /* wtmp for system up/down events */
#define PIDSLOTS 32 /* first this many ttys can be on */
struct slotent {
int errct; /* error count */
pid_t pid; /* pid of login process for this tty line */
};
#define ERRCT_DISABLE 10 /* disable after this many errors */
#define NO_PID 0 /* pid value indicating no process */
struct slotent slots[PIDSLOTS]; /* init table of ttys and pids */
int gothup = 0; /* flag, showing signal 1 was received */
int gotabrt = 0; /* flag, showing signal 6 was received */
int spawn = 1; /* flag, spawn processes only when set */
void tell(int fd, char *s);
void report(int fd, char *label);
void wtmp(int type, int linenr, char *line, pid_t pid);
void startup(int linenr, struct ttyent *ttyp);
int execute(char **cmd);
char **construct_argv(char *cmd);
void onhup(int sig);
void onterm(int sig);
void onabrt(int sig);
int main(void)
{
pid_t pid; /* pid of child process */
int fd; /* generally useful */
int linenr; /* loop variable */
int check; /* check if a new process must be spawned */
int sn; /* signal number */
struct slotent *slotp; /* slots[] pointer */
struct ttyent *ttyp; /* ttytab entry */
struct sigaction sa;
struct stat stb;
#define OPENFDS \
if (fstat(0, &stb) < 0) { \
/* Open standard input, output & error. */ \
(void) open("/dev/null", O_RDONLY); \
(void) open("/dev/log", O_WRONLY); \
dup(1); \
}
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
/* Default: Ignore every signal (except those that follow). */
sa.sa_handler = SIG_IGN;
for (sn = 1; sn < _NSIG; sn++) {
sigaction(sn, &sa, NULL);
}
/* Hangup: Reexamine /etc/ttytab for newly enabled terminal lines. */
sa.sa_handler = onhup;
sigaction(SIGHUP, &sa, NULL);
/* Terminate: Stop spawning login processes, shutdown is near. */
sa.sa_handler = onterm;
sigaction(SIGTERM, &sa, NULL);
/* Abort: Sent by the kernel on CTRL-ALT-DEL; shut the system down. */
sa.sa_handler = onabrt;
sigaction(SIGABRT, &sa, NULL);
/* Execute the /etc/rc file. */
if ((pid = fork()) != 0) {
/* Parent just waits. */
while (wait(NULL) != pid) {
if (gotabrt) reboot(RBT_HALT);
}
} else {
#if ! SYS_GETKENV
struct sysgetenv sysgetenv;
#endif
char bootopts[16];
static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL };
char **rcp = rc_command + 2;
/* Get the boot options from the boot environment. */
sysgetenv.key = "bootopts";
sysgetenv.keylen = 8+1;
sysgetenv.val = bootopts;
sysgetenv.vallen = sizeof(bootopts);
if (svrctl(PMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts;
*rcp = "start";
execute(rc_command);
report(2, "sh /etc/rc");
_exit(1); /* impossible, we hope */
}
OPENFDS;
/* Clear /etc/utmp if it exists. */
if ((fd = open(PATH_UTMP, O_WRONLY | O_TRUNC)) >= 0) close(fd);
/* Log system reboot. */
wtmp(BOOT_TIME, 0, NULL, 0);
/* Main loop. If login processes have already been started up, wait for one
* to terminate, or for a HUP signal to arrive. Start up new login processes
* for all ttys which don't have them. Note that wait() also returns when
* somebody's orphan dies, in which case ignore it. If the TERM signal is
* sent then stop spawning processes, shutdown time is near.
*/
check = 1;
while (1) {
while ((pid = waitpid(-1, NULL, check ? WNOHANG : 0)) > 0) {
/* Search to see which line terminated. */
for (linenr = 0; linenr < PIDSLOTS; linenr++) {
slotp = &slots[linenr];
if (slotp->pid == pid) {
/* Record process exiting. */
wtmp(DEAD_PROCESS, linenr, NULL, pid);
slotp->pid = NO_PID;
check = 1;
}
}
}
/* If a signal 1 (SIGHUP) is received, simply reset error counts. */
if (gothup) {
gothup = 0;
for (linenr = 0; linenr < PIDSLOTS; linenr++) {
slots[linenr].errct = 0;
}
check = 1;
}
/* Shut down on signal 6 (SIGABRT). */
if (gotabrt) {
gotabrt = 0;
startup(0, &TT_REBOOT);
}
if (spawn && check) {
/* See which lines need a login process started up. */
for (linenr = 0; linenr < PIDSLOTS; linenr++) {
slotp = &slots[linenr];
if ((ttyp = getttyent()) == NULL) break;
if (ttyp->ty_getty != NULL
/* ty_getty is a string, and TTY_ON is
* the way to check for enabled ternimanls. */
&& (ttyp->ty_status & TTY_ON)
&& slotp->pid == NO_PID
&& slotp->errct < ERRCT_DISABLE)
{
startup(linenr, ttyp);
}
}
endttyent();
}
check = 0;
}
}
void onhup(int sig)
{
gothup = 1;
spawn = 1;
}
void onterm(int sig)
{
spawn = 0;
}
void onabrt(int sig)
{
static int count = 0;
if (++count == 2) reboot(RBT_HALT);
gotabrt = 1;
}
void startup(int linenr, struct ttyent *ttyp)
{
/* Fork off a process for the indicated line. */
struct slotent *slotp; /* pointer to ttyslot */
pid_t pid; /* new pid */
int err[2]; /* error reporting pipe */
char line[32]; /* tty device name */
char **ty_getty_argv;
slotp = &slots[linenr];
/* Error channel for between fork and exec. */
if (pipe(err) < 0) err[0] = err[1] = -1;
if ((pid = fork()) == -1 ) {
report(2, "fork()");
sleep(10);
return;
}
if (pid == 0) {
/* Child */
close(err[0]);
fcntl(err[1], F_SETFD, fcntl(err[1], F_GETFD) | FD_CLOEXEC);
/* A new session. */
setsid();
/* Construct device name. */
strcpy(line, "/dev/");
strncat(line, ttyp->ty_name, sizeof(line) - 6);
/* Open the line for standard input and output. */
close(0);
close(1);
if (open(line, O_RDWR) < 0 || dup(0) < 0) {
write(err[1], &errno, sizeof(errno));
_exit(1);
}
/* Redirect standard error too. */
dup2(0, 2);
/* Construct argv for execute() */
ty_getty_argv = construct_argv(ttyp->ty_getty);
if (ty_getty_argv == NULL) {
report(2, "construct_argv");
} else {
/* Execute the getty process. */
execute(ty_getty_argv);
}
/* Oops, disaster strikes. */
fcntl(2, F_SETFL, fcntl(2, F_GETFL) | O_NONBLOCK);
if (linenr != 0 && ty_getty_argv) report(2, ty_getty_argv[0]);
write(err[1], &errno, sizeof(errno));
_exit(1);
}
/* Parent */
if (ttyp != &TT_REBOOT) slotp->pid = pid;
close(err[1]);
if (read(err[0], &errno, sizeof(errno)) != 0) {
/* If an errno value goes down the error pipe: Problems. */
switch (errno) {
case ENOENT:
case ENODEV:
case ENXIO:
/* Device nonexistent, no driver, or no minor device. */
slotp->errct = ERRCT_DISABLE;
close(err[0]);
return;
case 0:
/* Error already reported. */
break;
default:
/* Any other error on the line. */
report(2, ttyp->ty_name);
}
close(err[0]);
if (++slotp->errct >= ERRCT_DISABLE) {
tell(2, "init: ");
tell(2, ttyp->ty_name);
tell(2, ": excessive errors, shutting down\n");
} else {
sleep(5);
}
return;
}
close(err[0]);
if (ttyp != &TT_REBOOT) wtmp(LOGIN_PROCESS, linenr, ttyp->ty_name, pid);
slotp->errct = 0;
}
int execute(char **cmd)
{
/* Execute a command with a path search along /sbin:/bin:/usr/sbin:/usr/bin.
*/
static char *nullenv[] = { NULL };
char command[128];
char *path[] = { "/sbin", "/bin", "/usr/sbin", "/usr/bin" };
int i;
if (cmd[0][0] == '/') {
/* A full path. */
return execve(cmd[0], cmd, nullenv);
}
/* Path search. */
for (i = 0; i < 4; i++) {
if (strlen(path[i]) + 1 + strlen(cmd[0]) + 1 > sizeof(command)) {
errno= ENAMETOOLONG;
return -1;
}
strcpy(command, path[i]);
strcat(command, "/");
strcat(command, cmd[0]);
execve(command, cmd, nullenv);
if (errno != ENOENT) break;
}
return -1;
}
void wtmp(type, linenr, line, pid)
int type; /* type of entry */
int linenr; /* line number in ttytab */
char *line; /* tty name (only good on login) */
pid_t pid; /* pid of process */
{
/* Log an event into the UTMP and WTMP files. */
struct utmp utmp; /* UTMP/WTMP User Accounting */
int fd;
/* Clear the utmp record. */
memset((void *) &utmp, 0, sizeof(utmp));
/* Fill in utmp. */
switch (type) {
case BOOT_TIME:
/* Make a special reboot record. */
strcpy(utmp.ut_name, "reboot");
strcpy(utmp.ut_line, "~");
break;
case LOGIN_PROCESS:
/* A new login, fill in line name. */
strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
break;
case DEAD_PROCESS:
/* A logout. Use the current utmp entry, but make sure it is a
* user process exiting, and not getty or login giving up.
*/
if ((fd = open(PATH_UTMP, O_RDONLY)) < 0) {
if (errno != ENOENT) report(2, PATH_UTMP);
return;
}
if (lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
|| read(fd, &utmp, sizeof(utmp)) == -1
) {
report(2, PATH_UTMP);
close(fd);
return;
}
close(fd);
if (utmp.ut_type != USER_PROCESS) return;
strncpy(utmp.ut_name, "", sizeof(utmp.ut_name));
break;
}
/* Finish new utmp entry. */
utmp.ut_pid = pid;
utmp.ut_type = type;
utmp.ut_time = time((time_t *) 0);
switch (type) {
case LOGIN_PROCESS:
case DEAD_PROCESS:
/* Write new entry to utmp. */
if ((fd = open(PATH_UTMP, O_WRONLY)) < 0
|| lseek(fd, (off_t) (linenr+1) * sizeof(utmp), SEEK_SET) == -1
|| write(fd, &utmp, sizeof(utmp)) == -1
) {
if (errno != ENOENT) report(2, PATH_UTMP);
}
if (fd != -1) close(fd);
break;
}
switch (type) {
case BOOT_TIME:
/* Add new root wtmp entry. */
if ((fd = open(PATH_ROOT_WTMP, O_WRONLY | O_APPEND)) < 0
|| write(fd, &utmp, sizeof(utmp)) == -1
) {
if (errno != ENOENT) report(2, PATH_ROOT_WTMP);
}
if (fd != -1) close(fd);
/* fall-through */
case DEAD_PROCESS:
/* Add new wtmp entry. */
if ((fd = open(PATH_WTMP, O_WRONLY | O_APPEND)) < 0
|| write(fd, &utmp, sizeof(utmp)) == -1
) {
if (errno != ENOENT) report(2, PATH_WTMP);
}
if (fd != -1) close(fd);
break;
}
}
char **
construct_argv(char *cmd)
{
int argc = 0;
static const char sep[] = " \t";
char **argv = malloc(((strlen(cmd) + 1) / 2 + 1) * sizeof (char *));
if (argv == NULL)
return NULL;
if ((argv[argc++] = strtok(cmd, sep)) == 0) {
free(argv);
return NULL;
}
while ((argv[argc++] = strtok(NULL, sep)) != NULL)
continue;
return argv;
}
void tell(fd, s)
int fd;
char *s;
{
write(fd, s, strlen(s));
}
void report(fd, label)
int fd;
char *label;
{
int err = errno;
tell(fd, "init: ");
tell(fd, label);
tell(fd, ": ");
tell(fd, strerror(err));
tell(fd, "\n");
errno= err;
}

View file

@ -258,9 +258,13 @@ int read_super(struct super_block *sp)
magic = sp->s_magic; /* determines file system type */
if(magic == SUPER_V2 || magic == SUPER_MAGIC) {
printf("MFS: only supports V3 filesystems.\n");
return EINVAL;
}
/* Get file system version and type - only support v3. */
if(magic != SUPER_V3) {
printf("MFS: only supports V3 filesystems.\n");
return EINVAL;
}
version = V3;

View file

@ -13,11 +13,11 @@
#include <minix/callnr.h>
#include <signal.h>
#include <sys/svrctl.h>
#include <sys/reboot.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <minix/com.h>
#include <minix/config.h>
#include <minix/reboot.h>
#include <minix/sysinfo.h>
#include <minix/type.h>
#include <minix/ds.h>
@ -213,10 +213,9 @@ int do_reboot()
/* See how the system should be aborted. */
abort_flag = (unsigned) m_in.PM_REBOOT_HOW;
if (abort_flag >= RBT_INVALID) return(EINVAL);
/* notify readclock (some arm systems power off via RTC alarms) */
if (abort_flag == RBT_POWEROFF) {
if (abort_flag & RB_POWERDOWN) {
endpoint_t readclock_ep;
if (ds_retrieve_label_endpt("readclock.drv", &readclock_ep) == OK) {
message m; /* no params to set, nothing we can do if it fails */

View file

@ -20,6 +20,7 @@
#include <fcntl.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/ioc_tty.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/endpoint.h>
@ -267,6 +268,13 @@ int cdev_io(
if ((dp = cdev_get(dev, &minor_dev)) == NULL)
return(EIO);
/* Handle TIOCSCTTY ioctl: set controlling tty.
* TODO: cleaner implementation work in progress.
*/
if (op == CDEV_IOCTL && bytes == TIOCSCTTY && major(dev) == TTY_MAJOR) {
fp->fp_tty = dev;
}
/* Create a grant for the buffer provided by the user process. */
gid = make_grant(dp->dmap_driver, proc_e, op, buf, bytes);

View file

@ -14,6 +14,7 @@ SUBDIR= asa \
fsplit ftp genassym getopt \
head hexdump id indent infocmp join jot \
lam ldd leave \
last \
lock login logname lorder m4 \
machine make man menuc mesg \
mkdep mkfifo mkstr mktemp \
@ -30,8 +31,9 @@ SUBDIR= asa \
toproto \
uniq units unvis unzip users \
uuidgen vis \
uniq uname units unzip users \
wall wc what whatis who whois \
\
wc what who whois \
write xargs xinstall xstr yes
.if !defined(__MINIX)

10
usr.bin/last/Makefile Normal file
View file

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.7 2004/11/19 21:41:25 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= last
CPPFLAGS+=-DSUPPORT_UTMPX -DSUPPORT_UTMP
LDADD=-lutil
DPADD=${LIBUTIL}
.include <bsd.prog.mk>

161
usr.bin/last/last.1 Normal file
View file

@ -0,0 +1,161 @@
.\" $NetBSD: last.1,v 1.20 2012/05/12 14:52:57 reed Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)last.1 8.1 (Berkeley) 6/6/93
.\"
.Dd October 18, 2011
.Dt LAST 1
.Os
.Sh NAME
.Nm last
.Nd indicate last logins of users and ttys
.Sh SYNOPSIS
.Nm
.Op Fl Ns Ar n
.Op Fl nTx
.Op Fl f Ar file
.Op Fl H Ar hostsize
.Op Fl h Ar host
.Op Fl L Ar linesize
.Op Fl N Ar namesize
.Op Fl t Ar tty
.Op user ...
.Sh DESCRIPTION
.Nm
will list the sessions of specified
.Ar users ,
.Ar ttys ,
and
.Ar hosts ,
in reverse time order.
Each line of output contains
the user name, the tty from which the session was conducted, any
hostname, the start and stop times for the session, and the duration
of the session.
If the session is still continuing or was cut short by
a crash or shutdown,
.Nm
will so indicate.
.Pp
The following options are available:
.Pp
.Bl -tag -width xHxhostsizexx
.It Fl Ar n
Limits the report to
.Ar n
lines.
.It Fl f Ar file
.Nm
reads the file
.Ar file
instead of the default,
.Pa /var/log/wtmpx
or
.Pa /var/log/wtmp .
If the file ends with
.Sq x ,
it is treated as a
.Xr utmpx 5
format file, else it is treated as a
.Xr utmp 5
format file.
If the file is ``-'', standard input is used.
.It Fl H Ar hostsize
Use the provided hostsize as the width to format the host name field.
.It Fl h Ar host
.Ar Host
names may be names or internet numbers.
.It Fl L Ar linesize
Use the provided linesize as the width to format the tty field.
.It Fl N Ar namesize
Use the provided namesize as the width to format the login name field.
.It Fl n
Print host addresses numerically.
This option works only on
.Xr wtmpx 5
entries,
and prints nothing on
.Xr wtmp 5
entries.
.It Fl T
Display better time information, including the year and seconds.
.It Fl t Ar tty
Specify the
.Ar tty .
Tty names may be given fully or abbreviated, for example,
.Dq Li "last -t 03"
is equivalent to
.Dq Li "last -t tty03" .
.It Fl x
Assume that the file given is in
.Xr wtmpx 5
format, even if the filename does not end with an
.Sq x .
Also useful when reading such format from standard input.
.El
.Pp
If multiple arguments are given, the information which applies to any of the
arguments is printed, e.g.,
.Dq Li "last root -t console"
would list all of
.Dq Li root Ns 's
sessions as well as all sessions on the console terminal.
If no users, hostnames, or terminals are specified,
.Nm
prints a record of all logins and logouts.
.Pp
The pseudo-user
.Ar reboot
logs in at reboots of the system, thus
.Dq Li last reboot
will give an indication of mean time between reboot.
.Pp
If
.Nm
is interrupted, it indicates to what date the search has progressed.
If interrupted with a quit signal
.Nm
indicates how far the search has progressed and then continues.
.Sh FILES
.Bl -tag -width /var/log/wtmpx -compact
.It Pa /var/log/wtmp
login data base
.It Pa /var/log/wtmpx
login data base
.El
.Sh SEE ALSO
.Xr lastcomm 1 ,
.Xr utmp 5 ,
.Xr utmpx 5 ,
.Xr ac 8 ,
.Xr lastlogin 8
.Sh HISTORY
.Nm
appeared in
.Bx 1 .

405
usr.bin/last/last.c Normal file
View file

@ -0,0 +1,405 @@
/* $NetBSD: last.c,v 1.36 2012/03/15 03:04:05 dholland Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)last.c 8.2 (Berkeley) 4/2/94";
#endif
__RCSID("$NetBSD: last.c,v 1.36 2012/03/15 03:04:05 dholland Exp $");
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <tzfile.h>
#include <unistd.h>
#include <arpa/inet.h>
#ifdef SUPPORT_UTMPX
#include <utmpx.h>
#endif
#ifdef SUPPORT_UTMP
#include <utmp.h>
#endif
#include <util.h>
#ifndef UT_NAMESIZE
#define UT_NAMESIZE 8
#define UT_LINESIZE 8
#define UT_HOSTSIZE 16
#endif
#ifndef SIGNATURE
#define SIGNATURE -1
#endif
#define NO 0 /* false/no */
#define YES 1 /* true/yes */
#define TBUFLEN 30 /* length of time string buffer */
#define TFMT "%a %b %d %R" /* strftime format string */
#define LTFMT "%a %b %d %Y %T" /* strftime long format string */
#define TFMTS "%R" /* strftime format string - time only */
#define LTFMTS "%T" /* strftime long format string - " */
/* fmttime() flags */
#define FULLTIME 0x1 /* show year, seconds */
#define TIMEONLY 0x2 /* show time only, not date */
#define GMT 0x4 /* show time at GMT, for offsets only */
#define MAXUTMP 1024
typedef struct arg {
const char *name; /* argument */
#define HOST_TYPE -2
#define TTY_TYPE -3
#define USER_TYPE -4
int type; /* type of arg */
struct arg *next; /* linked list pointer */
} ARG;
static ARG *arglist; /* head of linked list */
typedef struct ttytab {
time_t logout; /* log out time */
char tty[128]; /* terminal name */
struct ttytab *next; /* linked list pointer */
} TTY;
static TTY *ttylist; /* head of linked list */
static time_t currentout; /* current logout value */
static long maxrec; /* records to display */
static int fulltime = 0; /* Display seconds? */
static int xflag; /* Assume file is wtmpx format */
static void addarg(int, const char *);
static TTY *addtty(const char *);
static void hostconv(char *);
static const char *ttyconv(char *);
#ifdef SUPPORT_UTMPX
static void wtmpx(const char *, int, int, int, int);
#endif
#ifdef SUPPORT_UTMP
static void wtmp(const char *, int, int, int, int);
#endif
static char *fmttime(time_t, int);
__dead static void usage(void);
static
void usage(void)
{
(void)fprintf(stderr, "usage: %s [-#%s] [-nTx] [-f file]"
" [-H hostsize] [-h host] [-L linesize]\n"
"\t [-N namesize] [-t tty] [user ...]\n", getprogname(),
#ifdef NOTYET_SUPPORT_UTMPX
"w"
#else
""
#endif
);
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
int ch;
char *p;
const char *file = NULL;
int namesize = UT_NAMESIZE;
int linesize = UT_LINESIZE;
int hostsize = UT_HOSTSIZE;
int numeric = 0;
maxrec = -1;
while ((ch = getopt(argc, argv, "0123456789f:H:h:L:nN:Tt:x")) != -1)
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/*
* kludge: last was originally designed to take
* a number after a dash.
*/
if (maxrec == -1) {
p = argv[optind - 1];
if (p[0] == '-' && p[1] == ch && !p[2])
maxrec = atol(++p);
else if (optind < argc)
maxrec = atol(argv[optind] + 1);
else
usage();
if (!maxrec)
return 0;
}
break;
case 'f':
file = optarg;
if ('\0' == file[0])
usage();
break;
case 'H':
hostsize = atoi(optarg);
if (hostsize < 1)
usage();
break;
case 'h':
hostconv(optarg);
addarg(HOST_TYPE, optarg);
break;
case 'L':
linesize = atoi(optarg);
if (linesize < 1)
usage();
break;
case 'N':
namesize = atoi(optarg);
if (namesize < 1)
usage();
break;
case 'n':
numeric = 1;
break;
case 'T':
fulltime = 1;
break;
case 't':
addarg(TTY_TYPE, ttyconv(optarg));
break;
case 'x':
xflag = 1;
break;
case '?':
default:
usage();
}
if (argc) {
setlinebuf(stdout);
for (argv += optind; *argv; ++argv) {
#define COMPATIBILITY
#ifdef COMPATIBILITY
/* code to allow "last p5" to work */
addarg(TTY_TYPE, ttyconv(*argv));
#endif
addarg(USER_TYPE, *argv);
}
}
if (file == NULL) {
#ifdef SUPPORT_UTMPX
if (access(_PATH_WTMPX, R_OK) == 0)
file = _PATH_WTMPX;
else
#endif
#ifdef SUPPORT_UTMP
if (access(_PATH_WTMP, R_OK) == 0)
file = _PATH_WTMP;
#endif
if (file == NULL)
#if defined(SUPPORT_UTMPX) && defined(SUPPORT_UTMP)
errx(EXIT_FAILURE, "Cannot access `%s' or `%s'", _PATH_WTMPX,
_PATH_WTMP);
#elif defined(SUPPORT_UTMPX)
errx(EXIT_FAILURE, "Cannot access `%s'", _PATH_WTMPX);
#elif defined(SUPPORT_UTMP)
errx(EXIT_FAILURE, "Cannot access `%s'", _PATH_WTMP);
#else
errx(EXIT_FAILURE, "No utmp or utmpx support compiled in.");
#endif
}
#if defined(SUPPORT_UTMPX) && defined(SUPPORT_UTMP)
if (file[strlen(file) - 1] == 'x' || xflag)
wtmpx(file, namesize, linesize, hostsize, numeric);
else
wtmp(file, namesize, linesize, hostsize, numeric);
#elif defined(SUPPORT_UTMPX)
wtmpx(file, namesize, linesize, hostsize, numeric);
#elif defined(SUPPORT_UTMP)
wtmp(file, namesize, linesize, hostsize, numeric);
#else
errx(EXIT_FAILURE, "No utmp or utmpx support compiled in.");
#endif
exit(EXIT_SUCCESS);
}
/*
* addarg --
* add an entry to a linked list of arguments
*/
static void
addarg(int type, const char *arg)
{
ARG *cur;
if (!(cur = (ARG *)malloc(sizeof(ARG))))
err(EXIT_FAILURE, "malloc failure");
cur->next = arglist;
cur->type = type;
cur->name = arg;
arglist = cur;
}
/*
* addtty --
* add an entry to a linked list of ttys
*/
static TTY *
addtty(const char *tty)
{
TTY *cur;
if (!(cur = (TTY *)malloc(sizeof(TTY))))
err(EXIT_FAILURE, "malloc failure");
cur->next = ttylist;
cur->logout = currentout;
memmove(cur->tty, tty, sizeof(cur->tty));
return (ttylist = cur);
}
/*
* hostconv --
* convert the hostname to search pattern; if the supplied host name
* has a domain attached that is the same as the current domain, rip
* off the domain suffix since that's what login(1) does.
*/
static void
hostconv(char *arg)
{
static int first = 1;
static char *hostdot, name[MAXHOSTNAMELEN + 1];
char *argdot;
if (!(argdot = strchr(arg, '.')))
return;
if (first) {
first = 0;
if (gethostname(name, sizeof(name)))
err(EXIT_FAILURE, "gethostname");
name[sizeof(name) - 1] = '\0';
hostdot = strchr(name, '.');
}
if (hostdot && !strcasecmp(hostdot, argdot))
*argdot = '\0';
}
/*
* ttyconv --
* convert tty to correct name.
*/
static const char *
ttyconv(char *arg)
{
char *mval;
if (!strcmp(arg, "co"))
return ("console");
/*
* kludge -- we assume that all tty's end with
* a two character suffix.
*/
if (strlen(arg) == 2) {
if (asprintf(&mval, "tty%s", arg) == -1)
err(EXIT_FAILURE, "malloc failure");
return (mval);
}
if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1))
return (&arg[sizeof(_PATH_DEV) - 1]);
return (arg);
}
/*
* fmttime --
* return pointer to (static) formatted time string.
*/
static char *
fmttime(time_t t, int flags)
{
struct tm *tm;
static char tbuf[TBUFLEN];
tm = (flags & GMT) ? gmtime(&t) : localtime(&t);
if (tm == NULL) {
strcpy(tbuf, "????");
return tbuf;
}
strftime(tbuf, sizeof(tbuf),
(flags & TIMEONLY)
? (flags & FULLTIME ? LTFMTS : TFMTS)
: (flags & FULLTIME ? LTFMT : TFMT),
tm);
return (tbuf);
}
#ifdef SUPPORT_UTMP
#define TYPE(a) 0
#define NAMESIZE UT_NAMESIZE
#define LINESIZE UT_LINESIZE
#define HOSTSIZE UT_HOSTSIZE
#define ut_timefld ut_time
#define HAS_UT_SS 0
#include "want.c"
#undef TYPE /*(a)*/
#undef NAMESIZE
#undef LINESIZE
#undef HOSTSIZE
#undef ut_timefld
#undef HAS_UT_SS
#endif
#ifdef SUPPORT_UTMPX
#define utmp utmpx
#define want wantx
#define wtmp wtmpx
#define gethost gethostx
#define buf bufx
#define onintr onintrx
#define TYPE(a) (a)->ut_type
#define NAMESIZE UTX_USERSIZE
#define LINESIZE UTX_LINESIZE
#define HOSTSIZE UTX_HOSTSIZE
#define ut_timefld ut_xtime
#define HAS_UT_SS 1
#include "want.c"
#endif

318
usr.bin/last/want.c Normal file
View file

@ -0,0 +1,318 @@
/* $NetBSD: want.c,v 1.17 2012/03/15 03:04:05 dholland Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
static struct utmp *buf;
static time_t seentime;
static void onintr(int);
static int want(struct utmp *, int);
static const char *gethost(struct utmp *, const char *, int);
static const char *
/*ARGSUSED*/
gethost(struct utmp *ut, const char *host, int numeric)
{
#if HAS_UT_SS == 0
return numeric ? "" : host;
#else
if (numeric) {
static char hbuf[512];
hbuf[0] = '\0';
(void)sockaddr_snprintf(hbuf, sizeof(hbuf), "%a",
(struct sockaddr *)&ut->ut_ss);
return hbuf;
} else
return host;
#endif
}
#define NULTERM(what) \
if (check ## what) \
(void)strlcpy(what ## p = what ## buf, bp->ut_ ## what, \
sizeof(what ## buf)); \
else \
what ## p = bp->ut_ ## what
/*
* wtmp --
* read through the wtmp file
*/
static void
wtmp(const char *file, int namesz, int linesz, int hostsz, int numeric)
{
struct utmp *bp; /* current structure */
TTY *T; /* tty list entry */
struct stat stb; /* stat of file for sz */
off_t offset;
int wfd;
char *ct;
const char *crmsg;
size_t len = sizeof(*buf) * MAXUTMP;
char namebuf[sizeof(bp->ut_name) + 1], *namep;
char linebuf[sizeof(bp->ut_line) + 1], *linep;
char hostbuf[sizeof(bp->ut_host) + 1], *hostp;
int checkname = namesz > (int)sizeof(bp->ut_name);
int checkline = linesz > (int)sizeof(bp->ut_line);
int checkhost = hostsz > (int)sizeof(bp->ut_host);
if ((buf = malloc(len)) == NULL)
err(EXIT_FAILURE, "Cannot allocate utmp buffer");
crmsg = NULL;
if (!strcmp(file, "-")) {
wfd = STDIN_FILENO;
file = "<stdin>";
} else if ((wfd = open(file, O_RDONLY, 0)) < 0) {
err(EXIT_FAILURE, "%s", file);
}
if (lseek(wfd, 0, SEEK_CUR) < 0) {
const char *dir;
char *tfile;
int tempfd;
ssize_t tlen;
if (ESPIPE != errno) {
err(EXIT_FAILURE, "lseek");
}
dir = getenv("TMPDIR");
if (asprintf(&tfile, "%s/last.XXXXXX", dir ? dir : _PATH_TMP) == -1)
err(EXIT_FAILURE, "asprintf");
tempfd = mkstemp(tfile);
if (tempfd < 0) {
err(EXIT_FAILURE, "mkstemp");
}
unlink(tfile);
for (;;) {
tlen = read(wfd, buf, len);
if (tlen < 0) {
err(1, "%s: read", file);
}
if (tlen == 0) {
break;
}
if (write(tempfd, buf, tlen) != tlen) {
err(1, "%s: write", tfile);
}
}
wfd = tempfd;
}
if (fstat(wfd, &stb) == -1)
err(EXIT_FAILURE, "%s: fstat", file);
if (!S_ISREG(stb.st_mode))
errx(EXIT_FAILURE, "%s: Not a regular file", file);
seentime = stb.st_mtime;
(void)signal(SIGINT, onintr);
(void)signal(SIGQUIT, onintr);
offset = stb.st_size;
/* Ignore trailing garbage or partial record */
offset -= offset % (off_t) sizeof(*buf);
while (offset >= (off_t) sizeof(*buf)) {
ssize_t ret, i;
size_t size;
size = MIN((off_t)len, offset);
offset -= size; /* Always a multiple of sizeof(*buf) */
ret = pread(wfd, buf, size, offset);
if (ret < 0) {
err(EXIT_FAILURE, "%s: pread", file);
} else if ((size_t) ret < size) {
err(EXIT_FAILURE, "%s: Unexpected end of file", file);
}
for (i = ret / sizeof(*buf) - 1; i >= 0; i--) {
bp = &buf[i];
NULTERM(name);
NULTERM(line);
NULTERM(host);
seentime = bp->ut_timefld;
/*
* if the terminal line is '~', the machine stopped.
* see utmp(5) for more info.
*/
if (linep[0] == '~' && !linep[1]) {
/* everybody just logged out */
for (T = ttylist; T; T = T->next)
T->logout = -bp->ut_timefld;
currentout = -bp->ut_timefld;
crmsg = strncmp(namep, "shutdown",
namesz) ? "crash" : "shutdown";
if (want(bp, NO)) {
ct = fmttime(bp->ut_timefld, fulltime);
printf("%-*.*s %-*.*s %-*.*s %s\n",
namesz, namesz, namep,
linesz, linesz, linep,
hostsz, hostsz,
gethost(bp, hostp, numeric), ct);
if (maxrec != -1 && !--maxrec)
return;
}
continue;
}
/*
* if the line is '{' or '|', date got set; see
* utmp(5) for more info.
*/
if ((linep[0] == '{' || linep[0] == '|') && !linep[1]) {
if (want(bp, NO)) {
ct = fmttime(bp->ut_timefld, fulltime);
printf("%-*.*s %-*.*s %-*.*s %s\n",
namesz, namesz, namep,
linesz, linesz, linep,
hostsz, hostsz,
gethost(bp, hostp, numeric),
ct);
if (maxrec && !--maxrec)
return;
}
continue;
}
/* find associated tty */
for (T = ttylist;; T = T->next) {
if (!T) {
/* add new one */
T = addtty(linep);
break;
}
if (!strncmp(T->tty, linep, LINESIZE))
break;
}
if (TYPE(bp) == SIGNATURE)
continue;
if (namep[0] && want(bp, YES)) {
ct = fmttime(bp->ut_timefld, fulltime);
printf("%-*.*s %-*.*s %-*.*s %s ",
namesz, namesz, namep,
linesz, linesz, linep,
hostsz, hostsz,
gethost(bp, hostp, numeric),
ct);
if (!T->logout)
puts(" still logged in");
else {
time_t delta; /* time difference */
if (T->logout < 0) {
T->logout = -T->logout;
printf("- %s", crmsg);
}
else
printf("- %s",
fmttime(T->logout,
fulltime | TIMEONLY));
delta = T->logout - bp->ut_timefld;
if (delta < SECSPERDAY)
printf(" (%s)\n",
fmttime(delta,
fulltime | TIMEONLY | GMT));
else
printf(" (%lld+%s)\n",
(long long)
delta / SECSPERDAY,
fmttime(delta,
fulltime | TIMEONLY | GMT));
}
if (maxrec != -1 && !--maxrec)
return;
}
T->logout = bp->ut_timefld;
}
}
fulltime = 1; /* show full time */
crmsg = fmttime(seentime, FULLTIME);
if ((ct = strrchr(file, '/')) != NULL)
ct++;
printf("\n%s begins %s\n", ct ? ct : file, crmsg);
}
/*
* want --
* see if want this entry
*/
static int
want(struct utmp *bp, int check)
{
ARG *step;
if (check) {
/*
* when uucp and ftp log in over a network, the entry in
* the utmp file is the name plus their process id. See
* etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
*/
if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
bp->ut_line[3] = '\0';
else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
bp->ut_line[4] = '\0';
}
if (!arglist)
return (YES);
for (step = arglist; step; step = step->next)
switch(step->type) {
case HOST_TYPE:
if (!strncasecmp(step->name, bp->ut_host, HOSTSIZE))
return (YES);
break;
case TTY_TYPE:
if (!strncmp(step->name, bp->ut_line, LINESIZE))
return (YES);
break;
case USER_TYPE:
if (!strncmp(step->name, bp->ut_name, NAMESIZE))
return (YES);
break;
}
return (NO);
}
/*
* onintr --
* on interrupt, we inform the user how far we've gotten
*/
static void
onintr(int signo)
{
/* FIXME: None of this is allowed in a signal handler */
printf("\ninterrupted %s\n", fmttime(seentime, FULLTIME));
if (signo == SIGINT) {
(void)raise_default_signal(signo);
exit(EXIT_FAILURE);
}
(void)fflush(stdout); /* fix required for rsh */
}

18
usr.bin/wall/Makefile Normal file
View file

@ -0,0 +1,18 @@
# $NetBSD: Makefile,v 1.10 2007/05/28 12:06:32 tls Exp $
# @(#)Makefile 8.1 (Berkeley) 6/6/93
.include <bsd.own.mk>
USE_FORT?= yes # setuid
PROG= wall
SRCS= wall.c utmpentry.c term_chk.c
BINGRP= tty
BINMODE=2555
DPADD+=${LIBUTIL}
LDADD+=-lutil
.PATH.c: ${NETBSDSRCDIR}/usr.bin/who ${NETBSDSRCDIR}/usr.bin/write
CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/who -DSUPPORT_UTMPX -DSUPPORT_UTMP
CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/write
.include <bsd.prog.mk>

74
usr.bin/wall/wall.1 Normal file
View file

@ -0,0 +1,74 @@
.\" $NetBSD: wall.1,v 1.7 2003/08/07 11:17:14 agc Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)wall.1 8.1 (Berkeley) 6/6/93
.\"
.Dd March 27, 2003
.Dt WALL 1
.Os
.Sh NAME
.Nm wall
.Nd write a message to users
.Sh SYNOPSIS
.Nm
.Op Fl g Ar group
.Op Ar file
.Sh DESCRIPTION
.Nm
displays the contents of
.Ar file
or, by default, its standard input, on the terminals of all
currently logged in users.
.Pp
Only the super-user can write on the
terminals of users who have chosen
to deny messages or are using a program which
automatically denies messages.
.Bl -tag -width indent
.It Fl g
Send messages to users in this group.
This option may be specified multiple times, and any user in any of the
specified groups will receive the message.
.El
.Sh SEE ALSO
.Xr mesg 1 ,
.Xr talk 1 ,
.Xr write 1 ,
.Xr shutdown 8
.Sh HISTORY
A
.Nm
command appeared in
.At v7 .
Support for
.Fl g
was added in
.Nx 2.0
(from
.Ox 2.0 ) .

276
usr.bin/wall/wall.c Normal file
View file

@ -0,0 +1,276 @@
/* $NetBSD: wall.c,v 1.29 2011/09/06 18:45:21 joerg Exp $ */
/*
* Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1988, 1990, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93";
#endif
__RCSID("$NetBSD: wall.c,v 1.29 2011/09/06 18:45:21 joerg Exp $");
#endif /* not lint */
/*
* This program is not related to David Wall, whose Stanford Ph.D. thesis
* is entitled "Mechanisms for Broadcast and Selective Broadcast".
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <ctype.h>
#include <err.h>
#include <grp.h>
#include <errno.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include "utmpentry.h"
#include "term_chk.h"
static void addgroup(char *);
static void makemsg(const char *);
__dead static void usage(void);
static struct wallgroup {
gid_t gid;
char *name;
char **mem;
struct wallgroup *next;
} *grouplist;
static int nobanner;
static size_t mbufsize;
static char *mbuf;
/* ARGSUSED */
int
main(int argc, char **argv)
{
int ch;
struct iovec iov;
char *p, **mem;
struct utmpentry *ep;
gid_t egid;
struct wallgroup *wg;
struct passwd *pw;
setprogname(argv[0]);
egid = getegid();
if (setegid(getgid()) == -1)
err(1, "setegid");
pw = getpwnam("nobody");
(void)check_sender(NULL, getuid(), egid);
while ((ch = getopt(argc, argv, "g:n")) != -1)
switch (ch) {
case 'n':
/* undoc option for shutdown: suppress banner */
if (geteuid() == 0 || (pw && getuid() == pw->pw_uid))
nobanner = 1;
break;
case 'g':
addgroup(optarg);
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc > 1)
usage();
makemsg(*argv);
iov.iov_base = mbuf;
iov.iov_len = mbufsize;
(void)getutentries(NULL, &ep);
(void)setegid(egid);
for (; ep; ep = ep->next) {
if (grouplist) {
int ingroup;
ingroup = 0;
pw = getpwnam(ep->name);
if (!pw)
continue;
for (wg = grouplist; wg && !ingroup; wg = wg->next) {
if (wg->gid == pw->pw_gid)
ingroup = 1;
for (mem = wg->mem; *mem && !ingroup; mem++)
if (strcmp(ep->name, *mem) == 0)
ingroup = 1;
}
if (ingroup == 0)
continue;
}
/* skip [xgk]dm/xserver entries (":0", ":1", etc.) */
if (ep->line[0] == ':' && isdigit((unsigned char)ep->line[1]))
continue;
if ((p = ttymsg(&iov, 1, ep->line, 60*5)) != NULL)
warnx("%s", p);
}
exit(0);
}
static void
addgroup(char *name)
{
int i;
struct group *grp;
struct wallgroup *g;
grp = getgrnam(name);
if ((grp = getgrnam(name)) == NULL)
errx(1, "unknown group `%s'", name);
for (i = 0; grp->gr_mem[i]; i++)
continue;
g = (struct wallgroup *)malloc(sizeof *g);
if (g == NULL)
err(1, "malloc");
g->gid = grp->gr_gid;
g->name = name;
g->mem = (char **)malloc(i + 1);
if (g->mem == NULL)
err(1, "malloc");
for (i = 0; grp->gr_mem[i] != NULL; i++) {
g->mem[i] = strdup(grp->gr_mem[i]);
if (g->mem[i] == NULL)
err(1, "malloc");
}
g->mem[i] = NULL;
g->next = grouplist;
grouplist = g;
}
static void
makemsg(const char *fname)
{
int ch, cnt;
struct tm *lt;
struct passwd *pw;
struct stat sbuf;
time_t now;
FILE *fp;
int fd;
const char *whom, *tty;
char *p, tmpname[MAXPATHLEN], lbuf[100],
hostname[MAXHOSTNAMELEN+1];
(void)snprintf(tmpname, sizeof tmpname, "%s/wall.XXXXXX", _PATH_TMP);
if ((fd = mkstemp(tmpname)) == -1)
err(1, "can't open temporary file");
(void)unlink(tmpname);
if (!(fp = fdopen(fd, "r+")))
err(1, "can't open temporary file");
if (!nobanner) {
if (!(whom = getlogin()))
whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
(void)gethostname(hostname, sizeof(hostname));
hostname[sizeof(hostname) - 1] = '\0';
(void)time(&now);
lt = localtime(&now);
/*
* all this stuff is to blank out a square for the message;
* we wrap message lines at column 79, not 80, because some
* terminals wrap after 79, some do not, and we can't tell.
* Which means that we may leave a non-blank character
* in column 80, but that can't be helped.
*/
(void)fprintf(fp, "\r%79s\r\n", " ");
(void)snprintf(lbuf, sizeof lbuf,
"Broadcast Message from %s@%s", whom, hostname);
(void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf);
tty = ttyname(STDERR_FILENO);
if (tty == NULL)
tty = "??";
(void)snprintf(lbuf, sizeof lbuf,
" (%s) at %d:%02d %s...", tty,
lt->tm_hour, lt->tm_min, lt->tm_zone);
(void)fprintf(fp, "%-79.79s\r\n", lbuf);
}
(void)fprintf(fp, "%79s\r\n", " ");
if (fname && !(freopen(fname, "r", stdin)))
err(1, "can't read %s", fname);
while (fgets(lbuf, sizeof(lbuf), stdin))
for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
if (cnt == 79 || ch == '\n') {
for (; cnt < 79; ++cnt)
putc(' ', fp);
putc('\r', fp);
putc('\n', fp);
cnt = -1;
}
if (ch != '\n')
putc(ch, fp);
}
(void)fprintf(fp, "%79s\r\n", " ");
rewind(fp);
if (fstat(fd, &sbuf))
err(1, "can't stat temporary file");
if ((uint64_t)sbuf.st_size > SIZE_T_MAX)
errx(1, "file too big");
mbufsize = sbuf.st_size;
if (!(mbuf = malloc(mbufsize)))
err(1, "malloc");
if (fread(mbuf, 1, mbufsize, fp) != mbufsize)
err(1, "can't read temporary file");
(void)fclose(fp);
}
static void
usage(void)
{
(void)fprintf(stderr, "usage: %s [-g group] [file]\n", getprogname());
exit(1);
}