source: rtems/c/src/libnetworking/pppd/chat.c @ 2f1b930

4.104.114.84.95
Last change on this file since 2f1b930 was 2f1b930, checked in by Joel Sherrill <joel.sherrill@…>, on 08/16/01 at 20:42:09

2001-08-16 Mike Siers <mikes@…>

  • Update of PPPD to 2.3.11 from 2.3.5 and addition of an example application. Mike's notes on the modifications:
    • renamed error() function because of namespace problems
    • removed calls to the exit() funciton
    • removed extra files from the pppd source directory
    • defined pppd task constant values in rtemspppd.h
    • modifyied example code to get actual tick per second value
    • placed the pppd 2.3.11 man page file (pppd.8) into the pppd directory
  • pppd/cbcp.c, pppd/cbcp.h, pppd/main.c, pppd/ppp_tty.c, pppd/pppmain.c, pppd/rtems-ppp.c, pppd/rtems-ppp.c: Deleted.
  • pppd/pppd.8, pppd/rtemsmain.c, pppd/rtemspppd.c, pppd/rtemspppd.h, pppd/sys-rtems.c, pppd/utils.c, pppd/example/Makefile, pppd/example/README, pppd/example/init.c, pppd/example/netconfig.h, pppd/example/ppp.conf, pppd/example/pppdapp.c, pppd/example/system.h: New files.
  • modem/ppp_tty.c, net/if_ppp.h, pppd/Makefile.am, pppd/README, pppd/STATUS, pppd/auth.c, pppd/ccp.c, pppd/ccp.h, pppd/chap.c, pppd/chap.h, pppd/chap_ms.c, pppd/chap_ms.h, pppd/chat.c, pppd/demand.c, pppd/fsm.c, pppd/fsm.h, pppd/ipcp.c, pppd/ipcp.h, pppd/ipxcp.c, pppd/ipxcp.h, pppd/lcp.c, pppd/lcp.h, pppd/magic.c, pppd/magic.h, pppd/options.c, pppd/patchlevel.h, pppd/pathnames.h, pppd/pppd.h, pppd/upap.c, pppd/upap.h: Modified.
  • Property mode set to 100644
