~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to clients/upsfetch.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Quette
  • Date: 2004-05-28 13:10:01 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040528131001-yj2m9qcez4ya2w14
Tags: upstream-1.4.2
ImportĀ upstreamĀ versionĀ 1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* upsfetch - library for UPS communications from client programs
2
 
 
3
 
   Copyright (C) 1999  Russell Kroll <rkroll@exploits.org>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
 
*/
19
 
 
20
 
#include "common.h"
21
 
#include <netdb.h>
22
 
#include <netinet/in.h>
23
 
#include <sys/socket.h>
24
 
#include "upsfetch.h"
25
 
#include "timehead.h"
26
 
 
27
 
        int     upserror, syserrno;
28
 
 
29
 
const char *upsstrerror (int errnum)
30
 
{
31
 
        static char     buf[SMALLBUF];
32
 
 
33
 
        buf[0] = '\0';
34
 
 
35
 
        switch (errnum) {
36
 
                case UPSF_UNKNOWN:
37
 
                        return "Unknown error";
38
 
                        break;
39
 
                case UPSF_VARNOTSUPP:
40
 
                        return "Variable not supported by UPS";
41
 
                        break;
42
 
                case UPSF_NOSUCHHOST:
43
 
                        return "No such host";
44
 
                        break;
45
 
                case UPSF_SENDFAILURE:
46
 
                        snprintf (buf, sizeof(buf), "Send failure: %s",
47
 
                                 strerror(syserrno));
48
 
                        break;
49
 
                case UPSF_RECVFAILURE:
50
 
                        snprintf (buf, sizeof(buf), "Receive failure: %s",
51
 
                                 strerror(syserrno));
52
 
                        break;
53
 
                case UPSF_SOCKFAILURE:
54
 
                        snprintf (buf, sizeof(buf), "Socket failure: %s",
55
 
                                 strerror(syserrno));
56
 
                        break;
57
 
                case UPSF_BINDFAILURE:
58
 
                        snprintf (buf, sizeof(buf), "bind failure: %s",
59
 
                                 strerror(syserrno));
60
 
                        break;
61
 
                case UPSF_RECVTIMEOUT:
62
 
                        return "Receive timeout";
63
 
                        break;
64
 
                case UPSF_NOCOMM1:
65
 
                        return "Data source is stale";
66
 
                        break;
67
 
                case UPSF_UNKNOWNUPS:
68
 
                        return "Unknown ups name";
69
 
                        break;
70
 
                case UPSF_ACCESSDENIED:
71
 
                        return "Access denied";
72
 
                        break;
73
 
                case UPSF_CONNFAILURE:
74
 
                        snprintf (buf, sizeof(buf), "Connection failure: %s",
75
 
                                 strerror(syserrno));
76
 
                        break;
77
 
                case UPSF_READERROR:
78
 
                        snprintf (buf, sizeof(buf), "Read error: %s",
79
 
                                 strerror(syserrno));
80
 
                        break;
81
 
                case UPSF_WRITEERROR:
82
 
                        snprintf (buf, sizeof(buf), "Write error: %s",
83
 
                                 strerror(syserrno));
84
 
                        break;
85
 
                case UPSF_INVALIDPW:
86
 
                        return "Invalid password";
87
 
                        break;
88
 
                case UPSF_BADPASSWD:
89
 
                        return "Password incorrect";
90
 
                        break;
91
 
                case UPSF_WRONGVAR:
92
 
                        return "Received wrong variable";
93
 
                        break;
94
 
                case UPSF_UNKNOWNLVL:
95
 
                        return "Unknown level";
96
 
                        break;
97
 
                case UPSF_UNKNOWNCMD:
98
 
                        return "Unknown command";
99
 
                        break;
100
 
                case UPSF_DATASTALE:
101
 
                        return "Data stale";
102
 
                        break;
103
 
                case UPSF_VARUNKNOWN:
104
 
                        return "Variable not recognized by server";
105
 
                        break;
106
 
                default:
107
 
                        snprintf(buf, sizeof(buf), "Unknown error 0x%04x", errnum);
108
 
                        break;
109
 
        }
110
 
 
111
 
        return (buf);
112
 
}
113
 
 
114
 
