File: ipc.c

package info (click to toggle)
node 0.3.0a-2woody1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 456 kB
  • ctags: 430
  • sloc: ansic: 3,381; sh: 162; makefile: 101
file content (145 lines) | stat: -rw-r--r-- 3,025 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#include "node.h"

/*
 * This one (c) 1996 by Heikki Hannikainen, OH7LZB <hessu@pspt.fi>
 */

#define FIRST_KEY (3694	- 1)		/* Where to start looking for a key */
#define LAST_KEY (FIRST_KEY + 200) 	/* How far to search */
#define M_LEN 1024			/* Largest message transferred */

struct nmsgbuf {
	long mtype;		/* message type, must be > 0 */
	char mtext[M_LEN];	/* message data */
};

static int ipc_id = -1;

static void usr2_handler(int sig)
{
	struct nmsgbuf buf;
	
	if (msgrcv(ipc_id, (struct msgbuf *)&buf, M_LEN, 0, IPC_NOWAIT|MSG_NOERROR) != -1) {
		node_msg("%s", buf.mtext);
	} else
		log(L_ERROR, "usr2_handler: Catched SIGUSR2, but couldn't receive a message");

	signal(SIGUSR2, usr2_handler); /* Restore handler */
}

int ipc_send(key_t key, long mtype, char *mtext)
{
	struct nmsgbuf buf;
	int id;
	
	if ((id = msgget(key, 7)) == -1) {
		node_perror("ipc_send: Could not get transmit channel", errno);
		return -1;
	}
	
	buf.mtype = mtype;
	strncpy(buf.mtext, mtext, M_LEN);
	
	if (msgsnd(id, (struct msgbuf *)&buf, M_LEN, 0) == -1) {
		node_perror("ipc_send: Could not send message", errno);
		return -1;
	}
	
	return 0;
}

int ipc_open(void)
{
	key_t key = FIRST_KEY;
	
	do {
		key++;
		ipc_id = msgget(key, 7 | IPC_CREAT | IPC_EXCL);
	} while ((ipc_id == -1) && (key != LAST_KEY));

	if (ipc_id == -1)
		node_perror("ipc_open: Could not get an IPC channel", errno);

#if 0
	node_msg("debug: ipc_id=%d key=%d", ipc_id, key);
#endif

	User.ipc_key = key;

	if (key != -1)
		signal(SIGUSR2, usr2_handler);
	else
		signal(SIGUSR2, SIG_IGN);

	return 0;
}

int ipc_close(void)
{
	struct msqid_ds buf;
	
	if (ipc_id != -1)	/* Remove the IPC channel */
		if (msgctl(ipc_id, IPC_RMID, &buf) == -1) {
			log(L_ERROR, "ipc_close: Could not remove IPC channel: %s", strerror(errno));
			return -1;
		}
	return 0;
}

int do_talk(int argc, char **argv)
{
	FILE *f;
	struct user u;
	char call[10];
	char mtext[M_LEN];
	int i, hits = 0, sent = 0;

	if (argc < 3) {
		node_msg("Usage: talk <user> <message>");
		return 0;
	}

	if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) {
		node_perror(DATA_NODE_LOGIN_FILE, errno);
		return 0;
	}
	
	sprintf(mtext, "Message from %s:\n", User.call);
	for (i = 2; i < argc; i++) {
		strncat(mtext, argv[i], M_LEN - strlen(mtext));
		strncat(mtext, " ", M_LEN - strlen(mtext));
	}
	strncat(mtext, "\n--", M_LEN - strlen(mtext));
	
	strncpy(call, argv[1], 9);
	call[9] = 0;

	while (fread(&u, sizeof(u), 1, f) == 1) {
		if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH))
			continue;
		if (!strcasecmp(u.call, call)) {
			hits++;
			if (u.ipc_key != -1 && u.state == STATE_IDLE) {
				ipc_send(u.ipc_key, 1, mtext);
				kill(u.pid, SIGUSR2);
				sent++;
			}
		}
	}
	fclose(f);
	
	if (hits == 0)
		node_msg("No such user %s", call);
	else if (sent == 0)
		node_msg("%s is busy, cannot talk to him right now.", call);

	return 0;
}