#include #include #include #include #include #include #include "xterminals.h" #include "xterminals.m" #include #include #include #include #include "procterm.h" #include #include <../../libmodules/guruengine/guruengine.h> #include static HELP_FILE help_terminal ("xterminals","terminal"); static HELP_FILE help_export ("xterminals","export"); static HELP_FILE help_import ("xterminals","import"); class XTERMINAL: public ARRAY_OBJ{ public: SSTRING dir; // Terminal configuration directory SSTRING name; SSTRING mac; // Ethernet mac address of the terminal SSTRING location; SSTRING groups; SSTRING appserver; SSTRING fontserver; SSTRING defprinter; // Default printer near this terminal char printserv; // Is the terminal handling printers char indirect; SSTRING ipnum; SSTRING wanted_resolution;// e.g. 800x600 SSTRING bits_per_pixel; // e.g. 8 SSTRING monitor_hsync; // e.g. 30-64 SSTRING monitor_vsync; // e.g. 50-100 /*~PROTOBEG~ XTERMINAL */ public: XTERMINAL (const char *_dir); XTERMINAL (void); void admin (void); int edit (const char *intro); const char *getipaddr (DHCP_API *api, bool&connected); void menu (void); int remove (DHCP_API *api); int write (void); /*~PROTOEND~ XTERMINAL */ }; PUBLIC XTERMINAL::XTERMINAL() { } static int xtermadmin_readfile(SSTRING &val, const char *dir, const char *file) { int ret = -1; char fpath[PATH_MAX]; snprintf (fpath,sizeof(fpath)-1,"%s/sysconfig/%s",dir,file); FILE *fin = fopen (fpath,"r"); if (fin != NULL){ char buf[100]; if (fgets_strip(buf,sizeof(buf)-1,fin,NULL)!=NULL){ val.setfrom (buf); ret = 0; } } return ret; } static int xtermadmin_readfile(VIEWITEMS &vis, const char *dir, const char *file) { char path[PATH_MAX]; snprintf (path,sizeof(path)-1,"%s/sysconfig/%s",dir,file); CONFIG_FILE conf (path,help_nil,CONFIGF_OPTIONAL); return vis.read (conf); } static int xtermadmin_get (VIEWITEMS &vis, const char *var, SSTRING &val) { char tmp[1000]; val.setfrom (vis.locateval(var,tmp)); return 0; } static int xtermadmin_get (VIEWITEMS &vis, const char *var, char &val) { char tmp[1000]; val = 0; const char *pt = vis.locateval(var,tmp); if (pt != NULL) val = strcmp(pt,"yes")==0 ? 1 : 0; return 0; } PUBLIC XTERMINAL::XTERMINAL(const char *_dir) { dir.setfrom (_dir); const char *pt = strrchr (_dir,'/'); if (pt != NULL) mac.setfrom (pt+1); xtermadmin_readfile (name,_dir,"TERMNAME"); xtermadmin_readfile (defprinter,_dir,"DEFPRINTER"); { VIEWITEMS vis; xtermadmin_readfile (vis,_dir,"xterminal"); xtermadmin_get (vis,"APPSERVER",appserver); xtermadmin_get (vis,"FONTSERVER",fontserver); xtermadmin_get (vis,"TERMLOCATION",location); xtermadmin_get (vis,"TERMGROUPS",groups); xtermadmin_get (vis,"INDIRECT",indirect); xtermadmin_get (vis,"RESOLUTION",wanted_resolution); xtermadmin_get (vis,"BITSPERPIXEL",bits_per_pixel); xtermadmin_get (vis,"HSYNC",monitor_hsync); xtermadmin_get (vis,"VSYNC",monitor_vsync); } { VIEWITEMS vis; xtermadmin_readfile (vis,_dir,"printserv"); xtermadmin_get (vis,"PRINTSERV",printserv); } } static int xtermadmin_writefile(SSTRING &val, const char *dir, const char *file) { int ret = -1; char fpath[PATH_MAX]; snprintf (fpath,sizeof(fpath)-1,"%s/sysconfig/%s",dir,file); FILE *fout = fopen (fpath,"w"); if (fout != NULL){ fprintf (fout,"%s\n",val.get()); ret = fclose (fout); } return ret; } /* Write a single line in a file if "isset". Remove the file if not The older xtermkit was barely testing the presence for some files to perform an action. Newer actually check the content :-). By removing the file when unset, we are compatible with both. */ static int xtermadmin_setfile( const char *dir, const char *file, bool isset, const char *value) { int ret = -1; char path[PATH_MAX]; snprintf (path,sizeof(path)-1,"%s/sysconfig/%s",dir,file); if (isset){ CONFIG_FILE f_xterm (path,help_nil,CONFIGF_OPTIONAL ,"root","root",0644); FILE_CFG *fout = f_xterm.fopen ("w"); if (fout != NULL){ fprintf (fout,"%s\n",value); ret = fclose (fout); } }else{ ret = unlink (path); } return ret; } static int xtermadmin_writefile(VIEWITEMS &vis, const char *dir, const char *file) { char path[PATH_MAX]; snprintf (path,sizeof(path)-1,"%s/sysconfig/%s",dir,file); CONFIG_FILE conf (path,help_nil,CONFIGF_OPTIONAL); return vis.write (conf,NULL); } static int xtermadmin_set (VIEWITEMS &vis, const char *var, SSTRING &val) { VIEWITEM *it = vis.locateassign (var); if (it == NULL){ it = new VIEWITEM(""); vis.add(it); } it->line.setfromf ("%s=%s",var,val.get()); return 0; } static int xtermadmin_set (VIEWITEMS &vis, const char *var, char val) { SSTRING tmp; tmp.setfrom (val != 0 ? "yes" : "no"); return xtermadmin_set (vis,var,tmp); } /* Update the configuration */ PUBLIC int XTERMINAL::write() { int ret = 0; const char *ptdir = dir.get(); ret |= xtermadmin_writefile (name,ptdir,"TERMNAME"); ret |= xtermadmin_writefile (defprinter,ptdir,"DEFPRINTER"); { VIEWITEMS vis; xtermadmin_readfile (vis,ptdir,"xterminal"); xtermadmin_set (vis,"APPSERVER",appserver); xtermadmin_set (vis,"FONTSERVER",fontserver); xtermadmin_set (vis,"TERMLOCATION",location); xtermadmin_set (vis,"TERMGROUPS",groups); xtermadmin_set (vis,"INDIRECT",indirect); xtermadmin_set (vis,"RESOLUTION",wanted_resolution); xtermadmin_set (vis,"BITSPERPIXEL",bits_per_pixel); xtermadmin_set (vis,"HSYNC",monitor_hsync); xtermadmin_set (vis,"VSYNC",monitor_vsync); ret |= xtermadmin_writefile (vis,ptdir,"xterminal"); } ret |= xtermadmin_setfile (ptdir,"printserv",printserv,"PRINTSERV=yes"); return ret; } /* Retrieve the IP number from /proc/net/arp Return -1 if not found */ static int xtermadmin_getipfromarp (const char *mac, SSTRING &ipnum) { int ret = -1; ipnum.setfrom (""); FILE *fin = fopen ("/proc/net/arp","r"); if (fin != NULL){ char line[1000]; if (fgets(line,sizeof(line)-1,fin)!=NULL){ // Ok, we have skipped the header while (fgets(line,sizeof(line)-1,fin)!=NULL){ char ip[100],stuff[100],hwaddr[100]; if (sscanf(line,"%s %s %s %s %s",ip,stuff,stuff,hwaddr,stuff)>= 4){ if (strcmp(mac,hwaddr)==0){ ipnum.setfrom (ip); ret = 0; break; } } } } fclose (fin); } return ret; } PUBLIC const char *XTERMINAL::getipaddr(DHCP_API *api, bool &connected) { connected = false; if (xtermadmin_getipfromarp (mac.get(),ipnum)!=-1){ connected = true; }else if (api != NULL){ api->getip(api,mac.get(),ipnum); } return ipnum.get(); } /* Remove the X terminal configuration from /var/xterminals Return -1 if any error. */ PUBLIC int XTERMINAL::remove(DHCP_API *api) { int ret = netconf_system_if ("xterminals-remove",dir.get()); if (ret == 0 && api != NULL){ api->release (api,mac.get()); } return ret; } PUBLIC int XTERMINAL::edit (const char *intro) { DIALOG dia; dia.newf_title (MSG_U(T_BASEINFO,"Base configuration"),1,MSG_R(T_BASEINFO),""); dia.newf_str (MSG_U(F_TERMNAME,"Terminal name"),name); dia.last_noempty(); dia.newf_str (MSG_U(F_LOCATION,"Location"),location); dia.newf_str (MSG_U(F_GROUPS,"Terminal groups"),groups); dia.newf_str (MSG_U(F_DEFPRINTER,"Default printer"),defprinter); dia.newf_chk ("",printserv,MSG_U(I_ATTACHEDPRINTER ,"Drive some printers")); dia.newf_title (MSG_U(T_GRSETTINGS,"Graphic settings"),1,MSG_R(T_GRSETTINGS),""); FIELD_LIST *res_list = dia.newf_list(MSG_U(F_RESOLL,"Screen resolution") ,wanted_resolution); res_list->addopt("640x480",""); res_list->addopt("800x600",""); res_list->addopt("1024x768",""); res_list->addopt("1280x1024",""); res_list->addopt("1600x1200",""); FIELD_LIST *bpp_list = dia.newf_list(MSG_U(F_BITSPIXEL,"Bits per pixel") ,bits_per_pixel); bpp_list->addopt("8",MSG_U(I_COL256,"256 colors")); bpp_list->addopt("16",MSG_U(I_COL65536,"65536 colors")); bpp_list->addopt("24",MSG_U(I_TRUECOLOR,"true colors")); bpp_list->addopt("32",MSG_R(I_TRUECOLOR)); FIELD_LIST *hsync_list = dia.newf_list(MSG_U(F_HORFREQ ,"Screen horizontal frequency range") ,monitor_hsync); hsync_list->addopt("31.5","KHz"); hsync_list->addopt("31.5-35.1","KHz (640x480@60Hz)"); hsync_list->addopt("31.5-37.9","KHz (800x600@56Hz)"); hsync_list->addopt("31.5-48.5","KHz (800x600@72Hz)"); hsync_list->addopt("31.5-57.0","KHz (1024x768@70Hz)"); hsync_list->addopt("31.5-64.3","KHz (1280x1024@60Hz)"); hsync_list->addopt("31.5-79.0","KHz (1280x1024@74Hz)"); hsync_list->addopt("31.5-82.0","KHz (1280x1024@76Hz)"); hsync_list->addopt("31.5-88.0","KHz (1600x1200@70Hz)"); hsync_list->addopt("31.5-94.0","KHz (1600x1200@76Hz)"); FIELD_LIST *vsync_list = dia.newf_list(MSG_U(F_VERFREQ ,"Screen vertical frequency range") ,monitor_vsync); vsync_list->addopt("50-70","Hz"); vsync_list->addopt("50-90","Hz"); vsync_list->addopt("50-100","Hz"); vsync_list->addopt("40-150","Hz"); dia.newf_title (MSG_U(T_EXTRAINFO,"Extra"),1,MSG_R(T_EXTRAINFO),""); dia.newf_str (MSG_U(F_APPSERVER,"Application server"),appserver); dia.last_noempty(); dia.newf_chk ("",indirect,MSG_U(I_INDIRECTLOGIN,"May log to several app server")); dia.newf_str (MSG_U(F_FONTSERVER,"Font server"),fontserver); dia.last_noempty(); int nof = 0; SSTRING title; title.setfromf(MSG_U(T_TERMEDIT,"Terminal %s configuration"),name.get()); while (1){ MENU_STATUS code = dia.edit (title.get(),intro,help_terminal,nof ,MENUBUT_CANCEL|MENUBUT_DEL|MENUBUT_ACCEPT); if (code == MENU_ESCAPE || code == MENU_CANCEL){ break; }else if (code == MENU_DEL){ if (xconf_delok()){ DHCP_API *api = dhcp_api_init ("xterminals"); remove(api); dhcp_api_end (api); break; } }else{ write (); break; } } return 0; } PUBLIC void XTERMINAL::admin () { DIALOG dia; } class XTERMINALS: public ARRAY{ /*~PROTOBEG~ XTERMINALS */ public: XTERMINAL *getitem (int no)const; /*~PROTOEND~ XTERMINALS */ }; PUBLIC XTERMINAL *XTERMINALS::getitem(int no) const { return (XTERMINAL*)ARRAY::getitem(no); } static int cmp_by_name (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2) { XTERMINAL *x1 = (XTERMINAL*)o1; XTERMINAL *x2 = (XTERMINAL*)o2; int ret = x1->name.cmp(x2->name); if (ret == 0){ ret = x1->location.cmp(x2->location); if (ret == 0){ ret = x1->dir.cmp(x2->dir); } } return ret; } PUBLIC void XTERMINAL::menu() { DIALOG_MENUPOPUP dia; dia.new_menuitem (MSG_R(M_CONFIGURE),MSG_U(I_THISTERM,"this terminal")); dia.new_menuitem (MSG_R(F_PERFORM),MSG_U(M_ADMIN,"Admin task")); int nof = 0; if (dia.editmenu("",nof)==MENU_OK){ if (nof == 0){ edit (""); }else{ admin (); } } } void xtermadmin_import() { SSTRING ident; (MSG_U(T_IMPORTCONFTERM,"Import terminal configurations") ,MSG_U(I_IMPORTCONFTERM ,"You have probably received a configuration floppy\n" "with your X terminals. We can import the content\n" "so X terminals will be immediatly usable") ,help_import); (mode,status); settitle (MSG_U(Q_PUTFLOPPY,"Insert floppy")); setintro (MSG_U(I_PUTFLOPPY ,"Insert terminal configuration floppy in the A: unit")); if (edit()){ POPEN pop ("xterminals-import","--label"); if (pop.isok()){ glocal.ident.setfrom (""); while (pop.wait(10)> 0){ char line[100]; while (pop.readout(line,99)!=-1) glocal.ident.append (line); } glocal.ident.strip_end(); } } status.is_possible = glocal.ident.is_filled(); settitle (MSG_U(T_IMPORTING,"Importing content")); setintro (MSG_U(I_IMPORTING ,"We have identified the floppy.\n" "It is a valid X terminal configuration floppy.\n" "You can see the identification string.\n" "If this is the proper floppy, hit next to import.\n")); dia.newf_info (MSG_R(F_BATCHNAME),glocal.ident.get()); dia.newline(); char over = 0; dia.newf_chk ("",over,MSG_U(I_OVERWRITE,"Overwrite existing configurations")); while (1){ if (edit()){ if (netconf_system_if ("xterminals-import" ,over ? "--import --overwrite" : "--import")==0){ xconf_notice (MSG_U(N_IMPORTOK,"Import succeeded")); break; }else{ xconf_error (MSG_U(N_IMPORTFAILED,"Import failed")); } }else{ break; } } } /* Extract the list of terminal configuration matching the name prefix and location prefix */ static int xtermadmin_pick ( const char *name_prefix, const char *location_prefix, XTERMINALS &terms) { const char *name; const char *location; int lenname; int lenloc; XTERMINALS *terms; glocal.name = name_prefix; glocal.location = location_prefix; glocal.lenname = strlen(name_prefix); glocal.lenloc = strlen(location_prefix); glocal.terms = &terms; ("/var/xterminals"); if (file_type(path)==1 && strcmp(basename,"preferred")!=0){ XTERMINAL *term = new XTERMINAL(path); if (term->location.ncmp(glocal.location,glocal.lenloc)==0 && term->name.ncmp(glocal.name,glocal.lenname)==0){ glocal.terms->add (term); }else{ delete term; } } return false; terms.sort (cmp_by_name); return terms.getnb(); } /* Pick some terminal configurations to export on a floppy */ void xtermadmin_export() { XTERMINALS terms; SSTRING name; SSTRING location; int lenname,lenloc; DIALOG dia; dia.newf_str (MSG_U(F_TERMPREFIX,"Terminal name"),glocal.name); dia.newf_str (MSG_R(F_LOCATION),glocal.location); dia.newf_title ("","-"); SSTRING ident; dia.newf_str (MSG_U(F_BATCHNAME,"Identification"),ident); dia.last_noempty(); char format = 0; dia.newf_chk (MSG_R(F_PERFORM),format,MSG_R(I_DOSFORMAT)); char lowlevel = 0; dia.newf_chk ("",lowlevel,MSG_R(I_LOWLEVEL)); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_EXPORTING ,"Export terminal configurations") ,MSG_U(I_EXPORTING ,"You have to select some terminal configurations\n" "you wish to save on a floppy.\n" "Those configurations will be imported in another\n" "application server.\n" "\n" "You can enter the common prefix for the name\n" "and the location.") ,help_export ,nof); if (code == MENU_ESCAPE || code == MENU_CANCEL){ break; }else if (ident.strchr('"')!=NULL){ xconf_error (MSG_U(E_NOQUOTE,"No quote allowed in the identification string")); nof = 3; }else{ glocal.terms.remove_all(); xtermadmin_pick (glocal.name.get(),glocal.location.get(),glocal.terms); if (glocal.terms.getnb()==0){ xconf_error (MSG_U(E_NOCONFSEL,"No matching terminal configuration")); }else{ SSTRING tmp; if (lowlevel) tmp.append (" --lowlevel"); if (format) tmp.append (" --format"); if (ident.is_filled()) tmp.appendf (" --label \"%s\"",ident.get()); for (int i=0; idir.get()); } if (netconf_system_if ("xterminals-export",tmp.get(),200)!=0){ xconf_error (MSG_U(E_EXPORTFAILED,"Export failed")); }else{ xconf_notice (MSG_U(N_EXPORTED,"%d terminal configurations exported") ,glocal.terms.getnb()); break; } } } } } void xtermadmin_clean() { XTERMINALS terms; SSTRING name; SSTRING location; int lenname,lenloc; DIALOG dia; dia.newf_str (MSG_R(F_TERMPREFIX),glocal.name); dia.newf_str (MSG_R(F_LOCATION),glocal.location); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_TERMFILTER,"Terminal selection") ,MSG_U(I_TERMFILTER ,"You have to select some terminal configurations\n" "you wish to delete.\n" "\n" "You can enter the common prefix for the name\n" "and the location.") ,help_nil ,nof); if (code == MENU_ESCAPE || code == MENU_CANCEL){ break; }else{ glocal.terms.remove_all(); xtermadmin_pick (glocal.name.get(),glocal.location.get() ,glocal.terms); if (glocal.terms.getnb()==0){ xconf_error (MSG_R(E_NOCONFSEL)); }else{ DIALOG dias; char sel[glocal.terms.getnb()]; memset (sel,1,sizeof(sel)); for (int i=0; iname.get(),sel[i],term->location.get()); } dias.setbutinfo (MENU_USR1,MSG_U(B_NONE,"None"),MSG_R(B_NONE)); dias.setbutinfo (MENU_USR2,MSG_U(B_ALL,"All"),MSG_R(B_ALL)); int nof = 0; while (1){ MENU_STATUS code = dias.edit (MSG_U(T_TERMSEL,"Select terminals") ,"",help_nil,nof ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_USR1|MENUBUT_USR2); if (code == MENU_ESCAPE || code == MENU_CANCEL){ break; }else if (code == MENU_USR1 || code == MENU_USR2){ memset (sel,code == MENU_USR1 ? 0 : 1,sizeof(sel)); dias.reload(); }else{ DHCP_API *api = dhcp_api_init ("xterminals"); for (int i=0; iremove(api); } dhcp_api_end (api); break; } } break; } } } } void xtermadmin() { XTERMINALS tb; PRIVATE_MESSAGE timer; dialog_settimer (glocal.timer,3,true); // Refresh the list every 3 seconds (MSG_U(T_ADMINTERM,"Configure terminals"),"",help_nil); newf_head (MSG_U(H_TERMINALS,"Terminal name\tLocation\tDef printer\tPrint server\tIP number\tStatus\tUser\tResolution")); waitfor (glocal.timer); sortable(); sortpolicy ("aaaaaaaa"); glocal.tb.remove_all(); ("/var/xterminals"); if (file_type(path)==1 && strcmp(basename,"preferred")!=0){ glocal.tb.add (new XTERMINAL(path)); } return false; glocal.tb.sort (cmp_by_name); PROCTERMS procs; procterm_get (NULL,"6000",false,procs); DHCP_API *api = dhcp_api_init ("xterminals"); for (int i=0; igetipaddr(api,connected); const char *user = ""; const char *status = connected ? MSG_U(I_TERMCONNECTED,"Connected") : ""; if (ip[0] != '\0'){ PROCTERMS ipprocs; procs.extractip (ip,ipprocs); for (int j=0; jgetexepath(); if (strstr(prog,"/kdm")!=NULL && strstr(prog,"/gdm")!=NULL && strstr(prog,"/xdm")!=NULL){ status = MSG_U(I_LOGGED,"Logged"); uid_t uid = t->getuid(); struct passwd *p = getpwuid (uid); if (p != NULL) user = p->pw_name; break; } } } new_menuitemf (term->name.get(),"%s\t%s\t%s\t%s\t%s\t%s\t%s/%s" ,term->location.get(),term->defprinter.get() ,term->printserv ? MSG_U(I_YES,"Yes") : MSG_U(I_NO,"No") ,ip ,status ,user ,term->wanted_resolution.get(),term->bits_per_pixel.get()); } dhcp_api_end (api); XTERMINAL *term = glocal.tb.getitem(no); term->menu (); dialog_deltimer (glocal.timer); } /* Record the various setting for the default X terminal configuration. This is stored in /var/xterminals/preferred */ void xtermadmin_setdefault () { if (file_type("/var/xterminals/preferred")!= 1){ xconf_error (MSG_U(E_NOPREFERRED ,"No default X terminal configuration\n" "Directory /var/xterminals/preferred does not exist\n" "Update your X terminal toolkit to get one")); }else{ XTERMINAL term ("/var/xterminals/preferred"); term.edit(MSG_U(T_TERMDEFAULT ,"This is the terminals default parameters\n" "By filling this form, you will save some time\n" "when configuring new terminals")); } }