main.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1985 AT&T
* All Rights Reserved
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.46 */
#include <stdio.h>
#include <signal.h>
#include <curses.h>
#include <term.h>
#include <unistd.h>
#include "wish.h"
#include "token.h"
#include "actrec.h"
#include "terror.h"
#include "ctl.h"
#include "vtdefs.h"
/* #include "status.h" empty include file abs 9/14/88 */
#include "moremacros.h"
#include "sizes.h"
/*
* External Globals
*/
int Vflag = 0; /* Set if running FACE User Interface */
pid_t Fmli_pid; /* Process id of this FMLI. EFT abs k16 */
char Semaphore[PATHSIZ] = "/tmp/FMLIsem."; /* for asynch coprocs */
bool Suspend_interupt;
char *Suspend_window;
char *Aliasfile; /* File of path aliases */
extern char *Home;
extern char *tigetstr(); /* curses routine */
extern long strtol(); /* abs k16 */
extern pid_t getpid(); /* EFT abs k18 */
extern void mess_init(); /* abs k18 */
extern char *Filesys;
extern char *Oasys;
/*
* Defines for SLK layout (4-4 or 3-2-3 layout can be specified in curses)
*/
#define FOURFOUR "4-4"
#define LAYOUT_DESC "slk_layout"
/*
* Default FMLI Stream handler
*/
token physical_stream();
token virtual_stream();
token actrec_stream();
token global_stream();
token menu_stream();
token error_stream();
token (*Defstream[])() = {
physical_stream,
virtual_stream,
actrec_stream,
global_stream,
error_stream,
NULL
};
extern char *Progname;
extern int curses_initialized;
/* Status line variables */
long Mail_check;
char *Mail_file;
time_t Cur_time; /* EFT abs k16 */
/*
* Static globals
*/
static char Vpid[12] = "VPID=";
static char Fcolor[17] = "HAS_COLORS=";
static char Display_H[16] = "DISPLAYH=";
static char Display_W[16] = "DISPLAYW=";
static void vm_initobjects();
static void vm_setup();
static void on_suspend();
static void sig_catch();
/* static int sig_catch(); abs */
main(argc, argv)
int argc;
char *argv[];
{
register int i, c;
static char mail_template[256] = "/usr/mail/";
token t;
extern char *optarg;
extern int optind;
char *initfile, *commfile, *p, *pidstr;
int labfmt, errflg;
vt_id vid, copyright();
char *itoa(), *estrtok(), *path_to_full();
char *filename(), *getenv(), *strnsave();
void susp_res(), vinterupt(), screen_clean();
time_t time(); /* EFT abs k16 */
extern int vt_redraw();
extern void exit(); /* abs 9/12/88, also removed decl below */
struct actrec *firstar, *wdw_to_ar();
/* LES: optimize malloc(3X) */
if (p = getenv("VMFMLI")) {
Vflag++;
putenv("VMFMLI=false");
}
/* Home assignment moved here from the if-block above,
* because Home not set if VMFMLI is not set and Home
* needed in read_inits()'s in some occasions - jukka.
*/
if ((Home = getenv("HOME")) == NULL)
fatal(MUNGED, "HOME!");
errflg = 0;
Progname = filename(argv[0]);
Aliasfile = initfile = commfile = (char *) NULL;
while ((c = getopt(argc, argv, "i:c:a:")) != EOF) {
switch(c) {
case 'i':
initfile = optarg;
break;
case 'c':
commfile = optarg;
break;
case 'a':
Aliasfile = strsave(optarg);
break;
case '?':
errflg++;
break;
}
}
/*
* Check arguments
*/
if (errflg) {
fprintf(stderr, "usage: %s [-i initfile] [-c commandfile] [-a aliasfile] object ...\n", Progname);
exit(-1); /* this is fmli's exit not the C library call */
}
if (optind == argc) {
fprintf(stderr, "Initial object must be specified\n");
exit(-1); /* this is fmli's exit not the C library call */
}
/*
* check that all objects exist AND that they are readable
*/
if (initfile && access(initfile, 4) < 0) {
errflg++;
fprintf(stderr, "Can't open initialization file \"%s\"\n", initfile);
}
if (commfile && access(commfile, 4) < 0) {
errflg++;
fprintf(stderr, "Can't open commands file \"%s\"\n", commfile);
}
if (Aliasfile && access(Aliasfile, 4) < 0) {
errflg++;
fprintf(stderr, "Can't open alias file \"%s\"\n", Aliasfile);
}
for (i = optind; i < argc; i++) {
if (access(argv[i], 4) < 0) {
errflg++;
fprintf(stderr, "Can't open object \"%s\"\n", argv[i]);
}
}
if (errflg)
exit(-1); /* this is fmli's exit not the C library call */
if (!isatty(fileno(stdin))) {
(void) fprintf(stderr, "Error: stdin is not a terminal\n");
exit(-1);
}
/*
* handle signals
*/
if (p = getenv("DEBUG"))
_Debug = (int) strtol(p, 0, 0);
/* changed signal()'s to sigset()'s.. abs */
if (sigset(SIGINT, SIG_IGN) != SIG_IGN)
sigset(SIGINT, exit); /* fmli's exit not the C library call */
if (sigset(SIGHUP, SIG_IGN) != SIG_IGN)
sigset(SIGHUP, exit); /* fmli's exit not the C library call */
if (sigset(SIGTERM, SIG_IGN) != SIG_IGN)
sigset(SIGTERM, exit); /* fmli's exit not the C library call */
(void) sigset(SIGALRM, sig_catch);
/* for job control: want to reset tty before suspending and.. */
#ifdef SIGTSTP /* .. cleanup after. */
(void) signal(SIGTSTP, on_suspend); /* must be signal not sigset */
#endif
/*
* initialize terminal/screen
*/
labfmt = 0;
if (initfile) {
/*
* Set up SLK layout as 4-4 or 3-2-3 ... This needs
* to be determined BEFORE curses is initialized
* in vt_init.
*/
char *slk_layout, *get_desc_val();
slk_layout = get_desc_val(initfile, LAYOUT_DESC);
if (strcmp(slk_layout, FOURFOUR) == 0)
labfmt = 1;
}
vt_init(labfmt);
onexit(screen_clean);
/*
* indicate in the environment if the terminal we just
* initialized has color capability or not --dmd
* ..also indicate the size of the display area. --abs
*/
if ( has_colors() )
strcat(Fcolor, "true");
else
strcat(Fcolor, "false");
putenv(Fcolor);
strcat(Display_W, itoa((long)COLS, 10)); /* abs k16 */
strcat(Display_H, itoa((long)LINES - RESERVED_LINES, 10)); /* abs k16 */
putenv(Display_W);
putenv(Display_H);
/*
* Read defaults from initialization file
*/
setup_slk_array();
read_inits(initfile);
/*
* set up default banner and working indicator strings ...
* and set color attributes if terminal supports color
*/
/* Changed the order of next two calls.
* First set colors and after it the baner line. mek k17
*/
set_def_colors();
set_def_status();
/*
* Define screen function keys for terminals that do not have
* them defined like att630. mek k17
* Must be After sigset(SIGALRM...). abs k18
*/
init_sfk(TRUE);
/*
* Put up an Introductory Object and the working indicator
*/
vid = copyright();
working(TRUE);
if (vid)
vt_close(vid);
/* remove this ifdef and sigset when i386 sleep(2C) is fixed to reset the
* SIGALRM signal handler. abs k18
*/
#ifdef i386
(void) sigset(SIGALRM, sig_catch); /* copied from above. abs k18 */
#endif
/*
* Initialize command table...
* Read commands from commands file
*/
cmd_table_init();
if (commfile)
read_cmds(commfile);
/*
* Set up FACE globals
*/
if (Vflag)
vm_setup();
else {
/* cannot dereference null ptrs */
Home = nil;
Oasys = nil;
Filesys = nil;
}
/*
* Set mailcheck (use mail_file variable as temp
* variable for MAILCHECK)
*/
Mail_check = 0L;
if (Mail_file = getenv("MAILCHECK"))
Mail_check = (long) atoi(Mail_file);
if (Mail_check == 0L)
Mail_check = 300L;
else
Mail_check = max(Mail_check, 120L);
if ((Mail_file = getenv("MAIL")) == NULL) {
Mail_file = mail_template;
strcat(Mail_file, getenv("LOGNAME"));
}
Cur_time = time((time_t)0L); /* EFT abs k16 */
/*
* Initialize object architecture (SORTMODE)
*/
oh_init();
/*
* set VPID env variable to pid for suspend/resume (SIGUSR1)
* and asynchronous activity (SIGUSR2)
*/
Fmli_pid = getpid();
pidstr = itoa((long)Fmli_pid, 10);
strcat(Vpid, pidstr);
putenv(Vpid);
strcat(Semaphore, pidstr); /* for enhanced asynch coprocs */
/* changed from signal()... abs */
sigset(SIGUSR1, susp_res); /* set sigs for suspend/resume */
sigset(SIGUSR2, vinterupt); /* set sigs for interactive windows */
/*
* Setup windows to be opened upon login
*/
for (i = optind; i < argc; i++) {
objop("OPEN", NULL, p = path_to_full(argv[i]), NULL);
free(p);
ar_ctl(ar_get_current(), CTSETLIFE, AR_INITIAL, NULL, NULL, NULL, NULL, NULL);
}
/*
* make the first window current
*/
if ((argc - optind) >= 1) {
if (firstar = wdw_to_ar(1))
{
/*
* clean-up messages left over by opening initial objects
*/
mess_init(); /* abs k18 */
ar_current(firstar, FALSE); /* abs k15 */
} else {
mess_flush(FALSE);
vt_flush();
sleep(3);
exit(-1); /* fmli's exit not the C library call */
}
}
/*
* Check wastebasket
*/
if (Vflag) {
vm_initobjects();
showmail(TRUE);
}
while ((t = stream(TOK_NOP, Defstream)) != TOK_LOGOUT)
;
exit(0); /* fmli's exit not the C library call */
}
static bool Suspend_allowed = TRUE;
bool
suspset(b)
bool b;
{
bool old = Suspend_allowed;
Suspend_allowed = b;
return(old);
}
long Interupt_pending = 0;
static void
vinterupt(sig)
int sig;
{
(void) sigset(sig, vinterupt); /* changed from signal() abs */
Interupt_pending++;
return;
}
static void
susp_res(sig)
int sig;
{
char buf[BUFSIZ];
pid_t respid; /* EFT abs k16 */
FILE *fp;
char *getepenv();
(void) sigset(sig, susp_res); /* changed from signal abs */
sprintf(buf, "/tmp/suspend%ld", getpid());
if ((fp = fopen(buf, "r")) == NULL) { /* resume failed */
_debug(stderr, "Unable to open resume file\n");
return;
}
(void) unlink(buf);
if (fgets(buf, BUFSIZ, fp) == NULL) {
_debug(stderr, "could not read resume file");
} else {
respid = strtol(buf, (char **)NULL, 0); /* EFT abs k16 */
if (!Suspend_allowed) {
fflush(stdout);
fflush(stderr);
printf("\r\n\nYou are not allowed to suspend at this time.\r\n");
printf("You are in the process of logging out of FACE.\r\n");
printf("Please take steps to end the application program you are\n\r");
printf("currently using.\n\r");
fflush(stdout);
sleep(4);
if (kill(respid, SIGUSR1) == FAIL)
Suspend_interupt = TRUE;
fclose(fp);
return;
}
if (fgets(buf, BUFSIZ, fp) != NULL) {
buf[strlen(buf) - 1] = '\0';
if (buf[0])
Suspend_window = strsave(buf);
else
Suspend_window = NULL;
} else
Suspend_window = NULL;
_debug(stderr, "Resume pid is %d\n", respid);
ar_ctl(ar_get_current(), CTSETPID, respid, NULL, NULL, NULL, NULL, NULL);
}
fclose(fp);
Suspend_interupt = TRUE; /* let wait loop in proc_current know */
return;
}
/* static int changed to void abs 9/12/88 */
static void
sig_catch(n)
int n;
{
/* signal(n, sig_catch);
abs */
sigset(n, sig_catch);
}
static void
pull() /* force various library routines to get pulled in */
{
menu_stream();
actrec_stream();
error_stream();
virtual_stream();
stubs();
indicator();
}
char Opwd[PATHSIZ+5];
extern char *Filecabinet;
extern char *Wastebasket;
static void
vm_setup()
{
static char filecabinet[] = "";
static char wastebasket[] = "/WASTEBASKET";
char *p, *getenv(), *getepenv();
/*
* get/set globals
*/
/* Home not initialized soon enough. Moved up into main(). -bhl */
/*if ((Home = getenv("HOME")) == NULL)
fatal(MUNGED, "HOME!");*/
if ((Filesys = getenv("VMSYS")) == NULL)
fatal(MUNGED, "VMSYS");
if ((Oasys = getenv("OASYS")) == NULL)
fatal(MUNGED, "OASYS");
Filecabinet = strnsave(Home, strlen(Home) + sizeof(filecabinet) - 1);
strcat(Filecabinet, filecabinet);
Wastebasket = strnsave(Home, strlen(Home) + sizeof(wastebasket) - 1);
strcat(Wastebasket, wastebasket);
sprintf(Opwd, "OPWD=%s", Filecabinet);
putenv(Opwd);
if (p = getepenv("UMASK")) /* set file masking */
umask((mode_t) strtol(p, NULL, 8)); /* EFT abs k16 */
}
#define MAX_WCUST (9)
static char Loginwins[] = "LOGINWIN "; /* leave space for a digit */
static void
vm_initobjects()
{
char *p;
register int i;
char *path_to_full(), *getepenv();
struct actrec *prev, *firstobj;
prev = NULL;
firstobj = ar_get_current();
for (i = 1; i <= MAX_WCUST; i++) {
Loginwins[sizeof(Loginwins) - 2] = '0' + i;
if ((p = getepenv(Loginwins)) != NULL && *p) {
p = path_to_full(p);
if (prev) /* aids ordering */
ar_current(prev, FALSE); /* abs k15 */
objop("OPEN", NULL, p, NULL);
if (firstobj != (prev = ar_get_current()))
ar_ctl(prev, CTSETLIFE, AR_PERMANENT, NULL, NULL, NULL, NULL, NULL);
free(p);
ar_current(firstobj, FALSE); /* aids ordering *//*abs k15*/
}
}
/* clean out WASTEBASKET, if needed */
if (p = getepenv("WASTEPROMPT")) {
objop("OPEN", "MENU", strCcmp(p, "yes") ?
"$VMSYS/OBJECTS/Menu.remove" :
"$VMSYS/OBJECTS/Menu.waste", NULL);
free(p);
}
else
objop("OPEN", "MENU", "$VMSYS/OBJECTS/Menu.remove", NULL);
}
/*
* Signal handler for SIGTSTP, the user job control suspend signal.
* Clear the screen and then do the default action for the signal.
* On return, redraw the screen.
*/
#ifdef SIGTSTP
static void
on_suspend(signum)
int signum;
{
if (curses_initialized)
endwin(); /* reset tty to normal */
kill(getpid(), signum);
/* start back here when resumed after job control suspend */
signal(signum, on_suspend); /* reset the signal */
(void) putchar('\0'); /* output something innocent so we will.. */
/* ..suspend on o/p if running in background */
if (curses_initialized)
vt_redraw(); /* refresh the screen */
}
#endif