File size: 17.4 KB
Line 
1/*
2 *      Chat -- a program for automatic session establishment (i.e. dial
3 *              the phone and log in).
4 *
5 * Standard termination codes:
6 *  0 - successful completion of the script
7 *  1 - invalid argument, expect string too large, etc.
8 *  2 - error on an I/O operation or fatal error condition.
9 *  3 - timeout waiting for a simple string.
10 *  4 - the first string declared as "ABORT"
11 *  5 - the second string declared as "ABORT"
12 *  6 - ... and so on for successive ABORT strings.
13 *
14 *      This software is in the public domain.
15 *
16 * -----------------
17 *      added -T and -U option and \T and \U substitution to pass a phone
18 *      number into chat script. Two are needed for some ISDN TA applications.
19 *      Keith Dart <kdart@cisco.com>
20 *     
21 *
22 *      Added SAY keyword to send output to stderr.
23 *      This allows to turn ECHO OFF and to output specific, user selected,
24 *      text to give progress messages. This best works when stderr
25 *      exists (i.e.: pppd in nodetach mode).
26 *
27 *      Added HANGUP directives to allow for us to be called
28 *      back. When HANGUP is set to NO, chat will not hangup at HUP signal.
29 *      We rely on timeouts in that case.
30 *
31 *      Added CLR_ABORT to clear previously set ABORT string. This has been
32 *      dictated by the HANGUP above as "NO CARRIER" (for example) must be
33 *      an ABORT condition until we know the other host is going to close
34 *      the connection for call back. As soon as we have completed the
35 *      first stage of the call back sequence, "NO CARRIER" is a valid, non
36 *      fatal string. As soon as we got called back (probably get "CONNECT"),
37 *      we should re-arm the ABORT "NO CARRIER". Hence the CLR_ABORT command.
38 *      Note that CLR_ABORT packs the abort_strings[] array so that we do not
39 *      have unused entries not being reclaimed.
40 *
41 *      In the same vein as above, added CLR_REPORT keyword.
42 *
43 *      Allow for comments. Line starting with '#' are comments and are
44 *      ignored. If a '#' is to be expected as the first character, the
45 *      expect string must be quoted.
46 *
47 *
48 *              Francis Demierre <Francis@SwissMail.Com>
49 *              Thu May 15 17:15:40 MET DST 1997
50 *
51 *
52 *      Added -r "report file" switch & REPORT keyword.
53 *              Robert Geer <bgeer@xmission.com>
54 *
55 *      Added -s "use stderr" and -S "don't use syslog" switches.
56 *              June 18, 1997
57 *              Karl O. Pinc <kop@meme.com>
58 *
59 *
60 *      Added -e "echo" switch & ECHO keyword
61 *              Dick Streefland <dicks@tasking.nl>
62 *
63 *
64 *      Considerable updates and modifications by
65 *              Al Longyear <longyear@pobox.com>
66 *              Paul Mackerras <paulus@cs.anu.edu.au>
67 *
68 *
69 *      The original author is:
70 *
71 *              Karl Fox <karl@MorningStar.Com>
72 *              Morning Star Technologies, Inc.
73 *              1760 Zollinger Road
74 *              Columbus, OH  43221
75 *              (614)451-1883
76 *
77 *
78 */
79
80#ifndef lint
81/* static char rcsid[] = ""; */
82#endif
83
84#include <stdio.h>
85#include <ctype.h>
86#include <time.h>
87#include <fcntl.h>
88#include <signal.h>
89#include <errno.h>
90#include <string.h>
91#include <stdlib.h>
92#include <unistd.h>
93#include <sys/types.h>
94#include <sys/stat.h>
95#include <syslog.h>
96
97#undef  TERMIOS
98#define TERMIOS
99
100
101#include <termios.h>
102
103#define STR_LEN 1024
104char temp2[STR_LEN];
105
106#ifndef SIGTYPE
107#define SIGTYPE void
108#endif
109
110#undef __P
111#undef __V
112
113#ifdef __STDC__
114#include <stdarg.h>
115#define __V(x)  x
116#define __P(x)  x
117#else
118#include <varargs.h>
119#define __V(x)  (va_alist) va_dcl
120#define __P(x)  ()
121#define const
122#endif
123
124#ifndef O_NONBLOCK
125#define O_NONBLOCK      O_NDELAY
126#endif
127
128
129/*************** Micro getopt() *********************************************/
130#define OPTION(c,v)     (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
131                                (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
132                                &&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
133#define OPTARG(c,v)     (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
134                                (_O=4,(char*)0):(char*)0)
135#define OPTONLYARG(c,v) (_O&2&&**v?(_O=1,--c,*v++):(char*)0)
136#define ARG(c,v)        (c?(--c,*v++):(char*)0)
137
138#if 0
139static int _O = 0;              /* Internal state */
140#endif
141/*************** Micro getopt() *********************************************/
142
143char *program_name;
144
145#define MAX_ABORTS              5
146#define MAX_REPORTS             5
147#define DEFAULT_CHAT_TIMEOUT    45
148#define fcntl(a, b,c ) 0
149#define MAX_TIMEOUTS 10
150
151int echo          = 0;
152int verbose       = 0;
153int to_log        = 1;
154int to_stderr     = 0;
155int Verbose       = 0;
156int quiet         = 0;
157int report        = 0;
158int exit_code     = 0;
159char *report_file = (char *) 0;
160char *chat_file   = (char *) 0;
161char *phone_num   = (char *) 0;
162char *phone_num2  = (char *) 0;
163int chat_timeout       = DEFAULT_CHAT_TIMEOUT;
164static int timeout       = DEFAULT_CHAT_TIMEOUT;
165int have_tty_parameters = 0;
166
167#ifdef TERMIOS
168#define term_parms struct termios
169#define get_term_param(param) tcgetattr(ttyfd, param)
170#define set_term_param(param) tcsetattr(ttyfd, TCSANOW, param)
171struct termios saved_tty_parameters;
172#endif
173
174char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ASWER","RINGING\r\n\r\nRINGING"};
175char *fail_reason = (char *)0,
176        fail_buffer[50];
177int n_aborts = MAX_ABORTS, abort_next = 0, timeout_next = 0, echo_next = 0;
178int clear_abort_next = 0;
179
180char *report_string[MAX_REPORTS] ;
181char  report_buffer[50] ;
182int n_reports = 0, report_next = 0, report_gathering = 0 ;
183int clear_report_next = 0;
184
185int say_next = 0, hup_next = 0;
186
187void *dup_mem __P((void *b, size_t c));
188void *copy_of __P((char *s));
189/*
190SIGTYPE sigalrm __P((int signo));
191SIGTYPE sigint __P((int signo));
192SIGTYPE sigterm __P((int signo));
193SIGTYPE sighup __P((int signo));
194*/
195void unalarm __P((void));
196void init __P((void));
197void set_tty_parameters __P((void));
198void echo_stderr __P((int));
199void break_sequence __P((void));
200void terminate __P((int status));
201void do_file __P((char *chat_file));
202int  get_string __P((register char *string));
203int  put_string __P((register char *s));
204int  write_char __P((int c));
205int  put_char __P((int c));
206int  get_char __P((void));
207void chat_send __P((register char *s));
208char *character __P((int c));
209void chat_expect __P((register char *s));
210char *clean __P((register char *s, int sending));
211void break_sequence __P((void));
212void terminate __P((int status));
213void pack_array __P((char **array, int end));
214char *expect_strtok __P((char *, char *));
215int vfmtmsg __P((char *, int, const char *, va_list));  /* vsprintf++ */
216
217#if 0
218int usleep( long usec );                                  /* returns 0 if ok, else -1 */
219#endif
220   
221extern int input_fd,output_fd;
222
223int main __P((int, char *[]));
224
225void *dup_mem(b, c)
226void *b;
227size_t c;
228{
229    void *ans = malloc (c);
230    if (!ans)
231                return NULL;
232
233    memcpy (ans, b, c);
234    return ans;
235}
236
237void *copy_of (s)
238char *s;
239{
240    return dup_mem (s, strlen (s) + 1);
241}
242
243/*
244 * chat [ -v ] [-T number] [-U number] [ -t timeout ] [ -f chat-file ] \
245 * [ -r report-file ] \
246 *              [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
247 *
248 *      Perform a UUCP-dialer-like chat script on stdin and stdout.
249 */
250char *getnextcommand(char **string)
251{
252        char *buf=*string,*res;
253        res=strchr(buf,'@');
254        if (res==NULL)
255                return NULL;
256        *res='\0';
257        *string=res+1;
258        return buf;
259}
260
261 
262extern int ttyfd;
263int chatmain(argv)
264char *argv;
265{
266  char    *arg;
267
268  /* initialize exit code */
269  exit_code = 0;
270
271printf("chat_main: %s\n", argv);
272
273  /* get first expect string */
274  arg = getnextcommand(&argv);
275  while ( arg != NULL ) {
276    /* process the expect string */
277    chat_expect(arg);
278
279    /* get the next send string */
280    arg = getnextcommand(&argv);
281    if ( arg != NULL ) {
282      /* process the send string */
283      chat_send(arg);
284
285      /* get the next expect string */
286      arg = getnextcommand(&argv);
287    }
288  }
289
290  return 0;
291}
292
293
294
295/*
296 *      Print an error message and terminate.
297 */
298
299void init()
300{
301    set_tty_parameters();
302}
303
304void set_tty_parameters()
305{
306    term_parms t;
307
308        if (get_term_param (&t) < 0)
309                syslog(LOG_NOTICE,"Can't get terminal parameters:")
310                ;
311       
312    saved_tty_parameters = t;
313    have_tty_parameters  = 1;
314    t.c_iflag     |= IGNBRK | ISTRIP | IGNPAR;
315    t.c_oflag      = 0;
316    t.c_lflag      = 0;
317    t.c_cc[VERASE] =
318    t.c_cc[VKILL]  = 0;
319    t.c_cc[VMIN]   = 0;
320    t.c_cc[VTIME]  = 1;
321    if (set_term_param (&t) < 0)
322                syslog(LOG_NOTICE,"Can't set terminal parameters:")
323                ;
324}
325
326void break_sequence()
327{
328
329/*    tcsendbreak (0, 0);*/
330}
331
332/*void terminate(status)
333int status;
334{
335    echo_stderr(-1);
336
337    if (have_tty_parameters) {
338        if (set_term_param (&saved_tty_parameters) < 0)
339            fatal(2, "Can't restore terminal parameters: %m");
340    }
341}
342*/
343/*
344 *      'Clean up' this string.
345 */
346char *clean(s, sending)
347register char *s;
348int sending;  /* set to 1 when sending (putting) this string. */
349{
350    char temp[STR_LEN], cur_chr;
351    register char *s1, *phchar;
352    int add_return = sending;
353#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
354
355    s1 = temp;
356    while (*s) {
357        cur_chr = *s++;
358        if (cur_chr == '^') {
359            cur_chr = *s++;
360            if (cur_chr == '\0') {
361                *s1++ = '^';
362                break;
363            }
364            cur_chr &= 0x1F;
365            if (cur_chr != 0) {
366                *s1++ = cur_chr;
367            }
368            continue;
369        }
370
371        if (cur_chr != '\\') {
372            *s1++ = cur_chr;
373            continue;
374        }
375
376        cur_chr = *s++;
377        if (cur_chr == '\0') {
378            if (sending) {
379                *s1++ = '\\';
380                *s1++ = '\\';
381            }
382            break;
383        }
384
385        switch (cur_chr) {
386        case 'b':
387            *s1++ = '\b';
388            break;
389
390        case 'c':
391            if (sending && *s == '\0')
392                add_return = 0;
393            else
394                *s1++ = cur_chr;
395            break;
396
397        case '\\':
398        case 'K':
399        case 'p':
400        case 'd':
401            if (sending)
402                *s1++ = '\\';
403
404            *s1++ = cur_chr;
405            break;
406
407        case 'T':
408            if (sending && phone_num) {
409                for ( phchar = phone_num; *phchar != '\0'; phchar++)
410                    *s1++ = *phchar;
411            }
412            else {
413                *s1++ = '\\';
414                *s1++ = 'T';
415            }
416            break;
417
418        case 'U':
419            if (sending && phone_num2) {
420                for ( phchar = phone_num2; *phchar != '\0'; phchar++)
421                    *s1++ = *phchar;
422            }
423            else {
424                *s1++ = '\\';
425                *s1++ = 'U';
426            }
427            break;
428
429        case 'q':
430            quiet = 1;
431            break;
432
433        case 'r':
434            *s1++ = '\r';
435            break;
436
437        case 'n':
438            *s1++ = '\n';
439            break;
440
441        case 's':
442            *s1++ = ' ';
443            break;
444
445        case 't':
446            *s1++ = '\t';
447            break;
448
449        case 'N':
450            if (sending) {
451                *s1++ = '\\';
452                *s1++ = '\0';
453            }
454            else
455                *s1++ = 'N';
456            break;
457           
458        default:
459            if (isoctal (cur_chr)) {
460                cur_chr &= 0x07;
461                if (isoctal (*s)) {
462                    cur_chr <<= 3;
463                    cur_chr |= *s++ - '0';
464                    if (isoctal (*s)) {
465                        cur_chr <<= 3;
466                        cur_chr |= *s++ - '0';
467                    }
468                }
469
470                if (cur_chr != 0 || sending) {
471                    if (sending && (cur_chr == '\\' || cur_chr == 0))
472                        *s1++ = '\\';
473                    *s1++ = cur_chr;
474                }
475                break;
476            }
477
478            if (sending)
479                *s1++ = '\\';
480            *s1++ = cur_chr;
481            break;
482        }
483    }
484
485    if (add_return)
486        *s1++ = '\r';
487
488    *s1++ = '\0'; /* guarantee closure */
489    *s1++ = '\0'; /* terminate the string */
490    return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
491}
492
493/*
494 * A modified version of 'strtok'. This version skips \ sequences.
495 */
496
497char *expect_strtok (s, term)
498     char *s, *term;
499{
500    static  char *str   = "";
501    int     escape_flag = 0;
502    char   *result;
503
504/*
505 * If a string was specified then do initial processing.
506 */
507    if (s)
508        str = s;
509
510/*
511 * If this is the escape flag then reset it and ignore the character.
512 */
513    if (*str)
514        result = str;
515    else
516        result = (char *) 0;
517
518    while (*str) {
519        if (escape_flag) {
520            escape_flag = 0;
521            ++str;
522            continue;
523        }
524
525        if (*str == '\\') {
526            ++str;
527            escape_flag = 1;
528            continue;
529        }
530
531/*
532 * If this is not in the termination string, continue.
533 */
534        if (strchr (term, *str) == (char *) 0) {
535            ++str;
536            continue;
537        }
538
539/*
540 * This is the terminator. Mark the end of the string and stop.
541 */
542        *str++ = '\0';
543        break;
544    }
545    return (result);
546}
547
548/*
549 * Process the expect string
550 */
551
552void   chat_expect (s)
553char *s;
554{
555    char *expect;
556    char *reply;
557
558    if (strcmp(s, "HANGUP") == 0) {
559        ++hup_next;
560        return ;
561    }
562 
563    if (strcmp(s, "ABORT") == 0) {
564        ++abort_next;
565        return ;
566    }
567
568    if (strcmp(s, "CLR_ABORT") == 0) {
569        ++clear_abort_next;
570        return ;
571    }
572
573    if (strcmp(s, "REPORT") == 0) {
574        ++report_next;
575        return ;
576    }
577
578    if (strcmp(s, "CLR_REPORT") == 0) {
579        ++clear_report_next;
580        return ;
581    }
582
583    if (strcmp(s, "TIMEOUT") == 0) {
584        ++timeout_next;
585        return ;
586    }
587
588    if (strcmp(s, "ECHO") == 0) {
589        ++echo_next;
590        return ;
591    }
592
593    if (strcmp(s, "SAY") == 0) {
594        ++say_next;
595        return ;
596    }
597
598/*
599 * Fetch the expect and reply string.
600 */
601    for (;;) {
602        expect = expect_strtok (s, "-");
603        s      = (char *)0 ;
604
605        if (expect == (char *) 0)
606            return ;
607
608        reply = expect_strtok (s, "-");
609
610/*
611 * Handle the expect string. If successful then exit.
612 */
613        if (get_string (expect))
614            return;
615
616/*
617 * If there is a sub-reply string then send it. Otherwise any condition
618 * is terminal.
619 */
620        if (reply == (char *) 0 || exit_code != 3)
621            break;
622
623        chat_send (reply);
624    }
625
626/*
627 * The expectation did not occur. This is terminal.
628 */
629    return ;
630}
631
632/*
633 *  process the reply string
634 */
635void chat_send (s)
636register char *s;
637{
638    if (say_next) {
639        say_next = 0;
640        s = clean(s,0);
641        write(ttyfd, s, strlen(s));
642        free(s);
643        return;
644    }
645
646    if (hup_next) {
647        hup_next = 0;
648    }
649
650    if (echo_next) {
651        echo_next = 0;
652        echo = (strcmp(s, "ON") == 0);
653        return;
654    }
655
656    if (abort_next) {
657        /* char *s1; */
658       
659       
660           ;
661       
662
663        return;
664    }
665
666    if (timeout_next) {
667        timeout=atoi(s);
668        timeout_next = 0;
669        chat_timeout = atoi(s);
670       
671        if (chat_timeout <= 0)
672            chat_timeout = DEFAULT_CHAT_TIMEOUT;
673
674
675        return;
676    }
677    if (strcmp(s, "EOT") == 0)
678        s = "^D\\c";
679    else if (strcmp(s, "BREAK") == 0)
680        s = "\\K\\c";
681
682    if (!put_string(s))
683            {
684              exit_code=1;
685              return;
686            }
687}
688
689int get_char()
690{
691    int status;
692    char c;
693    int tries=MAX_TIMEOUTS;
694
695        while(tries)
696        {
697            status = read(ttyfd, &c, 1);
698            switch (status) {
699                   case 1:
700                                return ((int)c & 0x7F);
701                    default:
702                                tries--;                       
703            }
704    }
705        return -1;                                             
706}
707
708int put_char(c)
709int c;
710{
711    int status;
712    char ch = c;
713
714        /* inter-character typing delay (?) */
715
716    status = write(ttyfd, &ch, 1);
717
718    switch (status) {
719    case 1:
720        return (0);
721       
722    default:
723       
724       
725    }
726  return 0;
727}
728
729int write_char (c)
730int c;
731{
732    if (put_char(c) < 0) {
733        return (0);
734    }
735    return (1);
736}
737
738int put_string (s)
739register char *s;
740{
741    quiet = 0;
742    s = clean(s, 1);
743    while (*s) {
744        register char c = *s++;
745
746        if (c != '\\') {
747            if (!write_char (c))
748                return 0;
749            continue;
750        }
751
752        c = *s++;
753        switch (c) {
754        case 'd':
755            sleep(1);
756            break;
757
758        case 'K':
759            break_sequence();
760            break;
761
762        case 'p':
763#if 0 /* FIXME!!! */
764            usleep(10000);      /* 1/100th of a second (arg is microseconds) */
765#else
766            sleep(1);
767#endif
768            break;
769
770        default:
771            if (!write_char (c))
772                return 0;
773            break;
774        }
775    }
776
777   /* alarm(0);*/
778    return (1);
779}
780
781/*
782 *      Echo a character to stderr.
783 *      When called with -1, a '\n' character is generated when
784 *      the cursor is not at the beginning of a line.
785 */
786void echo_stderr(n)
787int n;
788{
789/*    static int need_lf;
790    char *s;
791
792    switch (n) {
793    case '\r':           
794        break;
795    case -1:
796        if (need_lf == 0)
797            break;
798 
799    case '\n':
800        write(2, "\n", 1);
801        need_lf = 0;
802        break;
803    default:
804        s = character(n);
805        write(2, s, strlen(s));
806        need_lf = 1;
807        break;
808    }*/
809}
810
811/*
812 *      'Wait for' this string to appear on this file descriptor.
813 */
814
815int get_string(string)
816register char *string;
817{
818    int c, len, minlen;
819    register char *s = temp2, *end = s + STR_LEN;
820    char *logged = temp2;
821    struct termios tios;
822
823    tcgetattr(ttyfd, &tios);
824    tios.c_cc[VMIN] = 0;
825    tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
826    tcsetattr(ttyfd, TCSANOW, &tios);
827               
828    string = clean(string, 0);
829    len = strlen(string);
830    minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
831       
832    if (len > STR_LEN) {
833        exit_code = 1;
834        return 0;
835    }
836
837    if (len == 0) {
838                        return (1);
839    }
840
841
842   while ( (c = get_char()) >= 0) {
843                int n, abort_len;
844
845        *s++ = c;
846        *s=0;
847       
848        if (s - temp2 >= len &&
849            c == string[len - 1] &&
850            strncmp(s - len, string, len) == 0) {
851            return (1);
852        }
853
854        for (n = 0; n < n_aborts; ++n) {
855            if (s - temp2 >= (abort_len = strlen(abort_string[n])) &&
856                strncmp(s - abort_len, abort_string[n], abort_len) == 0) {
857
858                exit_code = n + 4;
859                strcpy(fail_reason = fail_buffer, abort_string[n]);
860                return (0);
861            }
862        }
863
864        if (s >= end) {
865            if (logged < s - minlen) {
866                logged = s;
867            }
868            s -= minlen;
869            memmove(temp2, s, minlen);
870            logged = temp2 + (logged - s);
871            s = temp2 + minlen;
872        }
873    }
874    exit_code = 3;
875    return (0);
876}
877
878/*
879 * Gross kludge to handle Solaris versions >= 2.6 having usleep.
880 */
881
882/*
883  usleep -- support routine for 4.2BSD system call emulations
884  last edit:  29-Oct-1984     D A Gwyn
885  */
886
887
888#if 0
889int
890usleep( usec )                            /* returns 0 if ok, else -1 */
891    long                usec;           /* delay in microseconds */
892{
893  rtems_status_code status;
894  rtems_interval    ticks_per_second;
895  rtems_interval    ticks;
896  status = rtems_clock_get(
897    RTEMS_CLOCK_GET_TICKS_PER_SECOND,
898    &ticks_per_second);
899    ticks = (usec * (ticks_per_second/1000))/1000;
900    status = rtems_task_wake_after( ticks );
901  return 0;
902}
903#endif
904
905void pack_array (array, end)
906    char **array; /* The address of the array of string pointers */
907    int    end;   /* The index of the next free entry before CLR_ */
908{
909    int i, j;
910
911    for (i = 0; i < end; i++) {
912        if (array[i] == NULL) {
913            for (j = i+1; j < end; ++j)
914                if (array[j] != NULL)
915                    array[i++] = array[j];
916            for (; i < end; ++i)
917                array[i] = NULL;
918            break;
919        }
920    }
921}
922
923/*
924 * vfmtmsg - format a message into a buffer.  Like vsprintf except we
925 * also specify the length of the output buffer, and we handle the
926 * %m (error message) format.
927 * Doesn't do floating-point formats.
928 * Returns the number of chars put into buf.
929 */
930#define OUTCHAR(c)      (buflen > 0? (--buflen, *buf++ = (c)): 0)
Note: See TracBrowser for help on using the repository browser.