/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 825 by stargo, Wed Mar 2 10:16:31 2005 UTC revision 1053 by astrand, Thu Mar 2 15:22:25 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions     Entrypoint and utility functions
4     Copyright (C) Matthew Chapman 1999-2003     Copyright (C) Matthew Chapman 1999-2005
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 30  Line 30 
30  #include <errno.h>  #include <errno.h>
31  #include "rdesktop.h"  #include "rdesktop.h"
32    
33    #ifdef HAVE_LOCALE_H
34    #include <locale.h>
35    #endif
36    #ifdef HAVE_ICONV
37    #ifdef HAVE_LANGINFO_H
38    #include <langinfo.h>
39    #endif
40    #endif
41    
42  #ifdef EGD_SOCKET  #ifdef EGD_SOCKET
43    #include <sys/types.h>
44  #include <sys/socket.h>         /* socket connect */  #include <sys/socket.h>         /* socket connect */
45  #include <sys/un.h>             /* sockaddr_un */  #include <sys/un.h>             /* sockaddr_un */
46  #endif  #endif
# Line 40  Line 50 
50  char g_title[64] = "";  char g_title[64] = "";
51  char g_username[64];  char g_username[64];
52  char g_hostname[16];  char g_hostname[16];
53  char keymapname[16];  char g_keymapname[PATH_MAX] = "";
54  int g_keylayout = 0x409;        /* Defaults to US keyboard layout */  unsigned int g_keylayout = 0x409;       /* Defaults to US keyboard layout */
55    int g_keyboard_type = 0x4;      /* Defaults to US keyboard layout */
56    int g_keyboard_subtype = 0x0;   /* Defaults to US keyboard layout */
57    int g_keyboard_functionkeys = 0xc;      /* Defaults to US keyboard layout */
58    
59  int g_width = 800;              /* width is special: If 0, the  int g_width = 800;              /* width is special: If 0, the
60                                     geometry will be fetched from                                     geometry will be fetched from
# Line 51  int g_width = 800;             /* width is special: Line 64  int g_width = 800;             /* width is special:
64  int g_height = 600;  int g_height = 600;
65  int g_xpos = 0;  int g_xpos = 0;
66  int g_ypos = 0;  int g_ypos = 0;
67    int g_pos = 0;                  /* 0 position unspecified,
68                                       1 specified,
69                                       2 xpos neg,
70                                       4 ypos neg  */
71  extern int g_tcp_port_rdp;  extern int g_tcp_port_rdp;
72  int g_server_bpp = 8;  int g_server_depth = 8;
73  int g_win_button_size = 0;      /* If zero, disable single app mode */  int g_win_button_size = 0;      /* If zero, disable single app mode */
74  BOOL g_bitmap_compression = True;  BOOL g_bitmap_compression = True;
75  BOOL g_sendmotion = True;  BOOL g_sendmotion = True;
# Line 61  BOOL g_bitmap_cache_persist_enable = Fal Line 78  BOOL g_bitmap_cache_persist_enable = Fal
78  BOOL g_bitmap_cache_precache = True;  BOOL g_bitmap_cache_precache = True;
79  BOOL g_encryption = True;  BOOL g_encryption = True;
80  BOOL packet_encryption = True;  BOOL packet_encryption = True;
81  BOOL g_desktop_save = True;  BOOL g_desktop_save = True;     /* desktop save order */
82    BOOL g_polygon_ellipse_orders = True;   /* polygon / ellipse orders */
83  BOOL g_fullscreen = False;  BOOL g_fullscreen = False;
84  BOOL g_grab_keyboard = True;  BOOL g_grab_keyboard = True;
85  BOOL g_hide_decorations = False;  BOOL g_hide_decorations = False;
86  BOOL g_use_rdp5 = True;  BOOL g_use_rdp5 = True;
87  BOOL g_console_session = False;  BOOL g_console_session = False;
88  BOOL g_numlock_sync = False;  BOOL g_numlock_sync = False;
89    BOOL lspci_enabled = False;
90  BOOL g_owncolmap = False;  BOOL g_owncolmap = False;
91  BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */  BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
92  uint32 g_embed_wnd;  uint32 g_embed_wnd;
93  uint32 g_rdp5_performanceflags =  uint32 g_rdp5_performanceflags =
94          RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;          RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
95    /* Session Directory redirection */
96    BOOL g_redirect = False;
97    char g_redirect_server[64];
98    char g_redirect_domain[16];
99    char g_redirect_password[64];
100    char g_redirect_username[64];
101    char g_redirect_cookie[128];
102    uint32 g_redirect_flags = 0;
103    
104  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
105  BOOL g_rdpsnd = False;  BOOL g_rdpsnd = False;
106  #endif  #endif
107    
108    #ifdef HAVE_ICONV
109    char g_codepage[16] = "";
110    #endif
111    
112  extern RDPDR_DEVICE g_rdpdr_device[];  extern RDPDR_DEVICE g_rdpdr_device[];
113  extern uint32 g_num_devices;  extern uint32 g_num_devices;
114  extern char *g_rdpdr_clientname;  extern char *g_rdpdr_clientname;
# Line 94  static void Line 125  static void
125  usage(char *program)  usage(char *program)
126  {  {
127          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
128          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
129          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
130    
131          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
# Line 112  usage(char *program) Line 143  usage(char *program)
143          fprintf(stderr, "   -g: desktop geometry (WxH)\n");          fprintf(stderr, "   -g: desktop geometry (WxH)\n");
144          fprintf(stderr, "   -f: full-screen mode\n");          fprintf(stderr, "   -f: full-screen mode\n");
145          fprintf(stderr, "   -b: force bitmap updates\n");          fprintf(stderr, "   -b: force bitmap updates\n");
146    #ifdef HAVE_ICONV
147            fprintf(stderr, "   -L: local codepage\n");
148    #endif
149          fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");          fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
150          fprintf(stderr, "   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -e: disable encryption (French TS)\n");
151          fprintf(stderr, "   -E: disable encryption from client to server\n");          fprintf(stderr, "   -E: disable encryption from client to server\n");
# Line 149  usage(char *program) Line 183  usage(char *program)
183          fprintf(stderr, "   -5: use RDP version 5 (default)\n");          fprintf(stderr, "   -5: use RDP version 5 (default)\n");
184  }  }
185    
186  void  static void
187  print_disconnect_reason(uint16 reason)  print_disconnect_reason(uint16 reason)
188  {  {
189          char *text;          char *text;
# Line 249  print_disconnect_reason(uint16 reason) Line 283  print_disconnect_reason(uint16 reason)
283          fprintf(stderr, "disconnect: %s.\n", text);          fprintf(stderr, "disconnect: %s.\n", text);
284  }  }
285    
286    static void
287    rdesktop_reset_state(void)
288    {
289            rdp_reset_state();
290    }
291    
292  static BOOL  static BOOL
293  read_password(char *password, int size)  read_password(char *password, int size)
294  {  {
# Line 341  main(int argc, char *argv[]) Line 381  main(int argc, char *argv[])
381          char fullhostname[64];          char fullhostname[64];
382          char domain[16];          char domain[16];
383          char password[64];          char password[64];
384          char shell[128];          char shell[256];
385          char directory[32];          char directory[256];
386          BOOL prompt_password, deactivated;          BOOL prompt_password, deactivated;
387          struct passwd *pw;          struct passwd *pw;
388          uint32 flags, ext_disc_reason = 0;          uint32 flags, ext_disc_reason = 0;
389          char *p;          char *p;
390          int c;          int c;
391            char *locale = NULL;
392          int username_option = 0;          int username_option = 0;
393            int run_count = 0;      /* Session Directory support */
394            BOOL continue_connect = True;   /* Session Directory support */
395    
396    #ifdef HAVE_LOCALE_H
397            /* Set locale according to environment */
398            locale = setlocale(LC_ALL, "");
399            if (locale)
400            {
401                    locale = xstrdup(locale);
402            }
403    
404    #endif
405          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
406          prompt_password = False;          prompt_password = False;
407          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
         strcpy(keymapname, "en-us");  
408          g_embed_wnd = 0;          g_embed_wnd = 0;
409    
410          g_num_devices = 0;          g_num_devices = 0;
# Line 366  main(int argc, char *argv[]) Line 416  main(int argc, char *argv[])
416  #endif  #endif
417    
418          while ((c = getopt(argc, argv,          while ((c = getopt(argc, argv,
419                             VNCOPT "u:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)                             VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
420          {          {
421                  switch (c)                  switch (c)
422                  {                  {
# Line 389  main(int argc, char *argv[]) Line 439  main(int argc, char *argv[])
439                                  username_option = 1;                                  username_option = 1;
440                                  break;                                  break;
441    
442                            case 'L':
443    #ifdef HAVE_ICONV
444                                    STRNCPY(g_codepage, optarg, sizeof(g_codepage));
445    #else
446                                    error("iconv support not available\n");
447    #endif
448                                    break;
449    
450                          case 'd':                          case 'd':
451                                  STRNCPY(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
452                                  break;                                  break;
# Line 422  main(int argc, char *argv[]) Line 480  main(int argc, char *argv[])
480                                  break;                                  break;
481    
482                          case 'k':                          case 'k':
483                                  STRNCPY(keymapname, optarg, sizeof(keymapname));                                  STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
484                                  break;                                  break;
485    
486                          case 'g':                          case 'g':
# Line 456  main(int argc, char *argv[]) Line 514  main(int argc, char *argv[])
514                                  }                                  }
515    
516                                  if (*p == '+' || *p == '-')                                  if (*p == '+' || *p == '-')
517                                    {
518                                            g_pos |= (*p == '-') ? 2 : 1;
519                                          g_xpos = strtol(p, &p, 10);                                          g_xpos = strtol(p, &p, 10);
520    
521                                    }
522                                  if (*p == '+' || *p == '-')                                  if (*p == '+' || *p == '-')
523                                    {
524                                            g_pos |= (*p == '-') ? 4 : 1;
525                                          g_ypos = strtol(p, NULL, 10);                                          g_ypos = strtol(p, NULL, 10);
526                                    }
527    
528                                  break;                                  break;
529    
# Line 523  main(int argc, char *argv[]) Line 587  main(int argc, char *argv[])
587                                  break;                                  break;
588    
589                          case 'X':                          case 'X':
590                                  g_embed_wnd = strtol(optarg, NULL, 10);                                  g_embed_wnd = strtol(optarg, NULL, 0);
591                                  break;                                  break;
592    
593                          case 'a':                          case 'a':
594                                  g_server_bpp = strtol(optarg, NULL, 10);                                  g_server_depth = strtol(optarg, NULL, 10);
595                                  if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15                                  if (g_server_depth != 8 &&
596                                      && g_server_bpp != 24)                                      g_server_depth != 16 &&
597                                        g_server_depth != 15 && g_server_depth != 24)
598                                  {                                  {
599                                          error("invalid server bpp\n");                                          error("Invalid server colour depth.\n");
600                                          return 1;                                          return 1;
601                                  }                                  }
602                                  break;                                  break;
603    
604                          case 'z':                          case 'z':
605                                  DEBUG(("rdp compression enabled\n"));                                  DEBUG(("rdp compression enabled\n"));
606                                  flags |= RDP_COMPRESSION;                                  flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
607                                  break;                                  break;
608    
609                          case 'x':                          case 'x':
610                                  if (strncmp("modem", optarg, 1) == 0)                                  if (str_startswith(optarg, "m"))        /* modem */
611                                  {                                  {
612                                          g_rdp5_performanceflags =                                          g_rdp5_performanceflags =
613                                                  RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |                                                  RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
614                                                  RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;                                                  RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
615                                  }                                  }
616                                  else if (strncmp("broadband", optarg, 1) == 0)                                  else if (str_startswith(optarg, "b"))   /* broadband */
617                                  {                                  {
618                                          g_rdp5_performanceflags = RDP5_NO_WALLPAPER;                                          g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
619                                  }                                  }
620                                  else if (strncmp("lan", optarg, 1) == 0)                                  else if (str_startswith(optarg, "l"))   /* lan */
621                                  {                                  {
622                                          g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;                                          g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
623                                  }                                  }
# Line 568  main(int argc, char *argv[]) Line 633  main(int argc, char *argv[])
633    
634                          case 'r':                          case 'r':
635    
636                                  if (strncmp("sound", optarg, 5) == 0)                                  if (str_startswith(optarg, "sound"))
637                                  {                                  {
638                                          optarg += 5;                                          optarg += 5;
639    
# Line 577  main(int argc, char *argv[]) Line 642  main(int argc, char *argv[])
642                                                  *optarg++;                                                  *optarg++;
643                                                  while ((p = next_arg(optarg, ',')))                                                  while ((p = next_arg(optarg, ',')))
644                                                  {                                                  {
645                                                          if (strncmp("remote", optarg, 6) == 0)                                                          if (str_startswith(optarg, "remote"))
646                                                                  flags |= RDP_LOGON_LEAVE_AUDIO;                                                                  flags |= RDP_LOGON_LEAVE_AUDIO;
647    
648                                                          if (strncmp("local", optarg, 5) == 0)                                                          if (str_startswith(optarg, "local"))
649  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
650                                                                  g_rdpsnd = True;                                                                  g_rdpsnd = True;
651  #else  #else
652                                                                  warning("Not compiled with sound support\n");                                                                  warning("Not compiled with sound support\n");
653  #endif  #endif
654    
655                                                          if (strncmp("off", optarg, 3) == 0)                                                          if (str_startswith(optarg, "off"))
656  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
657                                                                  g_rdpsnd = False;                                                                  g_rdpsnd = False;
658  #else  #else
# Line 606  main(int argc, char *argv[]) Line 671  main(int argc, char *argv[])
671  #endif  #endif
672                                          }                                          }
673                                  }                                  }
674                                  else if (strncmp("disk", optarg, 4) == 0)                                  else if (str_startswith(optarg, "disk"))
675                                  {                                  {
676                                          /* -r disk:h:=/mnt/floppy */                                          /* -r disk:h:=/mnt/floppy */
677                                          disk_enum_devices(&g_num_devices, optarg + 4);                                          disk_enum_devices(&g_num_devices, optarg + 4);
678                                  }                                  }
679                                  else if (strncmp("comport", optarg, 7) == 0)                                  else if (str_startswith(optarg, "comport"))
680                                  {                                  {
681                                          serial_enum_devices(&g_num_devices, optarg + 7);                                          serial_enum_devices(&g_num_devices, optarg + 7);
682                                  }                                  }
683                                  else if (strncmp("lptport", optarg, 7) == 0)                                  else if (str_startswith(optarg, "lspci"))
684                                    {
685                                            lspci_enabled = True;
686                                    }
687                                    else if (str_startswith(optarg, "lptport"))
688                                  {                                  {
689                                          parallel_enum_devices(&g_num_devices, optarg + 7);                                          parallel_enum_devices(&g_num_devices, optarg + 7);
690                                  }                                  }
691                                  else if (strncmp("printer", optarg, 7) == 0)                                  else if (str_startswith(optarg, "printer"))
692                                  {                                  {
693                                          printer_enum_devices(&g_num_devices, optarg + 7);                                          printer_enum_devices(&g_num_devices, optarg + 7);
694                                  }                                  }
695                                  else if (strncmp("clientname", optarg, 7) == 0)                                  else if (str_startswith(optarg, "clientname"))
696                                  {                                  {
697                                          g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);                                          g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
698                                          strcpy(g_rdpdr_clientname, optarg + 11);                                          strcpy(g_rdpdr_clientname, optarg + 11);
# Line 675  main(int argc, char *argv[]) Line 744  main(int argc, char *argv[])
744                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
745          }          }
746    
747    #ifdef HAVE_ICONV
748            if (g_codepage[0] == 0)
749            {
750                    if (setlocale(LC_CTYPE, ""))
751                    {
752                            STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
753                    }
754                    else
755                    {
756                            STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
757                    }
758            }
759    #endif
760    
761          if (g_hostname[0] == 0)          if (g_hostname[0] == 0)
762          {          {
763                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
# Line 690  main(int argc, char *argv[]) Line 773  main(int argc, char *argv[])
773                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
774          }          }
775    
776          if ((flags & RDP_COMPRESSION) && (g_server_bpp > 8))          if (g_keymapname[0] == 0)
777          {          {
778                  warning("rdp compression not supported for bpp > 8, compression disabled\n");                  if (locale && xkeymap_from_locale(locale))
779                  flags ^= RDP_COMPRESSION;                  {
780                            fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
781                    }
782                    else
783                    {
784                            STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
785                    }
786          }          }
787            if (locale)
788                    xfree(locale);
789    
790    
791          if (prompt_password && read_password(password, sizeof(password)))          if (prompt_password && read_password(password, sizeof(password)))
792                  flags |= RDP_LOGON_AUTO;                  flags |= RDP_LOGON_AUTO;
# Line 717  main(int argc, char *argv[]) Line 809  main(int argc, char *argv[])
809          if (g_rdpsnd)          if (g_rdpsnd)
810                  rdpsnd_init();                  rdpsnd_init();
811  #endif  #endif
812    
813            if (lspci_enabled)
814                    lspci_init();
815    
816          rdpdr_init();          rdpdr_init();
817    
818          if (!rdp_connect(server, flags, domain, password, shell, directory))          while (run_count < 2 && continue_connect)       /* add support for Session Directory; only reconnect once */
819                  return 1;          {
820                    if (run_count == 0)
821                    {
822                            if (!rdp_connect(server, flags, domain, password, shell, directory))
823                                    return 1;
824                    }
825                    else if (!rdp_reconnect
826                             (server, flags, domain, password, shell, directory, g_redirect_cookie))
827                            return 1;
828    
829          /* By setting encryption to False here, we have an encrypted login                  /* By setting encryption to False here, we have an encrypted login
830             packet but unencrypted transfer of other packets */                     packet but unencrypted transfer of other packets */
831          if (!packet_encryption)                  if (!packet_encryption)
832                  g_encryption = False;                          g_encryption = False;
833    
834    
835          DEBUG(("Connection successful.\n"));                  DEBUG(("Connection successful.\n"));
836          memset(password, 0, sizeof(password));                  memset(password, 0, sizeof(password));
837    
838          if (ui_create_window())                  if (run_count == 0)
839          {                          if (!ui_create_window())
840                  rdp_main_loop(&deactivated, &ext_disc_reason);                                  continue_connect = False;
841                  ui_destroy_window();  
842                    if (continue_connect)
843                            rdp_main_loop(&deactivated, &ext_disc_reason);
844    
845                    DEBUG(("Disconnecting...\n"));
846                    rdp_disconnect();
847    
848                    if ((g_redirect == True) && (run_count == 0))   /* Support for Session Directory */
849                    {
850                            /* reset state of major globals */
851                            rdesktop_reset_state();
852    
853                            STRNCPY(domain, g_redirect_domain, sizeof(domain));
854                            STRNCPY(g_username, g_redirect_username, sizeof(g_username));
855                            STRNCPY(password, g_redirect_password, sizeof(password));
856                            STRNCPY(server, g_redirect_server, sizeof(server));
857                            flags |= RDP_LOGON_AUTO;
858    
859                            g_redirect = False;
860                    }
861                    else
862                    {
863                            continue_connect = False;
864                            ui_destroy_window();
865                            break;
866                    }
867    
868                    run_count++;
869          }          }
870    
         DEBUG(("Disconnecting...\n"));  
         rdp_disconnect();  
871          cache_save_state();          cache_save_state();
872          ui_deinit();          ui_deinit();
873    
# Line 865  xmalloc(int size) Line 994  xmalloc(int size)
994          return mem;          return mem;
995  }  }
996    
997    /* strdup */
998    char *
999    xstrdup(const char *s)
1000    {
1001            char *mem = strdup(s);
1002            if (mem == NULL)
1003            {
1004                    perror("strdup");
1005                    exit(1);
1006            }
1007            return mem;
1008    }
1009    
1010  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
1011  void *  void *
1012  xrealloc(void *oldmem, int size)  xrealloc(void *oldmem, int size)
# Line 1038  toupper_str(char *p) Line 1180  toupper_str(char *p)
1180  }  }
1181    
1182    
1183    BOOL
1184    str_startswith(const char *s, const char *prefix)
1185    {
1186            return (strncmp(s, prefix, strlen(prefix)) == 0);
1187    }
1188    
1189    
1190    /* Split input into lines, and call linehandler for each
1191       line. Incomplete lines are saved in the rest variable, which should
1192       initially point to NULL. When linehandler returns False, stop and
1193       return False. Otherwise, return True.  */
1194    BOOL
1195    str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
1196    {
1197            char *buf, *p;
1198            char *oldrest;
1199            size_t inputlen;
1200            size_t buflen;
1201            size_t restlen = 0;
1202            BOOL ret = True;
1203    
1204            /* Copy data to buffer */
1205            inputlen = strlen(input);
1206            if (*rest)
1207                    restlen = strlen(*rest);
1208            buflen = restlen + inputlen + 1;
1209            buf = (char *) xmalloc(buflen);
1210            buf[0] = '\0';
1211            if (*rest)
1212                    STRNCPY(buf, *rest, buflen);
1213            strncat(buf, input, inputlen);
1214            p = buf;
1215    
1216            while (1)
1217            {
1218                    char *newline = strchr(p, '\n');
1219                    if (newline)
1220                    {
1221                            *newline = '\0';
1222                            if (!linehandler(p, data))
1223                            {
1224                                    p = newline + 1;
1225                                    ret = False;
1226                                    break;
1227                            }
1228                            p = newline + 1;
1229                    }
1230                    else
1231                    {
1232                            break;
1233    
1234                    }
1235            }
1236    
1237            /* Save in rest */
1238            oldrest = *rest;
1239            restlen = buf + buflen - p;
1240            *rest = (char *) xmalloc(restlen);
1241            STRNCPY((*rest), p, restlen);
1242            xfree(oldrest);
1243    
1244            xfree(buf);
1245            return ret;
1246    }
1247    
1248    /* Execute the program specified by argv. For each line in
1249       stdout/stderr output, call linehandler. Returns false on failure. */
1250    BOOL
1251    subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
1252    {
1253            pid_t child;
1254            int fd[2];
1255            int n = 1;
1256            char output[256];
1257            char *rest = NULL;
1258    
1259            if (pipe(fd) < 0)
1260            {
1261                    perror("pipe");
1262                    return False;
1263            }
1264    
1265            if ((child = fork()) < 0)
1266            {
1267                    perror("fork");
1268                    return False;
1269            }
1270    
1271            /* Child */
1272            if (child == 0)
1273            {
1274                    /* Close read end */
1275                    close(fd[0]);
1276    
1277                    /* Redirect stdout and stderr to pipe */
1278                    dup2(fd[1], 1);
1279                    dup2(fd[1], 2);
1280    
1281                    /* Execute */
1282                    execvp(argv[0], argv);
1283                    perror("Error executing child");
1284                    _exit(128);
1285            }
1286    
1287            /* Parent. Close write end. */
1288            close(fd[1]);
1289            while (n > 0)
1290            {
1291                    n = read(fd[0], output, 255);
1292                    output[n] = '\0';
1293                    str_handle_lines(output, &rest, linehandler, data);
1294            }
1295            xfree(rest);
1296    
1297            return True;
1298    }
1299    
1300    
1301  /* not all clibs got ltoa */  /* not all clibs got ltoa */
1302  #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)  #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1303    

Legend:
Removed from v.825  
changed lines
  Added in v.1053

  ViewVC Help
Powered by ViewVC 1.1.26