/* common error condition handler */
115
 
int errcheck (const char *buf)
116
 
{
117
 
        if (!strncmp(buf, "ERR", 3)) {
118
 
                upserror = UPSF_UNKNOWN;                /* default error */
119
 
 
120
 
                if (!strncmp(buf, "ERR ACCESS-DENIED", 17)) 
121
 
                        upserror = UPSF_ACCESSDENIED;
122
 
 
123
 
                if (!strncmp(buf, "ERR UNKNOWN-UPS", 15))
124
 
                        upserror = UPSF_UNKNOWNUPS;
125
 
 
126
 
                if (!strncmp(buf, "ERR INVALID-PASSWORD", 20))
127
 
                        upserror = UPSF_INVALIDPW;
128
 
 
129
 
                if (!strncmp(buf, "ERR PASSWORD-INCORRECT", 22))
130
 
                        upserror = UPSF_INVALIDPW;
131
 
 
132
 
                if (!strncmp(buf, "ERR UNKNOWN-COMMAND", 19))
133
 
                        upserror = UPSF_UNKNOWNCMD;
134
 
 
135
 
                if (!strncmp(buf, "ERR DATA-STALE", 14))
136
 
                        upserror = UPSF_DATASTALE;
137
 
 
138
 
                if (!strncmp(buf, "ERR VAR-NOT-SUPPORTED", 21))
139
 
                        upserror = UPSF_VARNOTSUPP;             
140
 
 
141
 
                if (!strncmp(buf, "ERR VAR-UNKNOWN", 15))
142
 
                        upserror = UPSF_VARUNKNOWN;             
143
 
 
144
 
                if (!strncmp(buf, "ERR CMD-NOT-SUPPORTED", 21))
145
 
                        upserror = UPSF_CMDNOTSUPP;
146
 
 
147
 
                return (-1);
148
 
        }
149
 
 
150
 
        /* legacy failure msg - deprecated */
151
 
        if (!strncmp(buf, "Unknown command", 15)) {
152
 
                upserror = UPSF_UNKNOWNCMD;
153
 
                return (-1);
154
 
        }
155
 
 
156
 
        return 0;
157
 
}
158
 
 
159
 
/* send <req> to <host> and put the answer in <buf> */
160
 
 
161
 
int fetch (const char *hostin, const char *req, char *buf, int buflen)
162
 
