nwrite.c
flamer at omsvax.UUCP
flamer at omsvax.UUCP
Sat Aug 13 02:04:59 AEST 1983
/* Program: nwrite.
* Author: Jim Earenluindil Trethewey.
* Version: 2.08 (VAX edition).
* Index: CSD246.
* Date: 27-Apr-1983.
* Last-edit: 08-Jul-1983.
* Language: C.
* Ppn: /rl2/cs414/trethewe.
* For: CS 416, Operating Systems III, Toshi Minoura.
* Oregon State University, Corvallis, Oregon.
*
* This is a UNIX multi-user interprocess communications (IPC) program.
*
* This module, nwrite.c, contains the program procedures.
*
* This program has a few flaws:
*
* 1. It is pretty slow. It should really only be run on a VAX
* or on a PDP-11 with few users.
* 2. The method used for writer-lock semaphores is strange.
* It would be nicer if the operating system had global
* sense-switches (like in COBOL, except all processes
* can see them), or other elegant P/V mechanism.
* 3. It uses the Berkeley extended signal set, not available
* in standard Version 7 UNIX. This makes it less portable.
* Also, work is going on at UCB to make nicer IPC features,
* which will require major program revisions when they are
* introduced.
* 4. The maximum number of users per conversation is limited to
* the maximum files allowed open on your system minus 3. For
* example, our file tables only allow 20 simultaneously open
* files: 17 talkers + stdin + stdout + stderr.
* The program can be rewritten so that this is not a factor
* (send_message = open + write + close for each talker) but
* this makes it slower.
*
* If you want to send flames or suggestions, here's how to find me:
*
* Jim Trethewey Jim Trethewey
* 2458 NE Kathryn St. Intel Corporation
* Hillsboro, OR 97123 OMO Engineering
* phone: 503-648-0697 Mail Stop HF2-2-243
* 5200 NE Elam Young Pkwy.
* Hillsboro, OR 97123
* phone: 503-640-5444
* uucp: ...!tektronix!ogcvax!omsvax!flamer
* ...!hp-pcd!ogcvax!omsvax!flamer
*
*/
#include "nwrite.h"
/*
* main: program mainline.
*/
main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
analyze (argc, argv);
environ = envp;
set_up ();
while (!done)
{
eval_input ();
}
restore_tty_context ();
}
/*
* add_mfrec: add a new person and master file record.
*/
add_mfrec ()
{
open_master ("a");
mfd.conversation = conversation;
strcpy (mfd.person, my_name);
strcpy (mfd.location, my_tty);
ascii_time ();
strcpy (mfd.time_on, current_time);
write_master ();
fclose (f_master);
}
/*
* analyze: look at argc and argv, see if OK and determine the
* lead-in character for 'tilde escapes'.
*/
analyze (argc, argv)
int argc;
char *argv [];
{
int byte;
if (argc > 1)
{
*argv++;
byte = 0;
while ((byte < 2) && ((*argv) [byte] == pattern [byte]))
{
byte++;
}
if ((byte == 2) && ((*argv) [byte] != NULL))
{
lead_in = (*argv) [byte];
}
else
{
lead_in = TILDE;
}
}
else
{
lead_in = TILDE;
}
}
/*
* ascii_time: get current time as ascii string CTIME(3).
*/
ascii_time ()
{
long clock;
char *t_clock;
char a_clock [26];
time (&clock);
t_clock = ctime (&clock);
strncpy (a_clock, t_clock, 24);
a_clock [24] = NULL;
strcpy (current_time, a_clock);
}
/*
* back_up: erase a character from the screen.
*/
back_up ()
{
if (isprint (line [column]) || isspace (line [column]))
{
force (ERASE);
if (writing)
{
send_message (ERASE);
}
}
column--;
}
/*
* call_up: call another person to talk to.
*/
call_up ()
{
parse_request ();
if (*callee != NULL)
{
lookup_callee_on_system ();
}
if (can_call)
{
mfd_search ();
if (conversation != NO)
{
if (was_found && (found_conversation == conversation))
{
printf ("? Already in this conversation.\n");
}
else
{
ring_ring ();
}
}
else
{
if (was_found)
{
conversation = found_conversation;
enter_conference ();
ascii_time ();
strcpy (current_time, current_time);
open_talk_files ();
sprintf (message, "\n%c[Just joined: %s on %s at %s]\n",
BEEP, my_name, my_tty, current_time);
printf ("[Joining conversation %d]\n", conversation);
send_message (message);
close_talk_files ();
}
else
{
choose_conversation ();
enter_conference ();
ring_ring ();
}
}
}
}
/*
* choose_conversation: grab the first free conversation number.
*/
choose_conversation ()
{
int taken;
load_mfd ();
conversation = 0;
taken = YES;
while (taken)
{
conversation++;
taken = NO;
for (ptr = t_o_s; ptr != NULL; ptr = ptr->next)
{
if (ptr->record.conversation == conversation)
{
taken = YES;
}
}
}
}
/*
* close_talk_files: close all conversation message files.
*/
close_talk_files ()
{
int i;
for (i = 1; i <= n_open_files; i++)
{
fclose (out_file [i]);
}
}
/*
* delete_mfrec: leave nwrite and get rid of master record entry.
*/
delete_mfrec ()
{
load_mfd ();
ptr_1 = t_o_s;
ptr_2 = ptr_1;
while (ptr_1 != NULL)
{
if (!strcmp (ptr_1->record.location, my_tty))
{
if (t_o_s != ptr_1)
{
ptr_2->next = ptr_1->next;
free (ptr_1);
ptr_1 = ptr_2->next;
}
else
{
t_o_s = ptr_1->next;
free (ptr_1);
ptr_1 = t_o_s;
ptr_2 = ptr_1;
}
}
else
{
if (t_o_s != ptr_1)
{
ptr_1 = ptr_1->next;
ptr_2 = ptr_2->next;
}
else
{
ptr_1 = ptr_1->next;
}
}
}
store_mfd ();
}
/*
* enter_conference: go into a conversation.
*/
enter_conference ()
{
load_mfd ();
for (ptr = t_o_s; ptr != NULL; ptr = ptr->next)
{
if (!strcmp (ptr->record.location, my_tty))
{
ptr->record.conversation = conversation;
ascii_time ();
strcpy (ptr->record.time_on, current_time);
}
}
store_mfd ();
}
/*
* eval_input: terminal char interrupt... what command is it?
*/
eval_input ()
{
column = position (0);
ch = getc (stdin);
while (ch == EOF)
{
ch = getc (stdin);
}
if (ch == lead_in)
{
tilde_escape ();
}
else
{
switch (ch)
{
case TILDE: tilde_escape ();
break;
case ESCAPE: over ();
break;
case CTRL(D): printf ("^D\r\n");
quit ();
break;
case '!': shell_escape ();
break;
case '?': help ();
break;
default: text_process ();
break;
}
}
fflush (stdout);
}
/*
* force: display message even if noecho set.
*/
force (message)
char message [];
{
printf ("%s", message);
}
/*
* get_line: get a complete line from the terminal.
*/
get_line ()
{
while ((ch != CRLF) &&
(ch != CTRL(D)) &&
(ch != ESCAPE) &&
(column > position (0)))
{
ch = getc (stdin);
while (ch == EOF)
{
ch = getc (stdin);
if (timed_out)
{
ch = CRLF;
timed_out = NO;
}
}
if (writing)
{
alarm (dead_man);
}
show_char (ch);
}
if (writing)
{
if (ch == CTRL(D))
{
quit ();
}
else if (ch == ESCAPE)
{
printf ("\r");
over ();
}
}
if (ch == CRLF)
{
line [column + 1] = NULL;
}
}
/*
* hang_up: exit from a conversation.
*/
hang_up ()
{
if (conversation != NO)
{
ascii_time ();
open_talk_files ();
sprintf (message, "\n[over and out: %s on %s at %s]\n",
my_name, my_tty, current_time);
force (message);
send_message (message);
close_talk_files ();
conversation = NO;
load_mfd ();
for (ptr = t_o_s; ptr != NULL; ptr = ptr->next)
{
if (!strcmp (ptr->record.location, my_tty))
{
ptr->record.conversation = NO;
}
}
store_mfd ();
}
else
{
printf ("? You aren't in a conversation to hang up from.\n");
}
}
/*
* help: show the list of valid commands.
*/
help ()
{
show_char (ch);
get_line ();
if (column != position (0))
{
help_text ();
printf ("?\n\n");
}
}
/*
* help_text: this is the actual list of valid nwrite commands.
*/
help_text ()
{
printf ("-----------------------------------------------------------------------\n");
printf ("nwrite v%4.2f as of %s\n", version, as_of);
printf ("\n");
printf ("%cc [<user_name> [<tty_name>]]\n", lead_in);
printf (" Call <user_name> on <tty_name> for conversation.\n");
printf ("%ce Toggle echo-plex on/off (for half-duplex tty's).\n", lead_in);
printf ("%ch Hang up: leave a conversation (\"over and out\").\n", lead_in);
printf ("%co Send \"over\" and relinquish write control.\n", lead_in);
printf ("%cq Quit nwrite.\n", lead_in);
printf ("%cw Who is in which conversations?\n", lead_in);
printf ("<escape> Like %co but works in-line.\n", lead_in);
printf ("^D Like %cq but works in-line.\n", lead_in);
printf ("? Print this help list.\n");
printf ("![<command>] Invoke subshell, optionally with <command>.\n");
printf ("<text> Attempt to get write control, send <text> in conversation.\n");
printf ("-----------------------------------------------------------------------\n");
}
/*
* id_me: find out my login_name and tty.
*/
id_me ()
{
if (!isatty (TTY))
{
printf ("? You shouldn't redirect standard input for nwrite.\n");
done = YES;
}
strcpy (my_name, getlogin ());
if (*my_name == NULL)
{
printf ("? You don't exist. Go away!\n");
done = YES;
}
strcpy (my_devtty, ttyname (TTY));
strcpy (my_tty, rindex (my_devtty, '/') + 1);
if (stat (my_devtty, &stat_buf) < 0)
{
printf ("? Can't find logical device for your tty.\n");
done = YES;
}
if (!(stat_buf.st_mode & S_OWRITE))
{
printf ("? You have write permission turned off.\n");
done = YES;
}
}
/*
* init_tty_context: set tty mode to that convenient for nwriting.
*/
init_tty_context ()
{
new_tty = old_tty;
new_tty.sg_flags |= CBREAK;
new_tty.sg_flags &= ~ECHO;
ioctl (TTY, TIOCSETP, &new_tty);
new_ltchars = old_ltchars;
new_lmodes = old_lmodes | LPENDIN | LINTRUP | LTOSTOP;
ioctl (TTY, TIOCLSET, &new_lmodes);
sigset (SIGALRM, time_out);
sigset (SIGTSTP, please_no);
sigset (SIGINT, please_no);
sigset (SIGQUIT, please_no);
sigset (SIGSTOP, please_no);
sigset (SIGHUP, SIG_IGN);
sigset (SIGPIPE, SIG_IGN);
sigset (SIGTINT, SIG_IGN);
sigset (SIGTTOU, SIG_IGN);
sigset (SIGTTIN, SIG_IGN);
}
/*
* load_mfd: build a linked_list of mfd records for manipulation.
*/
load_mfd ()
{
open_master ("r");
if (f_master != NULL)
{
t_o_s = NULL;
read_master ();
while (n != f_EOF)
{
ptr_2 = (struct mct_node *) malloc (sizeof (struct mct_node));
ptr_2->record.conversation = mfd.conversation;
strcpy (ptr_2->record.person, mfd.person);
strcpy (ptr_2->record.location, mfd.location);
strcpy (ptr_2->record.time_on, mfd.time_on);
ptr_2->next = NULL;
if (t_o_s == NULL)
{
t_o_s = ptr_2;
ptr_1 = t_o_s;
}
else
{
ptr_1->next = ptr_2;
ptr_1 = ptr_1->next;
}
read_master ();
}
fclose (f_master);
}
}
/*
* lookup_callee_on_system: look in /etc/utmp for callee and get his_tty.
*/
lookup_callee_on_system ()
{
int tty_specified;
f_utmp = fopen (h_utmp, "r");
match_tty = NO;
logged_on = NO;
if (*his_tty == NULL)
{
tty_specified = NO;
}
else
{
tty_specified = YES;
}
n = fread (&ubuf, sizeof ubuf, 1, f_utmp);
while (n != f_EOF)
{
name_match = !strncmp (ubuf.ut_name, callee, strlen (callee));
if (name_match)
{
if (*his_tty != NULL)
{
if (!match_tty)
{
match_tty = !strncmp (ubuf.ut_line, his_tty, strlen (his_tty));
}
}
else
{
strcpy (his_tty, ubuf.ut_line);
match_tty = YES;
}
logged_on++;
}
n = fread (&ubuf, sizeof ubuf, 1, f_utmp);
}
fclose (f_utmp);
can_call = NO;
if (!logged_on)
{
printf ("? %s is not logged in.\n", callee);
}
else
{
if (!match_tty)
{
printf ("? %s is not on %s.\n", callee, his_tty);
}
else if ((logged_on == 1) || tty_specified)
{
can_call = YES;
}
else
{
printf ("? %s is logged on more than once... please specify tty.\n", callee);
}
}
}
/*
* mfd_search: is the callee currently running nwrite?
*/
mfd_search ()
{
was_found = NO;
load_mfd ();
for (ptr = t_o_s; (ptr != NULL) && !was_found; ptr = ptr->next)
{
if (!strcmp (callee, ptr->record.person) &&
!strcmp (his_tty, ptr->record.location) &&
(ptr->record.conversation != NO))
{
was_found = YES;
found_conversation = ptr->record.conversation;
}
}
}
/*
* open_master: open the master file.
*/
open_master (mode)
char mode [];
{
f_master = fopen (h_mfd, mode);
if (f_master == NULL)
{
printf ("? Can't open conversation master file %s.\n", h_mfd);
}
}
/*
* open_talk_files: open conversation message files.
*/
open_talk_files ()
{
load_mfd ();
n_open_files = 0;
for (ptr = t_o_s; ptr != NULL; ptr = ptr->next)
{
if ((ptr->record.conversation == conversation) &&
strcmp (ptr->record.location, my_tty))
{
strcat (strcpy (f_devtty, h_tty), ptr->record.location);
f_otty = fopen (f_devtty, "w");
if (f_otty != NULL)
{
n_open_files++;
out_file [n_open_files] = f_otty;
}
}
}
}
/*
* over: I'm done with this message, relinquish write control.
*/
over ()
{
if (writing)
{
ascii_time ();
sprintf (message, "\n[over: %s on %s at %s]\n\n",
my_name, my_tty, current_time);
force (message);
send_message (message);
close_talk_files ();
alarm (0);
V (conversation);
}
else
{
printf ("? You don't have write control, you can't \"over\".\n");
}
}
/*
* P: lock myself as conversation writer (a pseudo-semaphore).
* Actually, the file <c_file> is linked to a user temp file.
*/
P (conversation)
int conversation;
{
char c_file [40];
int link_error;
sprintf (c_file, h_conv, conversation);
link_error = link (tmp_file, c_file);
if (!link_error)
{
writing = YES;
}
}
/*
* page_confirm: handle SIGTTOU signal.
*/
page_confirm ()
{
if (debug)
{
printf ("<<< page_confirm >>>\n");
}
}
/*
* parse_request: strip out arguments of the ~c command.
*/
parse_request ()
{
char word_1 [40], word_2 [40];
int i, j;
i = 0;
while (!isspace (line [i]) && (line [i] != NULL))
{
i++;
}
while (isspace (line [i]) && (line [i] != NULL))
{
i++;
}
j = 0;
while (!isspace (line [i]) && (line [i] != NULL))
{
word_1 [j++] = line [i++];
}
word_1 [j] = NULL;
while (isspace (line [i]) && (line [i] != NULL))
{
i++;
}
j = 0;
while (!isspace (line [i]) && (line [i] != NULL))
{
word_2 [j++] = line [i++];
}
word_2 [j] = NULL;
if (*word_1 != NULL)
{
if (*word_2 != NULL)
{
strcpy (his_tty, word_2);
}
else
{
if (strcmp (callee, word_1))
{
*his_tty = NULL;
}
}
strcpy (callee, word_1);
}
if (*callee == NULL)
{
printf ("? Call who?\n");
}
}
/*
* please_no: ask user not to use interrupt signals, etc.
*/
please_no ()
{
printf ("\n%cPlease %cuse %c^D %cto %cexit %cnwrite!\n",
BEEP, BEEP, BEEP, BEEP, BEEP, BEEP);
}
/*
* position: point to the i'th character in a string.
*/
position (i)
int i;
{
return (i - 1);
}
/*
* print_header: look official.
*/
print_header ()
{
printf ("\nnwrite v%4.2f\n", version);
printf ("%s\n", myname);
printf ("Type ? for help.\n");
}
/*
* quit: leave nwrite, go back to the shell.
*/
quit ()
{
if (writing)
{
over ();
}
if (conversation != NO)
{
hang_up ();
}
printf ("[Leaving nwrite]\n");
done = YES;
delete_mfrec ();
unlink (tmp_file);
sleep (1);
}
/*
* read_master: get a master_control_table record.
*/
read_master ()
{
n = fread (&mfd, sizeof mfd, 1, f_master);
}
/*
* read_pipe: get reader control flag from child process.
*/
read_pipe ()
{
int ctrl_flag;
read (ctrl_pipe [0], &ctrl_flag, 2);
return (ctrl_flag);
}
/*
* receive_message: if someone sends us a message, display it.
*/
receive_message ()
{
ch = getc (f_tty);
if (ch != EOF)
{
putc (ch, stdout);
fflush (stdout);
}
}
/*
* restore_tty_context: put tty modes back as they were.
*/
restore_tty_context ()
{
ioctl (TTY, TIOCSETP, &old_tty);
ioctl (TTY, TIOCLSET, &old_lmodes);
sigset (SIGALRM, SIG_DFL);
}
/*
* ring_ring: hello? are you there? I want to talk to you.
*/
ring_ring ()
{
char p_file [40];
char m_file [40];
strcat (strcpy (p_file, h_tty), his_tty);
f_pager = fopen (p_file, "w");
if (f_pager != NULL)
{
ascii_time ();
fprintf (f_pager, "\n%c%cMessage from: %s on %s at %s...\n",
BEEP, BEEP, my_name, my_tty, current_time);
fprintf (f_pager, "Use nwrite to respond.\n");
printf ("[Message sent to: %s on %s at %s]\n",
callee, his_tty, current_time);
fclose (f_pager);
}
else
{
printf ("[User %s on %s has write protection turned on...\n",
callee, his_tty);
sprintf (m_file, "mail %s", callee);
f_mail = popen (m_file, "w");
if (f_mail != NULL)
{
ascii_time ();
fprintf (f_mail, "\n%c%cMessage from: %s on %s at %s...\n",
BEEP, BEEP, my_name, my_tty, current_time);
fprintf (f_mail, "Use nwrite to respond.\n");
fclose (f_mail);
printf (" ...sent mail at %s]\n", current_time);
}
else
{
printf (" ...couldn't send mail either]\n");
}
}
}
/*
* save_tty_context: remember current tty modes so we can restore later.
*/
save_tty_context ()
{
ioctl (TTY, TIOCGETP, &old_tty);
ioctl (TTY, TIOCGLTC, &old_ltchars);
ioctl (TTY, TIOCLGET, &old_lmodes);
}
/*
* send_message: send the message to all receivers in conversation.
*/
send_message (message)
char message [];
{
int i;
for (i = 1; i <= n_open_files; i++)
{
fprintf (out_file [i], "%s", message);
fflush (out_file [i]);
}
}
/*
* set_up: lots of initialization.
*/
set_up ()
{
echo = YES;
done = NO;
print_header ();
printf ("\n");
save_tty_context ();
init_tty_context ();
id_me ();
conversation = NO;
timed_out = NO;
writing = NO;
*callee = NULL;
*his_tty = NULL;
if (!done)
{
add_mfrec ();
strcpy (tmp_file, mktemp (h_temp));
creat (tmp_file, MODE);
}
}
/*
* shell_escape: perform a shell command or invoke a subshell.
*/
shell_escape ()
{
int pid;
char *csh;
if (writing)
{
over ();
}
show_char (ch);
get_line ();
if (column != position (0))
{
restore_tty_context ();
pid = fork ();
if (pid == -1)
{
printf ("? Can't fork.\n");
}
else if (pid != 0)
{
while (wait (0) != pid)
{
/* spin in a tight loop */;
}
}
else
{
setuid (getuid ());
csh = getenv ("SHELL");
if (*csh == NULL)
{
csh = sh;
}
if (column == position (1))
{
execle (csh, "-", 0, environ);
}
else
{
execle (csh, &csh[4], "-c", &line[position (2)], 0, environ);
}
exit (0);
}
init_tty_context ();
printf ("!\n\n");
}
}
/*
* show_char: we typed something; show it.
*/
show_char (ch)
char ch;
{
if (isprint (ch) || isspace (ch))
{
if (echo)
{
putc (ch, stdout);
fflush (stdout);
}
else if ((ch == CRLF) && !echo)
{
printf ("\n");
}
if (writing)
{
sprintf (message, "%c", ch);
send_message (message);
}
column++;
line [column] = ch;
}
else
{
if (ch == old_tty.sg_erase)
{
if (!echo)
{
force (" ");
}
back_up ();
}
else if (ch == old_ltchars.t_werasc)
{
while (isspace (line [column]) && (column != position (0)))
{
back_up ();
}
while (!isspace (line [column]) &&
(isprint (line [column])) &&
(column != position (0)))
{
back_up ();
}
}
else if (ch == old_tty.sg_kill)
{
while (column != position (0))
{
back_up ();
}
}
else if (ch == CTRL(D))
{
printf ("^D\n");
}
}
}
/*
* store_mfd: we tweaked master records, now put them back.
*/
store_mfd ()
{
open_master ("w");
if (f_master != NULL)
{
ptr_1 = t_o_s;
while (ptr_1 != NULL)
{
mfd.conversation = ptr_1->record.conversation;
strcpy (mfd.person, ptr_1->record.person);
strcpy (mfd.location, ptr_1->record.location);
strcpy (mfd.time_on, ptr_1->record.time_on);
write_master ();
ptr_2 = ptr_1;
ptr_1 = ptr_1->next;
free (ptr_2);
}
fflush (f_master);
fclose (f_master);
}
}
/*
* text_process: try to get write control and/or send text message.
*/
text_process ()
{
if (writing)
{
show_char (ch);
get_line ();
}
else
{
if (conversation == NO)
{
printf ("? You haven't called anyone yet.\n");
}
else
{
P (conversation);
if (writing)
{
open_talk_files ();
ascii_time ();
sprintf (message, "\n[From: %s on %s at %s]\n",
my_name, my_tty, current_time);
send_message (message);
printf ("[you have write control of conversation %d]\n",
conversation);
show_char (ch);
alarm (dead_man);
get_line ();
}
}
}
}
/*
* tilde_escape: a tilde was typed, which command does he want?
*/
tilde_escape ()
{
show_char (ch);
get_line ();
if (column != position (0))
{
if (column == position (1))
{
ch = line [position (1)];
}
else
{
ch = line [position (2)];
}
switch (ch)
{
case 'c': call_up ();
break;
case 'e': toggle_echo ();
break;
case 'h': hang_up ();
break;
case 'o': over ();
break;
case 'q': quit ();
break;
case 'w': who ();
break;
default: printf ("? Invalid tilde escape. Type ? for help.\n");
break;
}
printf ("%c\n\n", lead_in);
}
}
/*
* time_out: take away write control if you're a terminal hog.
*/
time_out ()
{
if (writing)
{
ascii_time ();
sprintf (message, "\n%c[%d second time out: %s on %s at %s]\n",
BEEP, dead_man, my_name, my_tty, current_time);
force (message);
send_message (message);
V (conversation);
timed_out = YES;
}
}
/*
* toggle_echo: change echo/noecho (for half duplex tty's).
*/
toggle_echo ()
{
if (echo)
{
printf ("[Echo now OFF]\n");
}
else
{
printf ("[Echo now ON]\n");
}
echo = !echo;
}
/*
* trapse_list: print linked list for debugging purposes.
*/
trapse_list ()
{
struct mct_node *ptr;
printf ("=============================================================\n");
printf ("Conv Person Location Time On\n");
printf ("-------------------------------------------------------------\n");
for (ptr = t_o_s; ptr != NULL; ptr = ptr->next)
{
printf ("%3d %-12s %-12s %24s\n", ptr->record.conversation,
ptr->record.person, ptr->record.location, ptr->record.time_on);
}
printf ("=============================================================\n");
}
/*
* V: unlock write control (a pseudo-semaphore).
* Actually, the file <c_file> is unlinked from a user temp file.
*/
V (conversation)
int conversation;
{
char c_file [40];
writing = NO;
sprintf (c_file, h_conv, conversation);
unlink (c_file);
}
/*
* who: who is running nwrite, and what conversations are they in?
*/
who ()
{
load_mfd ();
printf ("Conversation User Where Talking since\n");
printf ("-----------------------------------------------------------------\n");
for (ptr = t_o_s; ptr != NULL; ptr = ptr->next)
{
if (ptr->record.conversation == 0)
{
printf (" -");
}
else
{
printf (" %3d", ptr->record.conversation);
}
printf (" %-8s %-8s %-25s\n",
ptr->record.person, ptr->record.location, ptr->record.time_on);
}
}
/*
* write_master: write a master_control_table record.
*/
write_master ()
{
int tries;
tries = 1;
n = fwrite (&mfd, sizeof mfd, 1, f_master);
while ((n < 1) && (tries < 10))
{
if (debug)
{
printf ("<<< failure to write master record. >>>\n");
}
tries++;
n = fwrite (&mfd, sizeof mfd, 1, f_master);
}
}
/*
* write_pipe: send the reader control flag to parent process.
*/
write_pipe (ctrl_flag)
int ctrl_flag;
{
write (ctrl_pipe [1], &ctrl_flag, 2);
}
More information about the Comp.sources.unix
mailing list