]>
Commit | Line | Data |
---|---|---|
a0223729 GB |
1 | /* |
2 | zsend.c simple zephyr sender | |
3 | Copyright (C) 1994 Darrell Kindred | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 | ||
19 | */ | |
20 | ||
21 | #include <strings.h> | |
22 | #include <stdio.h> | |
23 | #include <sys/types.h> | |
24 | #include <ctype.h> | |
25 | #include <zephyr/zephyr.h> | |
26 | #include <zephyr/zephyr_err.h> | |
27 | #include <netdb.h> | |
28 | #include <sys/socket.h> | |
29 | #include <sys/wait.h> | |
30 | #include <netinet/in.h> | |
31 | #include <arpa/inet.h> | |
32 | #include <sys/file.h> | |
33 | #include <signal.h> | |
34 | #include <string.h> | |
35 | #include <time.h> | |
36 | ||
37 | #define DEFAULT_CLASS "MESSAGE" | |
38 | #define DEFAULT_INSTANCE "PERSONAL" | |
39 | #define URGENT_INSTANCE "URGENT" | |
40 | #define DEFAULT_OPCODE "" | |
41 | #define FILSRV_CLASS "FILSRV" | |
42 | #ifdef CMU_INTERREALM | |
43 | #define DEFAULT_REALM "ANDREW.CMU.EDU" | |
44 | #endif | |
45 | ||
46 | extern Code_t ZCancelSubscriptions(), ZUnsetLocation(), ZClosePort(), | |
47 | //ZRetrieveSubscriptions(), | |
48 | ZGetSubscriptions(), ZSubscribeTo(), | |
49 | ZSendNotice(), ZInitialize(), ZOpenPort(), ZPending(), | |
50 | ZCompareUID(), ZReceiveNotice(), ZCheckAuthentication(), | |
51 | ZFreeNotice(), ZSetLocation(); | |
52 | #ifdef CMU_INTERREALM | |
53 | extern char *ZExpandRealm(); | |
54 | #endif | |
55 | ||
56 | typedef struct PendingReply PendingReply; | |
57 | struct PendingReply { | |
58 | char *instance; | |
59 | char *recipient; | |
60 | ZUnique_Id_t uid; | |
61 | PendingReply *next; | |
62 | }; | |
63 | ||
64 | struct Globals { | |
65 | const char *program; | |
66 | int argc; | |
67 | const char **argv; | |
68 | ||
69 | u_short port; | |
70 | int zfd; | |
71 | ||
72 | int debug; | |
73 | ||
74 | /* linked list of messages sent which are waiting for replies */ | |
75 | PendingReply *pending_replies; | |
76 | ||
77 | }; | |
78 | ||
79 | struct Globals global_storage, *globals = &global_storage; | |
80 | ||
81 | void usage(const char *progname) { | |
82 | fprintf(stderr, "usage: %s [options] [recipients]\n", progname); | |
83 | fprintf(stderr, " options:\n"); | |
84 | fprintf(stderr, " -i <inst> use instance <inst>\n"); | |
85 | fprintf(stderr, " -c <class> use class <class>\n"); | |
86 | #ifdef CMU_INTERREALM | |
87 | fprintf(stderr, " -r <realm> use realm <realm>\n"); | |
88 | #endif | |
89 | fprintf(stderr, " -s <sig> use signature <sig>\n"); | |
90 | fprintf(stderr, " -S <sender> use sender <sender>\n"); | |
91 | fprintf(stderr, " -O <opcode> use opcode <opcode>\n"); | |
92 | fprintf(stderr, " -m <msg> send msg instead of reading stdin (must be last arg)\n"); | |
93 | fprintf(stderr, " -d print debugging information\n"); | |
94 | } | |
95 | ||
96 | void exit_tzc() { | |
97 | ZClosePort(); | |
98 | exit(0); | |
99 | } | |
100 | ||
101 | Code_t check(Code_t e, char *s) { | |
102 | if (e) { | |
103 | printf(";;; return code %d\n",(int) e); | |
104 | fflush(stdout); | |
105 | com_err(__FILE__, e, s); | |
106 | exit(1); | |
107 | } | |
108 | return e; | |
109 | } | |
110 | ||
111 | Code_t warn(Code_t e, char *s) { | |
112 | if (e) | |
113 | com_err(__FILE__, e, s); | |
114 | return e; | |
115 | } | |
116 | ||
117 | char *auth_string(int n) { | |
118 | switch (n) { | |
119 | case ZAUTH_YES : return "yes"; | |
120 | case ZAUTH_FAILED : return "failed"; | |
121 | case ZAUTH_NO : return "no"; | |
122 | default : return "bad-auth-value"; | |
123 | } | |
124 | } | |
125 | ||
126 | char *kind_string(int n) { | |
127 | switch (n) { | |
128 | case UNSAFE: return "unsafe"; | |
129 | case UNACKED: return "unacked"; | |
130 | case ACKED: return "acked"; | |
131 | case HMACK: return "hmack"; | |
132 | case HMCTL: return "hmctl"; | |
133 | case SERVACK: return "servack"; | |
134 | case SERVNAK: return "servnak"; | |
135 | case CLIENTACK: return "clientack"; | |
136 | case STAT: return "stat"; | |
137 | default: return "bad-kind-value"; | |
138 | } | |
139 | } | |
140 | ||
141 | /* warning: this uses ctime which returns a pointer to a static buffer | |
142 | * which is overwritten with each call. */ | |
143 | char *time_str(time_t time_num) | |
144 | { | |
145 | char *now_name; | |
146 | now_name = ctime(&time_num); | |
147 | now_name[24] = '\0'; /* dump newline at end */ | |
148 | return(now_name); | |
149 | } | |
150 | ||
151 | /* return time in the format "14:15:03" */ | |
152 | /* uses ctime, which returns a ptr to a static buffer */ | |
153 | char *debug_time_str(time_t time_num) | |
154 | { | |
155 | char *now_name; | |
156 | now_name = ctime(&time_num); | |
157 | now_name[19] = '\0'; /* strip year */ | |
158 | return now_name+11; /* strip date */ | |
159 | } | |
160 | ||
161 | void | |
162 | setup() | |
163 | { | |
164 | check(ZInitialize(), "ZInitialize"); | |
165 | globals->port = 0; | |
166 | check(ZOpenPort(&globals->port), "ZOpenPort"); | |
167 | ||
168 | globals->pending_replies = NULL; | |
169 | } | |
170 | ||
171 | int get_message(char **msg, char *sig) { | |
172 | /* XXX fix this to be dynamic */ | |
173 | static char buf[65535]; | |
174 | int c, len; | |
175 | char *p; | |
176 | strcpy(buf, sig); | |
177 | len = strlen(sig)+1; | |
178 | p = &(buf[len]); | |
179 | while ((c=getchar()) != EOF) { | |
180 | *p++ = c; | |
181 | len++; | |
182 | } | |
183 | len++; | |
184 | *p = '\0'; | |
185 | *msg = buf; | |
186 | return len; | |
187 | } | |
188 | ||
189 | int get_message_arg(char **msg, char *msgptr, char *sig) { | |
190 | /* XXX fix this to be dynamic */ | |
191 | static char buf[65535]; | |
192 | int c, len; | |
193 | int i = 0; | |
194 | char *p; | |
195 | strcpy(buf, sig); | |
196 | len = strlen(sig)+1; | |
197 | strcpy(&buf[len], msgptr); | |
198 | len += strlen(msgptr)+1; | |
199 | *msg = buf; | |
200 | return len; | |
201 | } | |
202 | ||
203 | int main(int argc, const char *argv[]) { | |
204 | const char *program; | |
205 | const char **recipient; | |
206 | char *msg; | |
207 | int broadcast, msglen; | |
208 | int n_recips = 0; | |
209 | int (*auth)(); | |
210 | int use_zctl = 0, sw; | |
211 | int havemsg = 0; | |
212 | int haverealm = 0; | |
213 | extern char *optarg; | |
214 | extern int optind; | |
215 | char location[BUFSIZ]; | |
216 | ZNotice_t notice; | |
217 | int retval; | |
218 | char *sender=NULL, *signature="", *instance=DEFAULT_INSTANCE, | |
219 | *class=DEFAULT_CLASS, *opcode=DEFAULT_OPCODE, *msgptr=""; | |
220 | #ifdef CMU_INTERREALM | |
221 | char *realm=DEFAULT_REALM; | |
222 | char rlmrecip[BUFSIZ]; | |
223 | char *cp; | |
224 | #endif | |
225 | ||
226 | program = strrchr(argv[0], '/'); | |
227 | if (program == NULL) | |
228 | program = argv[0]; | |
229 | else | |
230 | program++; | |
231 | ||
232 | while ((sw = getopt(argc, argv, "di:s:c:S:m:O:r:")) != EOF) | |
233 | switch (sw) { | |
234 | case 'O': | |
235 | opcode = optarg; | |
236 | break; | |
237 | case 'i': | |
238 | instance = optarg; | |
239 | break; | |
240 | case 'c': | |
241 | class = optarg; | |
242 | break; | |
243 | case 's': | |
244 | signature = optarg; | |
245 | break; | |
246 | case 'S': | |
247 | sender = optarg; | |
248 | break; | |
249 | case 'd': | |
250 | /* debug = 1; */ | |
251 | break; | |
252 | #ifdef CMU_INTERREALM | |
253 | case 'r': | |
254 | realm = optarg; | |
255 | haverealm = 1; | |
256 | break; | |
257 | #endif | |
258 | case 'm': | |
259 | msgptr = optarg; | |
260 | havemsg = 1; | |
261 | break; | |
262 | case '?': | |
263 | default: | |
264 | usage(program); | |
265 | exit(1); | |
266 | } | |
267 | ||
268 | broadcast = (optind == argc); | |
269 | ||
270 | if (broadcast && !(strcmp(class, DEFAULT_CLASS) || | |
271 | (strcmp(instance, DEFAULT_INSTANCE) && | |
272 | strcmp(instance, URGENT_INSTANCE)))) { | |
273 | /* must specify recipient if using default class and | |
274 | (default instance or urgent instance) */ | |
275 | fprintf(stderr, "No recipients specified.\n"); | |
276 | usage(program); | |
277 | exit(1); | |
278 | } | |
279 | ||
280 | if(havemsg) | |
281 | msglen = get_message_arg(&msg, msgptr, signature); | |
282 | else | |
283 | msglen = get_message(&msg, signature); | |
284 | ||
285 | setup(); | |
286 | ||
287 | for ( ; broadcast || optind < argc; optind++) { | |
288 | bzero((char *) ¬ice, sizeof(notice)); | |
289 | ||
290 | notice.z_kind = UNACKED; | |
291 | notice.z_port = 0; | |
292 | notice.z_class = class; | |
293 | notice.z_opcode = opcode; | |
294 | notice.z_sender = sender; | |
295 | notice.z_class_inst = instance; | |
296 | #ifdef CMU_INTERREALM | |
297 | if (!broadcast && (cp = strchr(argv[optind], '@'))) { | |
298 | (void) strcpy(rlmrecip, argv[optind]); | |
299 | cp = strchr(rlmrecip, '@'); | |
300 | if (cp) { | |
301 | cp++; | |
302 | (void) strcpy(cp, (char *) ZExpandRealm(cp)); | |
303 | } | |
304 | notice.z_recipient = rlmrecip; | |
305 | } else if(haverealm) { | |
306 | rlmrecip[0] = '@'; | |
307 | (void) strcpy(&rlmrecip[1], (char *) ZExpandRealm(realm)); | |
308 | notice.z_recipient = rlmrecip; | |
309 | } else | |
310 | #endif | |
311 | notice.z_recipient = (char *) (broadcast ? "" : argv[optind]); | |
312 | notice.z_message = msg; | |
313 | notice.z_message_len = msglen; | |
314 | notice.z_default_format = "@bold(UNAUTHENTIC) Class $class, Instance $instance:\n$message"; | |
315 | auth = ZNOAUTH; | |
316 | if (auth == ZAUTH) { | |
317 | notice.z_default_format = "Class $class, Instance $instance:\nTo: @bold($recipient)\n$message"; | |
318 | } | |
319 | if ((retval = ZSendNotice(¬ice, auth)) != ZERR_NONE) { | |
320 | #if 1 | |
321 | char bfr[BUFSIZ]; | |
322 | (void) sprintf(bfr, "while sending notice to %s", | |
323 | notice.z_recipient); | |
324 | com_err(__FILE__, retval, bfr); | |
325 | #endif | |
326 | fprintf(stderr, "error %d from ZSendNotice while sending to %s\n", | |
327 | retval, notice.z_recipient); | |
328 | exit(1); | |
329 | } | |
330 | if (broadcast) | |
331 | break; | |
332 | } | |
333 | exit(0); | |
334 | } |