{
163
 
        int     res, port = PORT, fd, fromlen, err;
164
 
        struct  sockaddr_in xmit, dest, from;
165
 
        struct  hostent *serv;
166
 
        char    sbuf[LARGEBUF], host[LARGEBUF], *cpos;
167
 
        fd_set  rfd;
168
 
        struct  timeval tv;
169
 
 
170
 
        upserror = UPSF_UNKNOWN;
171
 
 
172
 
        snprintf (host, sizeof(host), "%s", hostin);
173
 
        cpos = strstr (host, ":");
174
 
 
175
 
        if (cpos != NULL) {
176
 
                cpos[0] = 0;
177
 
                port = atoi(++cpos);
178
 
        }
179
 
 
180
 
        if ((serv = gethostbyname(host)) == (struct hostent *) NULL) {
181
 
                upserror = UPSF_NOSUCHHOST;
182
 
                return (-1);
183
 
        }
184
 
 
185
 
        fd = socket (AF_INET, SOCK_DGRAM, 0);
186
 
        if (fd < 0) {
187
 
                upserror = UPSF_SOCKFAILURE;
188
 
                syserrno = errno;
189
 
                return (-1);
190
 
        }
191
 
 
192
 
        memset (&xmit, '\0', sizeof(xmit));
193
 
        xmit.sin_family = AF_INET;
194
 
 
195
 
        res = bind (fd, (struct sockaddr *) &xmit, sizeof(xmit));
196
 
        if (res < 0) {
197
 
                upserror = UPSF_BINDFAILURE;
198
 
                syserrno = errno;
199
 
                close (fd);
200
 
                return (-1);
201
 
        }
202
 
 
203
 
        memset (&dest, '\0', sizeof(dest));
204
 
        memcpy (&dest.sin_addr, serv->h_addr, serv->h_length);
205
 
        dest.sin_family = AF_INET;
206
 
        dest.sin_port = htons(port);
207
 
 
208
 
        snprintf (sbuf, sizeof(sbuf), "%s", req);
209
 
        res = sendto (fd, sbuf, strlen(sbuf), 0, 
210
 
                     (struct sockaddr *) &dest, sizeof(dest));
211
 
 
212
 
        if (res < 0) {
213
 
                syserrno = errno;
214
 
                upserror = UPSF_SENDFAILURE;
215
 
                close (fd);
216
 
                return (-1);    /* failure */
217
 
        }
218
 
 
219
 
        FD_ZERO (&rfd);
220
 
        FD_SET (fd, &rfd);
221
 
        tv.tv_sec = 2;  /* 2.0 seconds allowed for reply */
222
 
        tv.tv_usec = 0;
223
 
 
224
 
        res = select (fd + 1, &rfd, NULL, NULL, &tv);
225
 
 
226
 
        if (res > 0) {
227
 
                memset (buf, '\0', buflen);
228
 
                fromlen = sizeof(from);
229
 
                res = recvfrom (fd, buf, buflen, 0, (struct sockaddr *) &from,
230
 
                                &fromlen);
231
 
        }
232
 
        else {
233
 
                syserrno = errno;
234
 
                upserror = UPSF_RECVTIMEOUT;
235
 
                close (fd);
236
 
                return (-1);    /* failure */
237
 
        }
238
 
 
239
 
        if (res < 0) {
240
 
                syserrno = errno;
241
 
                upserror = UPSF_RECVFAILURE;
242
 
                close (fd);
243
 
                return (-1);    /* failure */
244
 
        }
245
 
 
246
 
        close(fd);
247
 
 
248
 
        if ((err = errcheck(buf)) != 0)
249
 
                return err;
250
 
 
251
 
        upserror = 0;
252
 
        return 1;       /* success */
253
 
}
254
 
 
255
 
/* warn about old upsd quirks, but still handle them for now */
256
 
static void warn_oldupsd(char *tag)
257
 
{
258
 
        fprintf(stderr, "upsfetch: old upsd detected (ANS %s)\n", tag);
259
 
}
260
 
 
261
 
int getupsvar(const char *hostin, const char *varname, char *buf, int buflen)
262
 
{
263
 
        char    cmd[SMALLBUF], tmp[LARGEBUF], *ptr, *host, *upsname, hosttmp[LARGEBUF],
264
 
                vartmp[SMALLBUF];
265
 
        int     ret;
266
 
 
267
 
        /* host = ups-1@localhost */
268
 
 
269
 
        snprintf(hosttmp, sizeof(hosttmp), "%s", hostin);
270
 
        ptr = strstr(hosttmp, "@");
271
 
 
272
 
        if (ptr != NULL) {
273
 
                ptr[0] = 0;
274
 
                upsname = hosttmp;
275
 
                host = ptr + 1;
276
 
                snprintf(cmd, sizeof(cmd), "REQ %s@%s", varname, upsname);
277
 
        }
278
 
        else {
279
 
                upsname = NULL;
280
 
                host = hosttmp;
281
 
                snprintf(cmd, sizeof(cmd), "REQ %s", varname);
282
 
        }
283
 
 
284
 
        ret = fetch(host, cmd, tmp, sizeof(tmp));
285
 
 
286
 
        if (ret != 1)
287
 
                return ret;
288
 
 
289
 
        tmp[strlen(tmp) - 1] = 0;
290
 
 
291
 
        /* ANS <varname> <answer> */
292
 
 
293
 
        /* check variable name for sanity */
294
 
        snprintf(vartmp, sizeof(vartmp), "%s", &tmp[4]);
295
 
        vartmp [strlen(varname)] = 0;
296
 
 
297
 
        if (strcasecmp(vartmp, varname) != 0) {
298
 
                upserror = UPSF_WRONGVAR;
299
 
                return -1;              /* failure */
300
 
        }
301
 
 
302
 
        if (upsname == NULL)            /* skip "ANS <varname> " */
303
 
                ptr = tmp + strlen(varname) + 5;
304
 
        else                            /* skip "ANS <varname>@<upsname> " */
305
 
                ptr = tmp + strlen(varname) + 5 + strlen(upsname) + 1;
306
 
 
307
 
        /* --- legacy stuff for older upsd versions --- */
308
 
 
309
 
        /* old upsd versions returned some errors as ANS <var> <error> */
310
 
 
311
 
        if (!strcmp(ptr, "DATA-STALE")) {
312
 
                warn_oldupsd("DATA-STALE");
313
 
                upserror = UPSF_DATASTALE;
314
 
                return -1;      /* failure */
315
 
        }
316
 
 
317
 
        if (!strcmp(ptr, "NOT-SUPPORTED")) {
318
 
                warn_oldupsd("NOT-SUPPORTED");
319
 
                upserror = UPSF_VARNOTSUPP;
320
 
                return -1;      /* failure */
321
 
        }
322
 
 
323
 
        if (!strcmp(ptr, "UNKNOWN")) {
324
 
                warn_oldupsd("UNKNOWN");
325
 
                upserror = UPSF_VARUNKNOWN;
326
 
                return -1;      /* failure */
327
 
        }
328
 
 
329
 
        if (!strcmp(ptr, "UNKNOWN-UPS")) {
330
 
                warn_oldupsd("UNKNOWN-UPS");
331
 
                upserror = UPSF_UNKNOWNUPS;
332
 
                return -1;      /* failure */
333
 
        }
334
 
 
335
 
        memset(buf, '\0', buflen);
336
 
        strlcpy(buf, ptr, buflen);
337
 
 
338
 
        return ret;
339
 
}
340
 
 
341
 
int getupsvarlist (const char *hostin, char *buf, int buflen)
342
 
{
343
 
        char    tmp[LARGEBUF], *ptr, *upsname, *host, cmd[128], hosttmp[LARGEBUF];
344
 
        int     ret;
345
 
 
346
 
        /* host = ups-1@localhost */
347
 
 
348
 
        snprintf (hosttmp, sizeof(hosttmp), "%s", hostin);
349
 
        ptr = strstr (hosttmp, "@");
350
 
 
351
 
        if (ptr != NULL) {
352
 
                ptr[0] = 0;
353
 
                host = ptr + 1;
354
 
                upsname = hosttmp;
355
 
                snprintf (cmd, sizeof(cmd), "LISTVARS %s", upsname);
356
 
        }
357
 
        else {
358
 
                upsname = NULL;
359
 
                host = hosttmp;
360
 
                snprintf (cmd, sizeof(cmd), "LISTVARS");
361
 
        }
362
 
 
363
 
        ret = fetch (host, cmd, tmp, sizeof(tmp));
364
 
 
365
 
        if (ret != 1)
366
 
                return (ret);
367
 
 
368
 
        /* VARS <varlist> */
369
 
        tmp[strlen(tmp) - 1] = 0;
370
 
 
371
 
        if (upsname == NULL)
372
 
                ptr = tmp + 5;  /* skip "VARS " */
373
 
        else
374
 
                ptr = tmp + 5 + strlen(upsname) + 2;  /* skip "VARS <name> " */
375
 
 
376
 
        memset (buf, '\0', buflen);
377
 
        strlcpy (buf, ptr, buflen);
378
 
 
379
 
        return (ret);
380
 
}
381
 
 
382
 
int upsconnect (const char *hostin)
383
 
{
384
 
        struct  sockaddr_in local, server;
385
 
        struct  hostent *serv;
386
 
        int     fd, port = PORT;
387
 
        char    *cpos, *host;
388
 
 
389
 
        host = xstrdup (hostin);
390
 
        cpos = strstr (host, ":");
391
 
        if (cpos != NULL) {
392
 
                cpos[0] = 0;
393
 
                port = atoi(++cpos);
394
 
        }
395
 
 
396
 
        if ((serv = gethostbyname(host)) == (struct hostent *) NULL) {
397
 
                upserror = UPSF_NOSUCHHOST;
398
 
                return (-1);
399
 
        }
400
 
 
401
 
        if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
402
 
                upserror = UPSF_SOCKFAILURE;
403
 
                syserrno = errno;
404
 
                return (-1);
405
 
        }               
406
 
 
407
 
        memset (&local, '\0', sizeof(struct sockaddr_in));
408
 
        local.sin_family = AF_INET;
409
 
        local.sin_port  = htons (INADDR_ANY);
410
 
 
411
 
        memset (&server, '\0', sizeof(struct sockaddr_in));
412
 
        server.sin_family = AF_INET;
413
 
 
414
 
        server.sin_port = htons (port);
415
 
        memcpy (&server.sin_addr, serv->h_addr, serv->h_length);
416
 
 
417
 
        if (bind (fd, (struct sockaddr *) &local, sizeof(struct sockaddr_in)) == -1) {
418
 
                upserror = UPSF_BINDFAILURE;
419
 
                syserrno = errno;
420
 
                close (fd);
421
 
                return (-1);
422
 
        }
423
 
 
424
 
        if (connect (fd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1) {
425
 
                upserror = UPSF_CONNFAILURE;
426
 
                syserrno = errno;
427
 
                close (fd);
428
 
                return (-1);
429
 
        }
430
 
 
431
 
        return (fd);
432
 
}
433
 
 
434
 
void closeupsfd (int fd)
435
 
{
436
 
        shutdown (fd, 2);
437
 
        close (fd);
438
 
}
439
 
 
440
 
/* read from <fd> until a LF */
441
 
int ups_readline (int fd, char *tmp, int buflen)
442
 
{
443
 
        int     tmpptr = 0, ret;
444
 
        char    ch;
445
 
 
446
 
        for (;;) {
447
 
                ret = read (fd, &ch, 1);
448
 
 
449
 
                if (ret < 1) {
450
 
                        upserror = UPSF_READERROR;
451
 
                        syserrno = errno;
452
 
                        return (ret);
453
 
                }
454
 
 
455
 
                if ((ch == 10) || (tmpptr >= buflen))
456
 
                        return 0;
457
 
 
458
 
                tmp[tmpptr++] = ch;
459
 
        }
460
 
 
461
 
        /* NOTREACHED */
462
 
        return 0;
463
 
}
464
 
 
465
 
int getupsvarlistfd (int fd, const char *upsname, char *buf, int buflen)
466
 
{
467
 
        char    tmp[LARGEBUF], *ptr, cmd[128];
468
 
        int     ret, err;
469
 
 
470
 
        if (upsname == NULL)
471
 
                snprintf (cmd, sizeof(cmd), "LISTVARS\n");
472
 
        else
473
 
                snprintf (cmd, sizeof(cmd), "LISTVARS %s\n", upsname);
474
 
 
475
 
        ret = write (fd, cmd, strlen(cmd));
476
 
 
477
 
        if (ret < 1) {
478
 
                upserror = UPSF_WRITEERROR;
479
 
                syserrno = errno;
480
 
                return (-1);
481
 
        }
482
 
 
483
 
        memset (tmp, '\0', sizeof(tmp));
484
 
 
485
 
        if ((err = ups_readline (fd, tmp, buflen)) != 0)
486
 
                return (err);
487
 
 
488
 
        if ((err = errcheck (tmp)) != 0)
489
 
                return (err);
490
 
 
491
 
        /* VARS <varlist> */
492
 
        if (upsname == NULL)
493
 
                ptr = tmp + 5;  /* skip "VARS " */
494
 
        else
495
 
                ptr = tmp + 5 + strlen(upsname) + 2;  /* skip "VARS <name> " */
496
 
 
497
 
        memset (buf, '\0', buflen);
498
 
        strlcpy (buf, ptr, buflen);
499
 
 
500
 
        return (ret);
501
 
}
502
 
 
503
 
int getupsvarfd (int fd, const char *upsname, const char *varname, char *buf, int buflen)
504
 
{
505
 
        char    cmd[SMALLBUF], tmp[LARGEBUF], *ptr;
506
 
        int     ret, err;
507
 
 
508
 
        if (upsname == NULL)
509
 
                snprintf (cmd, sizeof(cmd), "REQ %s\n", varname);
510
 
        else
511
 
                snprintf (cmd, sizeof(cmd), "REQ %s@%s\n", varname, upsname);
512
 
 
513
 
        ret = write (fd, cmd, strlen(cmd));
514
 
 
515
 
        if (ret < 1) {
516
 
                upserror = UPSF_WRITEERROR;
517
 
                syserrno = errno;
518
 
                return (-1);
519
 
        }
520
 
 
521
 
        memset (tmp, '\0', sizeof(tmp));
522
 
 
523
 
        if ((err = ups_readline (fd, tmp, buflen)) != 0)
524
 
                return (err);
525
 
 
526
 
        if ((err = errcheck (tmp)) != 0)
527
 
                return (err);
528
 
 
529
 
        /* ANS <varname> <answer> */
530
 
 
531
 
        if (upsname == NULL)            /* skip "ANS <varname> " */
532
 
                ptr = tmp + strlen(varname) + 5;
533
 
        else                            /* skip "ANS <varname>@<upsname> " */
534
 
                ptr = tmp + strlen(varname) + 5 + strlen(upsname) + 1;
535
 
 
536
 
        /* --- legacy stuff for older upsd versions --- */
537
 
 
538
 
        /* old upsd versions returned some errors as ANS <var> <error> */
539
 
 
540
 
        if (!strcmp(ptr, "DATA-STALE")) {
541
 
                warn_oldupsd("DATA-STALE");
542
 
                upserror = UPSF_DATASTALE;
543
 
                return -1;      /* failure */
544
 
        }
545
 
 
546
 
        if (!strcmp(ptr, "NOT-SUPPORTED")) {
547
 
                warn_oldupsd("NOT-SUPPORTED");
548
 
                fprintf(stderr, "upsfetch: old upsd detected! (ANS NOT-SUPPORTED)\n");
549
 
                upserror = UPSF_VARNOTSUPP;
550
 
                return -1;      /* failure */
551
 
        }
552
 
 
553
 
        if (!strcmp(ptr, "UNKNOWN-UPS")) {
554
 
                warn_oldupsd("UNKNOWN-UPS");
555
 
                upserror = UPSF_UNKNOWNUPS;
556
 
                return (-1);    /* failure */
557
 
        }
558
 
 
559
 
        memset(buf, '\0', buflen);
560
 
        strlcpy(buf, ptr, buflen);
561
 
 
562
 
        return ret;
563
 
}
564
 
 
565
 
/* send a raw buffer to upsd with basic error checking */
566
 
int upssendraw(int fd, const char *cmd)
567
 
{
568
 
        int     ret;
569
 
 
570
 
        upserror = UPSF_UNKNOWN;
571
 
 
572
 
        ret = write(fd, cmd, strlen(cmd));
573
 
 
574
 
        if (ret < 1) {
575
 
                upserror = UPSF_WRITEERROR;
576
 
                syserrno = errno;
577
 
                return -1;
578
 
        }
579
 
 
580
 
        upserror = 0;
581
 
        return 1;               /* success */
582
 
}
583
 
 
584
 
/* read a response from upsd with basic error checking */
585
 
int upsreadraw(int fd, char *buf, int buflen)
586
 
{
587
 
        char    tmp[SMALLBUF];
588
 
        int     err;
589
 
 
590
 
        memset(tmp, '\0', sizeof(tmp));
591
 
 
592
 
        if ((err = ups_readline(fd, tmp, sizeof(tmp))) != 0)
593
 
                return err;
594
 
 
595
 
        if ((err = errcheck(tmp)) != 0)
596
 
                return err;
597
 
 
598
 
        strlcpy(buf, tmp, buflen);
599
 
 
600
 
        upserror = 0;
601
 
        return 1;       /* success */
602
 
}
603